aboutsummaryrefslogtreecommitdiff
path: root/sys/fs/nullfs
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2010-08-31 01:16:45 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2010-08-31 01:16:45 +0000
commit2d0c83b139646fe95441531071a719b67e2d05d7 (patch)
tree0b3e5b90f700119b64016731df8e61e12225aa66 /sys/fs/nullfs
parent5bdff860e71f864e1f472010b0284ff6ae222b5d (diff)
downloadsrc-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.c27
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,