Received: by 2002:a05:6a10:f3d0:0:0:0:0 with SMTP id a16csp3345731pxv; Sun, 4 Jul 2021 16:09:45 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzJ60BPaUxpBTHG6gbKYlnzSmp0BgTUF7kJoQ2mq4al/Jau7eSpUyaQRDDcP2Zqy3YYyUrb X-Received: by 2002:a05:6e02:66e:: with SMTP id l14mr8424398ilt.211.1625440185246; Sun, 04 Jul 2021 16:09:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1625440185; cv=none; d=google.com; s=arc-20160816; b=NXyR3fFa5eaJ49Wpl6pW1QidRT7j48M6byi2PN+RBlou8HCyRaRkk9yyTMo4balSVz vZtHEY+y6iZ/OhiOJ6CgCoWl2Itk+jLapLfgFOpP32M4dnNMSookrZMlSqHXJNtiwjnq fsvF1nDo2hZJ5OUNWNWA9+2lJ8HKM7v1Hv0QPiXhvuorHXnVZsFsj2b7Y7W43tiLiNnk 9K83FD8XNuhth2QgpXaFYyEIVTs1FcvSYvJPclWywnuuCR2DdiWtBjTi0eOsPMyszB7G Ccer7CpV6a/wgefXvW18P8B9ZFxEqOL9b9Sj0DzMUZ1/KFmRyfThg/sBNp+vhXGx46Yc n+zA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=P4/JTfx1GWEd7nDRzMT4vhgXn8ObhYRvvIa9vT/5cog=; b=Z7T0YtW2wC1j9hrJ9KZF4LaCZzq1aRzdOwYSB1fJUjOJ5qnlGgDFsBPkByB0FObLHM SFXLOdGiCewLlHp8cAUGP8RqseAyjj384nhQHio8yC6qrqI2uaBB8EgX6D0Pi0aF4BHk dcO8ZyspIjOmmuLaQQ40EXcH1yMqM5IkZJrGbZVVR1XDiknUC+8+a9smpJ/ZpKgQ+BKp nhf3vf2xmaNxNaB5AcboWXPLBEFdMP0WuaFYe20jOedsYP3LDz9Xf9W3SbqXgp1uQ9F9 iTT7+6DXE5eUNEcXTt/F6qa9EkV17T8ZTgMw2Wvol3JSk8XLbkWUtCSjU9IjxU7ywOqj xr9g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=u3hPidvl; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id w3si13187532iol.91.2021.07.04.16.09.33; Sun, 04 Jul 2021 16:09:45 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=u3hPidvl; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232420AbhGDXKT (ORCPT + 99 others); Sun, 4 Jul 2021 19:10:19 -0400 Received: from mail.kernel.org ([198.145.29.99]:47420 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231392AbhGDXIj (ORCPT ); Sun, 4 Jul 2021 19:08:39 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id AACBA61364; Sun, 4 Jul 2021 23:06:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1625439963; bh=hF2Or2ggfZNj/iZ/CwzyC43xYr5V3icu8Dg9dnD9xV0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=u3hPidvl97zsUgD2rP3tx42skK1ZtWQbUKckKEYmPiHQKZs2PCdKW3AD4wXoMDaEs fkOVRX1ybd/lrQOXl4kqZjSFq1AllqSZRca/q4QSBk+yWv+FrAgaC4YptC7WtfYR+h 1327Pfhr54T8tEWLeKcgZJCIPT1T0YMcWDQghg0B8rSkSg0DBS5mxHfUkFFPFl7WaK NdnXJAD0VnGeZRqYObySEupF+AwBgSZdkGXqf5H/guW+87/rNrzAs+WYgNjcOpB6uo 0CQV6cXuy/yQit93LE5KOmRfPl1NVTYeCIWM6/jwg7o6psFBObDlueniKVWv1OnGg/ XGuc8GI2pxkwg== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Qu Wenruo , Ritesh Harjani , Anand Jain , David Sterba , Sasha Levin , linux-btrfs@vger.kernel.org Subject: [PATCH AUTOSEL 5.13 76/85] btrfs: fix the filemap_range_has_page() call in btrfs_punch_hole_lock_range() Date: Sun, 4 Jul 2021 19:04:11 -0400 Message-Id: <20210704230420.1488358-76-sashal@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210704230420.1488358-1-sashal@kernel.org> References: <20210704230420.1488358-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Qu Wenruo [ Upstream commit 0528476b6ac7832f31e2ed740a57ae31316b124e ] [BUG] With current subpage RW support, the following script can hang the fs with 64K page size. # mkfs.btrfs -f -s 4k $dev # mount $dev -o nospace_cache $mnt # fsstress -w -n 50 -p 1 -s 1607749395 -d $mnt The kernel will do an infinite loop in btrfs_punch_hole_lock_range(). [CAUSE] In btrfs_punch_hole_lock_range() we: - Truncate page cache range - Lock extent io tree - Wait any ordered extents in the range. We exit the loop until we meet all the following conditions: - No ordered extent in the lock range - No page is in the lock range The latter condition has a pitfall, it only works for sector size == PAGE_SIZE case. While can't handle the following subpage case: 0 32K 64K 96K 128K | |///////||//////| || lockstart=32K lockend=96K - 1 In this case, although the range crosses 2 pages, truncate_pagecache_range() will invalidate no page at all, but only zero the [32K, 96K) range of the two pages. Thus filemap_range_has_page(32K, 96K-1) will always return true, thus we will never meet the loop exit condition. [FIX] Fix the problem by doing page alignment for the lock range. Function filemap_range_has_page() has already handled lend < lstart case, we only need to round up @lockstart, and round_down @lockend for truncate_pagecache_range(). This modification should not change any thing for sector size == PAGE_SIZE case, as in that case our range is already page aligned. Tested-by: Ritesh Harjani # [ppc64] Tested-by: Anand Jain # [aarch64] Signed-off-by: Qu Wenruo Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Sasha Levin --- fs/btrfs/file.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 55f68422061d..7e6ed97a6d08 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -2483,6 +2483,17 @@ static int btrfs_punch_hole_lock_range(struct inode *inode, const u64 lockend, struct extent_state **cached_state) { + /* + * For subpage case, if the range is not at page boundary, we could + * have pages at the leading/tailing part of the range. + * This could lead to dead loop since filemap_range_has_page() + * will always return true. + * So here we need to do extra page alignment for + * filemap_range_has_page(). + */ + const u64 page_lockstart = round_up(lockstart, PAGE_SIZE); + const u64 page_lockend = round_down(lockend + 1, PAGE_SIZE) - 1; + while (1) { struct btrfs_ordered_extent *ordered; int ret; @@ -2503,7 +2514,7 @@ static int btrfs_punch_hole_lock_range(struct inode *inode, (ordered->file_offset + ordered->num_bytes <= lockstart || ordered->file_offset > lockend)) && !filemap_range_has_page(inode->i_mapping, - lockstart, lockend)) { + page_lockstart, page_lockend)) { if (ordered) btrfs_put_ordered_extent(ordered); break; -- 2.30.2