From patchwork Mon Dec 3 08:34:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 10708755 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0EB1118A7 for ; Mon, 3 Dec 2018 08:34:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0272429A80 for ; Mon, 3 Dec 2018 08:34:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EA9802AE0D; Mon, 3 Dec 2018 08:34:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A3E042A06C for ; Mon, 3 Dec 2018 08:34:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725855AbeLCIeY (ORCPT ); Mon, 3 Dec 2018 03:34:24 -0500 Received: from ipmailnode02.adl6.internode.on.net ([150.101.137.148]:60959 "EHLO ipmailnode02.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725830AbeLCIeY (ORCPT ); Mon, 3 Dec 2018 03:34:24 -0500 Received: from ppp59-167-129-252.static.internode.on.net (HELO dastard) ([59.167.129.252]) by ipmail02.adl6.internode.on.net with ESMTP; 03 Dec 2018 19:04:19 +1030 Received: from discord.disaster.area ([192.168.1.111]) by dastard with esmtp (Exim 4.80) (envelope-from ) id 1gTjgI-0003PR-UQ; Mon, 03 Dec 2018 19:34:19 +1100 Received: from dave by discord.disaster.area with local (Exim 4.91) (envelope-from ) id 1gTjgI-00005u-TN; Mon, 03 Dec 2018 19:34:18 +1100 From: Dave Chinner To: linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Cc: olga.kornievskaia@gmail.com, linux-nfs@vger.kernel.org, linux-unionfs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH 01/11] vfs: copy_file_range source range over EOF should fail Date: Mon, 3 Dec 2018 19:34:06 +1100 Message-Id: <20181203083416.28978-2-david@fromorbit.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181203083416.28978-1-david@fromorbit.com> References: <20181203083416.28978-1-david@fromorbit.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Chinner The man page says: EINVAL Requested range extends beyond the end of the source file But the current behaviour is that copy_file_range does a short copy up to the source file EOF. Fix the kernel behaviour to match the behaviour described in the man page. Signed-off-by: Dave Chinner Reviewed-by: Amir Goldstein --- fs/read_write.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/read_write.c b/fs/read_write.c index 4dae0399c75a..09d1816cf3cf 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1581,6 +1581,10 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, if (len == 0) return 0; + /* If the source range crosses EOF, fail the copy */ + if (pos_in >= i_size(inode_in) || pos_in + len > i_size(inode_in)) + return -EINVAL; + file_start_write(file_out); /* From patchwork Mon Dec 3 08:34:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 10708767 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B0E9418A7 for ; Mon, 3 Dec 2018 08:34:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A3C3F29A80 for ; Mon, 3 Dec 2018 08:34:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 977202AE0D; Mon, 3 Dec 2018 08:34:29 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3788F2A06C for ; Mon, 3 Dec 2018 08:34:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725919AbeLCIe3 (ORCPT ); Mon, 3 Dec 2018 03:34:29 -0500 Received: from ipmailnode02.adl6.internode.on.net ([150.101.137.148]:36689 "EHLO ipmailnode02.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725891AbeLCIe2 (ORCPT ); Mon, 3 Dec 2018 03:34:28 -0500 Received: from ppp59-167-129-252.static.internode.on.net (HELO dastard) ([59.167.129.252]) by ipmail02.adl6.internode.on.net with ESMTP; 03 Dec 2018 19:04:19 +1030 Received: from discord.disaster.area ([192.168.1.111]) by dastard with esmtp (Exim 4.80) (envelope-from ) id 1gTjgI-0003PS-VI; Mon, 03 Dec 2018 19:34:19 +1100 Received: from dave by discord.disaster.area with local (Exim 4.91) (envelope-from ) id 1gTjgI-00005x-UG; Mon, 03 Dec 2018 19:34:18 +1100 From: Dave Chinner To: linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Cc: olga.kornievskaia@gmail.com, linux-nfs@vger.kernel.org, linux-unionfs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH 02/11] vfs: introduce generic_copy_file_range() Date: Mon, 3 Dec 2018 19:34:07 +1100 Message-Id: <20181203083416.28978-3-david@fromorbit.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181203083416.28978-1-david@fromorbit.com> References: <20181203083416.28978-1-david@fromorbit.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Chinner Right now if vfs_copy_file_range() does not use any offload mechanism, it falls back to calling do_splice_direct(). This fails to do basic sanity checks on the files being copied. Before we start adding this necessarily functionality to the fallback path, separate it out into generic_copy_file_range(). generic_copy_file_range() has the same prototype as ->copy_file_range() so that filesystems can use it in their custom ->copy_file_range() method if they so choose. Signed-off-by: Dave Chinner Reviewed-by: Amir Goldstein Reviewed-by: Christoph Hellwig --- fs/read_write.c | 35 ++++++++++++++++++++++++++++++++--- include/linux/fs.h | 3 +++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/fs/read_write.c b/fs/read_write.c index 09d1816cf3cf..50114694c98b 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1540,6 +1540,36 @@ COMPAT_SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd, } #endif +/** + * generic_copy_file_range - copy data between two files + * @file_in: file structure to read from + * @pos_in: file offset to read from + * @file_out: file structure to write data to + * @pos_out: file offset to write data to + * @len: amount of data to copy + * @flags: copy flags + * + * This is a generic filesystem helper to copy data from one file to another. + * It has no constraints on the source or destination file owners - the files + * can belong to different superblocks and different filesystem types. Short + * copies are allowed. + * + * This should be called from the @file_out filesystem, as per the + * ->copy_file_range() method. + * + * Returns the number of bytes copied or a negative error indicating the + * failure. + */ + +ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in, + struct file *file_out, loff_t pos_out, + size_t len, unsigned int flags) +{ + return do_splice_direct(file_in, &pos_in, file_out, &pos_out, + len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0); +} +EXPORT_SYMBOL(generic_copy_file_range); + /* * copy_file_range() differs from regular file read and write in that it * specifically allows return partial success. When it does so is up to @@ -1611,9 +1641,8 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, goto done; } - ret = do_splice_direct(file_in, &pos_in, file_out, &pos_out, - len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0); - + ret = generic_copy_file_range(file_in, &pos_in, file_out, &pos_out, + len, flags); done: if (ret > 0) { fsnotify_access(file_in); diff --git a/include/linux/fs.h b/include/linux/fs.h index c95c0807471f..a4478764cf63 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1874,6 +1874,9 @@ extern ssize_t vfs_readv(struct file *, const struct iovec __user *, unsigned long, loff_t *, rwf_t); extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *, loff_t, size_t, unsigned int); +extern ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in, + struct file *file_out, loff_t pos_out, + size_t len, unsigned int flags); extern int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, loff_t *count, From patchwork Mon Dec 3 08:34:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 10708773 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 46F47109C for ; Mon, 3 Dec 2018 08:34:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3863C29A80 for ; Mon, 3 Dec 2018 08:34:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2C0462AE0D; Mon, 3 Dec 2018 08:34:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A3BEA29A80 for ; Mon, 3 Dec 2018 08:34:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725928AbeLCIea (ORCPT ); Mon, 3 Dec 2018 03:34:30 -0500 Received: from ipmailnode02.adl6.internode.on.net ([150.101.137.148]:60959 "EHLO ipmailnode02.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725913AbeLCIe3 (ORCPT ); Mon, 3 Dec 2018 03:34:29 -0500 Received: from ppp59-167-129-252.static.internode.on.net (HELO dastard) ([59.167.129.252]) by ipmail02.adl6.internode.on.net with ESMTP; 03 Dec 2018 19:04:19 +1030 Received: from discord.disaster.area ([192.168.1.111]) by dastard with esmtp (Exim 4.80) (envelope-from ) id 1gTjgJ-0003PT-06; Mon, 03 Dec 2018 19:34:19 +1100 Received: from dave by discord.disaster.area with local (Exim 4.91) (envelope-from ) id 1gTjgI-000060-VF; Mon, 03 Dec 2018 19:34:18 +1100 From: Dave Chinner To: linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Cc: olga.kornievskaia@gmail.com, linux-nfs@vger.kernel.org, linux-unionfs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH 03/11] vfs: no fallback for ->copy_file_range Date: Mon, 3 Dec 2018 19:34:08 +1100 Message-Id: <20181203083416.28978-4-david@fromorbit.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181203083416.28978-1-david@fromorbit.com> References: <20181203083416.28978-1-david@fromorbit.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Chinner Now that we have generic_copy_file_range(), remove it as a fallback case when offloads fail. This puts the responsibility for executing fallbacks on the filesystems that implement ->copy_file_range and allows us to add operational validity checks to generic_copy_file_range(). Rework vfs_copy_file_range() to call a new do_copy_file_range() helper to exceute the copying callout, and move calls to generic_file_copy_range() into filesystem methods where they currently return failures. Signed-off-by: Dave Chinner Reviewed-by: Amir Goldstein Acked-by: Anna Schumaker --- fs/ceph/file.c | 17 ++++++++++++++++- fs/cifs/cifsfs.c | 4 ++++ fs/fuse/file.c | 17 ++++++++++++++++- fs/nfs/nfs4file.c | 4 ++++ fs/overlayfs/file.c | 9 ++++++++- fs/read_write.c | 24 +++++++++++++++--------- 6 files changed, 63 insertions(+), 12 deletions(-) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 189df668b6a0..cf29f0410dcb 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -1885,7 +1885,7 @@ static int is_file_size_ok(struct inode *src_inode, struct inode *dst_inode, return 0; } -static ssize_t ceph_copy_file_range(struct file *src_file, loff_t src_off, +static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off, struct file *dst_file, loff_t dst_off, size_t len, unsigned int flags) { @@ -2096,6 +2096,21 @@ static ssize_t ceph_copy_file_range(struct file *src_file, loff_t src_off, return ret; } +static ssize_t ceph_copy_file_range(struct file *src_file, loff_t src_off, + struct file *dst_file, loff_t dst_off, + size_t len, unsigned int flags) +{ + ssize_t ret; + + ret = __ceph_copy_file_range(src_file, src_off, dst_file, dst_off, + len, flags); + + if (ret == -EOPNOTSUPP) + ret = generic_copy_file_range(src_file, src_off, dst_file, + dst_off, len, flags); + return ret; +} + const struct file_operations ceph_file_fops = { .open = ceph_open, .release = ceph_release, diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 865706edb307..5ef4baec6234 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -1141,6 +1141,10 @@ static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off, rc = cifs_file_copychunk_range(xid, src_file, off, dst_file, destoff, len, flags); free_xid(xid); + + if (rc == -EOPNOTSUPP) + rc = generic_copy_file_range(src_file, off, dst_file, + destoff, len, flags); return rc; } diff --git a/fs/fuse/file.c b/fs/fuse/file.c index b52f9baaa3e7..b86fb0298739 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -3024,7 +3024,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, return err; } -static ssize_t fuse_copy_file_range(struct file *file_in, loff_t pos_in, +static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, size_t len, unsigned int flags) { @@ -3100,6 +3100,21 @@ static ssize_t fuse_copy_file_range(struct file *file_in, loff_t pos_in, return err; } +static ssize_t fuse_copy_file_range(struct file *src_file, loff_t src_off, + struct file *dst_file, loff_t dst_off, + size_t len, unsigned int flags) +{ + ssize_t ret; + + ret = __fuse_copy_file_range(src_file, src_off, dst_file, dst_off, + len, flags); + + if (ret == -EOPNOTSUPP) + ret = generic_copy_file_range(src_file, src_off, dst_file, + dst_off, len, flags); + return ret; +} + static const struct file_operations fuse_file_operations = { .llseek = fuse_file_llseek, .read_iter = fuse_file_read_iter, diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index 46d691ba04bc..d7766a6eb0f4 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -141,6 +141,10 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in, ret = nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count); if (ret == -EAGAIN) goto retry; + + if (ret == -EOPNOTSUPP) + ret = generic_copy_file_range(file_in, pos_in, file_out, + pos_out, count, flags); return ret; } diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index 84dd957efa24..68736e5d6a56 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -486,8 +486,15 @@ static ssize_t ovl_copy_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, size_t len, unsigned int flags) { - return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, flags, + ssize_t ret; + + ret = ovl_copyfile(file_in, pos_in, file_out, pos_out, len, flags, OVL_COPY); + + if (ret == -EOPNOTSUPP) + ret = generic_copy_file_range(file_in, pos_in, file_out, + pos_out, len, flags); + return ret; } static loff_t ovl_remap_file_range(struct file *file_in, loff_t pos_in, diff --git a/fs/read_write.c b/fs/read_write.c index 50114694c98b..44339b44accc 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1570,6 +1570,18 @@ ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in, } EXPORT_SYMBOL(generic_copy_file_range); +static ssize_t do_copy_file_range(struct file *file_in, loff_t pos_in, + struct file *file_out, loff_t pos_out, + size_t len, unsigned int flags) +{ + if (file_out->f_op->copy_file_range) + return file_out->f_op->copy_file_range(file_in, pos_in, file_out, + pos_out, len, flags); + + return generic_copy_file_range(file_in, &pos_in, file_out, &pos_out, + len, flags); +} + /* * copy_file_range() differs from regular file read and write in that it * specifically allows return partial success. When it does so is up to @@ -1634,15 +1646,9 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, } } - if (file_out->f_op->copy_file_range) { - ret = file_out->f_op->copy_file_range(file_in, pos_in, file_out, - pos_out, len, flags); - if (ret != -EOPNOTSUPP) - goto done; - } - - ret = generic_copy_file_range(file_in, &pos_in, file_out, &pos_out, - len, flags); + ret = do_copy_file_range(file_in, pos_in, file_out, pos_out, len, + flags); + WARN_ON_ONCE(ret == -EOPNOTSUPP); done: if (ret > 0) { fsnotify_access(file_in); From patchwork Mon Dec 3 08:34:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 10708777 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A467816B1 for ; Mon, 3 Dec 2018 08:34:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9479129A80 for ; Mon, 3 Dec 2018 08:34:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 88A0F2AE26; Mon, 3 Dec 2018 08:34:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0B2302A06C for ; Mon, 3 Dec 2018 08:34:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725931AbeLCIeb (ORCPT ); Mon, 3 Dec 2018 03:34:31 -0500 Received: from ipmailnode02.adl6.internode.on.net ([150.101.137.148]:39077 "EHLO ipmailnode02.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725830AbeLCIeb (ORCPT ); Mon, 3 Dec 2018 03:34:31 -0500 Received: from ppp59-167-129-252.static.internode.on.net (HELO dastard) ([59.167.129.252]) by ipmail02.adl6.internode.on.net with ESMTP; 03 Dec 2018 19:04:19 +1030 Received: from discord.disaster.area ([192.168.1.111]) by dastard with esmtp (Exim 4.80) (envelope-from ) id 1gTjgJ-0003PU-11; Mon, 03 Dec 2018 19:34:19 +1100 Received: from dave by discord.disaster.area with local (Exim 4.91) (envelope-from ) id 1gTjgI-000064-WC; Mon, 03 Dec 2018 19:34:19 +1100 From: Dave Chinner To: linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Cc: olga.kornievskaia@gmail.com, linux-nfs@vger.kernel.org, linux-unionfs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH 04/11] vfs: add missing checks to copy_file_range Date: Mon, 3 Dec 2018 19:34:09 +1100 Message-Id: <20181203083416.28978-5-david@fromorbit.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181203083416.28978-1-david@fromorbit.com> References: <20181203083416.28978-1-david@fromorbit.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Chinner Like the clone and dedupe interfaces we've recently fixed, the copy_file_range() implementation is missing basic sanity, limits and boundary condition tests on the parameters that are passed to it from userspace. Create a new "generic_copy_file_checks()" function modelled on the generic_remap_checks() function to provide this missing functionality. Signed-off-by: Dave Chinner Reviewed-by: Amir Goldstein --- fs/read_write.c | 27 ++++++------------ include/linux/fs.h | 3 ++ mm/filemap.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 18 deletions(-) diff --git a/fs/read_write.c b/fs/read_write.c index 44339b44accc..69809345977e 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1578,7 +1578,7 @@ static ssize_t do_copy_file_range(struct file *file_in, loff_t pos_in, return file_out->f_op->copy_file_range(file_in, pos_in, file_out, pos_out, len, flags); - return generic_copy_file_range(file_in, &pos_in, file_out, &pos_out, + return generic_copy_file_range(file_in, pos_in, file_out, pos_out, len, flags); } @@ -1598,10 +1598,14 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, if (flags != 0) return -EINVAL; - if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode)) - return -EISDIR; - if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode)) - return -EINVAL; + /* this could be relaxed once a method supports cross-fs copies */ + if (inode_in->i_sb != inode_out->i_sb) + return -EXDEV; + + ret = generic_copy_file_checks(file_in, pos_in, file_out, pos_out, &len, + flags); + if (ret < 0) + return ret; ret = rw_verify_area(READ, file_in, &pos_in, len); if (unlikely(ret)) @@ -1611,22 +1615,9 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, if (unlikely(ret)) return ret; - if (!(file_in->f_mode & FMODE_READ) || - !(file_out->f_mode & FMODE_WRITE) || - (file_out->f_flags & O_APPEND)) - return -EBADF; - - /* this could be relaxed once a method supports cross-fs copies */ - if (inode_in->i_sb != inode_out->i_sb) - return -EXDEV; - if (len == 0) return 0; - /* If the source range crosses EOF, fail the copy */ - if (pos_in >= i_size(inode_in) || pos_in + len > i_size(inode_in)) - return -EINVAL; - file_start_write(file_out); /* diff --git a/include/linux/fs.h b/include/linux/fs.h index a4478764cf63..0d9d2d93d4df 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3022,6 +3022,9 @@ extern ssize_t generic_write_checks(struct kiocb *, struct iov_iter *); extern int generic_remap_checks(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, loff_t *count, unsigned int remap_flags); +extern int generic_copy_file_checks(struct file *file_in, loff_t pos_in, + struct file *file_out, loff_t pos_out, + size_t *count, unsigned int flags); extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *); extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *); extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *); diff --git a/mm/filemap.c b/mm/filemap.c index 81adec8ee02c..0a170425935b 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2975,6 +2975,75 @@ int generic_remap_checks(struct file *file_in, loff_t pos_in, return 0; } + +/* + * Performs necessary checks before doing a file copy + * + * Can adjust amount of bytes to copy + * Returns appropriate error code that caller should return or + * zero in case the copy should be allowed. + */ +int generic_copy_file_checks(struct file *file_in, loff_t pos_in, + struct file *file_out, loff_t pos_out, + size_t *req_count, unsigned int flags) +{ + struct inode *inode_in = file_inode(file_in); + struct inode *inode_out = file_inode(file_out); + uint64_t count = *req_count; + uint64_t bcount; + loff_t size_in, size_out; + loff_t bs = inode_out->i_sb->s_blocksize; + int ret; + + /* Don't touch certain kinds of inodes */ + if (IS_IMMUTABLE(inode_out)) + return -EPERM; + + if (IS_SWAPFILE(inode_in) || IS_SWAPFILE(inode_out)) + return -ETXTBSY; + + /* Don't copy dirs, pipes, sockets... */ + if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode)) + return -EISDIR; + if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode)) + return -EINVAL; + + if (!(file_in->f_mode & FMODE_READ) || + !(file_out->f_mode & FMODE_WRITE) || + (file_out->f_flags & O_APPEND)) + return -EBADF; + + /* Ensure offsets don't wrap. */ + if (pos_in + count < pos_in || pos_out + count < pos_out) + return -EOVERFLOW; + + size_in = i_size_read(inode_in); + size_out = i_size_read(inode_out); + + /* If the source range crosses EOF, fail the copy */ + if (pos_in >= size_in) + return -EINVAL; + if (pos_in + count > size_in) + return -EINVAL; + + ret = generic_access_check_limits(file_in, pos_in, &count); + if (ret) + return ret; + + ret = generic_write_check_limits(file_out, pos_out, &count); + if (ret) + return ret; + + /* Don't allow overlapped copying within the same file. */ + if (inode_in == inode_out && + pos_out + count > pos_in && + pos_out < pos_in + count) + return -EINVAL; + + *req_count = count; + return 0; +} + int pagecache_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) From patchwork Mon Dec 3 08:34:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 10708813 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8D23918A7 for ; Mon, 3 Dec 2018 08:34:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 80DC82A06C for ; Mon, 3 Dec 2018 08:34:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 752A52AE0D; Mon, 3 Dec 2018 08:34:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 34E4029A80 for ; Mon, 3 Dec 2018 08:34:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725953AbeLCIej (ORCPT ); Mon, 3 Dec 2018 03:34:39 -0500 Received: from ipmailnode02.adl6.internode.on.net ([150.101.137.148]:60959 "EHLO ipmailnode02.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725952AbeLCIeg (ORCPT ); Mon, 3 Dec 2018 03:34:36 -0500 Received: from ppp59-167-129-252.static.internode.on.net (HELO dastard) ([59.167.129.252]) by ipmail02.adl6.internode.on.net with ESMTP; 03 Dec 2018 19:04:20 +1030 Received: from discord.disaster.area ([192.168.1.111]) by dastard with esmtp (Exim 4.80) (envelope-from ) id 1gTjgJ-0003PV-1v; Mon, 03 Dec 2018 19:34:19 +1100 Received: from dave by discord.disaster.area with local (Exim 4.91) (envelope-from ) id 1gTjgJ-000067-0q; Mon, 03 Dec 2018 19:34:19 +1100 From: Dave Chinner To: linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Cc: olga.kornievskaia@gmail.com, linux-nfs@vger.kernel.org, linux-unionfs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH 05/11] vfs: use inode_permission in copy_file_range() Date: Mon, 3 Dec 2018 19:34:10 +1100 Message-Id: <20181203083416.28978-6-david@fromorbit.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181203083416.28978-1-david@fromorbit.com> References: <20181203083416.28978-1-david@fromorbit.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Chinner Similar to FI_DEDUPERANGE, make copy_file_range() check that we have write permissions to the destination inode. Signed-off-by: Dave Chinner Reviewed-by: Amir Goldstein --- mm/filemap.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mm/filemap.c b/mm/filemap.c index 0a170425935b..876df5275514 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -3013,6 +3013,11 @@ int generic_copy_file_checks(struct file *file_in, loff_t pos_in, (file_out->f_flags & O_APPEND)) return -EBADF; + /* may sure we really are allowed to write to the destination inode */ + ret = inode_permission(inode_out, MAY_WRITE); + if (ret < 0) + return ret; + /* Ensure offsets don't wrap. */ if (pos_in + count < pos_in || pos_out + count < pos_out) return -EOVERFLOW; From patchwork Mon Dec 3 08:34:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 10708783 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 87037109C for ; Mon, 3 Dec 2018 08:34:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7950429A80 for ; Mon, 3 Dec 2018 08:34:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6D8C82AE0D; Mon, 3 Dec 2018 08:34:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 23E3D2A06C for ; Mon, 3 Dec 2018 08:34:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725945AbeLCIec (ORCPT ); Mon, 3 Dec 2018 03:34:32 -0500 Received: from ipmailnode02.adl6.internode.on.net ([150.101.137.148]:60959 "EHLO ipmailnode02.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725922AbeLCIeb (ORCPT ); Mon, 3 Dec 2018 03:34:31 -0500 Received: from ppp59-167-129-252.static.internode.on.net (HELO dastard) ([59.167.129.252]) by ipmail02.adl6.internode.on.net with ESMTP; 03 Dec 2018 19:04:19 +1030 Received: from discord.disaster.area ([192.168.1.111]) by dastard with esmtp (Exim 4.80) (envelope-from ) id 1gTjgJ-0003PW-2t; Mon, 03 Dec 2018 19:34:19 +1100 Received: from dave by discord.disaster.area with local (Exim 4.91) (envelope-from ) id 1gTjgJ-00006A-1l; Mon, 03 Dec 2018 19:34:19 +1100 From: Dave Chinner To: linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Cc: olga.kornievskaia@gmail.com, linux-nfs@vger.kernel.org, linux-unionfs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH 06/11] vfs: copy_file_range needs to strip setuid bits Date: Mon, 3 Dec 2018 19:34:11 +1100 Message-Id: <20181203083416.28978-7-david@fromorbit.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181203083416.28978-1-david@fromorbit.com> References: <20181203083416.28978-1-david@fromorbit.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Chinner The file we are copying data into needs to have its setuid bit stripped before we start the data copy so that unprivileged users can't copy data into executables that are run with root privs. Signed-off-by: Dave Chinner Reviewed-by: Amir Goldstein --- fs/read_write.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/read_write.c b/fs/read_write.c index 69809345977e..3b101183ea19 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1574,6 +1574,16 @@ static ssize_t do_copy_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, size_t len, unsigned int flags) { + ssize_t ret; + + /* + * Clear the security bits if the process is not being run by root. + * This keeps people from modifying setuid and setgid binaries. + */ + ret = file_remove_privs(file_out); + if (ret) + return ret; + if (file_out->f_op->copy_file_range) return file_out->f_op->copy_file_range(file_in, pos_in, file_out, pos_out, len, flags); From patchwork Mon Dec 3 08:34:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 10708835 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F0AD018A7 for ; Mon, 3 Dec 2018 08:34:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E444D2A06C for ; Mon, 3 Dec 2018 08:34:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D8CF42AE26; Mon, 3 Dec 2018 08:34:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 950992AE0D for ; Mon, 3 Dec 2018 08:34:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725941AbeLCIec (ORCPT ); Mon, 3 Dec 2018 03:34:32 -0500 Received: from ipmailnode02.adl6.internode.on.net ([150.101.137.148]:36689 "EHLO ipmailnode02.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725891AbeLCIeb (ORCPT ); Mon, 3 Dec 2018 03:34:31 -0500 Received: from ppp59-167-129-252.static.internode.on.net (HELO dastard) ([59.167.129.252]) by ipmail02.adl6.internode.on.net with ESMTP; 03 Dec 2018 19:04:19 +1030 Received: from discord.disaster.area ([192.168.1.111]) by dastard with esmtp (Exim 4.80) (envelope-from ) id 1gTjgJ-0003PX-3r; Mon, 03 Dec 2018 19:34:19 +1100 Received: from dave by discord.disaster.area with local (Exim 4.91) (envelope-from ) id 1gTjgJ-00006D-2l; Mon, 03 Dec 2018 19:34:19 +1100 From: Dave Chinner To: linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Cc: olga.kornievskaia@gmail.com, linux-nfs@vger.kernel.org, linux-unionfs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH 07/11] vfs: copy_file_range should update file timestamps Date: Mon, 3 Dec 2018 19:34:12 +1100 Message-Id: <20181203083416.28978-8-david@fromorbit.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181203083416.28978-1-david@fromorbit.com> References: <20181203083416.28978-1-david@fromorbit.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Chinner Timestamps are not updated right now, so programs looking for timestamp updates for file modifications (like rsync) will not detect that files have changed. We are also accessing the source data when doing a copy (but not when cloning) so we need to update atime on the source file as well. Signed-off-by: Dave Chinner --- fs/read_write.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/read_write.c b/fs/read_write.c index 3b101183ea19..3288db1d5f21 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1576,6 +1576,16 @@ static ssize_t do_copy_file_range(struct file *file_in, loff_t pos_in, { ssize_t ret; + /* Update source timestamps, because we are accessing file data */ + file_accessed(file_in); + + /* Update destination timestamps, since we can alter file contents. */ + if (!(file_out->f_mode & FMODE_NOCMTIME)) { + ret = file_update_time(file_out); + if (ret) + return ret; + } + /* * Clear the security bits if the process is not being run by root. * This keeps people from modifying setuid and setgid binaries. From patchwork Mon Dec 3 08:34:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 10708799 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6759C16B1 for ; Mon, 3 Dec 2018 08:34:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 593202A06C for ; Mon, 3 Dec 2018 08:34:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4CF1B2AE0D; Mon, 3 Dec 2018 08:34:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ECD1029A80 for ; Mon, 3 Dec 2018 08:34:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725951AbeLCIee (ORCPT ); Mon, 3 Dec 2018 03:34:34 -0500 Received: from ipmailnode02.adl6.internode.on.net ([150.101.137.148]:39077 "EHLO ipmailnode02.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725930AbeLCIee (ORCPT ); Mon, 3 Dec 2018 03:34:34 -0500 Received: from ppp59-167-129-252.static.internode.on.net (HELO dastard) ([59.167.129.252]) by ipmail02.adl6.internode.on.net with ESMTP; 03 Dec 2018 19:04:19 +1030 Received: from discord.disaster.area ([192.168.1.111]) by dastard with esmtp (Exim 4.80) (envelope-from ) id 1gTjgJ-0003PY-4o; Mon, 03 Dec 2018 19:34:19 +1100 Received: from dave by discord.disaster.area with local (Exim 4.91) (envelope-from ) id 1gTjgJ-00006G-3l; Mon, 03 Dec 2018 19:34:19 +1100 From: Dave Chinner To: linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Cc: olga.kornievskaia@gmail.com, linux-nfs@vger.kernel.org, linux-unionfs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH 08/11] vfs: push EXDEV check down into ->remap_file_range Date: Mon, 3 Dec 2018 19:34:13 +1100 Message-Id: <20181203083416.28978-9-david@fromorbit.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181203083416.28978-1-david@fromorbit.com> References: <20181203083416.28978-1-david@fromorbit.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Chinner before we can enable cross-device copies into copy_file_range(), we have to ensure that ->remap_file_range() implemenations will correctly reject attempts to do cross filesystem clones. Currently these checks are done above calls to ->remap_file_range(), but we need to drive them inwards so that we get EXDEV protection for all callers of ->remap_file_range(). Signed-off-by: Dave Chinner --- fs/read_write.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/fs/read_write.c b/fs/read_write.c index 3288db1d5f21..174cf92eea1d 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1909,6 +1909,19 @@ int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, bool same_inode = (inode_in == inode_out); int ret; + /* + * FICLONE/FICLONERANGE ioctls enforce that src and dest files are on + * the same mount. Practically, they only need to be on the same file + * system. We check this here rather than at the ioctl layers because + * this is effectively a limitation of the fielsystem implementations, + * not so much the API itself. Further, ->remap_file_range() can be + * called from syscalls that don't have cross device copy restrictions + * (such as copy_file_range()) and so we need to catch them before we + * do any damage. + */ + if (inode_in->i_sb != inode_out->i_sb) + return -EXDEV; + /* Don't touch certain kinds of inodes */ if (IS_IMMUTABLE(inode_out)) return -EPERM; @@ -2013,14 +2026,6 @@ loff_t do_clone_file_range(struct file *file_in, loff_t pos_in, if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode)) return -EINVAL; - /* - * FICLONE/FICLONERANGE ioctls enforce that src and dest files are on - * the same mount. Practically, they only need to be on the same file - * system. - */ - if (inode_in->i_sb != inode_out->i_sb) - return -EXDEV; - if (!(file_in->f_mode & FMODE_READ) || !(file_out->f_mode & FMODE_WRITE) || (file_out->f_flags & O_APPEND)) From patchwork Mon Dec 3 08:34:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 10708823 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 836CB109C for ; Mon, 3 Dec 2018 08:34:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 779CA2A06C for ; Mon, 3 Dec 2018 08:34:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6C1DE2AE26; Mon, 3 Dec 2018 08:34:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EC20F2A06C for ; Mon, 3 Dec 2018 08:34:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725964AbeLCIei (ORCPT ); Mon, 3 Dec 2018 03:34:38 -0500 Received: from ipmailnode02.adl6.internode.on.net ([150.101.137.148]:39077 "EHLO ipmailnode02.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725953AbeLCIei (ORCPT ); Mon, 3 Dec 2018 03:34:38 -0500 Received: from ppp59-167-129-252.static.internode.on.net (HELO dastard) ([59.167.129.252]) by ipmail02.adl6.internode.on.net with ESMTP; 03 Dec 2018 19:04:20 +1030 Received: from discord.disaster.area ([192.168.1.111]) by dastard with esmtp (Exim 4.80) (envelope-from ) id 1gTjgJ-0003Pa-5q; Mon, 03 Dec 2018 19:34:19 +1100 Received: from dave by discord.disaster.area with local (Exim 4.91) (envelope-from ) id 1gTjgJ-00006J-4i; Mon, 03 Dec 2018 19:34:19 +1100 From: Dave Chinner To: linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Cc: olga.kornievskaia@gmail.com, linux-nfs@vger.kernel.org, linux-unionfs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH 09/11] vfs: push copy_file_ranges -EXDEV checks down Date: Mon, 3 Dec 2018 19:34:14 +1100 Message-Id: <20181203083416.28978-10-david@fromorbit.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181203083416.28978-1-david@fromorbit.com> References: <20181203083416.28978-1-david@fromorbit.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Chinner We want to enable cross-filesystem copy_file_range functionality where possible, so push the "same superblock only" checks down to the individual filesystem callouts so they can make their own decisions about cross-superblock copy offload. Signed-off-by: Dave Chinner Reviewed-by: Amir Goldstein --- fs/ceph/file.c | 4 +++- fs/cifs/cifsfs.c | 8 +++++++- fs/fuse/file.c | 5 ++++- fs/nfs/nfs4file.c | 16 ++++++++++------ fs/overlayfs/file.c | 10 +++++++++- fs/read_write.c | 10 ++++------ 6 files changed, 37 insertions(+), 16 deletions(-) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index cf29f0410dcb..eb876e19c1dc 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -1905,6 +1905,8 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off, if (src_inode == dst_inode) return -EINVAL; + if (src_inode->i_sb != dst_inode->i_sb) + return -EXDEV; if (ceph_snap(dst_inode) != CEPH_NOSNAP) return -EROFS; @@ -2105,7 +2107,7 @@ static ssize_t ceph_copy_file_range(struct file *src_file, loff_t src_off, ret = __ceph_copy_file_range(src_file, src_off, dst_file, dst_off, len, flags); - if (ret == -EOPNOTSUPP) + if (ret == -EOPNOTSUPP || ret == -EXDEV) ret = generic_copy_file_range(src_file, src_off, dst_file, dst_off, len, flags); return ret; diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 5ef4baec6234..03e4b9eacbd1 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -1072,6 +1072,12 @@ ssize_t cifs_file_copychunk_range(unsigned int xid, goto out; } + if (src_inode->i_sb != target_inode->i_sb) { + rc = -EXDEV; + goto out; + } + + if (!src_file->private_data || !dst_file->private_data) { rc = -EBADF; cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n"); @@ -1142,7 +1148,7 @@ static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off, len, flags); free_xid(xid); - if (rc == -EOPNOTSUPP) + if (rc == -EOPNOTSUPP || rc == -EXDEV) rc = generic_copy_file_range(src_file, off, dst_file, destoff, len, flags); return rc; diff --git a/fs/fuse/file.c b/fs/fuse/file.c index b86fb0298739..0758f831a4eb 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -3053,6 +3053,9 @@ static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in, if (fc->no_copy_file_range) return -EOPNOTSUPP; + if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) + return -EXDEV; + inode_lock(inode_out); if (fc->writeback_cache) { @@ -3109,7 +3112,7 @@ static ssize_t fuse_copy_file_range(struct file *src_file, loff_t src_off, ret = __fuse_copy_file_range(src_file, src_off, dst_file, dst_off, len, flags); - if (ret == -EOPNOTSUPP) + if (ret == -EOPNOTSUPP || ret == -EXDEV) ret = generic_copy_file_range(src_file, src_off, dst_file, dst_off, len, flags); return ret; diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index d7766a6eb0f4..4783c0c1c49e 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -133,16 +133,20 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, size_t count, unsigned int flags) { - ssize_t ret; + ssize_t ret = -EXDEV; if (file_inode(file_in) == file_inode(file_out)) return -EINVAL; -retry: - ret = nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count); - if (ret == -EAGAIN) - goto retry; - if (ret == -EOPNOTSUPP) + /* only offload copy if superblock is the same */ + if (file_inode(file_in)->i_sb == file_inode(file_out)->i_sb) { + do { + ret = nfs42_proc_copy(file_in, pos_in, file_out, + pos_out, count); + } while (ret == -EAGAIN); + } + + if (ret == -EOPNOTSUPP || ret == -EXDEV) ret = generic_copy_file_range(file_in, pos_in, file_out, pos_out, count, flags); return ret; diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index 68736e5d6a56..34fb0398d016 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -443,6 +443,14 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, const struct cred *old_cred; loff_t ret; + /* + * Temporary. Cross device copy checks should be left to the copy file + * call on the real inodes, but existing behaviour checks the upper + * files only. + */ + if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) + return -EXDEV; + ret = ovl_real_fdget(file_out, &real_out); if (ret) return ret; @@ -491,7 +499,7 @@ static ssize_t ovl_copy_file_range(struct file *file_in, loff_t pos_in, ret = ovl_copyfile(file_in, pos_in, file_out, pos_out, len, flags, OVL_COPY); - if (ret == -EOPNOTSUPP) + if (ret == -EOPNOTSUPP || ret == -EXDEV) ret = generic_copy_file_range(file_in, pos_in, file_out, pos_out, len, flags); return ret; diff --git a/fs/read_write.c b/fs/read_write.c index 174cf92eea1d..4e0666de0d69 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1565,6 +1565,10 @@ ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, size_t len, unsigned int flags) { + /* Temporary, do_splice_direct supports cross-sb copies */ + if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) + return -EXDEV; + return do_splice_direct(file_in, &pos_in, file_out, &pos_out, len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0); } @@ -1611,17 +1615,11 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, size_t len, unsigned int flags) { - struct inode *inode_in = file_inode(file_in); - struct inode *inode_out = file_inode(file_out); ssize_t ret; if (flags != 0) return -EINVAL; - /* this could be relaxed once a method supports cross-fs copies */ - if (inode_in->i_sb != inode_out->i_sb) - return -EXDEV; - ret = generic_copy_file_checks(file_in, pos_in, file_out, pos_out, &len, flags); if (ret < 0) From patchwork Mon Dec 3 08:34:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 10708807 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 371C1109C for ; Mon, 3 Dec 2018 08:34:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2B02A2A06C for ; Mon, 3 Dec 2018 08:34:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1C54B29A80; Mon, 3 Dec 2018 08:34:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CBB0029A80 for ; Mon, 3 Dec 2018 08:34:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725960AbeLCIeg (ORCPT ); Mon, 3 Dec 2018 03:34:36 -0500 Received: from ipmailnode02.adl6.internode.on.net ([150.101.137.148]:36689 "EHLO ipmailnode02.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725938AbeLCIee (ORCPT ); Mon, 3 Dec 2018 03:34:34 -0500 Received: from ppp59-167-129-252.static.internode.on.net (HELO dastard) ([59.167.129.252]) by ipmail02.adl6.internode.on.net with ESMTP; 03 Dec 2018 19:04:20 +1030 Received: from discord.disaster.area ([192.168.1.111]) by dastard with esmtp (Exim 4.80) (envelope-from ) id 1gTjgJ-0003Pg-7B; Mon, 03 Dec 2018 19:34:19 +1100 Received: from dave by discord.disaster.area with local (Exim 4.91) (envelope-from ) id 1gTjgJ-00006M-5e; Mon, 03 Dec 2018 19:34:19 +1100 From: Dave Chinner To: linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Cc: olga.kornievskaia@gmail.com, linux-nfs@vger.kernel.org, linux-unionfs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH 10/11] vfs: allow generic_copy_file_range to copy across devices Date: Mon, 3 Dec 2018 19:34:15 +1100 Message-Id: <20181203083416.28978-11-david@fromorbit.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181203083416.28978-1-david@fromorbit.com> References: <20181203083416.28978-1-david@fromorbit.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Chinner do_splice_direct() can copy across superblocks without problems. Remove the same superblock restriction on this fallback code. Signed-off-by: Dave Chinner Reviewed-by: Amir Goldstein --- fs/read_write.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fs/read_write.c b/fs/read_write.c index 4e0666de0d69..b0f231b10836 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1565,10 +1565,6 @@ ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, size_t len, unsigned int flags) { - /* Temporary, do_splice_direct supports cross-sb copies */ - if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) - return -EXDEV; - return do_splice_direct(file_in, &pos_in, file_out, &pos_out, len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0); } From patchwork Mon Dec 3 08:34:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 10708795 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F0C51109C for ; Mon, 3 Dec 2018 08:34:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E58A429A80 for ; Mon, 3 Dec 2018 08:34:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D9C252AE26; Mon, 3 Dec 2018 08:34:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 95A5F29A80 for ; Mon, 3 Dec 2018 08:34:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725956AbeLCIee (ORCPT ); Mon, 3 Dec 2018 03:34:34 -0500 Received: from ipmailnode02.adl6.internode.on.net ([150.101.137.148]:60959 "EHLO ipmailnode02.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725937AbeLCIee (ORCPT ); Mon, 3 Dec 2018 03:34:34 -0500 Received: from ppp59-167-129-252.static.internode.on.net (HELO dastard) ([59.167.129.252]) by ipmail02.adl6.internode.on.net with ESMTP; 03 Dec 2018 19:04:20 +1030 Received: from discord.disaster.area ([192.168.1.111]) by dastard with esmtp (Exim 4.80) (envelope-from ) id 1gTjgJ-0003Pl-7y; Mon, 03 Dec 2018 19:34:19 +1100 Received: from dave by discord.disaster.area with local (Exim 4.91) (envelope-from ) id 1gTjgJ-00006Q-6Y; Mon, 03 Dec 2018 19:34:19 +1100 From: Dave Chinner To: linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Cc: olga.kornievskaia@gmail.com, linux-nfs@vger.kernel.org, linux-unionfs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH 11/11] ovl: allow cross-device copy_file_range calls Date: Mon, 3 Dec 2018 19:34:16 +1100 Message-Id: <20181203083416.28978-12-david@fromorbit.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181203083416.28978-1-david@fromorbit.com> References: <20181203083416.28978-1-david@fromorbit.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Chinner Restrictions on cross-device copy_file_range() only affect the vfs_copy_file_range() call to the lower filesystems. They will handle the copy appropriately, so OVL will never see a EXDEV error from them. Hence we can remove the EXDEV checks and error handling from the ovl_copy_file_range() implementation. Signed-off-by: Dave Chinner Reviewed-by: Amir Goldstein --- fs/overlayfs/file.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index 34fb0398d016..146901d204df 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -443,14 +443,6 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, const struct cred *old_cred; loff_t ret; - /* - * Temporary. Cross device copy checks should be left to the copy file - * call on the real inodes, but existing behaviour checks the upper - * files only. - */ - if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) - return -EXDEV; - ret = ovl_real_fdget(file_out, &real_out); if (ret) return ret; @@ -499,7 +491,8 @@ static ssize_t ovl_copy_file_range(struct file *file_in, loff_t pos_in, ret = ovl_copyfile(file_in, pos_in, file_out, pos_out, len, flags, OVL_COPY); - if (ret == -EOPNOTSUPP || ret == -EXDEV) + WARN_ON_ONCE(ret == -EXDEV); + if (ret == -EOPNOTSUPP) ret = generic_copy_file_range(file_in, pos_in, file_out, pos_out, len, flags); return ret; From patchwork Mon Dec 3 08:39:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 10708873 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D874A13AF for ; Mon, 3 Dec 2018 08:40:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C9D6A2A967 for ; Mon, 3 Dec 2018 08:40:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BD80C2A98D; Mon, 3 Dec 2018 08:40:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 56AE82A97B for ; Mon, 3 Dec 2018 08:40:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726121AbeLCIkA (ORCPT ); Mon, 3 Dec 2018 03:40:00 -0500 Received: from ipmailnode02.adl6.internode.on.net ([150.101.137.148]:23697 "EHLO ipmailnode02.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726001AbeLCIj7 (ORCPT ); Mon, 3 Dec 2018 03:39:59 -0500 Received: from ppp59-167-129-252.static.internode.on.net (HELO dastard) ([59.167.129.252]) by ipmail02.adl6.internode.on.net with ESMTP; 03 Dec 2018 19:09:53 +1030 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1gTjlg-0003SC-Tg; Mon, 03 Dec 2018 19:39:52 +1100 Date: Mon, 3 Dec 2018 19:39:52 +1100 From: Dave Chinner To: linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org Cc: olga.kornievskaia@gmail.com, linux-nfs@vger.kernel.org, linux-unionfs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH 12/11] man-pages: copy_file_range updates Message-ID: <20181203083952.GC6311@dastard> References: <20181203083416.28978-1-david@fromorbit.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20181203083416.28978-1-david@fromorbit.com> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Chinner Update with all the missing errors the syscall can return, the behaviour the syscall should have w.r.t. to copies within single files, etc. Signed-off-by: Dave Chinner --- man2/copy_file_range.2 | 94 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 17 deletions(-) diff --git a/man2/copy_file_range.2 b/man2/copy_file_range.2 index 20374abb21f0..23b00c2f3fea 100644 --- a/man2/copy_file_range.2 +++ b/man2/copy_file_range.2 @@ -42,9 +42,9 @@ without the additional cost of transferring data from the kernel to user space and then back into the kernel. It copies up to .I len -bytes of data from file descriptor +bytes of data from the source file descriptor .I fd_in -to file descriptor +to target file descriptor .IR fd_out , overwriting any data that exists within the requested range of the target file. .PP @@ -74,6 +74,11 @@ is not changed, but .I off_in is adjusted appropriately. .PP +.I fd_in +and +.I fd_out +can refer to the same file. If they refer to the same file, then the source and +target ranges are not allowed to overlap. .PP The .I flags @@ -93,34 +98,73 @@ is set to indicate the error. .SH ERRORS .TP .B EBADF -One or more file descriptors are not valid; or +One or more file descriptors are not valid. +.TP +.B EBADF .I fd_in is not open for reading; or .I fd_out -is not open for writing; or -the +is not open for writing. +.TP +.B EBADF +The .B O_APPEND flag is set for the open file description referred to by .IR fd_out . .TP .B EFBIG -An attempt was made to write a file that exceeds the implementation-defined -maximum file size or the process's file size limit, -or to write at a position past the maximum allowed offset. +An attempt was made to write at a position past the maximum file offset the +kernel supports. +.TP +.B EFBIG +An attempt was made to write a range that exceeds the allowed maximum file size. +The maximum file size differs between filesystem implemenations and can be +different to the maximum allowed file offset. +.TP +.B EFBIG +An attempt was made to write beyond the process's file size resource +limit. This may also result in the process receiving a +.I SIGXFSZ +signal. .TP .B EINVAL -Requested range extends beyond the end of the source file; or the -.I flags -argument is not 0. +.I (off_in + len) +spans the end of the source file. .TP -.B EIO -A low-level I/O error occurred while copying. +.B EINVAL +.I fd_in +and +.I fd_out +refer to the same file and the source and target ranges overlap. +.TP +.B EINVAL +.I fd_in +or +.I fd_out +is not a regular file. .TP .B EISDIR .I fd_in or .I fd_out refers to a directory. +.B EINVAL +The +.I flags +argument is not 0. +.TP +.B EINVAL +.I off_in +or +.I (off_in + len) +is beyond the maximum valid file offset. +.TP +.B EOVERFLOW +The requested source or destination range is too large to represent in the +specified data types. +.TP +.B EIO +A low-level I/O error occurred while copying. .TP .B ENOMEM Out of memory. @@ -128,16 +172,32 @@ Out of memory. .B ENOSPC There is not enough space on the target filesystem to complete the copy. .TP -.B EXDEV -The files referred to by -.IR file_in " and " file_out -are not on the same mounted filesystem. +.B TXTBSY +.I fd_in +or +.I fd_out +refers to an active swap file. +.TP +.B EPERM +.I fd_out +refers to an immutable file. +.TP +.B EACCES +The user does not have write permissions for the destination file. .SH VERSIONS The .BR copy_file_range () system call first appeared in Linux 4.5, but glibc 2.27 provides a user-space emulation when it is not available. .\" https://sourceware.org/git/?p=glibc.git;a=commit;f=posix/unistd.h;h=bad7a0c81f501fbbcc79af9eaa4b8254441c4a1f +.PP +A major rework of the kernel implementation occurred in 4.21. Areas of the API +that weren't clearly defined were clarified and the API bounds are much more +strictly checked than on earlier kernels. Applications should target the +behaviour and requirements of 4.21 kernels. +.PP +First support for cross-filesystem copies was introduced in Linux 4.21. Older +kernels will return -EXDEV when cross-filesystem copies are attempted. .SH CONFORMING TO The .BR copy_file_range ()