void gvinum_stop(int argc, char **argv) { int err, fileid; fileid = kldfind(GVINUMMOD); if (fileid == -1) { warn("cannot find " GVINUMMOD); return; } /* * This little hack prevents that we end up in an infinite loop in * g_unload_class(). gv_unload() will return EAGAIN so that the GEOM * event thread will be free for the g_wither_geom() call from * gv_unload(). It's silly, but it works. */ printf("unloading " GVINUMMOD " kernel module... "); fflush(stdout); if ((err = kldunload(fileid)) != 0 && (errno == EAGAIN)) { sleep(1); err = kldunload(fileid); } if (err != 0) { printf(" failed!\n"); warn("cannot unload " GVINUMMOD); return; } printf("done\n"); exit(0); }
/** * Invalidate entry. For KLDs we try to unload it, for processes we SIGKILL it. */ static int invalidate_swrun_entry(struct swrun_entry *entry, int commit) { struct kinfo_proc *plist; int nproc; struct kld_file_stat stat; assert(entry != NULL); if (entry->index >= NO_PID + 1) { /* this is a kernel item */ HRDBG("atempt to unload KLD %d", entry->index - NO_PID - 1); if (entry->index == SWOSIndex) { /* can't invalidate the kernel itself */ return (SNMP_ERR_NOT_WRITEABLE); } stat.version = sizeof(stat); if (kldstat(entry->index - NO_PID - 1, &stat) == -1) { /* * not found, it's gone. Mark it as invalid for now, it * will be removed from the list at next global * refresh */ HRDBG("missing item with kid=%d", entry->index - NO_PID - 1); entry->status = (int32_t)SRS_INVALID; return (SNMP_ERR_NOERROR); } /* * There is no way to try to unload a module. There seems * also no way to find out whether it is busy without unloading * it. We can assume that it is busy, if the reference count * is larger than 2, but if it is 1 nothing helps. */ if (!commit) { if (stat.refs > 1) return (SNMP_ERR_NOT_WRITEABLE); return (SNMP_ERR_NOERROR); } if (kldunload(stat.id) == -1) { syslog(LOG_ERR,"kldunload for %d/%s failed: %m", stat.id, stat.name); if (errno == EBUSY) return (SNMP_ERR_NOT_WRITEABLE); else return (SNMP_ERR_RES_UNAVAIL); } } else { /* this is a process */ assert(hr_kd != NULL); plist = kvm_getprocs(hr_kd, KERN_PROC_PID, entry->index - 1, &nproc); if (plist == NULL || nproc != 1) { HRDBG("missing item with PID=%d", entry->index - 1); entry->status = (int32_t)SRS_INVALID; return (SNMP_ERR_NOERROR); } if (IS_KERNPROC(plist)) { /* you don't want to do this */ return (SNMP_ERR_NOT_WRITEABLE); } if (kill(entry->index - 1, commit ? SIGKILL : 0) < 0) { syslog(LOG_ERR,"kill (%d, SIGKILL) failed: %m", entry->index - 1); if (errno == ESRCH) { /* race: just gone */ entry->status = (int32_t)SRS_INVALID; return (SNMP_ERR_NOERROR); } return (SNMP_ERR_GENERR); } } return (SNMP_ERR_NOERROR); }