From: Ben Hutchings <ben@decadent.org.uk>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: akpm@linux-foundation.org, "Filipe Manana" <fdmanana@suse.com>
Subject: [PATCH 3.2 34/52] Btrfs: fix race leading to incorrect item deletion when dropping extents
Date: Tue, 24 Nov 2015 22:33:59 +0000 [thread overview]
Message-ID: <lsq.1448404439.577609638@decadent.org.uk> (raw)
In-Reply-To: <lsq.1448404438.351251660@decadent.org.uk>
3.2.74-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <fdmanana@suse.com>
commit aeafbf8486c9e2bd53f5cc3c10c0b7fd7149d69c upstream.
While running a stress test I got the following warning triggered:
[191627.672810] ------------[ cut here ]------------
[191627.673949] WARNING: CPU: 8 PID: 8447 at fs/btrfs/file.c:779 __btrfs_drop_extents+0x391/0xa50 [btrfs]()
(...)
[191627.701485] Call Trace:
[191627.702037] [<ffffffff8145f077>] dump_stack+0x4f/0x7b
[191627.702992] [<ffffffff81095de5>] ? console_unlock+0x356/0x3a2
[191627.704091] [<ffffffff8104b3b0>] warn_slowpath_common+0xa1/0xbb
[191627.705380] [<ffffffffa0664499>] ? __btrfs_drop_extents+0x391/0xa50 [btrfs]
[191627.706637] [<ffffffff8104b46d>] warn_slowpath_null+0x1a/0x1c
[191627.707789] [<ffffffffa0664499>] __btrfs_drop_extents+0x391/0xa50 [btrfs]
[191627.709155] [<ffffffff8115663c>] ? cache_alloc_debugcheck_after.isra.32+0x171/0x1d0
[191627.712444] [<ffffffff81155007>] ? kmemleak_alloc_recursive.constprop.40+0x16/0x18
[191627.714162] [<ffffffffa06570c9>] insert_reserved_file_extent.constprop.40+0x83/0x24e [btrfs]
[191627.715887] [<ffffffffa065422b>] ? start_transaction+0x3bb/0x610 [btrfs]
[191627.717287] [<ffffffffa065b604>] btrfs_finish_ordered_io+0x273/0x4e2 [btrfs]
[191627.728865] [<ffffffffa065b888>] finish_ordered_fn+0x15/0x17 [btrfs]
[191627.730045] [<ffffffffa067d688>] normal_work_helper+0x14c/0x32c [btrfs]
[191627.731256] [<ffffffffa067d96a>] btrfs_endio_write_helper+0x12/0x14 [btrfs]
[191627.732661] [<ffffffff81061119>] process_one_work+0x24c/0x4ae
[191627.733822] [<ffffffff810615b0>] worker_thread+0x206/0x2c2
[191627.734857] [<ffffffff810613aa>] ? process_scheduled_works+0x2f/0x2f
[191627.736052] [<ffffffff810613aa>] ? process_scheduled_works+0x2f/0x2f
[191627.737349] [<ffffffff810669a6>] kthread+0xef/0xf7
[191627.738267] [<ffffffff810f3b3a>] ? time_hardirqs_on+0x15/0x28
[191627.739330] [<ffffffff810668b7>] ? __kthread_parkme+0xad/0xad
[191627.741976] [<ffffffff81465592>] ret_from_fork+0x42/0x70
[191627.743080] [<ffffffff810668b7>] ? __kthread_parkme+0xad/0xad
[191627.744206] ---[ end trace bbfddacb7aaada8d ]---
$ cat -n fs/btrfs/file.c
691 int __btrfs_drop_extents(struct btrfs_trans_handle *trans,
(...)
758 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
759 if (key.objectid > ino ||
760 key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end)
761 break;
762
763 fi = btrfs_item_ptr(leaf, path->slots[0],
764 struct btrfs_file_extent_item);
765 extent_type = btrfs_file_extent_type(leaf, fi);
766
767 if (extent_type == BTRFS_FILE_EXTENT_REG ||
768 extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
(...)
774 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
(...)
778 } else {
779 WARN_ON(1);
780 extent_end = search_start;
781 }
(...)
This happened because the item we were processing did not match a file
extent item (its key type != BTRFS_EXTENT_DATA_KEY), and even on this
case we cast the item to a struct btrfs_file_extent_item pointer and
then find a type field value that does not match any of the expected
values (BTRFS_FILE_EXTENT_[REG|PREALLOC|INLINE]). This scenario happens
due to a tiny time window where a race can happen as exemplified below.
For example, consider the following scenario where we're using the
NO_HOLES feature and we have the following two neighbour leafs:
Leaf X (has N items) Leaf Y
[ ... (257 INODE_ITEM 0) (257 INODE_REF 256) ] [ (257 EXTENT_DATA 8192), ... ]
slot N - 2 slot N - 1 slot 0
Our inode 257 has an implicit hole in the range [0, 8K[ (implicit rather
than explicit because NO_HOLES is enabled). Now if our inode has an
ordered extent for the range [4K, 8K[ that is finishing, the following
can happen:
CPU 1 CPU 2
btrfs_finish_ordered_io()
insert_reserved_file_extent()
__btrfs_drop_extents()
Searches for the key
(257 EXTENT_DATA 4096) through
btrfs_lookup_file_extent()
Key not found and we get a path where
path->nodes[0] == leaf X and
path->slots[0] == N
Because path->slots[0] is >=
btrfs_header_nritems(leaf X), we call
btrfs_next_leaf()
btrfs_next_leaf() releases the path
inserts key
(257 INODE_REF 4096)
at the end of leaf X,
leaf X now has N + 1 keys,
and the new key is at
slot N
btrfs_next_leaf() searches for
key (257 INODE_REF 256), with
path->keep_locks set to 1,
because it was the last key it
saw in leaf X
finds it in leaf X again and
notices it's no longer the last
key of the leaf, so it returns 0
with path->nodes[0] == leaf X and
path->slots[0] == N (which is now
< btrfs_header_nritems(leaf X)),
pointing to the new key
(257 INODE_REF 4096)
__btrfs_drop_extents() casts the
item at path->nodes[0], slot
path->slots[0], to a struct
btrfs_file_extent_item - it does
not skip keys for the target
inode with a type less than
BTRFS_EXTENT_DATA_KEY
(BTRFS_INODE_REF_KEY < BTRFS_EXTENT_DATA_KEY)
sees a bogus value for the type
field triggering the WARN_ON in
the trace shown above, and sets
extent_end = search_start (4096)
does the if-then-else logic to
fixup 0 length extent items created
by a past bug from hole punching:
if (extent_end == key.offset &&
extent_end >= search_start)
goto delete_extent_item;
that evaluates to true and it ends
up deleting the key pointed to by
path->slots[0], (257 INODE_REF 4096),
from leaf X
The same could happen for example for a xattr that ends up having a key
with an offset value that matches search_start (very unlikely but not
impossible).
So fix this by ensuring that keys smaller than BTRFS_EXTENT_DATA_KEY are
skipped, never casted to struct btrfs_file_extent_item and never deleted
by accident. Also protect against the unexpected case of getting a key
for a lower inode number by skipping that key and issuing a warning.
Signed-off-by: Filipe Manana <fdmanana@suse.com>
[bwh: Backported to 3.2: drop use of ASSERT()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
fs/btrfs/file.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -605,8 +605,15 @@ next_slot:
}
btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
- if (key.objectid > ino ||
- key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end)
+
+ if (key.objectid > ino)
+ break;
+ if (WARN_ON_ONCE(key.objectid < ino) ||
+ key.type < BTRFS_EXTENT_DATA_KEY) {
+ path->slots[0]++;
+ goto next_slot;
+ }
+ if (key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end)
break;
fi = btrfs_item_ptr(leaf, path->slots[0],
@@ -625,8 +632,8 @@ next_slot:
btrfs_file_extent_inline_len(leaf,
path->slots[0], fi);
} else {
- WARN_ON(1);
- extent_end = search_start;
+ /* can't happen */
+ BUG();
}
if (extent_end <= search_start) {
next prev parent reply other threads:[~2015-11-24 22:36 UTC|newest]
Thread overview: 71+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-24 22:33 [PATCH 3.2 00/52] 3.2.74-rc1 review Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 11/52] Btrfs: fix file corruption and data loss after cloning inline extents Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 35/52] Btrfs: fix race leading to BUG_ON when running delalloc for nodatacow Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 28/52] recordmcount: Fix endianness handling bug for nop_mcount Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 45/52] binfmt_elf: Don't clobber passed executable's file header Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 40/52] net: fix a race in dst_release() Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 29/52] ipv6: fix tunnel error handling Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 44/52] FS-Cache: Handle a write to the page immediately beyond the EOF marker Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 12/52] iommu/vt-d: Fix ATSR handling for Root-Complex integrated endpoints Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 47/52] fs: if a coredump already exists, unlink and recreate with O_EXCL Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 42/52] FS-Cache: Increase reference of parent after registering, netfs success Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 46/52] fs: make dumpable=2 require fully qualified path Ben Hutchings
2015-11-25 2:06 ` James Morris
2015-11-25 17:57 ` Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 52/52] splice: sendfile() at once fails for big files Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 13/52] ARM: pxa: remove incorrect __init annotation on pxa27x_set_pwrmode Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 24/52] can: Use correct type in sizeof() in nla_put() Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 04/52] HID: core: Avoid uninitialized buffer access Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 17/52] Bluetooth: ath3k: Add new AR3012 0930:021c id Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 26/52] crypto: algif_hash - Only export and import on sockets with data Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 43/52] FS-Cache: Don't override netfs's primary_index if registering failed Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 23/52] megaraid_sas: Do not use PAGE_SIZE for max_sectors Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 32/52] scsi: restart list search after unlock in scsi_remove_target Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 27/52] megaraid_sas : SMAP restriction--do not access user memory from IOCTL code Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 18/52] Bluetooth: ath3k: Add support of AR3012 0cf3:817b device Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 38/52] Btrfs: fix race when listing an inode's xattrs Ben Hutchings
2015-11-25 23:11 ` Luis Henriques
2015-11-26 0:39 ` Ben Hutchings
2015-11-26 9:39 ` Filipe Manana
2015-11-24 22:33 ` [PATCH 3.2 22/52] ALSA: hda - Disable 64bit address for Creative HDA controllers Ben Hutchings
2015-11-25 23:05 ` Luis Henriques
2015-11-26 0:34 ` Ben Hutchings
2015-11-26 10:30 ` Luis Henriques
2015-11-24 22:33 ` [PATCH 3.2 16/52] ext4, jbd2: ensure entering into panic after recording an error in superblock Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 03/52] mac80211: fix driver RSSI event calculations Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 39/52] scsi: Fix a bdi reregistration race Ben Hutchings
2015-11-24 22:39 ` Bart Van Assche
2015-11-25 18:00 ` Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 41/52] KVM: svm: unconditionally intercept #DB Ben Hutchings
2015-11-25 11:31 ` Paolo Bonzini
2015-11-25 17:56 ` Ben Hutchings
2015-11-25 18:06 ` Paolo Bonzini
2015-11-24 22:33 ` [PATCH 3.2 49/52] RDS-TCP: Recover correctly from pskb_pull()/pksb_trim() failure in rds_tcp_data_recv Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 05/52] wm831x_power: Use IRQF_ONESHOT to request threaded IRQs Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 19/52] staging: rtl8712: Add device ID for Sitecom WLA2100 Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 31/52] firewire: ohci: fix JMicron JMB38x IT context discovery Ben Hutchings
2015-11-24 23:48 ` Stefan Richter
2015-11-24 22:33 ` [PATCH 3.2 36/52] perf: Fix inherited events vs. tracepoint filters Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 07/52] mtd: mtdpart: fix add_mtd_partitions error path Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 01/52] PCI: Fix devfn for VPD access through function 0 Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 08/52] devres: fix a for loop bounds check Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 50/52] ipmr: fix possible race resulting from improper usage of IP_INC_STATS_BH() in preemptible context Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 37/52] scsi_sysfs: Fix queue_ramp_up_period return code Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 02/52] PCI: Use function 0 VPD for identical functions, regular VPD for others Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 09/52] packet: fix match_fanout_group() Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 14/52] Btrfs: don't use ram_bytes for uncompressed inline items Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 06/52] mwifiex: fix mwifiex_rdeeprom_read() Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 15/52] Btrfs: fix truncation of compressed and inlined extents Ben Hutchings
2015-11-24 22:33 ` Ben Hutchings [this message]
2015-11-24 22:33 ` [PATCH 3.2 10/52] Btrfs: added helper btrfs_next_item() Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 51/52] net: avoid NULL deref in inet_ctl_sock_destroy() Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 21/52] MIPS: atomic: Fix comment describing atomic64_add_unless's return value Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 33/52] x86/cpu: Call verify_cpu() after having entered long mode too Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 30/52] ALSA: hda - Apply pin fixup for HP ProBook 6550b Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 48/52] irda: precedence bug in irlmp_seq_hb_idx() Ben Hutchings
2015-11-24 22:33 ` [PATCH 3.2 20/52] ACPI: Use correct IRQ when uninstalling ACPI interrupt handler Ben Hutchings
2015-11-25 2:37 ` Chen, Yu C
2015-11-24 22:33 ` [PATCH 3.2 25/52] mtd: blkdevs: fix potential deadlock + lockdep warnings Ben Hutchings
2015-11-25 2:22 ` [PATCH 3.2 00/52] 3.2.74-rc1 review Guenter Roeck
2015-11-25 17:57 ` Ben Hutchings
2015-11-25 17:43 ` Ben Hutchings
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=lsq.1448404439.577609638@decadent.org.uk \
--to=ben@decadent.org.uk \
--cc=akpm@linux-foundation.org \
--cc=fdmanana@suse.com \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®