From patchwork Fri Jun 17 01:28:04 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: 9182217 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 4BC876075D for ; Fri, 17 Jun 2016 01:28:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3DB4727C2C for ; Fri, 17 Jun 2016 01:28:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3291A283A1; Fri, 17 Jun 2016 01:28:16 +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=-6.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY 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 B7D7427C2C for ; Fri, 17 Jun 2016 01:28:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755147AbcFQB2O (ORCPT ); Thu, 16 Jun 2016 21:28:14 -0400 Received: from userp1040.oracle.com ([156.151.31.81]:30344 "EHLO userp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754906AbcFQB2N (ORCPT ); Thu, 16 Jun 2016 21:28:13 -0400 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1S6eI011748 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:06 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1S6hD021004 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:06 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1S6hD029653; Fri, 17 Jun 2016 01:28:06 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:28:05 -0700 Subject: [PATCH 095/119] xfs: CoW shared EOF block when truncating file From: "Darrick J. Wong" To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:28:04 -0700 Message-ID: <146612688440.12839.3166686602599403800.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.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] Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org 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(+) -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index e57bfe8..0fa86bd 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -38,6 +38,7 @@ #include "xfs_dir2.h" #include "xfs_trans_space.h" #include "xfs_pnfs.h" +#include "xfs_reflink.h" #include #include @@ -816,6 +817,14 @@ xfs_setattr_size( } /* + * 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 78f24c3..b42ffb0 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -1740,3 +1740,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 a369b2a..437087c5 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -50,6 +50,7 @@ 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); /* xfs_aops.c */ extern int xfs_map_cow_blocks(struct inode *inode, xfs_off_t offset,