PERFORCE change 99866 for review

Chris Jones cdjones at FreeBSD.org
Fri Jun 23 15:47:54 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=99866

Change 99866 by cdjones at cdjones_ides on 2006/06/23 15:47:27

	Integrate misc. unused stuff.

Affected files ...

.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_acct.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_clock.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_event.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_exit.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_linker.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_mbuf.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_module.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_mutex.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_switch.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_synch.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_sysctl.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_tc.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/link_elf.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/link_elf_obj.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/sched_4bsd.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/sched_core.c#1 branch
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/sched_ule.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/subr_bus.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/subr_firmware.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/subr_kdb.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/subr_rman.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/sys_pipe.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/sysv_msg.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/sysv_sem.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/sysv_shm.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/uipc_mbuf.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/uipc_socket.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/uipc_socket2.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/uipc_syscalls.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/uipc_usrreq.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/vfs_aio.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/vfs_cache.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/vfs_init.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/vfs_mount.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/vfs_subr.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/vfs_syscalls.c#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/sys/kern/vnode_if.src#2 integrate
.. //depot/projects/soc2006/cdjones_jail/src/usr.sbin/jail/jail.8#2 integrate

Differences ...

==== //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_acct.c#2 (text+ko) ====

@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/kern_acct.c,v 1.81 2006/03/28 21:26:59 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/kern_acct.c,v 1.82 2006/06/05 13:02:34 rwatson Exp $");
 
 #include "opt_mac.h"
 
@@ -171,8 +171,8 @@
 	 * appending and make sure it's a 'normal'.
 	 */
 	if (uap->path != NULL) {
-		NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_USERSPACE,
-		    uap->path, td);
+		NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1,
+		    UIO_USERSPACE, uap->path, td);
 		flags = FWRITE | O_APPEND;
 		error = vn_open(&nd, &flags, 0, -1);
 		if (error)

==== //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_clock.c#2 (text+ko) ====

@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/kern_clock.c,v 1.188 2006/04/17 20:14:51 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/kern_clock.c,v 1.190 2006/06/14 03:14:26 delphij Exp $");
 
 #include "opt_device_polling.h"
 #include "opt_hwpmc_hooks.h"
@@ -201,6 +201,7 @@
 	 * Run current process's virtual and profile time, as needed.
 	 */
 	mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
+	sched_tick();
 	if (p->p_flag & P_SA) {
 		/* XXXKSE What to do? */
 	} else {
@@ -256,7 +257,7 @@
 	 */
 	mtx_lock_spin_flags(&callout_lock, MTX_QUIET);
 	ticks++;
-	if (TAILQ_FIRST(&callwheel[ticks & callwheelmask]) != NULL) {
+	if (!TAILQ_EMPTY(&callwheel[ticks & callwheelmask])) {
 		need_softclock = 1;
 	} else if (softticks + 1 == ticks)
 		++softticks;

==== //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_event.c#2 (text+ko) ====

@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/kern_event.c,v 1.99 2006/04/14 14:27:28 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/kern_event.c,v 1.103 2006/06/12 21:46:23 jhb Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -754,15 +754,12 @@
 int
 kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int waitok)
 {
-	struct filedesc *fdp;
 	struct filterops *fops;
 	struct file *fp;
 	struct knote *kn, *tkn;
 	int error, filt, event;
 	int haskqglobal;
-	int fd;
 
-	fdp = NULL;
 	fp = NULL;
 	kn = NULL;
 	error = 0;
@@ -778,22 +775,13 @@
 findkn:
 	if (fops->f_isfd) {
 		KASSERT(td != NULL, ("td is NULL"));
-		fdp = td->td_proc->p_fd;
-		FILEDESC_LOCK(fdp);
-		/* validate descriptor */
-		fd = kev->ident;
-		if (fd < 0 || fd >= fdp->fd_nfiles ||
-		    (fp = fdp->fd_ofiles[fd]) == NULL) {
-			FILEDESC_UNLOCK(fdp);
-			error = EBADF;
+		error = fget(td, kev->ident, &fp);
+		if (error)
 			goto done;
-		}
-		fhold(fp);
 
 		if ((kev->flags & EV_ADD) == EV_ADD && kqueue_expand(kq, fops,
 		    kev->ident, 0) != 0) {
-			/* unlock and try again */
-			FILEDESC_UNLOCK(fdp);
+			/* try again */
 			fdrop(fp, td);
 			fp = NULL;
 			error = kqueue_expand(kq, fops, kev->ident, waitok);
@@ -811,15 +799,13 @@
 			 * they are the same thing.
 			 */
 			if (fp->f_data == kq) {
-				FILEDESC_UNLOCK(fdp);
 				error = EINVAL;
-				goto done_noglobal;
+				goto done;
 			}
 
 			KQ_GLOBAL_LOCK(&kq_global, haskqglobal);
 		}
 
-		FILEDESC_UNLOCK(fdp);
 		KQ_LOCK(kq);
 		if (kev->ident < kq->kq_knlistsize) {
 			SLIST_FOREACH(kn, &kq->kq_knlist[kev->ident], kn_link)
@@ -869,6 +855,7 @@
 			kn = tkn;
 			tkn = NULL;
 			if (kn == NULL) {
+				KQ_UNLOCK(kq);
 				error = ENOMEM;
 				goto done;
 			}
@@ -954,7 +941,6 @@
 
 done:
 	KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal);
-done_noglobal:
 	if (fp != NULL)
 		fdrop(fp, td);
 	if (tkn != NULL)
@@ -1708,7 +1694,7 @@
 void
 knlist_cleardel(struct knlist *knl, struct thread *td, int islocked, int killkn)
 {
-	struct knote *kn;
+	struct knote *kn, *kn2;
 	struct kqueue *kq;
 
 	if (islocked)
@@ -1719,7 +1705,7 @@
 		knl->kl_lock(knl->kl_lockarg);
 	}
 
-	SLIST_FOREACH(kn, &knl->kl_list, kn_selnext) {
+	SLIST_FOREACH_SAFE(kn, &knl->kl_list, kn_selnext, kn2) {
 		kq = kn->kn_kq;
 		KQ_LOCK(kq);
 		if ((kn->kn_status & KN_INFLUX)) {

==== //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_exit.c#2 (text+ko) ====

@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/kern_exit.c,v 1.288 2006/04/10 14:07:28 csjp Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/kern_exit.c,v 1.289 2006/05/29 21:28:56 tegge Exp $");
 
 #include "opt_compat.h"
 #include "opt_ktrace.h"
@@ -113,14 +113,13 @@
 	struct proc *p, *nq, *q;
 	struct tty *tp;
 	struct vnode *ttyvp;
-	struct vmspace *vm;
 	struct vnode *vtmp;
 #ifdef KTRACE
 	struct vnode *tracevp;
 	struct ucred *tracecred;
 #endif
 	struct plimit *plim;
-	int locked, refcnt;
+	int locked;
 
 	/*
 	 * Drop Giant if caller has it.  Eventually we should warn about
@@ -300,33 +299,7 @@
 	}
 	mtx_unlock(&ppeers_lock);
 
-	/* The next two chunks should probably be moved to vmspace_exit. */
-	vm = p->p_vmspace;
-	/*
-	 * Release user portion of address space.
-	 * This releases references to vnodes,
-	 * which could cause I/O if the file has been unlinked.
-	 * Need to do this early enough that we can still sleep.
-	 * Can't free the entire vmspace as the kernel stack
-	 * may be mapped within that space also.
-	 *
-	 * Processes sharing the same vmspace may exit in one order, and
-	 * get cleaned up by vmspace_exit() in a different order.  The
-	 * last exiting process to reach this point releases as much of
-	 * the environment as it can, and the last process cleaned up
-	 * by vmspace_exit() (which decrements exitingcnt) cleans up the
-	 * remainder.
-	 */
-	atomic_add_int(&vm->vm_exitingcnt, 1);
-	do
-		refcnt = vm->vm_refcnt;
-	while (!atomic_cmpset_int(&vm->vm_refcnt, refcnt, refcnt - 1));
-	if (refcnt == 1) {
-		shmexit(vm);
-		pmap_remove_pages(vmspace_pmap(vm));
-		(void) vm_map_remove(&vm->vm_map, vm_map_min(&vm->vm_map),
-		    vm_map_max(&vm->vm_map));
-	}
+	vmspace_exit(td);
 
 	sx_xlock(&proctree_lock);
 	if (SESS_LEADER(p)) {

==== //depot/projects/soc2006/cdjones_jail/src/sys/kern/kern_linker.c#2 (text+ko) ====

@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/kern_linker.c,v 1.120 2006/05/27 09:21:41 delphij Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/kern_linker.c,v 1.138 2006/06/21 20:42:08 jhb Exp $");
 
 #include "opt_ddb.h"
 #include "opt_hwpmc_hooks.h"
@@ -43,11 +43,13 @@
 #include <sys/sx.h>
 #include <sys/mac.h>
 #include <sys/module.h>
+#include <sys/mount.h>
 #include <sys/linker.h>
 #include <sys/fcntl.h>
 #include <sys/libkern.h>
 #include <sys/namei.h>
 #include <sys/vnode.h>
+#include <sys/syscallsubr.h>
 #include <sys/sysctl.h>
 
 #include "linker_if.h"
@@ -60,12 +62,27 @@
 int kld_debug = 0;
 #endif
 
+#define	KLD_LOCK()		do { sx_xlock(&kld_sx); mtx_lock(&Giant); } while (0)
+#define	KLD_UNLOCK()		do { mtx_unlock(&Giant); sx_xunlock(&kld_sx); } while (0)
+#define	KLD_LOCKED()		sx_xlocked(&kld_sx)
+#define	KLD_LOCK_ASSERT()	do { if (!cold) sx_assert(&kld_sx, SX_XLOCKED); } while (0)
+
 /*
  * static char *linker_search_path(const char *name, struct mod_depend
  * *verinfo);
  */
 static const char 	*linker_basename(const char *path);
 
+/*
+ * Find a currently loaded file given its filename.
+ */
+static linker_file_t linker_find_file_by_name(const char* _filename);
+
+/*
+ * Find a currently loaded file given its file id.
+ */
+static linker_file_t linker_find_file_by_id(int _fileid);
+
 /* Metadata from the static kernel */
 SET_DECLARE(modmetadata_set, struct mod_metadata);
 
@@ -73,7 +90,7 @@
 
 linker_file_t linker_kernel_file;
 
-static struct mtx kld_mtx;	/* kernel linker mutex */
+static struct sx kld_sx;	/* kernel linker lock */
 
 static linker_class_list_t classes;
 static linker_file_list_t linker_files;
@@ -83,17 +100,15 @@
 #define	LINKER_GET_NEXT_FILE_ID(a) do {					\
 	linker_file_t lftmp;						\
 									\
+	KLD_LOCK_ASSERT();						\
 retry:									\
-	mtx_lock(&kld_mtx);						\
 	TAILQ_FOREACH(lftmp, &linker_files, link) {			\
 		if (next_file_id == lftmp->id) {			\
 			next_file_id++;					\
-			mtx_unlock(&kld_mtx);				\
 			goto retry;					\
 		}							\
 	}								\
 	(a) = next_file_id;						\
-	mtx_unlock(&kld_mtx);	/* Hold for safe read of id variable */	\
 } while(0)
 
 
@@ -108,8 +123,14 @@
 typedef struct modlist *modlist_t;
 static modlisthead_t found_modules;
 
-static modlist_t	modlist_lookup2(const char *name,
-			    struct mod_depend *verinfo);
+static int	linker_file_add_dependency(linker_file_t file,
+		    linker_file_t dep);
+static caddr_t	linker_file_lookup_symbol_internal(linker_file_t file,
+		    const char* name, int deps);
+static int	linker_load_module(const char *kldname,
+		    const char *modname, struct linker_file *parent,
+		    struct mod_depend *verinfo, struct linker_file **lfpp);
+static modlist_t modlist_lookup2(const char *name, struct mod_depend *verinfo);
 
 static char *
 linker_strdup(const char *str)
@@ -125,7 +146,7 @@
 linker_init(void *arg)
 {
 
-	mtx_init(&kld_mtx, "kernel linker", NULL, MTX_DEF);
+	sx_init(&kld_sx, "kernel linker");
 	TAILQ_INIT(&classes);
 	TAILQ_INIT(&linker_files);
 }
@@ -171,7 +192,7 @@
 	/*
 	 * Perform a bubble sort of the system initialization objects by
 	 * their subsystem (primary key) and order (secondary key).
-	 * 
+	 *
 	 * Since some things care about execution order, this is the operation
 	 * which ensures continued function.
 	 */
@@ -215,7 +236,7 @@
 	/*
 	 * Perform a reverse bubble sort of the system initialization objects
 	 * by their subsystem (primary key) and order (secondary key).
-	 * 
+	 *
 	 * Since some things care about execution order, this is the operation
 	 * which ensures continued function.
 	 */
@@ -256,8 +277,10 @@
 	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
 		return;
 
+	mtx_lock(&Giant);
 	for (oidp = start; oidp < stop; oidp++)
 		sysctl_register_oid(*oidp);
+	mtx_unlock(&Giant);
 }
 
 static void
@@ -271,8 +294,10 @@
 	if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
 		return;
 
+	mtx_lock(&Giant);
 	for (oidp = start; oidp < stop; oidp++)
 		sysctl_unregister_oid(*oidp);
+	mtx_unlock(&Giant);
 }
 
 static int
@@ -286,7 +311,7 @@
 	    " in %s\n", lf->filename));
 
 	if (linker_file_lookup_set(lf, "modmetadata_set", &start,
-	    &stop, 0) != 0) {
+	    &stop, NULL) != 0) {
 		/*
 		 * This fallback should be unnecessary, but if we get booted
 		 * from boot2 instead of loader and we are missing our
@@ -330,22 +355,23 @@
 {
 	linker_class_t lc;
 	linker_file_t lf;
-	int foundfile, error = 0;
+	int foundfile, error;
 
 	/* Refuse to load modules if securelevel raised */
 	if (securelevel > 0)
 		return (EPERM);
 
+	KLD_LOCK_ASSERT();
 	lf = linker_find_file_by_name(filename);
 	if (lf) {
 		KLD_DPF(FILE, ("linker_load_file: file %s is already loaded,"
 		    " incrementing refs\n", filename));
 		*result = lf;
 		lf->refs++;
-		goto out;
+		return (0);
 	}
-	lf = NULL;
 	foundfile = 0;
+	error = 0;
 
 	/*
 	 * We do not need to protect (lock) classes here because there is
@@ -366,14 +392,13 @@
 			error = linker_file_register_modules(lf);
 			if (error == EEXIST) {
 				linker_file_unload(lf, LINKER_UNLOAD_FORCE);
-				goto out;
+				return (error);
 			}
 			linker_file_register_sysctls(lf);
 			linker_file_sysinit(lf);
 			lf->flags |= LINKER_FILE_LINKED;
 			*result = lf;
-			error = 0;
-			goto out;
+			return (0);
 		}
 	}
 	/*
@@ -393,7 +418,6 @@
 			error = ENOEXEC;
 	} else
 		error = ENOENT;		/* Nothing found */
-out:
 	return (error);
 }
 
@@ -402,67 +426,107 @@
     linker_file_t *result)
 {
 	modlist_t mod;
+	int error;
 
+	KLD_LOCK();
 	if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
 		*result = mod->container;
 		(*result)->refs++;
+		KLD_UNLOCK();
 		return (0);
 	}
 
-	return (linker_load_module(NULL, modname, NULL, verinfo, result));
+	error = linker_load_module(NULL, modname, NULL, verinfo, result);
+	KLD_UNLOCK();
+	return (error);
+}
+
+int
+linker_release_module(const char *modname, struct mod_depend *verinfo,
+    linker_file_t lf)
+{
+	modlist_t mod;
+	int error;
+
+	KLD_LOCK();
+	if (lf == NULL) {
+		KASSERT(modname != NULL,
+		    ("linker_release_module: no file or name"));
+		mod = modlist_lookup2(modname, verinfo);
+		if (mod == NULL) {
+			KLD_UNLOCK();
+			return (ESRCH);
+		}
+		lf = mod->container;
+	} else
+		KASSERT(modname == NULL && verinfo == NULL,
+		    ("linker_release_module: both file and name"));
+	error =	linker_file_unload(lf, LINKER_UNLOAD_NORMAL);
+	KLD_UNLOCK();
+	return (error);
 }
 
-linker_file_t
+static linker_file_t
 linker_find_file_by_name(const char *filename)
 {
-	linker_file_t lf = 0;
+	linker_file_t lf;
 	char *koname;
 
 	koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
-	if (koname == NULL)
-		goto out;
 	sprintf(koname, "%s.ko", filename);
 
-	mtx_lock(&kld_mtx);
+	KLD_LOCK_ASSERT();
 	TAILQ_FOREACH(lf, &linker_files, link) {
 		if (strcmp(lf->filename, koname) == 0)
 			break;
 		if (strcmp(lf->filename, filename) == 0)
 			break;
 	}
-	mtx_unlock(&kld_mtx);
-out:
-	if (koname)
-		free(koname, M_LINKER);
+	free(koname, M_LINKER);
 	return (lf);
 }
 
-linker_file_t
+static linker_file_t
 linker_find_file_by_id(int fileid)
 {
-	linker_file_t lf = 0;
-	
-	mtx_lock(&kld_mtx);
+	linker_file_t lf;
+
+	KLD_LOCK_ASSERT();
 	TAILQ_FOREACH(lf, &linker_files, link)
 		if (lf->id == fileid)
 			break;
-	mtx_unlock(&kld_mtx);
 	return (lf);
 }
 
+int
+linker_file_foreach(linker_predicate_t *predicate, void *context)
+{
+	linker_file_t lf;
+	int retval = 0;
+
+	KLD_LOCK();
+	TAILQ_FOREACH(lf, &linker_files, link) {
+		retval = predicate(lf, context);
+		if (retval != 0)
+			break;
+	}
+	KLD_UNLOCK();
+	return (retval);
+}
+
 linker_file_t
 linker_make_file(const char *pathname, linker_class_t lc)
 {
 	linker_file_t lf;
 	const char *filename;
 
-	lf = NULL;
+	KLD_LOCK_ASSERT();
 	filename = linker_basename(pathname);
 
 	KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename));
 	lf = (linker_file_t)kobj_create((kobj_class_t)lc, M_LINKER, M_WAITOK);
 	if (lf == NULL)
-		goto out;
+		return (NULL);
 	lf->refs = 1;
 	lf->userrefs = 0;
 	lf->flags = 0;
@@ -472,10 +536,7 @@
 	lf->deps = NULL;
 	STAILQ_INIT(&lf->common);
 	TAILQ_INIT(&lf->modules);
-	mtx_lock(&kld_mtx);
 	TAILQ_INSERT_TAIL(&linker_files, lf, link);
-	mtx_unlock(&kld_mtx);
-out:
 	return (lf);
 }
 
@@ -487,8 +548,6 @@
 	struct common_symbol *cp;
 	int error, i;
 
-	error = 0;
-
 	/* Refuse to unload modules if securelevel raised. */
 	if (securelevel > 0)
 		return (EPERM);
@@ -498,55 +557,55 @@
 		return (error);
 #endif
 
+	KLD_LOCK_ASSERT();
 	KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
-	if (file->refs == 1) {
-		KLD_DPF(FILE, ("linker_file_unload: file is unloading,"
-		    " informing modules\n"));
+
+	/* Easy case of just dropping a reference. */
+	if (file->refs > 1) {
+		file->refs--;
+		return (0);
+	}
+
+	KLD_DPF(FILE, ("linker_file_unload: file is unloading,"
+	    " informing modules\n"));
+
+	/*
+	 * Inform any modules associated with this file.
+	 */
+	MOD_XLOCK;
+	for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
+		next = module_getfnext(mod);
+		MOD_XUNLOCK;
 
 		/*
-		 * Inform any modules associated with this file.
+		 * Give the module a chance to veto the unload.
 		 */
+		if ((error = module_unload(mod, flags)) != 0) {
+			KLD_DPF(FILE, ("linker_file_unload: module %p"
+			    " vetoes unload\n", mod));
+			return (error);
+		}
 		MOD_XLOCK;
-		for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
-			next = module_getfnext(mod);
-			MOD_XUNLOCK;
+		module_release(mod);
+	}
+	MOD_XUNLOCK;
 
-			/*
-			 * Give the module a chance to veto the unload.
-			 */
-			if ((error = module_unload(mod, flags)) != 0) {
-				KLD_DPF(FILE, ("linker_file_unload: module %p"
-				    " vetoes unload\n", mod));
-				goto out;
-			} else
-				MOD_XLOCK;
-			module_release(mod);
-		}
-		MOD_XUNLOCK;
-	}
-	file->refs--;
-	if (file->refs > 0) {
-		goto out;
-	}
-	for (ml = TAILQ_FIRST(&found_modules); ml; ml = nextml) {
-		nextml = TAILQ_NEXT(ml, link);
+	TAILQ_FOREACH_SAFE(ml, &found_modules, link, nextml) {
 		if (ml->container == file) {
 			TAILQ_REMOVE(&found_modules, ml, link);
 			free(ml, M_LINKER);
 		}
 	}
 
-	/* 
-	 * Don't try to run SYSUNINITs if we are unloaded due to a 
+	/*
+	 * Don't try to run SYSUNINITs if we are unloaded due to a
 	 * link error.
 	 */
 	if (file->flags & LINKER_FILE_LINKED) {
 		linker_file_sysuninit(file);
 		linker_file_unregister_sysctls(file);
 	}
-	mtx_lock(&kld_mtx);
 	TAILQ_REMOVE(&linker_files, file, link);
-	mtx_unlock(&kld_mtx);
 
 	if (file->deps) {
 		for (i = 0; i < file->ndeps; i++)
@@ -566,15 +625,15 @@
 		file->filename = NULL;
 	}
 	kobj_delete((kobj_t) file, M_LINKER);
-out:
-	return (error);
+	return (0);
 }
 
-int
+static int
 linker_file_add_dependency(linker_file_t file, linker_file_t dep)
 {
 	linker_file_t *newdeps;
 
+	KLD_LOCK_ASSERT();
 	newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t *),
 	    M_LINKER, M_WAITOK | M_ZERO);
 	if (newdeps == NULL)
@@ -593,25 +652,51 @@
 
 /*
  * Locate a linker set and its contents.  This is a helper function to avoid
- * linker_if.h exposure elsewhere.  Note: firstp and lastp are really void ***
+ * linker_if.h exposure elsewhere.  Note: firstp and lastp are really void **.
+ * This function is used in this file so we can avoid having lots of (void **)
+ * casts.
  */
 int
 linker_file_lookup_set(linker_file_t file, const char *name,
     void *firstp, void *lastp, int *countp)
 {
+	int error, locked;
 
-	return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp));
+	locked = KLD_LOCKED();
+	if (!locked)
+		KLD_LOCK();
+	error = LINKER_LOOKUP_SET(file, name, firstp, lastp, countp);
+	if (!locked)
+		KLD_UNLOCK();
+	return (error);
 }
 
 caddr_t
 linker_file_lookup_symbol(linker_file_t file, const char *name, int deps)
 {
+	caddr_t sym;
+	int locked;
+
+	locked = KLD_LOCKED();
+	if (!locked)
+		KLD_LOCK();
+	sym = linker_file_lookup_symbol_internal(file, name, deps);
+	if (!locked)
+		KLD_UNLOCK();
+	return (sym);
+}
+
+static caddr_t
+linker_file_lookup_symbol_internal(linker_file_t file, const char *name,
+    int deps)
+{
 	c_linker_sym_t sym;
 	linker_symval_t symval;
 	caddr_t address;
 	size_t common_size = 0;
 	int i;
 
+	KLD_LOCK_ASSERT();
 	KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
 	    file, name, deps));
 
@@ -632,8 +717,8 @@
 	}
 	if (deps) {
 		for (i = 0; i < file->ndeps; i++) {
-			address = linker_file_lookup_symbol(file->deps[i],
-			    name, 0);
+			address = linker_file_lookup_symbol_internal(
+			    file->deps[i], name, 0);
 			if (address) {
 				KLD_DPF(SYM, ("linker_file_lookup_symbol:"
 				    " deps value=%p\n", address));
@@ -663,10 +748,6 @@
 		cp = malloc(sizeof(struct common_symbol)
 		    + common_size + strlen(name) + 1, M_LINKER,
 		    M_WAITOK | M_ZERO);
-		if (cp == NULL) {
-			KLD_DPF(SYM, ("linker_file_lookup_symbol: nomem\n"));
-			return (0);
-		}
 		cp->address = (caddr_t)(cp + 1);
 		cp->name = cp->address + common_size;
 		strcpy(cp->name, name);
@@ -685,7 +766,7 @@
 /*
  * DDB Helpers.  DDB has to look across multiple files with their own symbol
  * tables and string tables.
- * 
+ *
  * Note that we do not obey list locking protocols here.  We really don't need
  * DDB to hang because somebody's got the lock held.  We'll take the chance
  * that the files list is inconsistant instead.
@@ -754,64 +835,74 @@
  * MPSAFE
  */
 int
-kldload(struct thread *td, struct kldload_args *uap)
+kern_kldload(struct thread *td, const char *file, int *fileid)
 {
 #ifdef HWPMC_HOOKS
 	struct pmckern_map_in pkm;
 #endif
-	char *kldname, *modname;
-	char *pathname = NULL;
+	const char *kldname, *modname;
 	linker_file_t lf;
-	int error = 0;
-
-	td->td_retval[0] = -1;
-
-	mtx_lock(&Giant);
+	int error;
 
 	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
-		goto out;
+		return (error);
 
 	if ((error = suser(td)) != 0)
-		goto out;
-
-	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
-	if ((error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL)) != 0)
-		goto out;
+		return (error);
 
 	/*
-	 * If path do not contain qualified name or any dot in it
-	 * (kldname.ko, or kldname.ver.ko) treat it as interface
+	 * If file does not contain a qualified name or any dot in it
+	 * (kldname.ko, or kldname.ver.ko) treat it as an interface
 	 * name.
 	 */
-	if (index(pathname, '/') || index(pathname, '.')) {
-		kldname = pathname;
+	if (index(file, '/') || index(file, '.')) {
+		kldname = file;
 		modname = NULL;
 	} else {
 		kldname = NULL;
-		modname = pathname;
+		modname = file;
 	}
+
+	KLD_LOCK();
 	error = linker_load_module(kldname, modname, NULL, NULL, &lf);
 	if (error)
-		goto out;
-
+		goto unlock;
 #ifdef HWPMC_HOOKS
 	pkm.pm_file = lf->filename;
 	pkm.pm_address = (uintptr_t) lf->address;
 	PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm);
 #endif
 	lf->userrefs++;
-	td->td_retval[0] = lf->id;
-out:
-	if (pathname)
-		free(pathname, M_TEMP);
-	mtx_unlock(&Giant);
+	if (fileid != NULL)
+		*fileid = lf->id;
+unlock:
+	KLD_UNLOCK();
+	return (error);
+}
+
+int
+kldload(struct thread *td, struct kldload_args *uap)
+{
+	char *pathname = NULL;
+	int error, fileid;
+
+	td->td_retval[0] = -1;
+
+	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+	error = copyinstr(uap->file, pathname, MAXPATHLEN, NULL);
+	if (error == 0) {
+		error = kern_kldload(td, pathname, &fileid);
+		if (error == 0)
+			td->td_retval[0] = fileid;
+	}
+	free(pathname, M_TEMP);
 	return (error);
 }
 
 /*
  * MPSAFE
  */
-static int
+int
 kern_kldunload(struct thread *td, int fileid, int flags)
 {
 #ifdef HWPMC_HOOKS
@@ -820,14 +911,13 @@
 	linker_file_t lf;
 	int error = 0;
 
-	mtx_lock(&Giant);
-
 	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
-		goto out;
+		return (error);
 
 	if ((error = suser(td)) != 0)
-		goto out;
+		return (error);
 
+	KLD_LOCK();
 	lf = linker_find_file_by_id(fileid);
 	if (lf) {
 		KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
@@ -838,17 +928,17 @@
 			printf("kldunload: attempt to unload file that was"
 			    " loaded by the kernel\n");
 			error = EBUSY;
-			goto out;
-		}
-		lf->userrefs--;
+		} else {
 #ifdef HWPMC_HOOKS
-		/* Save data needed by hwpmc(4) before unloading the kld. */
-		pkm.pm_address = (uintptr_t) lf->address;
-		pkm.pm_size = lf->size;
+			/* Save data needed by hwpmc(4) before unloading. */
+			pkm.pm_address = (uintptr_t) lf->address;
+			pkm.pm_size = lf->size;
 #endif
-		error = linker_file_unload(lf, flags);
-		if (error)
-			lf->userrefs++;
+			lf->userrefs--;
+			error = linker_file_unload(lf, flags);
+			if (error)
+				lf->userrefs++;
+		}
 	} else
 		error = ENOENT;
 
@@ -856,8 +946,7 @@
 	if (error == 0)
 		PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
 #endif
-out:
-	mtx_unlock(&Giant);
+	KLD_UNLOCK();
 	return (error);
 }
 
@@ -893,7 +982,7 @@
 	char *pathname;
 	const char *filename;
 	linker_file_t lf;
-	int error = 0;
+	int error;
 
 #ifdef MAC
 	error = mac_check_kld_stat(td->td_ucred);
@@ -901,7 +990,6 @@
 		return (error);
 #endif
 
-	mtx_lock(&Giant);
 	td->td_retval[0] = -1;
 
 	pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
@@ -909,15 +997,15 @@
 		goto out;
 
 	filename = linker_basename(pathname);
+	KLD_LOCK();
 	lf = linker_find_file_by_name(filename);
 	if (lf)
 		td->td_retval[0] = lf->id;
 	else
 		error = ENOENT;
+	KLD_UNLOCK();
 out:
-	if (pathname)
-		free(pathname, M_TEMP);
-	mtx_unlock(&Giant);
+	free(pathname, M_TEMP);

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list