]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
UBUNTU: SAUCE: aufs: for v4.5, use vfs_clone_file_range() in copy-up
authorJ. R. Okajima <hooanon05g@gmail.com>
Thu, 17 Aug 2017 13:09:00 +0000 (15:09 +0200)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Wed, 23 Aug 2017 15:56:36 +0000 (17:56 +0200)
BugLink: http://bugs.launchpad.net/bugs/1709749
In mainline, ioctl(FICLONE) is introduced by the commit
04b38d6 2015-12-07 vfs: pull btrfs clone API to vfs layer
so are vfs_clone_file_ranage() and f_op->clone_file_ranage().
Compared to copy_file_range(2), cloning doesn't return with the partial
success. Using this method in aufs copy-up, the speed will be improved.

But unfortunately this method is supported by nfs4.2, btrfs and cifs
only (currently). Additionally, linux nfs server 4.2 implementation
simply calls vfs_clone_file_ranage(), which means if the backend fs
doesn't support this operation, it returns EOPNOTSUPP.

So the benefit is rather limited, but it must be a good thing.

Signed-off-by: J. R. Okajima <hooanon05g@gmail.com>
(backported from commit b4d3dcc92a13d53952fe6e9a640201ef87475302
 https://github.com/sfjro/aufs4-standalone.git)
[saf: Resolved conflicts based primarily on resolution found in
 fd18affa818115edad7e1b7472f26ac4d73e73a1]
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
fs/aufs/cpup.c
fs/aufs/vfsub.h

index 7112866b30ba232317577bc4e0e3c17e4f40de26..48e4d851155378c066ec79a67676beb5b0560497 100644 (file)
@@ -393,7 +393,7 @@ static int au_cp_regular(struct au_cp_generic *cpg)
                        .label = &&out_src
                }
        };
-       struct super_block *sb;
+       struct super_block *sb, *h_src_sb;
        struct inode *h_src_inode;
        struct task_struct *tsk = current;
 
@@ -411,9 +411,28 @@ static int au_cp_regular(struct au_cp_generic *cpg)
 
        /* try stopping to update while we copyup */
        h_src_inode = d_inode(file[SRC].dentry);
-       if (!au_test_nfs(h_src_inode->i_sb))
+       h_src_sb = h_src_inode->i_sb;
+       if (!au_test_nfs(h_src_sb))
                IMustLock(h_src_inode);
-       err = au_copy_file(file[DST].file, file[SRC].file, cpg->len);
+
+       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);
+       }
 
        /* i wonder if we had O_NO_DELAY_FPUT flag */
        if (tsk->flags & PF_KTHREAD)
index 8fae3d491ddfb2f620561d8581401d1782bed01c..71d2bc47d5c9cf9dd1843e0012848999f3241756 100644 (file)
@@ -266,6 +266,22 @@ int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
                struct file *h_file);
 int vfsub_fsync(struct file *file, struct path *path, int datasync);
 
+/*
+ * re-use branch fs's ioctl(FICLONE) while aufs itself doesn't support such
+ * ioctl.
+ */
+static inline int vfsub_clone_file_range(struct file *src, struct file *dst,
+                                        u64 len)
+{
+       int err;
+
+       lockdep_off();
+       err = vfs_clone_file_range(src, 0, dst, 0, len);
+       lockdep_on();
+
+       return err;
+}
+
 /* ---------------------------------------------------------------------- */
 
 static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)