Exemplo n.º 1
0
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);
}
Exemplo n.º 2
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);
}