From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.4 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 67AE4C43387 for ; Sat, 5 Jan 2019 17:18:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2BB512085A for ; Sat, 5 Jan 2019 17:18:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1546708694; bh=Aqee/tGqpYICRfIldKtMQwrN8xpZ9Vxov//V8p324FA=; h=Subject:To:Cc:From:Date:List-ID:From; b=QVrpMuqU7iJLlWSgG6t3czivGcUQGjRVhVhGBQPUy/V5zBxWP/MagyO/EGICiF00l bYwDGH0tGG7xX6ZStbNlmJQWseSptswZcRLClxZHsyt8oIkgzxwB5AyaU50IgPq/fy VbmS1oxsrWNKUd5p1H5NGb7HR3tle9aaXATRUJNM= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726296AbfAERSN (ORCPT ); Sat, 5 Jan 2019 12:18:13 -0500 Received: from out1-smtp.messagingengine.com ([66.111.4.25]:44397 "EHLO out1-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726252AbfAERSN (ORCPT ); Sat, 5 Jan 2019 12:18:13 -0500 Received: from compute6.internal (compute6.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 5A08F21CF3; Sat, 5 Jan 2019 12:18:12 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute6.internal (MEProxy); Sat, 05 Jan 2019 12:18:12 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :date:from:message-id:mime-version:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=471Jj8 w8l2cF20oJOpIWv7wNap+p6o7FGF96cQAo2s4=; b=muB6ymMspgExGmp1RYRhAm 0Dg0ymj3oUOQ6SqNJBuqcw4ozkklWFymoYR8PgPVzezR2+0QGR0KW+Kk/Lw9jtP2 Lz4owvvfk5+68zdQesIqJOmobmQM1whKrxUwM9ehROjA18v4ww4OCt3gfWqUtRBl c524fCawQCoBbxO0vK+XpwbS06sQ1c23X2FwPRekfmSoRrOh2mhiSt89UKKqozgT LTbOZ0/nIK1Z/dwmt5UOzAk+D6CpGtqZZxOvU8Iq0JwEa6rufAsHXZNEk2ncqkdy m4xJvGKQwjbcpTVTjc49yBw2BqyWftiuE26ThKaqISo1Z8Igq26q2No6yJHY49Mg == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedtledrvdefgddutdduucdltddurdegtdekrddttd dmucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfquhht necuuegrihhlohhuthemuceftddtnecunecujfgurhepuffvhfffkfggtgfgsehtkeertd dttdflnecuhfhrohhmpeeoghhrvghgkhhhsehlihhnuhigfhhouhhnuggrthhiohhnrdho rhhgqeenucfkphepiedvrdduudelrdduieeirdelnecurfgrrhgrmhepmhgrihhlfhhroh hmpehgrhgvgheskhhrohgrhhdrtghomhenucevlhhushhtvghrufhiiigvpeeh X-ME-Proxy: Received: from localhost (unknown [62.119.166.9]) by mail.messagingengine.com (Postfix) with ESMTPA id 6C177E40A1; Sat, 5 Jan 2019 12:18:04 -0500 (EST) Subject: FAILED: patch "[PATCH] Btrfs: send, fix race with transaction commits that create" failed to apply to 4.14-stable tree To: fdmanana@suse.com, dsterba@suse.com Cc: From: Date: Sat, 05 Jan 2019 18:17:58 +0100 Message-ID: <1546708678172117@kroah.com> MIME-Version: 1.0 Content-Type: text/plain; charset=ANSI_X3.4-1968 Content-Transfer-Encoding: 8bit Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org The patch below does not apply to the 4.14-stable tree. If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to . thanks, greg k-h ------------------ original commit in Linus's tree ------------------ >From be6821f82c3cc36e026f5afd10249988852b35ea Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Tue, 11 Dec 2018 10:19:45 +0000 Subject: [PATCH] Btrfs: send, fix race with transaction commits that create snapshots If we create a snapshot of a snapshot currently being used by a send operation, we can end up with send failing unexpectedly (returning -ENOENT error to user space for example). The following diagram shows how this happens. CPU 1 CPU2 CPU3 btrfs_ioctl_send() (...) create_snapshot() -> creates snapshot of a root used by the send task btrfs_commit_transaction() create_pending_snapshot() __get_inode_info() btrfs_search_slot() btrfs_search_slot_get_root() down_read commit_root_sem get reference on eb of the commit root -> eb with bytenr == X up_read commit_root_sem btrfs_cow_block(root node) btrfs_free_tree_block() -> creates delayed ref to free the extent btrfs_run_delayed_refs() -> runs the delayed ref, adds extent to fs_info->pinned_extents btrfs_finish_extent_commit() unpin_extent_range() -> marks extent as free in the free space cache transaction commit finishes btrfs_start_transaction() (...) btrfs_cow_block() btrfs_alloc_tree_block() btrfs_reserve_extent() -> allocates extent at bytenr == X btrfs_init_new_buffer(bytenr X) btrfs_find_create_tree_block() alloc_extent_buffer(bytenr X) find_extent_buffer(bytenr X) -> returns existing eb, which the send task got (...) -> modifies content of the eb with bytenr == X -> uses an eb that now belongs to some other tree and no more matches the commit root of the snapshot, resuts will be unpredictable The consequences of this race can be various, and can lead to searches in the commit root performed by the send task failing unexpectedly (unable to find inode items, returning -ENOENT to user space, for example) or not failing because an inode item with the same number was added to the tree that reused the metadata extent, in which case send can behave incorrectly in the worst case or just fail later for some reason. Fix this by performing a copy of the commit root's extent buffer when doing a search in the context of a send operation. CC: stable@vger.kernel.org # 4.4.x: 1fc28d8e2e9: Btrfs: move get root out of btrfs_search_slot to a helper CC: stable@vger.kernel.org # 4.4.x: f9ddfd0592a: Btrfs: remove unused check of skip_locking CC: stable@vger.kernel.org # 4.4.x Signed-off-by: Filipe Manana Signed-off-by: David Sterba diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 72745235896f..4252e89df6ae 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -2587,14 +2587,27 @@ static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root, root_lock = BTRFS_READ_LOCK; if (p->search_commit_root) { - /* The commit roots are read only so we always do read locks */ - if (p->need_commit_sem) + /* + * The commit roots are read only so we always do read locks, + * and we always must hold the commit_root_sem when doing + * searches on them, the only exception is send where we don't + * want to block transaction commits for a long time, so + * we need to clone the commit root in order to avoid races + * with transaction commits that create a snapshot of one of + * the roots used by a send operation. + */ + if (p->need_commit_sem) { down_read(&fs_info->commit_root_sem); - b = root->commit_root; - extent_buffer_get(b); - level = btrfs_header_level(b); - if (p->need_commit_sem) + b = btrfs_clone_extent_buffer(root->commit_root); up_read(&fs_info->commit_root_sem); + if (!b) + return ERR_PTR(-ENOMEM); + + } else { + b = root->commit_root; + extent_buffer_get(b); + } + level = btrfs_header_level(b); /* * Ensure that all callers have set skip_locking when * p->search_commit_root = 1. @@ -2720,6 +2733,10 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root, again: prev_cmp = -1; b = btrfs_search_slot_get_root(root, p, write_lock_level); + if (IS_ERR(b)) { + ret = PTR_ERR(b); + goto done; + } while (b) { level = btrfs_header_level(b);