linux-stable/fs/btrfs
Qu Wenruo 87160d1087 btrfs: repair super block num_devices automatically
commit d201238ccd upstream.

[BUG]
There is a report that a btrfs has a bad super block num devices.

This makes btrfs to reject the fs completely.

  BTRFS error (device sdd3): super_num_devices 3 mismatch with num_devices 2 found here
  BTRFS error (device sdd3): failed to read chunk tree: -22
  BTRFS error (device sdd3): open_ctree failed

[CAUSE]
During btrfs device removal, chunk tree and super block num devs are
updated in two different transactions:

  btrfs_rm_device()
  |- btrfs_rm_dev_item(device)
  |  |- trans = btrfs_start_transaction()
  |  |  Now we got transaction X
  |  |
  |  |- btrfs_del_item()
  |  |  Now device item is removed from chunk tree
  |  |
  |  |- btrfs_commit_transaction()
  |     Transaction X got committed, super num devs untouched,
  |     but device item removed from chunk tree.
  |     (AKA, super num devs is already incorrect)
  |
  |- cur_devices->num_devices--;
  |- cur_devices->total_devices--;
  |- btrfs_set_super_num_devices()
     All those operations are not in transaction X, thus it will
     only be written back to disk in next transaction.

So after the transaction X in btrfs_rm_dev_item() committed, but before
transaction X+1 (which can be minutes away), a power loss happen, then
we got the super num mismatch.

This has been fixed by commit bbac58698a ("btrfs: remove device item
and update super block in the same transaction").

[FIX]
Make the super_num_devices check less strict, converting it from a hard
error to a warning, and reset the value to a correct one for the current
or next transaction commit.

As the number of device items is the critical information where the
super block num_devices is only a cached value (and also useful for
cross checking), it's safe to automatically update it. Other device
related problems like missing device are handled after that and may
require other means to resolve, like degraded mount. With this fix,
potentially affected filesystems won't fail mount and require the manual
repair by btrfs check.

Reported-by: Luca Béla Palkovics <luca.bela.palkovics@gmail.com>
Link: https://lore.kernel.org/linux-btrfs/CA+8xDSpvdm_U0QLBAnrH=zqDq_cWCOH5TiV46CKmp3igr44okQ@mail.gmail.com/
CC: stable@vger.kernel.org # 4.14+
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-06-14 16:53:43 +02:00
..
tests Btrfs: fix selftests failure due to uninitialized i_mode in test inodes 2020-12-29 13:47:07 +01:00
acl.c Btrfs: setup a nofs context for memory allocation at __btrfs_set_acl 2019-03-23 14:35:21 +01:00
async-thread.c btrfs: fix memory ordering between normal and ordered work functions 2021-11-26 11:40:40 +01:00
async-thread.h Btrfs: fix crash during unmount due to race with delayed inode workers 2020-04-24 08:00:48 +02:00
backref.c btrfs: remove BUG_ON(!eie) in find_parent_nodes 2022-01-27 09:00:56 +01:00
backref.h
btrfs_inode.h Btrfs: fix fsync of files with multiple hard links in new directories 2019-01-09 17:14:50 +01:00
check-integrity.c btrfs: fix possible NULL-pointer dereference in integrity checks 2020-02-28 16:36:05 +01:00
check-integrity.h
compression.c btrfs: mark compressed range uptodate only if all bio succeed 2021-08-08 08:53:29 +02:00
compression.h btrfs: correctly validate compression type 2019-09-19 09:08:03 +02:00
ctree.c btrfs: fix race when picking most recent mod log operation for an old root 2021-05-22 10:57:20 +02:00
ctree.h Btrfs: fix unexpected failure of nocow buffered writes after snapshotting when low on space 2020-10-14 09:51:11 +02:00
dedupe.h
delayed-inode.c btrfs: abort transaction if we fail to update the delayed inode 2021-07-20 16:17:32 +02:00
delayed-inode.h
delayed-ref.c Btrfs: fix race between adding and putting tree mod seq elements and nodes 2020-02-14 16:32:19 -05:00
delayed-ref.h
dev-replace.c btrfs: Ensure replaced device doesn't have pending chunk allocation 2019-07-10 09:54:41 +02:00
dev-replace.h
dir-item.c
disk-io.c btrfs: add "0x" prefix for unsupported optional features 2022-06-14 16:53:43 +02:00
disk-io.h
export.c btrfs: export helpers for subvolume name/id resolution 2020-08-26 10:29:54 +02:00
export.h btrfs: export helpers for subvolume name/id resolution 2020-08-26 10:29:54 +02:00
extent-tree.c btrfs: unlock newly allocated extent buffer after error 2022-03-16 12:57:09 +01:00
extent_io.c Btrfs: fix missing error return if writeback for extent buffer never started 2020-11-18 18:27:54 +01:00
extent_io.h btrfs: fix qgroup reserve overflow the qgroup limit 2022-04-20 09:08:30 +02:00
extent_map.c Btrfs: fix race between using extent maps and merging them 2020-02-28 16:35:53 +01:00
extent_map.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
file-item.c btrfs: fix error handling in btrfs_del_csums 2021-06-10 12:43:51 +02:00
file.c btrfs: always wait on ordered extents at fsync time 2021-10-27 09:51:39 +02:00
free-space-cache.c btrfs: clarify error returns values in __load_free_space_cache 2021-03-03 18:22:43 +01:00
free-space-cache.h
free-space-tree.c
free-space-tree.h
hash.c
hash.h
inode-item.c
inode-map.c Btrfs: fix inode cache waiters hanging on path allocation failure 2020-01-27 14:46:46 +01:00
inode-map.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
inode.c Revert "btrfs: compression: don't try to compress if we don't have enough pages" 2021-09-22 11:45:16 +02:00
ioctl.c btrfs: fix metadata extent leak after failure to create subvolume 2021-05-22 10:57:15 +02:00
Kconfig btrfs: disable build on platforms having page size 256K 2021-07-20 16:17:32 +02:00
locking.c
locking.h
lzo.c
Makefile btrfs: Move leaf and node validation checker to tree-checker.c 2018-12-05 19:41:12 +01:00
math.h
ordered-data.c Btrfs: fix btrfs_wait_ordered_range() so that it waits for all ordered extents 2020-02-28 16:36:14 +01:00
ordered-data.h
orphan.c
print-tree.c btrfs: require only sector size alignment for parent eb bytenr 2020-09-23 10:46:30 +02:00
print-tree.h
props.c btrfs: correctly validate compression type 2019-09-19 09:08:03 +02:00
props.h
qgroup.c btrfs: fix transaction leak and crash after RO remount caused by qgroup rescan 2021-01-23 15:48:42 +01:00
qgroup.h btrfs: qgroup: Avoid calling qgroup functions if qgroup is not enabled 2018-11-13 11:15:13 -08:00
raid56.c btrfs: fix raid6 qstripe kmap 2021-03-11 13:51:04 +01:00
raid56.h
rcu-string.h
reada.c btrfs: fix use-after-free on readahead extent after failure to create it 2020-11-05 11:07:00 +01:00
relocation.c btrfs: convert logic BUG_ON()'s in replace_path to ASSERT()'s 2021-05-22 10:57:17 +02:00
root-tree.c btrfs: Don't panic when we can't find a root key 2019-05-31 06:47:20 -07:00
scrub.c btrfs: don't prematurely free work in scrub_missing_raid56_worker() 2019-12-31 12:37:53 +01:00
send.c btrfs: send: in case of IO error log it 2022-02-23 11:57:33 +01:00
send.h
struct-funcs.c
super.c btrfs: fix transaction leak and crash after RO remount caused by qgroup rescan 2021-01-23 15:48:42 +01:00
sysfs.c btrfs: sysfs: use NOFS for device creation 2020-08-26 10:29:54 +02:00
sysfs.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
transaction.c btrfs: clear defrag status of a root if starting transaction fails 2021-07-20 16:17:28 +02:00
transaction.h
tree-checker.c btrfs: tree-checker: Don't check max block group size as current max chunk size limit is unreliable 2018-12-08 13:03:39 +01:00
tree-checker.h btrfs: tree-checker: Fix false panic for sanity test 2018-12-05 19:41:12 +01:00
tree-defrag.c
tree-log.c btrfs: always log symlinks in full mode 2022-05-12 12:17:10 +02:00
tree-log.h
ulist.c
ulist.h
uuid-tree.c btrfs: handle ENOENT in btrfs_uuid_tree_iterate 2019-12-31 12:36:44 +01:00
volumes.c btrfs: repair super block num_devices automatically 2022-06-14 16:53:43 +02:00
volumes.h btrfs: Remove btrfs_bio::flags member 2019-12-17 20:39:16 +01:00
xattr.c
xattr.h
zlib.c
zstd.c