Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Btrfs: Initialize btrfs_root->highest_objectid when loading tree root and subvolume roots

The following call trace is seen when btrfs/031 test is executed in a loop,

[ 158.661848] ------------[ cut here ]------------
[ 158.662634] WARNING: CPU: 2 PID: 890 at /home/chandan/repos/linux/fs/btrfs/ioctl.c:558 create_subvol+0x3d1/0x6ea()
[ 158.664102] BTRFS: Transaction aborted (error -2)
[ 158.664774] Modules linked in:
[ 158.665266] CPU: 2 PID: 890 Comm: btrfs Not tainted 4.4.0-rc6-g511711a #2
[ 158.666251] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
[ 158.667392] ffffffff81c0a6b0 ffff8806c7c4f8e8 ffffffff81431fc8 ffff8806c7c4f930
[ 158.668515] ffff8806c7c4f920 ffffffff81051aa1 ffff880c85aff000 ffff8800bb44d000
[ 158.669647] ffff8808863b5c98 0000000000000000 00000000fffffffe ffff8806c7c4f980
[ 158.670769] Call Trace:
[ 158.671153] [<ffffffff81431fc8>] dump_stack+0x44/0x5c
[ 158.671884] [<ffffffff81051aa1>] warn_slowpath_common+0x81/0xc0
[ 158.672769] [<ffffffff81051b27>] warn_slowpath_fmt+0x47/0x50
[ 158.673620] [<ffffffff813bc98d>] create_subvol+0x3d1/0x6ea
[ 158.674440] [<ffffffff813777c9>] btrfs_mksubvol.isra.30+0x369/0x520
[ 158.675376] [<ffffffff8108a4aa>] ? percpu_down_read+0x1a/0x50
[ 158.676235] [<ffffffff81377a81>] btrfs_ioctl_snap_create_transid+0x101/0x180
[ 158.677268] [<ffffffff81377b52>] btrfs_ioctl_snap_create+0x52/0x70
[ 158.678183] [<ffffffff8137afb4>] btrfs_ioctl+0x474/0x2f90
[ 158.678975] [<ffffffff81144b8e>] ? vma_merge+0xee/0x300
[ 158.679751] [<ffffffff8115be31>] ? alloc_pages_vma+0x91/0x170
[ 158.680599] [<ffffffff81123f62>] ? lru_cache_add_active_or_unevictable+0x22/0x70
[ 158.681686] [<ffffffff813d99cf>] ? selinux_file_ioctl+0xff/0x1d0
[ 158.682581] [<ffffffff8117b791>] do_vfs_ioctl+0x2c1/0x490
[ 158.683399] [<ffffffff813d3cde>] ? security_file_ioctl+0x3e/0x60
[ 158.684297] [<ffffffff8117b9d4>] SyS_ioctl+0x74/0x80
[ 158.685051] [<ffffffff819b2bd7>] entry_SYSCALL_64_fastpath+0x12/0x6a
[ 158.685958] ---[ end trace 4b63312de5a2cb76 ]---
[ 158.686647] BTRFS: error (device loop0) in create_subvol:558: errno=-2 No such entry
[ 158.709508] BTRFS info (device loop0): forced readonly
[ 158.737113] BTRFS info (device loop0): disk space caching is enabled
[ 158.738096] BTRFS error (device loop0): Remounting read-write after error is not allowed
[ 158.851303] BTRFS error (device loop0): cleaner transaction attach returned -30

This occurs because,

Mount filesystem
Create subvol with ID 257
Unmount filesystem
Mount filesystem
Delete subvol with ID 257
btrfs_drop_snapshot()
Add root corresponding to subvol 257 into
btrfs_transaction->dropped_roots list
Create new subvol (i.e. create_subvol())
257 is returned as the next free objectid
btrfs_read_fs_root_no_name()
Finds the btrfs_root instance corresponding to the old subvol with ID 257
in btrfs_fs_info->fs_roots_radix.
Returns error since btrfs_root_item->refs has the value of 0.

To fix the issue the commit initializes tree root's and subvolume root's
highest_objectid when loading the roots from disk.

Signed-off-by: Chandan Rajendra <chandan@linux.vnet.ibm.com>
Signed-off-by: David Sterba <dsterba@suse.com>

authored by

Chandan Rajendra and committed by
David Sterba
f32e48e9 ee592d07

+33 -8
+27
fs/btrfs/disk-io.c
··· 1582 1582 ret = get_anon_bdev(&root->anon_dev); 1583 1583 if (ret) 1584 1584 goto free_writers; 1585 + 1586 + mutex_lock(&root->objectid_mutex); 1587 + ret = btrfs_find_highest_objectid(root, 1588 + &root->highest_objectid); 1589 + if (ret) { 1590 + mutex_unlock(&root->objectid_mutex); 1591 + goto free_root_dev; 1592 + } 1593 + 1594 + ASSERT(root->highest_objectid <= BTRFS_LAST_FREE_OBJECTID); 1595 + 1596 + mutex_unlock(&root->objectid_mutex); 1597 + 1585 1598 return 0; 1586 1599 1600 + free_root_dev: 1601 + free_anon_bdev(root->anon_dev); 1587 1602 free_writers: 1588 1603 btrfs_free_subvolume_writers(root->subv_writers); 1589 1604 fail: ··· 2915 2900 btrfs_set_root_node(&tree_root->root_item, tree_root->node); 2916 2901 tree_root->commit_root = btrfs_root_node(tree_root); 2917 2902 btrfs_set_root_refs(&tree_root->root_item, 1); 2903 + 2904 + mutex_lock(&tree_root->objectid_mutex); 2905 + ret = btrfs_find_highest_objectid(tree_root, 2906 + &tree_root->highest_objectid); 2907 + if (ret) { 2908 + mutex_unlock(&tree_root->objectid_mutex); 2909 + goto recovery_tree_root; 2910 + } 2911 + 2912 + ASSERT(tree_root->highest_objectid <= BTRFS_LAST_FREE_OBJECTID); 2913 + 2914 + mutex_unlock(&tree_root->objectid_mutex); 2918 2915 2919 2916 ret = btrfs_read_roots(fs_info, tree_root); 2920 2917 if (ret)
+1 -8
fs/btrfs/inode-map.c
··· 515 515 return ret; 516 516 } 517 517 518 - static int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid) 518 + int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid) 519 519 { 520 520 struct btrfs_path *path; 521 521 int ret; ··· 554 554 { 555 555 int ret; 556 556 mutex_lock(&root->objectid_mutex); 557 - 558 - if (unlikely(root->highest_objectid < BTRFS_FIRST_FREE_OBJECTID)) { 559 - ret = btrfs_find_highest_objectid(root, 560 - &root->highest_objectid); 561 - if (ret) 562 - goto out; 563 - } 564 557 565 558 if (unlikely(root->highest_objectid >= BTRFS_LAST_FREE_OBJECTID)) { 566 559 ret = -ENOSPC;
+1
fs/btrfs/inode-map.h
··· 9 9 struct btrfs_trans_handle *trans); 10 10 11 11 int btrfs_find_free_objectid(struct btrfs_root *root, u64 *objectid); 12 + int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid); 12 13 13 14 #endif
+4
fs/btrfs/ioctl.c
··· 568 568 goto fail; 569 569 } 570 570 571 + mutex_lock(&new_root->objectid_mutex); 572 + new_root->highest_objectid = new_dirid; 573 + mutex_unlock(&new_root->objectid_mutex); 574 + 571 575 /* 572 576 * insert the directory item 573 577 */