From patchwork Mon Mar 6 20:23:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liu Bo X-Patchwork-Id: 9607747 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 F139D6046A for ; Mon, 6 Mar 2017 22:18:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 40A5728477 for ; Mon, 6 Mar 2017 22:18:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 341DD2847B; Mon, 6 Mar 2017 22:18: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=-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 C3DAF28477 for ; Mon, 6 Mar 2017 22:18:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754005AbdCFWSd (ORCPT ); Mon, 6 Mar 2017 17:18:33 -0500 Received: from userp1050.oracle.com ([156.151.31.82]:20484 "EHLO userp1050.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752950AbdCFWSb (ORCPT ); Mon, 6 Mar 2017 17:18:31 -0500 Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by userp1050.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id v26KPh4S010659 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 6 Mar 2017 20:25:44 GMT Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id v26KOZOG009755 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 6 Mar 2017 20:24:35 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.14.4) with ESMTP id v26KOYCv008829 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 6 Mar 2017 20:24:35 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id v26KOWwD001106; Mon, 6 Mar 2017 20:24:33 GMT Received: from localhost.us.oracle.com (/10.211.47.181) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 06 Mar 2017 12:24:32 -0800 From: Liu Bo To: linux-btrfs@vger.kernel.org Cc: David Sterba , Qu Wenruo Subject: [PATCH v2] Btrfs: fix unexpected file hole after disk errors Date: Mon, 6 Mar 2017 12:23:30 -0800 Message-Id: <1488831810-26684-1-git-send-email-bo.li.liu@oracle.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1488330280-22678-1-git-send-email-bo.li.liu@oracle.com> References: <1488330280-22678-1-git-send-email-bo.li.liu@oracle.com> X-Source-IP: userp1040.oracle.com [156.151.31.81] Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Btrfs creates hole extents to cover any unwritten section right before doing buffer writes after commit 3ac0d7b96a26 ("btrfs: Change the expanding write sequence to fix snapshot related bug."). However, that takes the start position of the buffered write to compare against the current EOF, hole extents would be created only if (EOF < start). If the EOF is at the middle of the buffered write, no hole extents will be created and a file hole without a hole extent is left in this file. This bug was revealed by generic/019 in fstests. 'fsstress' in this test may create the above situation and the test then fails all requests including writes, so the buffer write which is supposed to cover the hole (without the hole extent) couldn't make it on disk. Running fsck against such btrfs ends up with detecting file extent holes. Things could be more serious, some stale data would be exposed to userspace if files with this kind of hole are truncated to a position of the hole, because the on-disk inode size is beyond the last extent in the file. This fixes the bug by comparing the end position against the EOF. Cc: David Sterba Cc: Qu Wenruo Signed-off-by: Liu Bo Reviewed-by: Qu Wenruo --- v2: update comments to be precise. fs/btrfs/file.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 520cb72..dcf0286 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1865,11 +1865,13 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb, pos = iocb->ki_pos; count = iov_iter_count(from); start_pos = round_down(pos, fs_info->sectorsize); + end_pos = round_up(pos + count, fs_info->sectorsize); oldsize = i_size_read(inode); - if (start_pos > oldsize) { - /* Expand hole size to cover write data, preventing empty gap */ - end_pos = round_up(pos + count, - fs_info->sectorsize); + if (end_pos > oldsize) { + /* + * Expand hole size to cover write data in order to prevent an + * empty gap in case of a write failure. + */ err = btrfs_cont_expand(inode, oldsize, end_pos); if (err) { inode_unlock(inode);