diff options
author | truckman <truckman@FreeBSD.org> | 2002-09-19 13:32:45 +0000 |
---|---|---|
committer | truckman <truckman@FreeBSD.org> | 2002-09-19 13:32:45 +0000 |
commit | f2807820032fe586ea72f9048accb23a9d17c75f (patch) | |
tree | fed75b0fd3d3243127e21c52a13f663281ff50f1 /sys/kern | |
parent | 38695c19fde9598c887707063c968842a2395e6c (diff) | |
download | FreeBSD-src-f2807820032fe586ea72f9048accb23a9d17c75f.zip FreeBSD-src-f2807820032fe586ea72f9048accb23a9d17c75f.tar.gz |
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)
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/vfs_extattr.c | 4 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 4 | ||||
-rw-r--r-- | sys/kern/vnode_if.src | 2 |
3 files changed, 7 insertions, 3 deletions
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; |