Module Name: src Committed By: hannken Date: Wed Mar 12 09:38:51 UTC 2014
Modified Files: src/sys/miscfs/genfs: genfs_vnops.c Log Message: Restructure genfs_deadlock() and genfs_lock() to always lock before testing for dead node. Use ISSET() to test flags, add assertions. Save the mount for fstrans_done() before genfs_unlock() unlocks the node. To generate a diff of this commit: cvs rdiff -u -r1.190 -r1.191 src/sys/miscfs/genfs/genfs_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/miscfs/genfs/genfs_vnops.c diff -u src/sys/miscfs/genfs/genfs_vnops.c:1.190 src/sys/miscfs/genfs/genfs_vnops.c:1.191 --- src/sys/miscfs/genfs/genfs_vnops.c:1.190 Thu Feb 27 16:51:38 2014 +++ src/sys/miscfs/genfs/genfs_vnops.c Wed Mar 12 09:38:51 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: genfs_vnops.c,v 1.190 2014/02/27 16:51:38 hannken Exp $ */ +/* $NetBSD: genfs_vnops.c,v 1.191 2014/03/12 09:38:51 hannken Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -57,7 +57,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.190 2014/02/27 16:51:38 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.191 2014/03/12 09:38:51 hannken Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -290,33 +290,42 @@ genfs_deadlock(void *v) struct vnode *vp = ap->a_vp; int flags = ap->a_flags; krw_t op; + int error; - if ((flags & LK_NOWAIT) != 0) { - if (!mutex_tryenter(vp->v_interlock)) + op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER); + if (ISSET(flags, LK_NOWAIT)) { + if (! rw_tryenter(&vp->v_lock, op)) return EBUSY; - if ((vp->v_iflag & VI_XLOCK)) { + if (mutex_tryenter(vp->v_interlock)) { + if (ISSET(vp->v_iflag, VI_XLOCK)) + error = EBUSY; + else { + KASSERT(ISSET(vp->v_iflag, VI_CLEAN)); + error = (ISSET(flags, LK_RETRY) ? 0 : ENOENT); + } mutex_exit(vp->v_interlock); - return EBUSY; - } + } else + error = EBUSY; + if (error) + rw_exit(&vp->v_lock); + return error; } + rw_enter(&vp->v_lock, op); mutex_enter(vp->v_interlock); - if ((vp->v_iflag & VI_XLOCK)) + if (ISSET(vp->v_iflag, VI_XLOCK)) { + rw_exit(&vp->v_lock); vwait(vp, VI_XLOCK); + mutex_exit(vp->v_interlock); + rw_enter(&vp->v_lock, op); + mutex_enter(vp->v_interlock); + } + KASSERT(ISSET(vp->v_iflag, VI_CLEAN)); mutex_exit(vp->v_interlock); - - if ((flags & LK_RETRY) == 0) + if (! ISSET(flags, LK_RETRY)) { + rw_exit(&vp->v_lock); return ENOENT; - - op = ((flags & LK_EXCLUSIVE) != 0 ? RW_WRITER : RW_READER); - if ((flags & LK_NOWAIT) != 0) { - if (! rw_tryenter(&vp->v_lock, op)) - return EBUSY; - return 0; } - - rw_enter(&vp->v_lock, op); - return 0; } @@ -350,39 +359,45 @@ genfs_lock(void *v) struct mount *mp = vp->v_mount; int flags = ap->a_flags; krw_t op; + int error; - op = ((flags & LK_EXCLUSIVE) != 0 ? RW_WRITER : RW_READER); - if ((flags & LK_NOWAIT) != 0) { - if (!mutex_tryenter(vp->v_interlock)) - return EBUSY; - if ((vp->v_iflag & (VI_XLOCK | VI_CLEAN)) != 0) { - mutex_exit(vp->v_interlock); - return EBUSY; - } - mutex_exit(vp->v_interlock); + op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER); + if (ISSET(flags, LK_NOWAIT)) { if (fstrans_start_nowait(mp, FSTRANS_SHARED)) return EBUSY; if (! rw_tryenter(&vp->v_lock, op)) { fstrans_done(mp); return EBUSY; } - return 0; + if (mutex_tryenter(vp->v_interlock)) { + if (ISSET(vp->v_iflag, VI_XLOCK)) + error = EBUSY; + else if (ISSET(vp->v_iflag, VI_CLEAN)) + error = ENOENT; + else + error = 0; + mutex_exit(vp->v_interlock); + } else + error = EBUSY; + if (error) { + rw_exit(&vp->v_lock); + fstrans_done(mp); + } + return error; } fstrans_start(mp, FSTRANS_SHARED); rw_enter(&vp->v_lock, op); - mutex_enter(vp->v_interlock); - if ((vp->v_iflag & (VI_XLOCK | VI_CLEAN)) != 0) { + if (ISSET(vp->v_iflag, VI_XLOCK) || ISSET(vp->v_iflag, VI_CLEAN)) { rw_exit(&vp->v_lock); fstrans_done(mp); - if ((vp->v_iflag & VI_XLOCK)) - vwait(vp, VI_XLOCK); + vwait(vp, VI_XLOCK); + KASSERT(ISSET(vp->v_iflag, VI_CLEAN)); mutex_exit(vp->v_interlock); return ENOENT; } mutex_exit(vp->v_interlock); - return 0; } @@ -396,9 +411,10 @@ genfs_unlock(void *v) struct vnode *a_vp; } */ *ap = v; struct vnode *vp = ap->a_vp; + struct mount *mp = vp->v_mount; rw_exit(&vp->v_lock); - fstrans_done(vp->v_mount); + fstrans_done(mp); return 0; }