summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2005-03-13 11:56:28 +0000
committerjeff <jeff@FreeBSD.org>2005-03-13 11:56:28 +0000
commita71cdca338d54f3150d43c613b14946adb1b8cf6 (patch)
treee3e4842b7f5cf2a85eb6d1c9495e04d544687f79 /sys/kern
parentd29b61a36562eb17d64543ec501e3ee4b5c98e57 (diff)
downloadFreeBSD-src-a71cdca338d54f3150d43c613b14946adb1b8cf6.zip
FreeBSD-src-a71cdca338d54f3150d43c613b14946adb1b8cf6.tar.gz
- Do a vn_start_write in vn_close, we may write if this is the last ref
on an unlinked file. We can't know if this is the case until after we have the lock. - Lock the vnode in vn_close, many filesystems had code which was unsafe without the lock held, and holding it greatly simplifies vgone(). - Adjust vn_lock() to check for the VI_DOOMED flag where appropriate. Sponsored by: Isilon Systems, Inc.
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/vfs_vnops.c41
1 files changed, 20 insertions, 21 deletions
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 5c92ba8..755b1c0 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -288,23 +288,18 @@ vn_close(vp, flags, file_cred, td)
struct ucred *file_cred;
struct thread *td;
{
+ struct mount *mp;
int error;
VFS_ASSERT_GIANT(vp->v_mount);
+ vn_start_write(vp, &mp, V_WAIT);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (flags & FWRITE)
vp->v_writecount--;
error = VOP_CLOSE(vp, flags, file_cred, td);
- /*
- * XXX - In certain instances VOP_CLOSE has to do the vrele
- * itself. If the vrele has been done, it will return EAGAIN
- * to indicate that the vrele should not be done again. When
- * this happens, we just return success. The correct thing to
- * do would be to have all VOP_CLOSE instances do the vrele.
- */
- if (error == EAGAIN)
- return (0);
- vrele(vp);
+ vput(vp);
+ vn_finished_write(mp);
return (error);
}
@@ -817,17 +812,11 @@ debug_vn_lock(vp, flags, td, filename, line)
do {
if ((flags & LK_INTERLOCK) == 0)
VI_LOCK(vp);
- if ((vp->v_iflag & VI_XLOCK) && vp->v_vxthread != curthread) {
- if ((flags & LK_NOWAIT) != 0) {
- VI_UNLOCK(vp);
- return (ENOENT);
- }
- vx_waitl(vp);
- if ((flags & LK_RETRY) == 0) {
- VI_UNLOCK(vp);
- return (ENOENT);
- }
- }
+ if ((vp->v_iflag & VI_DOOMED) && vp->v_vxthread != td &&
+ (flags & LK_NOWAIT)) {
+ VI_UNLOCK(vp);
+ return (ENOENT);
+ }
#ifdef DEBUG_LOCKS
vp->filename = filename;
vp->line = line;
@@ -838,6 +827,16 @@ debug_vn_lock(vp, flags, td, filename, line)
*/
error = VOP_LOCK(vp, flags | LK_NOPAUSE | LK_INTERLOCK, td);
flags &= ~LK_INTERLOCK;
+ /*
+ * Callers specify LK_RETRY if they wish to get dead vnodes.
+ * If RETRY is not set, we return ENOENT instead.
+ */
+ if (error != 0 && (vp->v_iflag & VI_DOOMED) &&
+ vp->v_vxthread != td && (flags & LK_RETRY) == 0) {
+ VOP_UNLOCK(vp, 0, td);
+ error = ENOENT;
+ break;
+ }
} while (flags & LK_RETRY && error != 0);
return (error);
}
OpenPOWER on IntegriCloud