From bd1592e6fdc9f33b109228ed4295c8f5022d4f5f Mon Sep 17 00:00:00 2001 From: "J. R. Okajima" Date: Thu, 17 Aug 2017 15:09:00 +0200 Subject: [PATCH] UBUNTU: SAUCE: aufs: for v4.5, use vfs_clone_file_range() in copy-up 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 (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 Acked-by: Stefan Bader Acked-by: Kleber Sacilotto de Souza Signed-off-by: Kleber Sacilotto de Souza --- fs/aufs/cpup.c | 25 ++++++++++++++++++++++--- fs/aufs/vfsub.h | 16 ++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c index 7112866b30ba..48e4d8511553 100644 --- a/fs/aufs/cpup.c +++ b/fs/aufs/cpup.c @@ -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) diff --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h index 8fae3d491ddf..71d2bc47d5c9 100644 --- a/fs/aufs/vfsub.h +++ b/fs/aufs/vfsub.h @@ -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) -- 2.39.2