]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.4.181/btrfs-do-not-start-a-transaction-at-iterate_extent_inodes.patch
Linux 4.4.181
[thirdparty/kernel/stable-queue.git] / releases / 4.4.181 / btrfs-do-not-start-a-transaction-at-iterate_extent_inodes.patch
1 From bfc61c36260ca990937539cd648ede3cd749bc10 Mon Sep 17 00:00:00 2001
2 From: Filipe Manana <fdmanana@suse.com>
3 Date: Wed, 17 Apr 2019 11:30:30 +0100
4 Subject: Btrfs: do not start a transaction at iterate_extent_inodes()
5
6 From: Filipe Manana <fdmanana@suse.com>
7
8 commit bfc61c36260ca990937539cd648ede3cd749bc10 upstream.
9
10 When finding out which inodes have references on a particular extent, done
11 by backref.c:iterate_extent_inodes(), from the BTRFS_IOC_LOGICAL_INO (both
12 v1 and v2) ioctl and from scrub we use the transaction join API to grab a
13 reference on the currently running transaction, since in order to give
14 accurate results we need to inspect the delayed references of the currently
15 running transaction.
16
17 However, if there is currently no running transaction, the join operation
18 will create a new transaction. This is inefficient as the transaction will
19 eventually be committed, doing unnecessary IO and introducing a potential
20 point of failure that will lead to a transaction abort due to -ENOSPC, as
21 recently reported [1].
22
23 That's because the join, creates the transaction but does not reserve any
24 space, so when attempting to update the root item of the root passed to
25 btrfs_join_transaction(), during the transaction commit, we can end up
26 failling with -ENOSPC. Users of a join operation are supposed to actually
27 do some filesystem changes and reserve space by some means, which is not
28 the case of iterate_extent_inodes(), it is a read-only operation for all
29 contextes from which it is called.
30
31 The reported [1] -ENOSPC failure stack trace is the following:
32
33 heisenberg kernel: ------------[ cut here ]------------
34 heisenberg kernel: BTRFS: Transaction aborted (error -28)
35 heisenberg kernel: WARNING: CPU: 0 PID: 7137 at fs/btrfs/root-tree.c:136 btrfs_update_root+0x22b/0x320 [btrfs]
36 (...)
37 heisenberg kernel: CPU: 0 PID: 7137 Comm: btrfs-transacti Not tainted 4.19.0-4-amd64 #1 Debian 4.19.28-2
38 heisenberg kernel: Hardware name: FUJITSU LIFEBOOK U757/FJNB2A5, BIOS Version 1.21 03/19/2018
39 heisenberg kernel: RIP: 0010:btrfs_update_root+0x22b/0x320 [btrfs]
40 (...)
41 heisenberg kernel: RSP: 0018:ffffb5448828bd40 EFLAGS: 00010286
42 heisenberg kernel: RAX: 0000000000000000 RBX: ffff8ed56bccef50 RCX: 0000000000000006
43 heisenberg kernel: RDX: 0000000000000007 RSI: 0000000000000092 RDI: ffff8ed6bda166a0
44 heisenberg kernel: RBP: 00000000ffffffe4 R08: 00000000000003df R09: 0000000000000007
45 heisenberg kernel: R10: 0000000000000000 R11: 0000000000000001 R12: ffff8ed63396a078
46 heisenberg kernel: R13: ffff8ed092d7c800 R14: ffff8ed64f5db028 R15: ffff8ed6bd03d068
47 heisenberg kernel: FS: 0000000000000000(0000) GS:ffff8ed6bda00000(0000) knlGS:0000000000000000
48 heisenberg kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
49 heisenberg kernel: CR2: 00007f46f75f8000 CR3: 0000000310a0a002 CR4: 00000000003606f0
50 heisenberg kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
51 heisenberg kernel: DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
52 heisenberg kernel: Call Trace:
53 heisenberg kernel: commit_fs_roots+0x166/0x1d0 [btrfs]
54 heisenberg kernel: ? _cond_resched+0x15/0x30
55 heisenberg kernel: ? btrfs_run_delayed_refs+0xac/0x180 [btrfs]
56 heisenberg kernel: btrfs_commit_transaction+0x2bd/0x870 [btrfs]
57 heisenberg kernel: ? start_transaction+0x9d/0x3f0 [btrfs]
58 heisenberg kernel: transaction_kthread+0x147/0x180 [btrfs]
59 heisenberg kernel: ? btrfs_cleanup_transaction+0x530/0x530 [btrfs]
60 heisenberg kernel: kthread+0x112/0x130
61 heisenberg kernel: ? kthread_bind+0x30/0x30
62 heisenberg kernel: ret_from_fork+0x35/0x40
63 heisenberg kernel: ---[ end trace 05de912e30e012d9 ]---
64
65 So fix that by using the attach API, which does not create a transaction
66 when there is currently no running transaction.
67
68 [1] https://lore.kernel.org/linux-btrfs/b2a668d7124f1d3e410367f587926f622b3f03a4.camel@scientia.net/
69
70 Reported-by: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>
71 CC: stable@vger.kernel.org # 4.4+
72 Signed-off-by: Filipe Manana <fdmanana@suse.com>
73 Reviewed-by: David Sterba <dsterba@suse.com>
74 Signed-off-by: David Sterba <dsterba@suse.com>
75 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
76
77 ---
78 fs/btrfs/backref.c | 18 ++++++++++++------
79 1 file changed, 12 insertions(+), 6 deletions(-)
80
81 --- a/fs/btrfs/backref.c
82 +++ b/fs/btrfs/backref.c
83 @@ -1685,13 +1685,19 @@ int iterate_extent_inodes(struct btrfs_f
84 extent_item_objectid);
85
86 if (!search_commit_root) {
87 - trans = btrfs_join_transaction(fs_info->extent_root);
88 - if (IS_ERR(trans))
89 - return PTR_ERR(trans);
90 + trans = btrfs_attach_transaction(fs_info->extent_root);
91 + if (IS_ERR(trans)) {
92 + if (PTR_ERR(trans) != -ENOENT &&
93 + PTR_ERR(trans) != -EROFS)
94 + return PTR_ERR(trans);
95 + trans = NULL;
96 + }
97 + }
98 +
99 + if (trans)
100 btrfs_get_tree_mod_seq(fs_info, &tree_mod_seq_elem);
101 - } else {
102 + else
103 down_read(&fs_info->commit_root_sem);
104 - }
105
106 ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid,
107 tree_mod_seq_elem.seq, &refs,
108 @@ -1721,7 +1727,7 @@ int iterate_extent_inodes(struct btrfs_f
109
110 free_leaf_list(refs);
111 out:
112 - if (!search_commit_root) {
113 + if (trans) {
114 btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem);
115 btrfs_end_transaction(trans, fs_info->extent_root);
116 } else {