From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6C08917C7CA; Sun, 26 Jan 2025 14:48:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737902930; cv=none; b=RUCOlPMY3DyM8TMRh0VAUFNo8SvwYGoGASukQppMuohv/cyuhUbZSd4b9/cYWTRh9Kco6y63Pc4bzMbzETKFz7WHJ3DSP1JAPVlSPZ00/MuvOOjSKLC0+GpgPgVw8Hrt3k0T6wPTv70QKJmLi2Eylq3mR3hkMbv3IY6UJQP1VQU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737902930; c=relaxed/simple; bh=MU9+PXemyyAWBnXcqmyyUTuV4lQc8bZQ0e89J3SOaps=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=VZxMPaG+AUIldL3ZqVgGLmrrBKFa98XUeNQEWIAFyDkcdS7d5cuEa3V+TW7nms5ULKKH273s2FOF974JrCEcDUYO139jxA21r064bBYVhhXMmd72ptm4GHmx8AhvH5V8vB01gLwyZI3HCwoOasaWKqPWIRTf8HnHTbZJKbkC1R0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FsUEOzZJ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FsUEOzZJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E5278C4CEE2; Sun, 26 Jan 2025 14:48:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1737902929; bh=MU9+PXemyyAWBnXcqmyyUTuV4lQc8bZQ0e89J3SOaps=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FsUEOzZJjG0bUck86oNpe3XtvFtgZ+CyTFrRD/TFQoudd2VyKll4qFf3H5ir5w9t7 aTcTZi9BKjt6AaFeqba2PIEW5rX/70eQkjk/MAAdaEZbgh9FSItJyALQlLLEGyLKip qSBZksynZyzZv9oFT9v4hXoq3agbYHBzhMNoKMJHegNPQTQ1wkeJwhwzfg13gF32QE h3s947G4sWtK/aJlw7MdyJMhoLVg1Jr706R4vvy3r46z94uR43Lo5JA9GRFUkf8deo +JL0JA+Gr4DLoMiD9+PJLjytS7jRbBD0AAi82No/jKQBS9iBQAANkQEdC9kbOdek6i kB5V5trMkLP8A== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Hao-ran Zheng , Filipe Manana , David Sterba , Sasha Levin , clm@fb.com, josef@toxicpanda.com, linux-btrfs@vger.kernel.org Subject: [PATCH AUTOSEL 6.13 5/7] btrfs: fix data race when accessing the inode's disk_i_size at btrfs_drop_extents() Date: Sun, 26 Jan 2025 09:48:36 -0500 Message-Id: <20250126144839.925271-5-sashal@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250126144839.925271-1-sashal@kernel.org> References: <20250126144839.925271-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 6.13 Content-Transfer-Encoding: 8bit From: Hao-ran Zheng [ Upstream commit 5324c4e10e9c2ce307a037e904c0d9671d7137d9 ] A data race occurs when the function `insert_ordered_extent_file_extent()` and the function `btrfs_inode_safe_disk_i_size_write()` are executed concurrently. The function `insert_ordered_extent_file_extent()` is not locked when reading inode->disk_i_size, causing `btrfs_inode_safe_disk_i_size_write()` to cause data competition when writing inode->disk_i_size, thus affecting the value of `modify_tree`. The specific call stack that appears during testing is as follows: ============DATA_RACE============ btrfs_drop_extents+0x89a/0xa060 [btrfs] insert_reserved_file_extent+0xb54/0x2960 [btrfs] insert_ordered_extent_file_extent+0xff5/0x1760 [btrfs] btrfs_finish_one_ordered+0x1b85/0x36a0 [btrfs] btrfs_finish_ordered_io+0x37/0x60 [btrfs] finish_ordered_fn+0x3e/0x50 [btrfs] btrfs_work_helper+0x9c9/0x27a0 [btrfs] process_scheduled_works+0x716/0xf10 worker_thread+0xb6a/0x1190 kthread+0x292/0x330 ret_from_fork+0x4d/0x80 ret_from_fork_asm+0x1a/0x30 ============OTHER_INFO============ btrfs_inode_safe_disk_i_size_write+0x4ec/0x600 [btrfs] btrfs_finish_one_ordered+0x24c7/0x36a0 [btrfs] btrfs_finish_ordered_io+0x37/0x60 [btrfs] finish_ordered_fn+0x3e/0x50 [btrfs] btrfs_work_helper+0x9c9/0x27a0 [btrfs] process_scheduled_works+0x716/0xf10 worker_thread+0xb6a/0x1190 kthread+0x292/0x330 ret_from_fork+0x4d/0x80 ret_from_fork_asm+0x1a/0x30 ================================= The main purpose of the check of the inode's disk_i_size is to avoid taking write locks on a btree path when we have a write at or beyond EOF, since in these cases we don't expect to find extent items in the root to drop. However if we end up taking write locks due to a data race on disk_i_size, everything is still correct, we only add extra lock contention on the tree in case there's concurrency from other tasks. If the race causes us to not take write locks when we actually need them, then everything is functionally correct as well, since if we find out we have extent items to drop and we took read locks (modify_tree set to 0), we release the path and retry again with write locks. Since this data race does not affect the correctness of the function, it is a harmless data race, use data_race() to check inode->disk_i_size. Reviewed-by: Filipe Manana Signed-off-by: Hao-ran Zheng Signed-off-by: Filipe Manana Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Sasha Levin --- fs/btrfs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 14e27473c5bce..4d7c7a296d2d1 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -224,7 +224,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, if (args->drop_cache) btrfs_drop_extent_map_range(inode, args->start, args->end - 1, false); - if (args->start >= inode->disk_i_size && !args->replace_extent) + if (data_race(args->start >= inode->disk_i_size) && !args->replace_extent) modify_tree = 0; update_refs = (btrfs_root_id(root) != BTRFS_TREE_LOG_OBJECTID); -- 2.39.5