From 0463dc9ef1434e3b6ae43d661f49724ab1d53f00 Mon Sep 17 00:00:00 2001 From: Jeff Roberson Date: Sun, 13 Mar 2005 11:56:28 +0000 Subject: [PATCH] - 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. --- sys/kern/vfs_vnops.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 5c92ba8a67ae..755b1c08976f 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); }