freeBSD nullfs together with nfs and "silly rename"
Rick Macklem
rmacklem at uoguelph.ca
Sat Jun 12 14:59:36 UTC 2010
On Sat, 12 Jun 2010, Kostik Belousov wrote:
> On Sat, Jun 12, 2010 at 11:56:10AM +0300, Mikolaj Golub wrote:
>>
>> On Sun, 6 Jun 2010 16:44:43 +0200 Leon Me??ner wrote:
>>
>> LM> Hi,
>> LM> I hope this is not the wrong list to ask. Didn't get any answers on
>> LM> -questions.
>>
>> LM> When you try to do the following inside a nullfs mounted directory,
>> LM> where the nullfs origin is itself mounted via nfs you get an error:
>>
>> LM> # foo
>> LM> # tail -f foo&
>> LM> # rm -f foo
>> LM> tail: foo: Stale NFS file handle
>> LM> # fg
>>
>> LM> This is really a problem when running services inside jails and using
>> LM> NFS as storage. As of [2] it looks like this problem is known for a
>> LM> while. On a normal NFS mount this does not happen as "silly renaming"
>> LM> [1] works there (producing nasty little .nfsXXXX files).
>>
>> nfs_sillyrename() is called when vnode's usecount is more then 1. It is
>> expected that unlink() syscall increases vnode's usecount in namei() and if
>> the file has been already opened usecount will be more then 1.
>>
>> But with nullfs layer present the reference counts are held by the upper node,
>> not the lower (nfs) one, so when unlink() is called it increases usecount of
>> the upper vnode, not nfs vnode and nfs_sillyrename() is never called.
>>
>> The strightforward solution looks like to implement null_remove() that will
>> increase lower vnode's refcount before calling null_bypass() and then
>> decrement it after the call. See the attached patch (it works for me on both
>> 8-STABLE and CURRENT).
>
> The upper vnode holds a reference to the lower vnode, as you noted.
> Now, with your patch, I believe that _all_ calls to the nfs_remove()
> are happen with refcount > 1.
>
I'm not familiar with the nullfs so this might be way off, but would
this patch be ok by any chance?
Index: sys/fs/nullfs/null_vnops.c
===================================================================
--- sys/fs/nullfs/null_vnops.c (revision 208960)
+++ sys/fs/nullfs/null_vnops.c (working copy)
@@ -499,6 +499,23 @@
}
/*
+ * 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.
+ */
+static int
+null_remove(struct vop_remove_args *ap)
+{
+ int retval;
+ struct vnode *lvp;
+
+ if (ap->a_vp->v_usecount > 1) {
+ lvp = NULLVPTOLOWERVP(ap->a_vp);
+ VREF(lvp);
+ } else
+ lvp = NULL;
+ retval = null_bypass(&ap->a_gen);
+ if (lvp != NULL)
+ 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 +826,7 @@
.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,
More information about the freebsd-stable
mailing list