Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/pgoyette-localcount]: src/sys First pass of adding localcount(9) support...
details: https://anonhg.NetBSD.org/src/rev/04deb8a18b67
branches: pgoyette-localcount
changeset: 852787:04deb8a18b67
user: pgoyette <pgoyette%NetBSD.org@localhost>
date: Sat Jul 16 07:54:13 2016 +0000
description:
First pass of adding localcount(9) support for devsw. As with the
earlier autoconf changes, nothing currently uses this new feature.
diffstat:
sys/kern/subr_devsw.c | 126 +++++++++++++++++++++++++++++++++++++++++++++----
sys/sys/conf.h | 11 +++-
2 files changed, 124 insertions(+), 13 deletions(-)
diffs (261 lines):
diff -r 8f9255296e48 -r 04deb8a18b67 sys/kern/subr_devsw.c
--- a/sys/kern/subr_devsw.c Sat Jul 16 02:13:07 2016 +0000
+++ b/sys/kern/subr_devsw.c Sat Jul 16 07:54:13 2016 +0000
@@ -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 @@
#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 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 @@
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 @@
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 @@
return (EEXIST);
bdevsw[*devmajor] = devsw;
+ KASSERT(devsw->d_localcount != NULL);
+ localcount_init(devsw->d_localcount);
return (0);
}
@@ -317,32 +328,65 @@
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 (j = 0 ; j < max_cdevsws ; j++) {
+ if (cdevsw[j] != cdev)
+ continue;
+
+ KASSERTMSG(cdev->d_localcount != NULL,
+ "%s: no cdev localcount", __func__);
break;
}
}
- if (cdev != NULL) {
- for (i = 0 ; i < max_cdevsws ; i++) {
- if (cdevsw[i] != cdev)
- continue;
- cdevsw[i] = NULL;
- 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;
}
}
@@ -375,6 +419,35 @@
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 @@
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.
*
diff -r 8f9255296e48 -r 04deb8a18b67 sys/sys/conf.h
--- a/sys/sys/conf.h Sat Jul 16 02:13:07 2016 +0000
+++ b/sys/sys/conf.h Sat Jul 16 07:54:13 2016 +0000
@@ -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 @@
/*
* 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 @@
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 @@
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_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 *);
Home |
Main Index |
Thread Index |
Old Index