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;
}