From patchwork Fri May 31 16:46:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 1108457 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="LFLr6fmp"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45Fr2s421yz9s3l for ; Sat, 1 Jun 2019 02:47:17 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727030AbfEaQrO (ORCPT ); Fri, 31 May 2019 12:47:14 -0400 Received: from mail-wm1-f66.google.com ([209.85.128.66]:50705 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727003AbfEaQrN (ORCPT ); Fri, 31 May 2019 12:47:13 -0400 Received: by mail-wm1-f66.google.com with SMTP id f204so2453641wme.0; Fri, 31 May 2019 09:47:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=7z+URgKWKe9baBNXTRuiwAT8xxeo4lu6F54jeoU5vwA=; b=LFLr6fmpK1pv59BZ5pGUGCOjYzE4yp97eEuGDDRdFTBA5bMeUpACnEKw54TdDVG58q Gz2KSF+rmusjkhvqwlDCfYITVnz+L4I7qgTMmNnJYQwZmcsoXXGkedodYGm/b5vlsq7q QI1bnRvTW1AYYo4ucUYJQw6pDrPLEOGJLU+XGp1i1HeDDZiP5/zfDM/qX8/9MGwCYy07 LnQ+x7BaBb32uenPLaHeXumiEacQ9shNbhdxfNEtV7eUhsVS4bD8uP17SuGbUrfyj/ej ea3QyVOYRKZJUEJWyDmsRCCC+lX/1AhYgSmhqz8thB8aj1sZL6dZ4d6VCCSqQXu5fHED j+YA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=7z+URgKWKe9baBNXTRuiwAT8xxeo4lu6F54jeoU5vwA=; b=E5vNR6YikYgL+3bUQhTtTa6RsQ+rHjhg1GJEy+2WmFX+A/yaejGsCNIkmAeSUdm3rJ tX4fDg12SVi8aAymFCrIQhWl3iDvv4jD5RrnMSu4UU8vF59SKm01UR8OFNLSNoLPRd97 NpjjQdQJ8MYmLKDuKHcGt+bgM+PCvyHau7ba4WEpsq/ah1AioTlUZrtGSJCnNwYHfSiI LzLAKAJ54jRqg3j5CYakMHy1TPJY4ZDrbyY+LSohZql9eZkY41YIPm71Ei5d3GSx3gUI Zo+G/pTUut0fMtOYdmm5cwqTmbnNvVPJbfieP5jpgAeN2jelpqjzXNbGmvPWK0R2xuU7 Jj+g== X-Gm-Message-State: APjAAAWvF6TFUggC1pr9XfuAeMf+c4WIQzEKSZmBSYQq3sX+TBh+MMGt BU+/SBNj1ec5kj8j7MIXdbA= X-Google-Smtp-Source: APXvYqz3T4EEheFeEouY+WuKNMAIR95jioZXVsKQWFBS1fa+ziG4bTL0aCq8vUDOoku1rSk0AKcxlg== X-Received: by 2002:a1c:f606:: with SMTP id w6mr6665229wmc.130.1559321230954; Fri, 31 May 2019 09:47:10 -0700 (PDT) Received: from localhost.localdomain ([5.102.238.208]) by smtp.gmail.com with ESMTPSA id n5sm7669593wrj.27.2019.05.31.09.47.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 May 2019 09:47:10 -0700 (PDT) From: Amir Goldstein To: "Darrick J . Wong" Cc: Dave Chinner , Christoph Hellwig , linux-xfs@vger.kernel.org, Olga Kornievskaia , Luis Henriques , Al Viro , linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org, ceph-devel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, Dave Chinner Subject: [PATCH v4 1/9] vfs: introduce generic_copy_file_range() Date: Fri, 31 May 2019 19:46:53 +0300 Message-Id: <20190531164701.15112-2-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190531164701.15112-1-amir73il@gmail.com> References: <20190531164701.15112-1-amir73il@gmail.com> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org 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 Signed-off-by: Amir Goldstein Reviewed-by: Darrick J. Wong --- 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 c543d965e288..676b02fae589 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1565,6 +1565,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 @@ -1632,9 +1662,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 f7fdfe93e25d..ea17858310ff 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1889,6 +1889,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 Fri May 31 16:46:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 1108464 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="s6OYwpzS"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45Fr3P017sz9sBb for ; Sat, 1 Jun 2019 02:47:45 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727064AbfEaQrR (ORCPT ); Fri, 31 May 2019 12:47:17 -0400 Received: from mail-wm1-f65.google.com ([209.85.128.65]:39827 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727017AbfEaQrQ (ORCPT ); Fri, 31 May 2019 12:47:16 -0400 Received: by mail-wm1-f65.google.com with SMTP id z23so6340819wma.4; Fri, 31 May 2019 09:47:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+W6U4ETnLrYkikxbMk/wh3iIEZoEwtztQ/QLH5NUi74=; b=s6OYwpzSfktPnuWB7OCyn3/Tl6N6XIqLaHNOX1vXUkGxdrkwC4RJZoEkNkg1Xz4Zki SeR2xx5Le7pQyBkCJ0EN/V2+8w7YmG59iFW9w6ovln0m8z6nyjnBNpC3BlFRz9JoBNdR s7hPvd/1F7vFW+rl6lsdkFuJPPw3+gVO9x35fKrIXjWZE+bMI9iekdg2uZzeFa8G/oBM DFbXNFWhBPqBCSjMMHU4wKYNQg76gaA3ouC2HDo1py6TpnM8Dl9+CPhKUxNRj+LBHGRV HrscDpDVoVUHPCMiRmAkudCmrsut3SNYFC8MgIXMYr1mglvyX3anOn/6pKadkjq+yjPz Hb5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+W6U4ETnLrYkikxbMk/wh3iIEZoEwtztQ/QLH5NUi74=; b=lPUHaR5auXw9NUnBczbEOGB0YRdbVrQlF69WH56gcb2LhbnhIVMVNXKFOslI7Mj30f g8TGMG0+W1HTbRSIRWDKtNE2tIntH39ENyK+IhmpGg5hEamGvF2KWHqkZhToPq4iVrky aQwStAfDrKWwk4A21Ff6fbk7FlLf0HcMjeviKrgQhml9t2Vl5z9BlhSmZrRiB+25N3w1 grpMY3W3twKlasDH3ZSVsMos+3WsyLnrNsDgG3lESIoAhymSw9jPBQ+hczOBO56zdclf jWZY+l/VoZSeLAWB31wJ/yt7Fkf9XLaCVC8A+aSqhfqjA0rTtc8yjDdNpJQ1OYu4/mr0 yaWA== X-Gm-Message-State: APjAAAWEwVPJhoxMeNY7C+j/Jvoipcq3u+9R+Ro+zSKkF6ff5l1hn9Sp F2O4VjKIdZlylIE6clPpChBN/2v7 X-Google-Smtp-Source: APXvYqzKDScvDo0NdEwGNoYdjUwALmg5duYiEBzHqOazCGLCpbYM2Vr2iMvo78lm8PF+PPP0I3I77Q== X-Received: by 2002:a1c:c545:: with SMTP id v66mr6486620wmf.51.1559321232909; Fri, 31 May 2019 09:47:12 -0700 (PDT) Received: from localhost.localdomain ([5.102.238.208]) by smtp.gmail.com with ESMTPSA id n5sm7669593wrj.27.2019.05.31.09.47.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 May 2019 09:47:12 -0700 (PDT) From: Amir Goldstein To: "Darrick J . Wong" Cc: Dave Chinner , Christoph Hellwig , linux-xfs@vger.kernel.org, Olga Kornievskaia , Luis Henriques , Al Viro , linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org, ceph-devel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, Dave Chinner Subject: [PATCH v4 2/9] vfs: no fallback for ->copy_file_range Date: Fri, 31 May 2019 19:46:54 +0300 Message-Id: <20190531164701.15112-3-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190531164701.15112-1-amir73il@gmail.com> References: <20190531164701.15112-1-amir73il@gmail.com> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org 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 execute the copying callout, and move calls to generic_file_copy_range() into filesystem methods where they currently return failures. [Amir] overlayfs is not responsible of executing the fallback. It is the responsibility of the underlying filesystem. Signed-off-by: Dave Chinner Signed-off-by: Amir Goldstein Reviewed-by: Darrick J. Wong --- fs/ceph/file.c | 21 ++++++++++++++++++--- fs/cifs/cifsfs.c | 4 ++++ fs/fuse/file.c | 21 ++++++++++++++++++--- fs/nfs/nfs4file.c | 20 +++++++++++++++++--- fs/read_write.c | 25 ++++++++++++++++--------- 5 files changed, 73 insertions(+), 18 deletions(-) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 305daf043eb0..e87f7b2023af 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -1889,9 +1889,9 @@ 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, - struct file *dst_file, loff_t dst_off, - size_t len, unsigned int flags) +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) { struct inode *src_inode = file_inode(src_file); struct inode *dst_inode = file_inode(dst_file); @@ -2100,6 +2100,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 f5fcd6360056..c65823270313 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -1148,6 +1148,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 3959f08279e6..e03901ae729b 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -3097,9 +3097,9 @@ 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, - struct file *file_out, loff_t pos_out, - size_t len, unsigned int flags) +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) { struct fuse_file *ff_in = file_in->private_data; struct fuse_file *ff_out = file_out->private_data; @@ -3173,6 +3173,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 cf42a8b939e3..4842f3ab3161 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -129,9 +129,9 @@ nfs4_file_flush(struct file *file, fl_owner_t id) } #ifdef CONFIG_NFS_V4_2 -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) +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) { if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY)) return -EOPNOTSUPP; @@ -140,6 +140,20 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in, return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count); } +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; + + ret = __nfs4_copy_file_range(file_in, pos_in, file_out, pos_out, count, + flags); + if (ret == -EOPNOTSUPP) + ret = generic_copy_file_range(file_in, pos_in, file_out, + pos_out, count, flags); + return ret; +} + static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence) { loff_t ret; diff --git a/fs/read_write.c b/fs/read_write.c index 676b02fae589..b63dcb4e4fe9 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1595,6 +1595,19 @@ 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 @@ -1655,15 +1668,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 Fri May 31 16:46:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 1108459 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="sWNCZqzh"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45Fr301yc7z9sB8 for ; Sat, 1 Jun 2019 02:47:24 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727083AbfEaQrS (ORCPT ); Fri, 31 May 2019 12:47:18 -0400 Received: from mail-wm1-f68.google.com ([209.85.128.68]:54356 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727003AbfEaQrS (ORCPT ); Fri, 31 May 2019 12:47:18 -0400 Received: by mail-wm1-f68.google.com with SMTP id g135so3260669wme.4; Fri, 31 May 2019 09:47:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zD+G66icCrS83U+p0kj1jVa8Ed5aOLuiZE56AA1YrhI=; b=sWNCZqzhaJm/4HJauaa9QW9+p0kio32kz/pibNec/NwcF9x/RJ+iU6qoSJV6D/Ebqb 2FmHHDFY7nZBdh4GOkQ4zu3rb9YhT7P5gh9SE21RqNNsFqyq1Uj+2Gw0wpBqTtoU2Xpt N0JjE+xNZ2BMjjfk1HBrFfv39id1kMivh6VnLLR+QlPzMstZRlcihQZpjeQ6VS/4MGvp ua4/Ug/pPLL5RaGR4qnRpkYq09vHvo+A1tpsrZ354Mg4B1wFy0JnoQ2unzUUHM/MO4NN PBAUZoym1D92/fJDtMl0laheZ4rOzMFtMquVzjmvPrUa0wEeGrRboqMRLA3Ch2CA8QKw PrwQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zD+G66icCrS83U+p0kj1jVa8Ed5aOLuiZE56AA1YrhI=; b=GOCEF75zEKg1MsnYGwlcrbG0iShYapiIYFdyvRYqup7XGzZetk5ab4SiCre05h1/29 4A2Oz/lMLw0mjRYAvycm8Kv09Lw5Pg7bBQSm8Vy3ScqAqziwkXc6DCQM4fSmyFV6wqkc LotYHbGoBPLAq+CQ/5acaW4kXr7uPMU/8NqXGVMZzvb2z8NmrCGuoiCb7QxZJWpBCHi4 ZU2I5lomImoZegbjelP5RJDjuuxqwn4bLoNwPSDV8c46Ue3yau0aJFx18UJF2GTGt+xV ZRwV0SypDmNJr9CW3BZWTeb37QSI0uDl5n0Oo00Rmei+HrQYfDTO6n+G6SdLO+P2cTPz gnRQ== X-Gm-Message-State: APjAAAWvtFkjHZ3S4nKkHDqEwgeLRHb4/19Ab0WMv3yFa6rSSnM2nXq3 nMqqobTFX5FqFlYxUf3z+VM= X-Google-Smtp-Source: APXvYqzgtgOxhQAEKCd6LXP6m3DrP2CcaEho6Vi6DDXxj5zFoCxQu0yF0irMj6KB+Uhd6FqZRklExg== X-Received: by 2002:a1c:700b:: with SMTP id l11mr6355720wmc.106.1559321234671; Fri, 31 May 2019 09:47:14 -0700 (PDT) Received: from localhost.localdomain ([5.102.238.208]) by smtp.gmail.com with ESMTPSA id n5sm7669593wrj.27.2019.05.31.09.47.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 May 2019 09:47:14 -0700 (PDT) From: Amir Goldstein To: "Darrick J . Wong" Cc: Dave Chinner , Christoph Hellwig , linux-xfs@vger.kernel.org, Olga Kornievskaia , Luis Henriques , Al Viro , linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org, ceph-devel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH v4 3/9] vfs: introduce generic_file_rw_checks() Date: Fri, 31 May 2019 19:46:55 +0300 Message-Id: <20190531164701.15112-4-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190531164701.15112-1-amir73il@gmail.com> References: <20190531164701.15112-1-amir73il@gmail.com> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org Factor out helper with some checks on in/out file that are common to clone_file_range and copy_file_range. Suggested-by: Darrick J. Wong Signed-off-by: Amir Goldstein Reviewed-by: Darrick J. Wong --- fs/read_write.c | 38 +++++++++++--------------------------- include/linux/fs.h | 1 + mm/filemap.c | 24 ++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/fs/read_write.c b/fs/read_write.c index b63dcb4e4fe9..f1900bdb3127 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1617,17 +1617,18 @@ 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; - 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 (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) + return -EXDEV; + + ret = generic_file_rw_checks(file_in, file_out); + if (unlikely(ret)) + return ret; ret = rw_verify_area(READ, file_in, &pos_in, len); if (unlikely(ret)) @@ -1637,15 +1638,6 @@ 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; @@ -2013,29 +2005,21 @@ loff_t do_clone_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, loff_t len, unsigned int remap_flags) { - struct inode *inode_in = file_inode(file_in); - struct inode *inode_out = file_inode(file_out); loff_t ret; WARN_ON_ONCE(remap_flags & REMAP_FILE_DEDUP); - 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; - /* * 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) + if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) return -EXDEV; - if (!(file_in->f_mode & FMODE_READ) || - !(file_out->f_mode & FMODE_WRITE) || - (file_out->f_flags & O_APPEND)) - return -EBADF; + ret = generic_file_rw_checks(file_in, file_out); + if (ret < 0) + return ret; if (!file_in->f_op->remap_file_range) return -EOPNOTSUPP; diff --git a/include/linux/fs.h b/include/linux/fs.h index ea17858310ff..89b9b73eb581 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3049,6 +3049,7 @@ 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_file_rw_checks(struct file *file_in, struct file *file_out); 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 df2006ba0cfa..a38619a4a6af 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -3041,6 +3041,30 @@ int generic_remap_checks(struct file *file_in, loff_t pos_in, return 0; } + +/* + * Performs common checks before doing a file copy/clone + * from @file_in to @file_out. + */ +int generic_file_rw_checks(struct file *file_in, struct file *file_out) +{ + struct inode *inode_in = file_inode(file_in); + struct inode *inode_out = file_inode(file_out); + + /* 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; + + 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 Fri May 31 16:46:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 1108458 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="QpnnyvOY"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45Fr2w1ysgz9s3l for ; Sat, 1 Jun 2019 02:47:20 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727094AbfEaQrT (ORCPT ); Fri, 31 May 2019 12:47:19 -0400 Received: from mail-wm1-f65.google.com ([209.85.128.65]:38644 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727074AbfEaQrS (ORCPT ); Fri, 31 May 2019 12:47:18 -0400 Received: by mail-wm1-f65.google.com with SMTP id t5so6345131wmh.3; Fri, 31 May 2019 09:47:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=X3WeVFmopGuuzSMfd02xY46iy5YQ5i2IPT3FFyazWHY=; b=QpnnyvOYWKnYRoirb83FihX5x9ZV23YEQlEPdDZsKWmtyF+bShusbkmqzPeuusWzyC XqOpO/1iGnZOfvLJuwLIcavfSQAhJnaLlMvijfeA69g8zNJSmydIhaYqIJlVQX7FuaGX 7mFSLTlflUU9fglzB1TwhElftrZ2JIcjFV8WKOMBXHgBMl3e7BJcm/FrjpMfLUqr1qL4 QgnrT4uCyKHxqFRNKi/oH7DZvWt0X8Nh27texCBdLPB9oGSySHeQXgbxxRHpfL7Z8h7S gbM8yA0gZpaJPfgtlmvenO25R2j1PloAemnID7qIAYxsEI+B8rCnjYyeY6Qm6SHk0olK dVYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=X3WeVFmopGuuzSMfd02xY46iy5YQ5i2IPT3FFyazWHY=; b=Q66VuEf1Qc2AZUUsl67Noy7u0zRpJiUVAGP0NJ+bfc34vY9zdTXI5u+ajHD67wka+8 Q0PVVvHnRwjNZrP1XCpv2eiXUvH5ur/XddJQ8bAxDpoRtisZbEuq8tYjjjsdSMn5qNd3 zEPSPt0+ay5Jspt/lJ34BIOVNi/DJeRBDZJ9E6PQD6tvR4p9uIOC4T3rnfH1M1PjPMHb 2BbgxxGva1sqiOPUf9zaj2TBM0iKGTXD3jLq0FzhSlV9vRelLsT14lcHmZqB4ppiSwBa XU5exHOTebL/TOket7kx4mRl2gDbP0qyBe/36QP/iP/jkjHda9KY1tSEDBvfl4THaji9 p88Q== X-Gm-Message-State: APjAAAXqSlFUYRecAnQ1uzouV+hf1OZ2MjTPMf4TfjBqjN18S+1FDxJ1 SVL7JLBxgKNqJ5hUE+1uFYo= X-Google-Smtp-Source: APXvYqxOcnHUJG5TmXGvN85Yqz1uaieM1YNFDJzzjxfr378SsXYh9iw73KZ+B4Jdp14HbM0rD0FMPQ== X-Received: by 2002:a1c:63d7:: with SMTP id x206mr6406035wmb.19.1559321236505; Fri, 31 May 2019 09:47:16 -0700 (PDT) Received: from localhost.localdomain ([5.102.238.208]) by smtp.gmail.com with ESMTPSA id n5sm7669593wrj.27.2019.05.31.09.47.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 May 2019 09:47:15 -0700 (PDT) From: Amir Goldstein To: "Darrick J . Wong" Cc: Dave Chinner , Christoph Hellwig , linux-xfs@vger.kernel.org, Olga Kornievskaia , Luis Henriques , Al Viro , linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org, ceph-devel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH v4 4/9] vfs: remove redundant checks from generic_remap_checks() Date: Fri, 31 May 2019 19:46:56 +0300 Message-Id: <20190531164701.15112-5-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190531164701.15112-1-amir73il@gmail.com> References: <20190531164701.15112-1-amir73il@gmail.com> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org The access limit checks on input file range in generic_remap_checks() are redundant because the input file size is guaranteed to be within limits and pos+len are already checked to be within input file size. Beyond the fact that the check cannot fail, if it would have failed, it could return -EFBIG for input file range error. There is no precedent for that. -EFBIG is returned in syscalls that would change file length. With that call removed, we can fold generic_access_check_limits() into generic_write_check_limits(). Signed-off-by: Amir Goldstein Reviewed-by: Darrick J. Wong --- mm/filemap.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index a38619a4a6af..44361928bbb0 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2895,24 +2895,11 @@ EXPORT_SYMBOL(read_cache_page_gfp); * LFS limits. If pos is under the limit it becomes a short access. If it * exceeds the limit we return -EFBIG. */ -static int generic_access_check_limits(struct file *file, loff_t pos, - loff_t *count) -{ - struct inode *inode = file->f_mapping->host; - loff_t max_size = inode->i_sb->s_maxbytes; - - if (!(file->f_flags & O_LARGEFILE)) - max_size = MAX_NON_LFS; - - if (unlikely(pos >= max_size)) - return -EFBIG; - *count = min(*count, max_size - pos); - return 0; -} - static int generic_write_check_limits(struct file *file, loff_t pos, loff_t *count) { + struct inode *inode = file->f_mapping->host; + loff_t max_size = inode->i_sb->s_maxbytes; loff_t limit = rlimit(RLIMIT_FSIZE); if (limit != RLIM_INFINITY) { @@ -2923,7 +2910,15 @@ static int generic_write_check_limits(struct file *file, loff_t pos, *count = min(*count, limit - pos); } - return generic_access_check_limits(file, pos, count); + if (!(file->f_flags & O_LARGEFILE)) + max_size = MAX_NON_LFS; + + if (unlikely(pos >= max_size)) + return -EFBIG; + + *count = min(*count, max_size - pos); + + return 0; } /* @@ -2963,7 +2958,7 @@ EXPORT_SYMBOL(generic_write_checks); /* * Performs necessary checks before doing a clone. * - * Can adjust amount of bytes to clone. + * Can adjust amount of bytes to clone via @req_count argument. * Returns appropriate error code that caller should return or * zero in case the clone should be allowed. */ @@ -3001,10 +2996,6 @@ int generic_remap_checks(struct file *file_in, loff_t pos_in, return -EINVAL; count = min(count, size_in - (uint64_t)pos_in); - 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; From patchwork Fri May 31 16:46:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 1108460 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="tRhizwQU"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45Fr325jyjz9s3l for ; Sat, 1 Jun 2019 02:47:26 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727109AbfEaQrX (ORCPT ); Fri, 31 May 2019 12:47:23 -0400 Received: from mail-wm1-f67.google.com ([209.85.128.67]:40685 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727090AbfEaQrW (ORCPT ); Fri, 31 May 2019 12:47:22 -0400 Received: by mail-wm1-f67.google.com with SMTP id u16so1107745wmc.5; Fri, 31 May 2019 09:47:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=GmLRwLyr1TL2SZV/3Hd0cBEDiPM6bKDbyVa4EFRX9Nw=; b=tRhizwQUhrX+aMyNwadDebnZmz5EGLojFJbg/LvY+WEbk+XlLXHoxRHmmGytYm/NUW 73hrgn+WmYuXQAYRnzb/NzC9Pf259gT8xVUdkLXr2kcSAV5kJl19PcV0UZlYD75/EwZk JPEIvN9Iq238lc82xLRf/Pc6f/Hi4motCGr4x3pjXjsVAyyIA/Cv7jyjLz29LVFVzddk q2/i1cxnMNlKAHSOcoBJwgOjcVdGOspDEZEHYUjejVmDj9Dvg7nMqDEqWsw3tWdMIvXi SpGFGR3YL5mFmR2smqs8Q/i6pc7y6H3cXrLg86KDGMmf/svdQEjREPMxR93PdcVH63uv IdCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=GmLRwLyr1TL2SZV/3Hd0cBEDiPM6bKDbyVa4EFRX9Nw=; b=EQqaQJEsR1/Gbdp/cnz3KV9VtEit8U0jx9nOR/r6f4xCmWLQ14MIntPF2stzVcMnAA X12tIm6pw9haaFXjfsXz8eJcRKN5FAxYpKIYKDixPeG3+LsAmtXRLW0t5KGtakqGMaqW YxxtxdRwoROCb4wGuJV9yYFokNbrfVBTwG5OiN6lGXAeAmLgYPX/mARm6+l7bxSg4k4k NDCWQHSgYSjZoEiH33zUzlCEtvzZvDOwOby77b5i3yGvXzflmA+m6BnFfFMJed6KbkSR FDJdCipVHPyHEMuQHe9u+MhDjsUC3Mq9rnw1dqKD5hluyYzBGKxk3Jvr9TYTiIAIWl4W vLtA== X-Gm-Message-State: APjAAAXg1GaxCflGpNB6Fmdt2t1fMIvgeZSQMzvXFs/b2354ksysuGpd v2naoEwD0K6dsZH3Ldp0n5w= X-Google-Smtp-Source: APXvYqx4DhdAGt74ECyqU8faH377pazZGlGYfEzIKGE6g7bwR6OOr+jqfTSunXQ0eDP/29u+PaCTPQ== X-Received: by 2002:a7b:c043:: with SMTP id u3mr5757205wmc.56.1559321238387; Fri, 31 May 2019 09:47:18 -0700 (PDT) Received: from localhost.localdomain ([5.102.238.208]) by smtp.gmail.com with ESMTPSA id n5sm7669593wrj.27.2019.05.31.09.47.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 May 2019 09:47:17 -0700 (PDT) From: Amir Goldstein To: "Darrick J . Wong" Cc: Dave Chinner , Christoph Hellwig , linux-xfs@vger.kernel.org, Olga Kornievskaia , Luis Henriques , Al Viro , linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org, ceph-devel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, Dave Chinner Subject: [PATCH v4 5/9] vfs: add missing checks to copy_file_range Date: Fri, 31 May 2019 19:46:57 +0300 Message-Id: <20190531164701.15112-6-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190531164701.15112-1-amir73il@gmail.com> References: <20190531164701.15112-1-amir73il@gmail.com> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org 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. [Amir] Shorten copy length instead of checking pos_in limits because input file size already abides by the limits. Signed-off-by: Dave Chinner Signed-off-by: Amir Goldstein Reviewed-by: Darrick J. Wong --- fs/read_write.c | 3 ++- include/linux/fs.h | 3 +++ mm/filemap.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/fs/read_write.c b/fs/read_write.c index f1900bdb3127..b0fb1176b628 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1626,7 +1626,8 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) return -EXDEV; - ret = generic_file_rw_checks(file_in, file_out); + ret = generic_copy_file_checks(file_in, pos_in, file_out, pos_out, &len, + flags); if (unlikely(ret)) return ret; diff --git a/include/linux/fs.h b/include/linux/fs.h index 89b9b73eb581..e4d382c4342a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3050,6 +3050,9 @@ 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_file_rw_checks(struct file *file_in, struct file *file_out); +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 44361928bbb0..aac71aef4c61 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -3056,6 +3056,59 @@ int generic_file_rw_checks(struct file *file_in, struct file *file_out) return 0; } +/* + * Performs necessary checks before doing a file copy + * + * Can adjust amount of bytes to copy via @req_count argument. + * 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; + loff_t size_in; + int ret; + + ret = generic_file_rw_checks(file_in, file_out); + if (ret) + return 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; + + /* Ensure offsets don't wrap. */ + if (pos_in + count < pos_in || pos_out + count < pos_out) + return -EOVERFLOW; + + /* Shorten the copy to EOF */ + size_in = i_size_read(inode_in); + if (pos_in >= size_in) + count = 0; + else + count = min(count, size_in - (uint64_t)pos_in); + + 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 Fri May 31 16:46:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 1108461 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="XwdbJXZD"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45Fr353FCjz9s3l for ; Sat, 1 Jun 2019 02:47:29 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727120AbfEaQr1 (ORCPT ); Fri, 31 May 2019 12:47:27 -0400 Received: from mail-wm1-f66.google.com ([209.85.128.66]:36176 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726791AbfEaQrX (ORCPT ); Fri, 31 May 2019 12:47:23 -0400 Received: by mail-wm1-f66.google.com with SMTP id v22so6350709wml.1; Fri, 31 May 2019 09:47:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=jGXSvLa7NNCoOVvlvMxKeItWZVCcyVMKXFY2Xr6oVfM=; b=XwdbJXZDONlGTsiGHQlCU9tuovtGGMRRnMtHaj8HzeH3pB7ZlJ4kKQm5PlwcCgXoxS r3Pbcy63CkUe1x2o3uOclLYLEfb9QJasjsEarxAqxFIQRanhGb9AYoyZYEGk9M0ob+YJ 9gSWG922Bafz2y12P7T8ISgOiFq0CampMVDrryxwOlBHh8J7hOgGoY2BgFY5uTAcY6vA wKlMjFV1f+DBMRlEh3v61jPS3NA2+6IG9bjGH6BZVJxFwdL79ASXP4sa9y/agNMaJyOY /WvXqvIyDKujS8a4byEXP+r0Kz56D3gs045G1CtYH1XVW290b86B/kbkfnMQCKOINLNc DeQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=jGXSvLa7NNCoOVvlvMxKeItWZVCcyVMKXFY2Xr6oVfM=; b=C8Oyc13coVtT399eWPulwOkZ9abJBgpLw3BxZFp2Cg6ucNFgD3yh15YCuozQF8I5ml lR6KfGO2zcqW1UKo3p/nAxrn9AUokMiJvmuZ3DccESn4Nt94kdbffXLioy8PLz6wYqqb JeVTYfBnbrcClK1YF+gz1aHIvrlkBWVGggqsRM5di8Itiwn6G6ZUTtDV7WINWtDXheP/ N+4OPqZc4CPrAaOHgxIQdJ0hdsLDhC6hQHF5m5OOix5V5vbSpD97P9o2FYk2RofcZfnk 7fANlBgEt3YVZK+uhc28WDQJ/T4t0+eOkMqdlOUs9OHJYgCjE2RUqjl02zolbOyeJCSW JHDA== X-Gm-Message-State: APjAAAULY3ikgCto8nwa/76HA6rX8NsPKTMjzQwNoqpr2S+NmzseFz0k 7bRU5l5GBWNdCzh1tUDvUDU= X-Google-Smtp-Source: APXvYqwHKCdYfvR2HLz+xaIUZ1eV2cOfULE8MIAz9Yk42YD3i5z7576EF9U2LJ+AQNXtv18H+34TJg== X-Received: by 2002:a1c:7f10:: with SMTP id a16mr6398399wmd.30.1559321240180; Fri, 31 May 2019 09:47:20 -0700 (PDT) Received: from localhost.localdomain ([5.102.238.208]) by smtp.gmail.com with ESMTPSA id n5sm7669593wrj.27.2019.05.31.09.47.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 May 2019 09:47:19 -0700 (PDT) From: Amir Goldstein To: "Darrick J . Wong" Cc: Dave Chinner , Christoph Hellwig , linux-xfs@vger.kernel.org, Olga Kornievskaia , Luis Henriques , Al Viro , linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org, ceph-devel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH v4 6/9] vfs: introduce file_modified() helper Date: Fri, 31 May 2019 19:46:58 +0300 Message-Id: <20190531164701.15112-7-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190531164701.15112-1-amir73il@gmail.com> References: <20190531164701.15112-1-amir73il@gmail.com> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org The combination of file_remove_privs() and file_update_mtime() is quite common in filesystem ->write_iter() methods. Modelled after the helper file_accessed(), introduce file_modified() and use it from generic_remap_file_range_prep(). Note that the order of calling file_remove_privs() before file_update_mtime() in the helper was matched to the more common order by filesystems and not the current order in generic_remap_file_range_prep(). Signed-off-by: Amir Goldstein --- fs/inode.c | 20 ++++++++++++++++++++ fs/read_write.c | 21 +++------------------ include/linux/fs.h | 2 ++ 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index df6542ec3b88..4348cfb14562 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1899,6 +1899,26 @@ int file_update_time(struct file *file) } EXPORT_SYMBOL(file_update_time); +/* Caller must hold the file's inode lock */ +int file_modified(struct file *file) +{ + int err; + + /* + * Clear the security bits if the process is not being run by root. + * This keeps people from modifying setuid and setgid binaries. + */ + err = file_remove_privs(file); + if (err) + return err; + + if (unlikely(file->f_mode & FMODE_NOCMTIME)) + return 0; + + return file_update_time(file); +} +EXPORT_SYMBOL(file_modified); + int inode_needs_sync(struct inode *inode) { if (IS_SYNC(inode)) diff --git a/fs/read_write.c b/fs/read_write.c index b0fb1176b628..cec7e7b1f693 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1980,25 +1980,10 @@ int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, return ret; /* If can't alter the file contents, we're done. */ - if (!(remap_flags & REMAP_FILE_DEDUP)) { - /* Update the timestamps, since we can alter file contents. */ - if (!(file_out->f_mode & FMODE_NOCMTIME)) { - ret = file_update_time(file_out); - if (ret) - return ret; - } + if (!(remap_flags & REMAP_FILE_DEDUP)) + ret = file_modified(file_out); - /* - * 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; - } - - return 0; + return ret; } EXPORT_SYMBOL(generic_remap_file_range_prep); diff --git a/include/linux/fs.h b/include/linux/fs.h index e4d382c4342a..79ffa2958bd8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2177,6 +2177,8 @@ static inline void file_accessed(struct file *file) touch_atime(&file->f_path); } +extern int file_modified(struct file *file); + int sync_inode(struct inode *inode, struct writeback_control *wbc); int sync_inode_metadata(struct inode *inode, int wait); From patchwork Fri May 31 16:46:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 1108465 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="hZUB8Bfi"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45Fr3Q3ggWz9sB8 for ; Sat, 1 Jun 2019 02:47:46 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726791AbfEaQrn (ORCPT ); Fri, 31 May 2019 12:47:43 -0400 Received: from mail-wm1-f66.google.com ([209.85.128.66]:40688 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727108AbfEaQrY (ORCPT ); Fri, 31 May 2019 12:47:24 -0400 Received: by mail-wm1-f66.google.com with SMTP id u16so1107866wmc.5; Fri, 31 May 2019 09:47:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=AoxRD2reTRu3UbtqGj5ISPmNh4fBERakEl1ic6Mj7VQ=; b=hZUB8BfixI6FKtOwYyF+FSnRfKr2MZ4wIS/cQvwhtnNQCb1qHeECQGh3BbI6we792p Dc/5aKNKNr1fLOSkH67ZHzHrHTF0Bi0xOIn4ONkwRvgesYmoHafemuJwuqNweOuNrPg7 npQhL4lIaznHXmf0xQUXpgp0EE5PbK31m61CBosRlZqGc0ELjzfbCosv7k9T1cejiCHZ 6wSK7t5qpfUSx8k4SJLTU/Y0wzJXsUkWrH2RyvlTcVP5esHqKA6YahGJeym5iPWx8oip xsdJA/uHHS9zBPWaUYkALGkuQ9XOqhCK0sILULAUY9ojLNCCrXhZ8fqPr+2Qaxy0ugeu LiuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=AoxRD2reTRu3UbtqGj5ISPmNh4fBERakEl1ic6Mj7VQ=; b=J/poo/edfIuckqoE+6k6vnemL4tqbuEcvTyldsBHpYvMvFXykaK06+Pd8PTE1SdUyj 2YDcBRl5IideJC7rULggz+59qAHMMp0rArchIDAxA61WYMYrtlpc2LDj7dz946Wbn9mp hfM4Z9M/+xpU9e5Ptk0batrkR+R/k7QK5pX2v7uiWV/Php+z5kuxTcrIGvlt3hiHzzE1 +OrqZXyfDiAiW866VolQv8YRH6D/D2tHRYT83Tzd33cM/yNOTOkQGOGbSlraGlsZ4m1L 61Tdgdjvqk53HlwfC1Z7syZGGgZR6o7ohqa/81stcr11XOGduAG0SBuNDjZVWVRlI26T kmKw== X-Gm-Message-State: APjAAAWWfqWheLF9IOpXRYlbcPP/mNiXlETl2DkZLdqZUnOubpQw//BY D6g8P/d3/s5OPFpUUNd+RP8= X-Google-Smtp-Source: APXvYqwtkQxzoxWnfxYDSEJu7tBG9jmgGjQzb8U7LiEzTUjCh93ZAES7osPXOwBo4hmJn/Gr18ak4A== X-Received: by 2002:a1c:cc02:: with SMTP id h2mr6323602wmb.13.1559321242531; Fri, 31 May 2019 09:47:22 -0700 (PDT) Received: from localhost.localdomain ([5.102.238.208]) by smtp.gmail.com with ESMTPSA id n5sm7669593wrj.27.2019.05.31.09.47.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 May 2019 09:47:21 -0700 (PDT) From: Amir Goldstein To: "Darrick J . Wong" Cc: Dave Chinner , Christoph Hellwig , linux-xfs@vger.kernel.org, Olga Kornievskaia , Luis Henriques , Al Viro , linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org, ceph-devel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH v4 7/9] xfs: use file_modified() helper Date: Fri, 31 May 2019 19:46:59 +0300 Message-Id: <20190531164701.15112-8-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190531164701.15112-1-amir73il@gmail.com> References: <20190531164701.15112-1-amir73il@gmail.com> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org Note that by using the helper, the order of calling file_remove_privs() after file_update_mtime() in xfs_file_aio_write_checks() has changed. Signed-off-by: Amir Goldstein Reviewed-by: Darrick J. Wong --- fs/xfs/xfs_file.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 76748255f843..916a35cae5e9 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -367,20 +367,7 @@ xfs_file_aio_write_checks( * lock above. Eventually we should look into a way to avoid * the pointless lock roundtrip. */ - if (likely(!(file->f_mode & FMODE_NOCMTIME))) { - error = file_update_time(file); - if (error) - return error; - } - - /* - * If we're writing the file then make sure to clear the setuid and - * setgid bits if the process is not being run by root. This keeps - * people from modifying setuid and setgid binaries. - */ - if (!IS_NOSEC(inode)) - return file_remove_privs(file); - return 0; + return file_modified(file); } static int From patchwork Fri May 31 16:47:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 1108462 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="OYZGopPI"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45Fr3G3R1gz9sMM for ; Sat, 1 Jun 2019 02:47:38 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727140AbfEaQr3 (ORCPT ); Fri, 31 May 2019 12:47:29 -0400 Received: from mail-wm1-f65.google.com ([209.85.128.65]:54371 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727090AbfEaQr2 (ORCPT ); Fri, 31 May 2019 12:47:28 -0400 Received: by mail-wm1-f65.google.com with SMTP id g135so3260969wme.4; Fri, 31 May 2019 09:47:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=13bIynaRm34FrH0n8xWjSPCIT6ibxHwcE1TmN0qrOd4=; b=OYZGopPIgKXTAcfamW8N1HcbscQbjtfz+63cMCIKX2h2G1DIszXrLfICIWzh2juny1 uZAAsTIeqRDO5cyI47QMQI2P9yQqGTC9pbF7wNygnPnzSUBafRcPAYBeDrfkdnef3ppT KX5jT4tlMO/ixe4uDyDaH2hIis9goBtQxlDisU7AAe1kF6usCkkEjGNhuYGysihe3itt 0DHbSnhDCUoSMT4bbYwdAziikMq6aaxoVo1loa7UkrbZotp58JHuByOM99EpJOAC0tHH Q+Z5txKXP5XsrTNMNoLf/aENmh4kTGbpBr4AkCFILCANpb9EuUV3E6MLiGIA7g/V76Wc zLcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=13bIynaRm34FrH0n8xWjSPCIT6ibxHwcE1TmN0qrOd4=; b=tEmZUwULHR6h3XLGzNDRZEwB9KtX5pwVFsnSeAGCUthryrFa7Q7tyEggjekeNSOJin aQ2vu7BIvMaHcT4SSOjLV9KmmrrgIiKIimFQIZ+h471WTsGYbJrKkFiZF45YCFXx/3od FeLIx0V1nuNE+ka1rInfRxVMw+JdsP3gAB9JYvkOLoz4TVQ7r3XB+wc7j+avRzgw02M8 Ov58FQFCWVax+YpbSSfztMb/x9ZyMNzCjnBWijHoQ/vRED/1ts9/4A2RcT2mw7LWpFxg yABUR7bGmVS9mLkbq/qgqWNGtpbI/PLcf1CQttO1jS2GObpOMNhk91og5xMqw2Jp8xMn 6Hzg== X-Gm-Message-State: APjAAAUbwBChWkqSEoNqmUQFHjg4yat5UPSqhV5bVwvTFHgYjNIpoAHa WBVjwTgJZQvXzPRTmhc9ZQC+QTjo X-Google-Smtp-Source: APXvYqykJDJXjVuCo8nV8XzpwynyCeN0fTGZRZ7mBKHGTQX30Y8yEkPChspLKCKQlwAx8f3pDep5pA== X-Received: by 2002:a7b:cc0a:: with SMTP id f10mr1217916wmh.81.1559321244873; Fri, 31 May 2019 09:47:24 -0700 (PDT) Received: from localhost.localdomain ([5.102.238.208]) by smtp.gmail.com with ESMTPSA id n5sm7669593wrj.27.2019.05.31.09.47.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 May 2019 09:47:24 -0700 (PDT) From: Amir Goldstein To: "Darrick J . Wong" Cc: Dave Chinner , Christoph Hellwig , linux-xfs@vger.kernel.org, Olga Kornievskaia , Luis Henriques , Al Viro , linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org, ceph-devel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, Steve French , Dave Chinner Subject: [PATCH v4 8/9] vfs: allow copy_file_range to copy across devices Date: Fri, 31 May 2019 19:47:00 +0300 Message-Id: <20190531164701.15112-9-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190531164701.15112-1-amir73il@gmail.com> References: <20190531164701.15112-1-amir73il@gmail.com> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org 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 and fallack to generic_copy_file_range() for cross-superblock copy. [Amir] We do not call ->remap_file_range() in case the inodes are not on the same sb and do not call ->copy_file_range() in case the inodes are not on the same filesystem type. This changes behavior of the copy_file_range(2) syscall, which will now allow cross filesystem in-kernel copy. CIFS already supports cross-superblock copy, between two shares to the same server. This functionality will now be available via the copy_file_range(2) syscall. Cc: Steve French Signed-off-by: Dave Chinner Signed-off-by: Amir Goldstein Reviewed-by: Darrick J. Wong --- fs/ceph/file.c | 4 +++- fs/cifs/cifsfs.c | 2 +- fs/fuse/file.c | 5 ++++- fs/nfs/nfs4file.c | 5 ++++- fs/read_write.c | 20 ++++++++++++++------ 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index e87f7b2023af..4cd41ed5cc53 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -1909,6 +1909,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; @@ -2109,7 +2111,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 c65823270313..f11eea6125c1 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -1149,7 +1149,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 e03901ae729b..569baf286835 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -3126,6 +3126,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) { @@ -3182,7 +3185,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 4842f3ab3161..f4157eb1f69d 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -133,6 +133,9 @@ 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) { + /* Only offload copy if superblock is the same */ + if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) + return -EXDEV; if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY)) return -EOPNOTSUPP; if (file_inode(file_in) == file_inode(file_out)) @@ -148,7 +151,7 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in, ret = __nfs4_copy_file_range(file_in, pos_in, file_out, pos_out, count, flags); - if (ret == -EOPNOTSUPP) + 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/read_write.c b/fs/read_write.c index cec7e7b1f693..eb3898fb3328 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1599,7 +1599,18 @@ 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) + /* + * Although we now allow filesystems to handle cross sb copy, passing + * an inode of the wrong filesystem type to filesystem operation can + * often result in an attempt to dereference the wrong concrete inode + * struct, so avoid doing that until we really have a good reason. + * The incentive for passing inode from different sb to filesystem is + * NFS cross server copy and for that use case, enforcing same + * filesystem type is acceptable. + */ + if (file_out->f_op->copy_file_range && + file_inode(file_in)->i_sb->s_type == + file_inode(file_out)->i_sb->s_type) return file_out->f_op->copy_file_range(file_in, pos_in, file_out, pos_out, len, flags); @@ -1622,10 +1633,6 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, if (flags != 0) return -EINVAL; - /* this could be relaxed once a method supports cross-fs copies */ - if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) - return -EXDEV; - ret = generic_copy_file_checks(file_in, pos_in, file_out, pos_out, &len, flags); if (unlikely(ret)) @@ -1648,7 +1655,8 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, * Try cloning first, this is supported by more file systems, and * more efficient if both clone and copy are supported (e.g. NFS). */ - if (file_in->f_op->remap_file_range) { + if (file_in->f_op->remap_file_range && + file_inode(file_in)->i_sb == file_inode(file_out)->i_sb) { loff_t cloned; cloned = file_in->f_op->remap_file_range(file_in, pos_in, From patchwork Fri May 31 16:47:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 1108463 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="cdHWOU+n"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45Fr3N00lHz9sB8 for ; Sat, 1 Jun 2019 02:47:43 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727161AbfEaQri (ORCPT ); Fri, 31 May 2019 12:47:38 -0400 Received: from mail-wm1-f66.google.com ([209.85.128.66]:34960 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726791AbfEaQr2 (ORCPT ); Fri, 31 May 2019 12:47:28 -0400 Received: by mail-wm1-f66.google.com with SMTP id c6so3429041wml.0; Fri, 31 May 2019 09:47:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=HRG15X28X6wLonYTWAY6EmVHhxYS6KtDUNRAcBO9y7g=; b=cdHWOU+n5BJ1iIXZj596n6F7J0DaRYo/l9Q9ZkRKB58Hy9KKixfylYue3GMy8EUVeA lVW+aVOAWJkROkcM4kwa7yX4bIaXRZHxJY4qJxXJJY0f2i/N7s1bMruD2G3Te75el3Oz qdm7gLaE50S+GKI61kLrS5r3YZkOQkdRyYiyY9VFw2PYZx/YRMRyI0dNkEds7nCJYfhi 3ZxdnMYYWrXhQixn2ndazZmOo82Q/+x2VC2vE6bw8U9WJRpHfG7Updc1i1VICHYKdNg0 k8UNn5IdUuzpCOwfK0mRDvXEYN+O/TczVc2/DDhtZD6cupGIW6odrFuW9gYqQPcnJ8yi nuAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=HRG15X28X6wLonYTWAY6EmVHhxYS6KtDUNRAcBO9y7g=; b=ZELYVDvzGZVbblLhydMUpBnCWKU/OnyKVK6fPoEtzba+IMDjVxJPcZRgyj6ClsrrlN n6YU+cT13qd+HDkC4JLxUs41Ly/+IWfe3y8atAyhL96uKj1aeSkCcopwsFdIVw4A6Yzx LBOAOKFMBAV+UQu6CtdZK52R7M8C8812IpLE0Qu0/nOQKQjGHGBIDOAaWPrc/NbNmIE3 rVN0sk5qxcRiHE7IyC/UrCeA/n8FFcHcRxdPyoJ43ssJTXVrFa85AvET4uqm1WGdW0Bc NNEpmU6rWN5YoMNi+dS+aYrKnD6lksSaah5i5wqI8/RDB3MX56nf249R2X6mamVEh90y oarA== X-Gm-Message-State: APjAAAWszJLB2LDsRKZ17shzoJnExxNxMp+9MioG3NajZpQishiWMWBU F2s98IS75oEMoJ8FDOh4yjc= X-Google-Smtp-Source: APXvYqwWgIYQ2clqTkQy9eygreKjNGojYUYCr7ZzWiQwEdeft9nzlvN4fuQ1DUcp3eNqfXaqES0nVA== X-Received: by 2002:a1c:f712:: with SMTP id v18mr6653743wmh.143.1559321246752; Fri, 31 May 2019 09:47:26 -0700 (PDT) Received: from localhost.localdomain ([5.102.238.208]) by smtp.gmail.com with ESMTPSA id n5sm7669593wrj.27.2019.05.31.09.47.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 31 May 2019 09:47:26 -0700 (PDT) From: Amir Goldstein To: "Darrick J . Wong" Cc: Dave Chinner , Christoph Hellwig , linux-xfs@vger.kernel.org, Olga Kornievskaia , Luis Henriques , Al Viro , linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org, ceph-devel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org Subject: [PATCH v4 9/9] fuse: copy_file_range needs to strip setuid bits and update timestamps Date: Fri, 31 May 2019 19:47:01 +0300 Message-Id: <20190531164701.15112-10-amir73il@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190531164701.15112-1-amir73il@gmail.com> References: <20190531164701.15112-1-amir73il@gmail.com> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org Like ->write_iter(), we update mtime and strip setuid of dst file before copy and like ->read_iter(), we update atime of src file after copy. Signed-off-by: Amir Goldstein Acked-by: Miklos Szeredi --- fs/fuse/file.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 569baf286835..eab00cd089e8 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -3131,6 +3131,10 @@ static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in, inode_lock(inode_out); + err = file_modified(file_out); + if (err) + goto out; + if (fc->writeback_cache) { err = filemap_write_and_wait_range(inode_out->i_mapping, pos_out, pos_out + len); @@ -3172,6 +3176,7 @@ static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in, clear_bit(FUSE_I_SIZE_UNSTABLE, &fi_out->state); inode_unlock(inode_out); + file_accessed(file_in); return err; }