Module Name:    src
Committed By:   pgoyette
Date:           Sat Jul 16 07:54:14 UTC 2016

Modified Files:
        src/sys/kern [pgoyette-localcount]: subr_devsw.c
        src/sys/sys [pgoyette-localcount]: conf.h

Log Message:
First pass of adding localcount(9) support for devsw.  As with the
earlier autoconf changes, nothing currently uses this new feature.


To generate a diff of this commit:
cvs rdiff -u -r1.34 -r1.34.2.1 src/sys/kern/subr_devsw.c
cvs rdiff -u -r1.146 -r1.146.2.1 src/sys/sys/conf.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/subr_devsw.c
diff -u src/sys/kern/subr_devsw.c:1.34 src/sys/kern/subr_devsw.c:1.34.2.1
--- src/sys/kern/subr_devsw.c:1.34	Mon Feb  1 05:05:43 2016
+++ src/sys/kern/subr_devsw.c	Sat Jul 16 07:54:13 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_devsw.c,v 1.34 2016/02/01 05:05:43 riz Exp $	*/
+/*	$NetBSD: subr_devsw.c,v 1.34.2.1 2016/07/16 07:54:13 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2002, 2007, 2008 The NetBSD Foundation, Inc.
@@ -69,7 +69,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_devsw.c,v 1.34 2016/02/01 05:05:43 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_devsw.c,v 1.34.2.1 2016/07/16 07:54:13 pgoyette Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_dtrace.h"
@@ -85,6 +85,8 @@ __KERNEL_RCSID(0, "$NetBSD: subr_devsw.c
 #include <sys/buf.h>
 #include <sys/reboot.h>
 #include <sys/sdt.h>
+#include <sys/condvar.h>
+#include <sys/localcount.h>
 
 #ifdef DEVSW_DEBUG
 #define	DPRINTF(x)	printf x
@@ -107,7 +109,8 @@ static int bdevsw_attach(const struct bd
 static int cdevsw_attach(const struct cdevsw *, devmajor_t *);
 static void devsw_detach_locked(const struct bdevsw *, const struct cdevsw *);
 
-kmutex_t device_lock;
+kmutex_t	device_lock;
+kcondvar_t	device_cv;
 
 void (*biodone_vfs)(buf_t *) = (void *)nullop;
 
@@ -118,6 +121,7 @@ devsw_init(void)
 	KASSERT(sys_bdevsws < MAXDEVSW - 1);
 	KASSERT(sys_cdevsws < MAXDEVSW - 1);
 	mutex_init(&device_lock, MUTEX_DEFAULT, IPL_NONE);
+	cv_init(&device_cv, "devsw");
 }
 
 int
@@ -160,8 +164,13 @@ devsw_attach(const char *devname,
 			goto fail;
 		}
 
-		if (bdev != NULL)
+		if (bdev != NULL) {
+			KASSERT(bdev->d_localcount != NULL);
+			localcount_init(bdev->d_localcount);
 			bdevsw[*bmajor] = bdev;
+		}
+		KASSERT(cdev->d_localcount != NULL);
+		localcount_init(cdev->d_localcount);
 		cdevsw[*cmajor] = cdev;
 
 		mutex_exit(&device_lock);
@@ -270,6 +279,8 @@ bdevsw_attach(const struct bdevsw *devsw
 		return (EEXIST);
 
 	bdevsw[*devmajor] = devsw;
+	KASSERT(devsw->d_localcount != NULL);
+	localcount_init(devsw->d_localcount);
 
 	return (0);
 }
@@ -317,33 +328,66 @@ cdevsw_attach(const struct cdevsw *devsw
 		return (EEXIST);
 
 	cdevsw[*devmajor] = devsw;
+	KASSERT(devsw->d_localcount != NULL);
+	localcount_init(devsw->d_localcount);
 
 	return (0);
 }
 
+/*
+ * First, look up both bdev and cdev indices, and confirm that the
+ * localcount pointer(s) exist.  Then drain any existing references,
+ * deactivate the localcount(s).  Finally, remove the {b,c}devsw[]
+ * entries.
+ */
+
 static void
 devsw_detach_locked(const struct bdevsw *bdev, const struct cdevsw *cdev)
 {
-	int i;
+	int i, j;
 
 	KASSERT(mutex_owned(&device_lock));
 
+	i = max_bdevsws;
 	if (bdev != NULL) {
 		for (i = 0 ; i < max_bdevsws ; i++) {
 			if (bdevsw[i] != bdev)
 				continue;
-			bdevsw[i] = NULL;
+
+			KASSERTMSG(bdev->d_localcount != NULL,
+			    "%s: no bdev localcount", __func__);
 			break;
 		}
 	}
+	j = max_cdevsws;
 	if (cdev != NULL) {
-		for (i = 0 ; i < max_cdevsws ; i++) {
-			if (cdevsw[i] != cdev)
+		for (j = 0 ; j < max_cdevsws ; j++) {
+			if (cdevsw[j] != cdev)
 				continue;
-			cdevsw[i] = NULL;
+
+			KASSERTMSG(cdev->d_localcount != NULL,
+			    "%s: no cdev localcount", __func__);
 			break;
 		}
 	}
+	if (i < max_bdevsws) {
+		localcount_drain(bdev->d_localcount, &device_cv, &device_lock);
+		localcount_fini(bdev->d_localcount);
+		bdevsw[i] = NULL;
+	}
+	if (j < max_cdevsws ) {
+		/*
+		 * Take care not to drain/fini the d_localcount if the same
+		 * one was used for both cdev and bdev!
+		 */
+		if (i >= max_bdevsws ||
+		    bdev->d_localcount != cdev->d_localcount) {
+			localcount_drain(cdev->d_localcount, &device_cv,
+			    &device_lock);
+			localcount_fini(cdev->d_localcount);
+		}
+		cdevsw[j] = NULL;
+	}
 }
 
 int
@@ -375,6 +419,35 @@ bdevsw_lookup(dev_t dev)
 	return (bdevsw[bmajor]);
 }
 
+const struct bdevsw *
+bdevsw_lookup_acquire(dev_t dev)
+{
+	devmajor_t bmajor;
+
+	if (dev == NODEV)
+		return (NULL);
+	bmajor = major(dev);
+	if (bmajor < 0 || bmajor >= max_bdevsws)
+		return (NULL);
+
+	if (bdevsw[bmajor]->d_localcount != NULL)
+		localcount_acquire(bdevsw[bmajor]->d_localcount);
+
+	return (bdevsw[bmajor]);
+}
+
+void
+bdevsw_release(const struct bdevsw *bd)
+{
+	devmajor_t bmaj;
+
+	bmaj = bdevsw_lookup_major(bd);
+
+	KASSERTMSG(bmaj != NODEVMAJOR, "%s: no bmajor to release!", __func__);
+	if (bd->d_localcount != NULL)
+		localcount_release(bd->d_localcount, &device_cv, &device_lock);
+}
+
 /*
  * Look up a character device by number.
  *
@@ -394,6 +467,35 @@ cdevsw_lookup(dev_t dev)
 	return (cdevsw[cmajor]);
 }
 
+const struct cdevsw *
+cdevsw_lookup_acquire(dev_t dev)
+{
+	devmajor_t cmajor;
+
+	if (dev == NODEV)
+		return (NULL);
+	cmajor = major(dev);
+	if (cmajor < 0 || cmajor >= max_cdevsws)
+		return (NULL);
+
+	if (cdevsw[cmajor]->d_localcount != NULL)
+		localcount_acquire(cdevsw[cmajor]->d_localcount);
+
+	return (cdevsw[cmajor]);
+}
+
+void
+cdevsw_release(const struct cdevsw *cd)
+{
+	devmajor_t cmaj;
+
+	cmaj = cdevsw_lookup_major(cd);
+
+	KASSERTMSG(cmaj != NODEVMAJOR, "%s: no cmajor to release!", __func__);
+	if (cd->d_localcount != NULL)
+		localcount_release(cd->d_localcount, &device_cv, &device_lock);
+}
+
 /*
  * Look up a block device by reference to its operations set.
  *

Index: src/sys/sys/conf.h
diff -u src/sys/sys/conf.h:1.146 src/sys/sys/conf.h:1.146.2.1
--- src/sys/sys/conf.h:1.146	Sun Jan 17 23:16:46 2016
+++ src/sys/sys/conf.h	Sat Jul 16 07:54:13 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: conf.h,v 1.146 2016/01/17 23:16:46 christos Exp $	*/
+/*	$NetBSD: conf.h,v 1.146.2.1 2016/07/16 07:54:13 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 1990, 1993
@@ -67,6 +67,8 @@ struct vnode;
 /*
  * Block device switch table
  */
+struct localcount;
+
 struct bdevsw {
 	int		(*d_open)(dev_t, int, int, struct lwp *);
 	int		(*d_close)(dev_t, int, int, struct lwp *);
@@ -76,6 +78,7 @@ struct bdevsw {
 	int		(*d_psize)(dev_t);
 	int		(*d_discard)(dev_t, off_t, off_t);
 	int		d_flag;
+	struct localcount *d_localcount;
 };
 
 /*
@@ -94,6 +97,7 @@ struct cdevsw {
 	int		(*d_kqfilter)(dev_t, struct knote *);
 	int		(*d_discard)(dev_t, off_t, off_t);
 	int		d_flag;
+	struct localcount *d_localcount;
 };
 
 #ifdef _KERNEL
@@ -106,6 +110,11 @@ int devsw_attach(const char *, const str
 int devsw_detach(const struct bdevsw *, const struct cdevsw *);
 const struct bdevsw *bdevsw_lookup(dev_t);
 const struct cdevsw *cdevsw_lookup(dev_t);
+const struct bdevsw *bdevsw_lookup_acquire(dev_t);
+const struct cdevsw *cdevsw_lookup_acquire(dev_t);
+void bdevsw_release(const struct bdevsw *);
+void cdevsw_release(const struct cdevsw *);
+
 devmajor_t bdevsw_lookup_major(const struct bdevsw *);
 devmajor_t cdevsw_lookup_major(const struct cdevsw *);
 

Reply via email to