PERFORCE change 94124 for review
John Baldwin
jhb at FreeBSD.org
Mon Mar 27 19:30:05 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=94124
Change 94124 by jhb at jhb_slimer on 2006/03/27 19:29:53
- Conditionalize Giant for VFS operations.
- Use the right msleep wait channel to avoid possible panics due to
races with kldunload when tearing down the kthread and use the
queue mutex to protect writes to the flags member of the softc once
a md device is created.
Affected files ...
.. //depot/projects/smpng/sys/dev/md/md.c#75 edit
Differences ...
==== //depot/projects/smpng/sys/dev/md/md.c#75 (text+ko) ====
@@ -88,7 +88,8 @@
#define MD_MODVER 1
-#define MD_SHUTDOWN 0x10000 /* Tell worker thread to terminate. */
+#define MD_SHUTDOWN 0x10000 /* Tell worker thread to terminate. */
+#define MD_EXITING 0x20000 /* Worker thread is exiting. */
#ifndef MD_NSECT
#define MD_NSECT (10000 * 2)
@@ -485,12 +486,11 @@
static int
mdstart_vnode(struct md_s *sc, struct bio *bp)
{
- int error;
+ int error, vfslocked;
struct uio auio;
struct iovec aiov;
struct mount *mp;
- mtx_assert(&Giant, MA_OWNED);
/*
* VNODE I/O
*
@@ -519,6 +519,7 @@
* When reading set IO_DIRECT to try to avoid double-caching
* the data. When writing IO_DIRECT is not optimal.
*/
+ vfslocked = VFS_LOCK_GIANT(sc->vnode->v_mount);
if (bp->bio_cmd == BIO_READ) {
vn_lock(sc->vnode, LK_EXCLUSIVE | LK_RETRY, curthread);
error = VOP_READ(sc->vnode, &auio, IO_DIRECT, sc->cred);
@@ -531,6 +532,7 @@
VOP_UNLOCK(sc->vnode, 0, curthread);
vn_finished_write(mp);
}
+ VFS_UNLOCK_GIANT(vfslocked);
bp->bio_resid = auio.uio_resid;
return (error);
}
@@ -641,35 +643,20 @@
{
struct md_s *sc;
struct bio *bp;
- int error, hasgiant;
+ int error;
sc = arg;
mtx_lock_spin(&sched_lock);
sched_prio(curthread, PRIBIO);
mtx_unlock_spin(&sched_lock);
- switch (sc->type) {
- case MD_VNODE:
- mtx_lock(&Giant);
- hasgiant = 1;
- break;
- case MD_MALLOC:
- case MD_PRELOAD:
- case MD_SWAP:
- default:
- hasgiant = 0;
- break;
- }
-
for (;;) {
+ mtx_lock(&sc->queue_mtx);
if (sc->flags & MD_SHUTDOWN) {
- sc->procp = NULL;
- wakeup(&sc->procp);
- if (hasgiant)
- mtx_unlock(&Giant);
+ sc->flags |= MD_EXITING;
+ mtx_unlock_spin(&sc->queue_mtx);
kthread_exit(0);
}
- mtx_lock(&sc->queue_mtx);
bp = bioq_takefirst(&sc->bio_queue);
if (!bp) {
msleep(sc, &sc->queue_mtx, PRIBIO | PDROP, "mdwait", 0);
@@ -867,7 +854,7 @@
{
struct vattr vattr;
struct nameidata nd;
- int error, flags;
+ int error, flags, vfslocked;
error = copyinstr(mdio->md_file, sc->file, sizeof(sc->file), NULL);
if (error != 0)
@@ -879,15 +866,17 @@
*/
if ((mdio->md_options & MD_READONLY) != 0)
flags &= ~FWRITE;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, sc->file, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, sc->file, td);
error = vn_open(&nd, &flags, 0, -1);
if (error != 0)
return (error);
+ vfslocked = NDHASGIANT(&nd);
NDFREE(&nd, NDF_ONLY_PNBUF);
if (nd.ni_vp->v_type != VREG ||
(error = VOP_GETATTR(nd.ni_vp, &vattr, td->td_ucred, td))) {
VOP_UNLOCK(nd.ni_vp, 0, td);
(void)vn_close(nd.ni_vp, flags, td->td_ucred, td);
+ VFS_UNLOCK_GIANT(vfslocked);
return (error ? error : EINVAL);
}
VOP_UNLOCK(nd.ni_vp, 0, td);
@@ -904,15 +893,17 @@
error = mdsetcred(sc, td->td_ucred);
if (error != 0) {
(void)vn_close(nd.ni_vp, flags, td->td_ucred, td);
+ VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
+ VFS_UNLOCK_GIANT(vfslocked);
return (0);
}
static int
mddestroy(struct md_s *sc, struct thread *td)
{
-
+ int vfslocked;
if (sc->gp) {
sc->gp->softc = NULL;
@@ -922,16 +913,18 @@
sc->gp = NULL;
sc->pp = NULL;
}
+ mtx_lock(&sc->queue_mtx);
sc->flags |= MD_SHUTDOWN;
wakeup(sc);
- while (sc->procp != NULL)
- tsleep(&sc->procp, PRIBIO, "mddestroy", hz / 10);
+ while (!(sc->flags & MD_EXITING))
+ msleep(sc->procp, &sc->queue_mtx, PRIBIO, "mddestroy", hz / 10);
+ mtx_unlock(&sc->queue_mtx);
mtx_destroy(&sc->queue_mtx);
if (sc->vnode != NULL) {
- mtx_lock(&Giant);
+ vfslocked = VFS_LOCK_GIANT(sc->vnode->v_mount);
(void)vn_close(sc->vnode, sc->flags & MD_READONLY ?
FREAD : (FREAD|FWRITE), sc->cred, td);
- mtx_unlock(&Giant);
+ VFS_UNLOCK_GIANT(vfslocked);
}
if (sc->cred != NULL)
crfree(sc->cred);
More information about the p4-projects
mailing list