Subject: Re: rename() over NFS

From: Eric Blake <[email-masked]>
Date: Sat, 13 Nov 2010 14:24:11 -0700

On 11/13/2010 07:30 AM, Jim Meyering wrote:
> Bruno Haible wrote:
>> Jim Meyering wrote:
>>> if you see ways to improve things without impacting performance
>>> or maintainability, I'm all for it.
>>
>> Maintainability wouldn't be impacted, because the fix would be to use
>> lib/rename.c, with
>>   #define RENAME_DEST_EXISTS_BUG 1
>>   #define RENAME_HARD_LINK_BUG 1
>>
>> But performance would be impacted, since 2 lstat() calls would happen
>> before every rename().
> 
> That sounds like it would be excessive.
> Currently, moving 100 regular files into a subdir
> incurs 100% of its time in 100 rename and 200 stat calls:
> 
> % time     seconds  usecs/call     calls    errors syscall
> ------ ----------- ----------- --------- --------- ----------------
>  79.69    0.000051           1       100           rename
>  20.31    0.000013           0       200       100 lstat
>   0.00    0.000000           0         8           read
> 
> Adding a rename wrapper and doubling the number of lstat calls
> per file would represent a significant slow-down.

The two lstat() calls occur before coreutils calls rename().  And it
appears that the NFS rename() bug that we are concerned about is only in
the case of renaming one directory onto another empty one; which is
generally only possible via 'mv -T a b' (where b is the empty directory
to be overwritten by directory a).

So maybe it's still possible to do a relatively-maintainable patch to
coreutils that detects when we are about to call rename() onto an
existing directory (basically, when 'mv -T' is in effect), and manually
call rmdir("b") before renaming "a", which should work around the NFS
bug, all without needing a rename() wrapper.  At any rate, the gnulib
documentation would need a patch describing the bug, and stating that
gnulib does not work around it.

But I'm not sure if changing mv to avoid this corner-case POSIX
violation on NFS not renaming directories properly is made any better by
inserting the rmdir() call, since that also feels like it is a POSIX
violation for not making an atomic rename attempt.  Maybe all the more
we can do is document this, and ping the kernel folks to see if they can
fix their NFS implementation bug.

-- 
Eric Blake   [email-masked]    +1-801-349-2682
Libvirt virtualization library http://libvirt.org