Vasily Tarasov:
> Here is the content of the files:

Ok, thanx.
I could reproduce the problem on my local aufs4.11 (not 4.11.3), and
here is a fix for you.
Even if everything goes well, the fix won't be included in next Monday
release since it is too late.


J. R. Okajima

commit aa77e32fdb0a56fed2d3120055f01c39cecb8add
Author: J. R. Okajima <hooanon...@gmail.com>
Date:   Fri Jun 9 07:44:36 2017 +0900

    aufs: bugfix, copy-up using clone_file_range() on XFS branch
    
    XFS has its version and older one doesn't support clone_file_range(). It
    simply returns EOPNOTSUPP. Additionally XFS acquires inode_lock for a
    normal read().
    This commit fixes the error path after trying clone_file_range().
    
    Reported-by: Vasily Tarasov <tara...@vasily.name>
    See-also: 
http://www.mail-archive.com/aufs-users@lists.sourceforge.net/msg05498.html
    Signed-off-by: J. R. Okajima <hooanon...@gmail.com>

diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c
index 125fef6..5c51d94 100644
--- a/fs/aufs/cpup.c
+++ b/fs/aufs/cpup.c
@@ -352,6 +352,41 @@ int au_copy_file(struct file *dst, struct file *src, 
loff_t len)
        return err;
 }
 
+static int au_clone_or_copy(struct file *dst, struct file *src, loff_t len)
+{
+       int err;
+       struct super_block *h_src_sb;
+       struct inode *h_src_inode;
+
+       h_src_inode = file_inode(src);
+       h_src_sb = h_src_inode->i_sb;
+       if (!au_test_nfs(h_src_sb)) {
+               inode_unlock(h_src_inode);
+               err = vfsub_clone_file_range(src, dst, len);
+               inode_lock(h_src_inode);
+       } else
+               err = vfsub_clone_file_range(src, dst, len);
+       /* older XFS has a condition in cloning */
+       if (err != -EOPNOTSUPP)
+               goto out;
+
+       /*
+        * XFS acquires inode_lock.
+        * the backend fs on NFS may not support cloning.
+        */
+       if (!au_test_xfs(h_src_sb))
+               err = au_copy_file(dst, src, len);
+       else {
+               inode_unlock(h_src_inode);
+               err = au_copy_file(dst, src, len);
+               inode_lock(h_src_inode);
+       }
+
+out:
+       AuTraceErr(err);
+       return err;
+}
+
 /*
  * to support a sparse file which is opened with O_APPEND,
  * we need to close the file.
@@ -406,21 +441,9 @@ static int au_cp_regular(struct au_cp_generic *cpg)
        if (h_src_sb != file_inode(file[DST].file)->i_sb
            || !file[DST].file->f_op->clone_file_range)
                err = au_copy_file(file[DST].file, file[SRC].file, cpg->len);
-       else {
-               if (!au_test_nfs(h_src_sb)) {
-                       inode_unlock(h_src_inode);
-                       err = vfsub_clone_file_range(file[SRC].file,
-                                                    file[DST].file, cpg->len);
-                       inode_lock(h_src_inode);
-               } else
-                       err = vfsub_clone_file_range(file[SRC].file,
-                                                    file[DST].file, cpg->len);
-               if (unlikely(err == -EOPNOTSUPP && au_test_nfs(h_src_sb)))
-                       /* the backend fs on NFS may not support cloning */
-                       err = au_copy_file(file[DST].file, file[SRC].file,
-                                          cpg->len);
-               AuTraceErr(err);
-       }
+       else
+               err = au_clone_or_copy(file[DST].file, file[SRC].file,
+                                      cpg->len);
 
        /* i wonder if we had O_NO_DELAY_FPUT flag */
        if (tsk->flags & PF_KTHREAD)

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

Reply via email to