From patchwork Thu Mar 27 02:51:58 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 3896121 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id B1A40BF540 for ; Thu, 27 Mar 2014 02:52:15 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C35C620221 for ; Thu, 27 Mar 2014 02:52:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A33E3201BA for ; Thu, 27 Mar 2014 02:52:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753169AbaC0CwF (ORCPT ); Wed, 26 Mar 2014 22:52:05 -0400 Received: from cn.fujitsu.com ([59.151.112.132]:49453 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1752098AbaC0CwE convert rfc822-to-8bit (ORCPT ); Wed, 26 Mar 2014 22:52:04 -0400 X-IronPort-AV: E=Sophos;i="4.97,739,1389715200"; d="scan'208";a="28519146" Received: from unknown (HELO edo.cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 27 Mar 2014 10:49:37 +0800 Received: from G08CNEXCHPEKD02.g08.fujitsu.local (localhost.localdomain [127.0.0.1]) by edo.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id s2R2px81008047 for ; Thu, 27 Mar 2014 10:51:59 +0800 Received: from G08CNEXMBPEKD02.g08.fujitsu.local ([10.167.33.84]) by G08CNEXCHPEKD02.g08.fujitsu.local ([10.167.33.83]) with mapi id 14.03.0146.002; Thu, 27 Mar 2014 10:51:59 +0800 From: "quwenruo@cn.fujitsu.com" To: "linux-btrfs@vger.kernel.org" Subject: [PATCH] btrfs: Change the expanding write sequence to fix snapshot related bug. Thread-Topic: [PATCH] btrfs: Change the expanding write sequence to fix snapshot related bug. Thread-Index: AQHPSWeFmb0zscYhb0WjKPwJP9e1Dg== Date: Thu, 27 Mar 2014 02:51:58 +0000 Message-ID: <1395888786-11736-1-git-send-email-quwenruo@cn.fujitsu.com> Accept-Language: ja-JP, zh-CN, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.167.226.24] MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Spam-Status: No, score=-7.3 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When testing fsstress with snapshot making background, some snapshot following problem. Snapshot 270: inode 323: size 0 Snapshot 271: inode 323: size 349145 |-------Hole---|---------Empty gap-------|-------Hole-----| 0 122880 172032 349145 Snapshot 272: inode 323: size 349145 |-------Hole---|------------Data---------|-------Hole-----| 0 122880 172032 349145 The fsstress operation on inode 323 is the following: write: offset 126832 len 43124 truncate: size 349145 Since the write with offset is consist of 2 operations: 1. punch hole 2. write data Hole punching is faster than data write, so hole punching in write and truncate is done first and then buffered write, so the snapshot 271 got empty gap, which will not pass btrfsck. To fix the bug, this patch will change the write sequence which will first punch a hole covering the write end if a hole is needed. Reported-by: Gui Hecheng Signed-off-by: Qu Wenruo --- fs/btrfs/file.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index b2143b8..f53f592 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1718,6 +1718,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, struct btrfs_root *root = BTRFS_I(inode)->root; loff_t *ppos = &iocb->ki_pos; u64 start_pos; + u64 end_pos; ssize_t num_written = 0; ssize_t err = 0; size_t count, ocount; @@ -1772,7 +1773,9 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, start_pos = round_down(pos, root->sectorsize); if (start_pos > i_size_read(inode)) { - err = btrfs_cont_expand(inode, i_size_read(inode), start_pos); + /* Expand hole size to cover write data, preventing empty gap */ + end_pos = round_up(pos + iov->iov_len, root->sectorsize); + err = btrfs_cont_expand(inode, i_size_read(inode), end_pos); if (err) { mutex_unlock(&inode->i_mutex); goto out;