Skip to content

Commit f32e48e

Browse files
Chandan Rajendrakdave
authored andcommitted
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 <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent ee592d0 commit f32e48e

File tree

4 files changed

+33
-8
lines changed

4 files changed

+33
-8
lines changed

fs/btrfs/disk-io.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,8 +1582,23 @@ int btrfs_init_fs_root(struct btrfs_root *root)
15821582
ret = get_anon_bdev(&root->anon_dev);
15831583
if (ret)
15841584
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+
15851598
return 0;
15861599

1600+
free_root_dev:
1601+
free_anon_bdev(root->anon_dev);
15871602
free_writers:
15881603
btrfs_free_subvolume_writers(root->subv_writers);
15891604
fail:
@@ -2901,6 +2916,18 @@ int open_ctree(struct super_block *sb,
29012916
tree_root->commit_root = btrfs_root_node(tree_root);
29022917
btrfs_set_root_refs(&tree_root->root_item, 1);
29032918

2919+
mutex_lock(&tree_root->objectid_mutex);
2920+
ret = btrfs_find_highest_objectid(tree_root,
2921+
&tree_root->highest_objectid);
2922+
if (ret) {
2923+
mutex_unlock(&tree_root->objectid_mutex);
2924+
goto recovery_tree_root;
2925+
}
2926+
2927+
ASSERT(tree_root->highest_objectid <= BTRFS_LAST_FREE_OBJECTID);
2928+
2929+
mutex_unlock(&tree_root->objectid_mutex);
2930+
29042931
ret = btrfs_read_roots(fs_info, tree_root);
29052932
if (ret)
29062933
goto recovery_tree_root;

fs/btrfs/inode-map.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
515515
return ret;
516516
}
517517

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)
519519
{
520520
struct btrfs_path *path;
521521
int ret;
@@ -555,13 +555,6 @@ int btrfs_find_free_objectid(struct btrfs_root *root, u64 *objectid)
555555
int ret;
556556
mutex_lock(&root->objectid_mutex);
557557

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-
565558
if (unlikely(root->highest_objectid >= BTRFS_LAST_FREE_OBJECTID)) {
566559
ret = -ENOSPC;
567560
goto out;

fs/btrfs/inode-map.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
99
struct btrfs_trans_handle *trans);
1010

1111
int btrfs_find_free_objectid(struct btrfs_root *root, u64 *objectid);
12+
int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid);
1213

1314
#endif

fs/btrfs/ioctl.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,10 @@ static noinline int create_subvol(struct inode *dir,
568568
goto fail;
569569
}
570570

571+
mutex_lock(&new_root->objectid_mutex);
572+
new_root->highest_objectid = new_dirid;
573+
mutex_unlock(&new_root->objectid_mutex);
574+
571575
/*
572576
* insert the directory item
573577
*/

0 commit comments

Comments
 (0)