From patchwork Thu Aug 25 23:37:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 9300323 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E4D68607F0 for ; Thu, 25 Aug 2016 23:38:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D45512940E for ; Thu, 25 Aug 2016 23:38:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C77AC29416; Thu, 25 Aug 2016 23:38:12 +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=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from oss.sgi.com (oss.sgi.com [192.48.182.195]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3A3B42940E for ; Thu, 25 Aug 2016 23:38:12 +0000 (UTC) Received: from oss.sgi.com (localhost [IPv6:::1]) by oss.sgi.com (Postfix) with ESMTP id 7DCE37E38; Thu, 25 Aug 2016 18:37:38 -0500 (CDT) X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id CC5317E38 for ; Thu, 25 Aug 2016 18:37:36 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 9D9AF8F8033 for ; Thu, 25 Aug 2016 16:37:36 -0700 (PDT) X-ASG-Debug-ID: 1472168254-0bf57b5312209470001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id NZBuo3Yfxevj2Hl6 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 25 Aug 2016 16:37:34 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u7PNbWQr014544 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 25 Aug 2016 23:37:33 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u7PNbWCc009754 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 25 Aug 2016 23:37:32 GMT Received: from abhmp0016.oracle.com (abhmp0016.oracle.com [141.146.116.22]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u7PNbVkF028936; Thu, 25 Aug 2016 23:37:32 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 25 Aug 2016 16:37:31 -0700 Subject: [PATCH 51/71] xfs: CoW shared EOF block when truncating file From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 51/71] xfs: CoW shared EOF block when truncating file To: david@fromorbit.com, darrick.wong@oracle.com Date: Thu, 25 Aug 2016 16:37:30 -0700 Message-ID: <147216825024.867.15854938687374361206.stgit@birch.djwong.org> In-Reply-To: <147216791538.867.12413509832420924168.stgit@birch.djwong.org> References: <147216791538.867.12413509832420924168.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1472168254 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3144 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.32328 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Cc: linux-xfs@vger.kernel.org, xfs@oss.sgi.com X-BeenThere: xfs@oss.sgi.com X-Mailman-Version: 2.1.14 Precedence: list List-Id: XFS Filesystem from SGI List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: xfs-bounces@oss.sgi.com Sender: xfs-bounces@oss.sgi.com X-Virus-Scanned: ClamAV using ClamSMTP When shrinking a file, the VFS zeroes everything in the associated page between the new EOF and the previous EOF to avoid leaking data. If this block is shared we need to CoW it before the VFS does its zeroing to avoid corrupting the other files. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_iops.c | 9 +++++++++ fs/xfs/xfs_reflink.c | 42 ++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_reflink.h | 1 + 3 files changed, 52 insertions(+) diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index b24c310..dc3f5ba5 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -39,6 +39,7 @@ #include "xfs_trans_space.h" #include "xfs_pnfs.h" #include "xfs_iomap.h" +#include "xfs_reflink.h" #include #include @@ -827,6 +828,14 @@ xfs_setattr_size( return error; /* + * CoW the EOF block of the file if it's necessary to avoid + * corrupting other files. + */ + error = xfs_reflink_cow_eof_block(ip, newsize); + if (error) + return error; + + /* * We are going to log the inode size change in this transaction so * any previous writes that are beyond the on disk EOF and the new * EOF that have not been written out need to be written here. If we diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index d717e80..c0034c1 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -1701,3 +1701,45 @@ out: trace_xfs_reflink_unshare_error(ip, error, _RET_IP_); return error; } + +/* + * If we're trying to truncate a file whose last block is shared and the new + * size isn't aligned to a block boundary, we need to dirty that last block + * ahead of the VFS zeroing the page. + */ +int +xfs_reflink_cow_eof_block( + struct xfs_inode *ip, + xfs_off_t newsize) +{ + struct xfs_mount *mp = ip->i_mount; + xfs_fileoff_t fbno; + xfs_off_t isize; + int error; + + if (!xfs_is_reflink_inode(ip) || + (newsize & ((1 << VFS_I(ip)->i_blkbits) - 1)) == 0) + return 0; + + /* Try to CoW the shared last block */ + xfs_ilock(ip, XFS_ILOCK_EXCL); + fbno = XFS_B_TO_FSBT(mp, newsize); + isize = i_size_read(VFS_I(ip)); + + if (newsize > isize) + trace_xfs_reflink_cow_eof_block(ip, isize, newsize - isize); + else + trace_xfs_reflink_cow_eof_block(ip, newsize, isize - newsize); + + error = xfs_reflink_dirty_extents(ip, fbno, fbno + 1, isize); + if (error) + goto out_unlock; + xfs_iunlock(ip, XFS_ILOCK_EXCL); + + return 0; + +out_unlock: + xfs_iunlock(ip, XFS_ILOCK_EXCL); + trace_xfs_reflink_cow_eof_block_error(ip, error, _RET_IP_); + return error; +} diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index 906c74d..89fe0e3 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -51,5 +51,6 @@ extern int xfs_reflink_remap_range(struct xfs_inode *src, xfs_off_t srcoff, unsigned int flags); extern int xfs_reflink_unshare(struct xfs_inode *ip, xfs_off_t offset, xfs_off_t len); +extern int xfs_reflink_cow_eof_block(struct xfs_inode *ip, xfs_off_t newsize); #endif /* __XFS_REFLINK_H */