From f2807820032fe586ea72f9048accb23a9d17c75f Mon Sep 17 00:00:00 2001 From: truckman Date: Thu, 19 Sep 2002 13:32:45 +0000 Subject: VOP_FSYNC() requires that it's vnode argument be locked, which nfs_link() wasn't doing. Rather than just lock and unlock the vnode around the call to VOP_FSYNC(), implement rwatson's suggestion to lock the file vnode in kern_link() before calling VOP_LINK(), since the other filesystems also locked the file vnode right away in their link methods. Remove the locking and and unlocking from the leaf filesystem link methods. Reviewed by: rwatson, bde (except for the unionfs_link() changes) --- sys/fs/unionfs/union_vnops.c | 23 +++++++++++++++-------- sys/gnu/ext2fs/ext2_vnops.c | 15 ++++----------- sys/gnu/fs/ext2fs/ext2_vnops.c | 15 ++++----------- sys/kern/vfs_extattr.c | 4 +++- sys/kern/vfs_syscalls.c | 4 +++- sys/kern/vnode_if.src | 2 +- sys/ufs/ufs/ufs_vnops.c | 15 ++++----------- 7 files changed, 34 insertions(+), 44 deletions(-) (limited to 'sys') diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index 92d92ed..9d0d2a1 100644 --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -1224,8 +1224,8 @@ union_remove(ap) /* * union_link: * - * tdvp will be locked on entry, vp will not be locked on entry. - * tdvp should remain locked on return and vp should remain unlocked + * tdvp and vp will be locked on entry. + * tdvp and vp should remain locked on return. * on return. */ @@ -1250,7 +1250,6 @@ union_link(ap) struct union_node *tun = VTOUNION(ap->a_vp); if (tun->un_uppervp == NULLVP) { - vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td); #if 0 if (dun->un_uppervp == tun->un_dirvp) { if (dun->un_flags & UN_ULOCK) { @@ -1267,14 +1266,13 @@ union_link(ap) dun->un_flags |= UN_ULOCK; } #endif - VOP_UNLOCK(ap->a_vp, 0, td); + if (error) + return (error); } vp = tun->un_uppervp; + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); } - if (error) - return (error); - /* * Make sure upper is locked, then unlock the union directory we were * called with to avoid a deadlock while we are calling VOP_LINK on @@ -1289,11 +1287,20 @@ union_link(ap) error = VOP_LINK(tdvp, vp, cnp); /* call link on upper */ /* + * Unlock tun->un_uppervp if we locked it above. + */ + if (ap->a_tdvp->v_op == ap->a_vp->v_op) + VOP_UNLOCK(vp, 0, td); + /* * We have to unlock tdvp prior to relocking our calling node in - * order to avoid a deadlock. + * order to avoid a deadlock. We also have to unlock ap->a_vp + * before relocking the directory, but then we have to relock + * ap->a_vp as our caller expects. */ + VOP_UNLOCK(ap->a_vp, 0, td); union_unlock_upper(tdvp, td); vn_lock(ap->a_tdvp, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td); return (error); } diff --git a/sys/gnu/ext2fs/ext2_vnops.c b/sys/gnu/ext2fs/ext2_vnops.c index dd24a9d..c1fba78 100644 --- a/sys/gnu/ext2fs/ext2_vnops.c +++ b/sys/gnu/ext2fs/ext2_vnops.c @@ -827,7 +827,6 @@ ext2_link(ap) struct vnode *vp = ap->a_vp; struct vnode *tdvp = ap->a_tdvp; struct componentname *cnp = ap->a_cnp; - struct thread *td = cnp->cn_thread; struct inode *ip; int error; @@ -837,19 +836,16 @@ ext2_link(ap) #endif if (tdvp->v_mount != vp->v_mount) { error = EXDEV; - goto out2; - } - if (tdvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, td))) { - goto out2; + goto out; } ip = VTOI(vp); if ((nlink_t)ip->i_nlink >= LINK_MAX) { error = EMLINK; - goto out1; + goto out; } if (ip->i_flags & (IMMUTABLE | APPEND)) { error = EPERM; - goto out1; + goto out; } ip->i_nlink++; ip->i_flag |= IN_CHANGE; @@ -860,10 +856,7 @@ ext2_link(ap) ip->i_nlink--; ip->i_flag |= IN_CHANGE; } -out1: - if (tdvp != vp) - VOP_UNLOCK(vp, 0, td); -out2: +out: return (error); } diff --git a/sys/gnu/fs/ext2fs/ext2_vnops.c b/sys/gnu/fs/ext2fs/ext2_vnops.c index dd24a9d..c1fba78 100644 --- a/sys/gnu/fs/ext2fs/ext2_vnops.c +++ b/sys/gnu/fs/ext2fs/ext2_vnops.c @@ -827,7 +827,6 @@ ext2_link(ap) struct vnode *vp = ap->a_vp; struct vnode *tdvp = ap->a_tdvp; struct componentname *cnp = ap->a_cnp; - struct thread *td = cnp->cn_thread; struct inode *ip; int error; @@ -837,19 +836,16 @@ ext2_link(ap) #endif if (tdvp->v_mount != vp->v_mount) { error = EXDEV; - goto out2; - } - if (tdvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, td))) { - goto out2; + goto out; } ip = VTOI(vp); if ((nlink_t)ip->i_nlink >= LINK_MAX) { error = EMLINK; - goto out1; + goto out; } if (ip->i_flags & (IMMUTABLE | APPEND)) { error = EPERM; - goto out1; + goto out; } ip->i_nlink++; ip->i_flag |= IN_CHANGE; @@ -860,10 +856,7 @@ ext2_link(ap) ip->i_nlink--; ip->i_flag |= IN_CHANGE; } -out1: - if (tdvp != vp) - VOP_UNLOCK(vp, 0, td); -out2: +out: return (error); } diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index e1b2d7f..5ad587c 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -1027,10 +1027,12 @@ kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg) if (nd.ni_vp != NULL) { vrele(nd.ni_vp); error = EEXIST; - } else { + } else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td)) + == 0) { VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); + VOP_UNLOCK(vp, 0, td); } NDFREE(&nd, NDF_ONLY_PNBUF); vput(nd.ni_dvp); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index e1b2d7f..5ad587c 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1027,10 +1027,12 @@ kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg) if (nd.ni_vp != NULL) { vrele(nd.ni_vp); error = EEXIST; - } else { + } else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td)) + == 0) { VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); + VOP_UNLOCK(vp, 0, td); } NDFREE(&nd, NDF_ONLY_PNBUF); vput(nd.ni_dvp); diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index 3202058..28b5d2e 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -261,7 +261,7 @@ vop_remove { # #% link tdvp L L L -#% link vp U U U +#% link vp L L L # vop_link { IN struct vnode *tdvp; diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index b7d6425..5ec4b6e 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -814,7 +814,6 @@ ufs_link(ap) struct vnode *vp = ap->a_vp; struct vnode *tdvp = ap->a_tdvp; struct componentname *cnp = ap->a_cnp; - struct thread *td = cnp->cn_thread; struct inode *ip; struct direct newdir; int error; @@ -825,19 +824,16 @@ ufs_link(ap) #endif if (tdvp->v_mount != vp->v_mount) { error = EXDEV; - goto out2; - } - if (tdvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, td))) { - goto out2; + goto out; } ip = VTOI(vp); if ((nlink_t)ip->i_nlink >= LINK_MAX) { error = EMLINK; - goto out1; + goto out; } if (ip->i_flags & (IMMUTABLE | APPEND)) { error = EPERM; - goto out1; + goto out; } ip->i_effnlink++; ip->i_nlink++; @@ -859,10 +855,7 @@ ufs_link(ap) if (DOINGSOFTDEP(vp)) softdep_change_linkcnt(ip); } -out1: - if (tdvp != vp) - VOP_UNLOCK(vp, 0, td); -out2: +out: VN_KNOTE(vp, NOTE_LINK); VN_KNOTE(tdvp, NOTE_WRITE); return (error); -- cgit v1.1