Hi all,

it turns out that the patch set from March 2013 ("new copyup x/6") as a
side-effect fixes a potential deadlock in the rename() call.  Previous
versions of aufs can run in the following deadlock:

  1) Rename from read-only branch to a different directory
  2) Aufs locks vfs_rename on the file system on the writable branch
  3) Aufs performs a copy-up from the read-only branch

Now, in our case the read-only branch is a Fuse network file system.
Reading a file (for copy-up) can involve downloading the file and
putting it in a local cache directory.  If that local cache directory is
on the same file system as the writable branch, and if the Fuse file
system itself uses rename() in that cache directory, the procedure
deadlocks.

Attached there is a patch for aufs2.1-32 which is supposed to abort
rename() with EXDEV error whenever there is a copy-up from one directory
to another.  For a reason I don't really understand, the deadlock does
not occur if the source and destination directory for the copy-up is the
same.

I understand that this patch might require applications to fall-back
from rename to copy & delete.  This is only if they try to rename()
across directories and never if they fully operate on the writable
branch.  For instance, an installer could extract a tarball on the
writable branch and then rename files to their final destinations.

Perhaps the patch is useful to others.  If the patch is obviously doing
something terribly wrong, I'd be glad to know.

Cheers,
Jakob
--- fs/aufs/i_op_ren.c.orig     2014-09-18 19:46:41.959001888 +0200
+++ fs/aufs/i_op_ren.c  2014-09-18 05:11:26.552001874 +0200
@@ -922,6 +922,12 @@
        if (unlikely(err))
                goto out_children;

+       /* Workaround: if r/o branch is on fuse and reading the file triggers a 
rename() */
+       if ((au_dbstart(a->src_dentry) != a->btgt) && (a->src_dir != 
a->dst_dir)) {
+               err = -EXDEV;
+               goto out_children;
+       }
+
        /* prepare the writable parent dir on the same branch */
        if (a->dst_bstart == a->btgt) {
                au_fset_ren(a->flags, WHDST);
------------------------------------------------------------------------------
Slashdot TV.  Video for Nerds.  Stuff that Matters.
http://pubads.g.doubleclick.net/gampad/clk?id=160591471&iu=/4140/ostg.clktrk

Reply via email to