diff options
author | Rick Macklem <rmacklem@FreeBSD.org> | 2010-08-31 01:16:45 +0000 |
---|---|---|
committer | Rick Macklem <rmacklem@FreeBSD.org> | 2010-08-31 01:16:45 +0000 |
commit | 2d0c83b139646fe95441531071a719b67e2d05d7 (patch) | |
tree | 0b3e5b90f700119b64016731df8e61e12225aa66 /sys/fs/nullfs | |
parent | 5bdff860e71f864e1f472010b0284ff6ae222b5d (diff) | |
download | src-2d0c83b139646fe95441531071a719b67e2d05d7.tar.gz src-2d0c83b139646fe95441531071a719b67e2d05d7.zip |
Add a null_remove() function to nullfs, so that the v_usecount
of the lower level vnode is incremented to greater than 1 when
the upper level vnode's v_usecount is greater than one. This
is necessary for the NFS clients, so that they will do a silly
rename of the file instead of actually removing it when the
file is still in use. It is "racy", since the v_usecount is
incremented in many places in the kernel with
minimal synchronization, but an extraneous silly rename is
preferred to not doing a silly rename when it is required.
The only other file systems that currently check the value
of v_usecount in their VOP_REMOVE() functions are nwfs and
smbfs. These file systems choose to fail a remove when the
v_usecount is greater than 1 and I believe will function
more correctly with this patch, as well.
Tested by: to.my.trociny at gmail.com
Submitted by: to.my.trociny at gmail.com (earlier version)
Reviewed by: kib
MFC after: 2 weeks
Notes
Notes:
svn path=/head/; revision=212043
Diffstat (limited to 'sys/fs/nullfs')
-rw-r--r-- | sys/fs/nullfs/null_vnops.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index af49e3e18c17..b86ba83cb307 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -499,6 +499,32 @@ null_accessx(struct vop_accessx_args *ap) } /* + * Increasing refcount of lower vnode is needed at least for the case + * when lower FS is NFS to do sillyrename if the file is in use. + * Unfortunately v_usecount is incremented in many places in + * the kernel and, as such, there may be races that result in + * the NFS client doing an extraneous silly rename, but that seems + * preferable to not doing a silly rename when it is needed. + */ +static int +null_remove(struct vop_remove_args *ap) +{ + int retval, vreleit; + struct vnode *lvp; + + if (vrefcnt(ap->a_vp) > 1) { + lvp = NULLVPTOLOWERVP(ap->a_vp); + VREF(lvp); + vreleit = 1; + } else + vreleit = 0; + retval = null_bypass(&ap->a_gen); + if (vreleit != 0) + vrele(lvp); + return (retval); +} + +/* * We handle this to eliminate null FS to lower FS * file moving. Don't know why we don't allow this, * possibly we should. @@ -809,6 +835,7 @@ struct vop_vector null_vnodeops = { .vop_open = null_open, .vop_print = null_print, .vop_reclaim = null_reclaim, + .vop_remove = null_remove, .vop_rename = null_rename, .vop_setattr = null_setattr, .vop_strategy = VOP_EOPNOTSUPP, |