From 406f1511f1535ca408aa9ac463c9d00a0fedbb00 Mon Sep 17 00:00:00 2001 From: rmacklem Date: Tue, 31 Aug 2010 01:16:45 +0000 Subject: 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 --- sys/fs/nullfs/null_vnops.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'sys/fs/nullfs') diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index af49e3e..b86ba83 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, -- cgit v1.1