Re: [BUG] "git clean -df ." silently doesn't delete folders with stale .nfs* files

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Jun 10, 2024 at 6:22 PM Yuri <yuri@xxxxxxxxx> wrote:
> No, *only* the .nfsXXXX file exists in the xx directory when git runs.

In the case you showed, yes. However, there are *at least* two
*different* problem cases, one of which gives Git no warning that
something weird is going on.

The way "NFS silly renames" work is this:

 * an NFS client tells an NFS server to do operations, and this
   is (nominally) stateless;

 * if an NFS client tells the server to remove a file, the server
   attempts to remove the file;

 * but for POSIX-style operation, if a client knows that some file
   is *open* and that *same client* intends to remove the file,
   the client *must not* send a removal request.  Instead, the
   client sends a "rename" request, renaming the original file
   to ".nfs<unique-id>".  When the client's last user of the file
   closes its last file descriptor, the client *then* sends the
   final remove for the renamed file.

So, the scenarios we must consider are these:

 1. Nobody has the file open anywhere.  The client will send a
    removal request and the server will obey or not depending on
    permissions.

 2. The server itself has the file open, but no client does.  The
    client will send a removal request and the server (assuming it
    is itself a POSIX system) will unlink the open file, really
    deleting the file later on final close.

 3. The server does not have the file open, but some client does.
    This could be a *different* client, in which case your Git
    process will result in a removal request, which will operate
    as in cases 1 and 2 above.  Or this could be *your* client, in
    which case your Git process will cause your client OS to send
    a "silly rename" if it has not already done so, *or* will cause
    your client *not* to send a removal request.

So, the main problem cases are case 3, where your own client is
the one that has the file open.  This causes your OS to *convert*
an unlink() call into a rename() call for a "silly rename", in
effect, *if* your OS has not yet done a silly rename.  But if your
OS has *already done* a "silly rename", your OS knows that the
".nfs<unique-id>" name is its own preserved name.

If the silly-rename operation has already occurred, your OS has
the option of making the unlink(".nfs<unique-id>") operation fail,
or ignoring it entirely.  If not, however, your OS has only one
option: to convert the unlink() to a silly rename and *report
success*.

That last case will definitely fool Git, which sees a successful
result of its unlink() call.  The other case -- the one where the
silly rename has already occurred -- will either report a failure
to unlink the silly-name ".nfs<unique-id>" file, which Git could
detect at that point, or will report success, lying to Git.

In both cases, of course, the directory will be non-empty at
the end of the series of unlink() calls, and the attempt to remove
the directory will fail with ENOTEMPTY.  Presumably Git should
detect this and warn, but there's nothing else Git can do here.

Anyway, that's the OS view of this mess. I leave the work on
Git itself to others. :-)

Chris





[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux