lkml.org 
[lkml]   [2016]   [Mar]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 093/342] Btrfs: Initialize btrfs_root->highest_objectid when loading tree root and subvolume roots
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Chandan Rajendra <chandan@linux.vnet.ibm.com>

    commit f32e48e925964c4f8ab917850788a87e1cef3bad upstream.

    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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/btrfs/disk-io.c | 27 +++++++++++++++++++++++++++
    fs/btrfs/inode-map.c | 9 +--------
    fs/btrfs/inode-map.h | 1 +
    fs/btrfs/ioctl.c | 4 ++++
    4 files changed, 33 insertions(+), 8 deletions(-)

    --- a/fs/btrfs/disk-io.c
    +++ b/fs/btrfs/disk-io.c
    @@ -1582,8 +1582,23 @@ int btrfs_init_fs_root(struct btrfs_root
    ret = get_anon_bdev(&root->anon_dev);
    if (ret)
    goto free_writers;
    +
    + mutex_lock(&root->objectid_mutex);
    + ret = btrfs_find_highest_objectid(root,
    + &root->highest_objectid);
    + if (ret) {
    + mutex_unlock(&root->objectid_mutex);
    + goto free_root_dev;
    + }
    +
    + ASSERT(root->highest_objectid <= BTRFS_LAST_FREE_OBJECTID);
    +
    + mutex_unlock(&root->objectid_mutex);
    +
    return 0;

    +free_root_dev:
    + free_anon_bdev(root->anon_dev);
    free_writers:
    btrfs_free_subvolume_writers(root->subv_writers);
    fail:
    @@ -2900,6 +2915,18 @@ retry_root_backup:
    tree_root->commit_root = btrfs_root_node(tree_root);
    btrfs_set_root_refs(&tree_root->root_item, 1);

    + mutex_lock(&tree_root->objectid_mutex);
    + ret = btrfs_find_highest_objectid(tree_root,
    + &tree_root->highest_objectid);
    + if (ret) {
    + mutex_unlock(&tree_root->objectid_mutex);
    + goto recovery_tree_root;
    + }
    +
    + ASSERT(tree_root->highest_objectid <= BTRFS_LAST_FREE_OBJECTID);
    +
    + mutex_unlock(&tree_root->objectid_mutex);
    +
    ret = btrfs_read_roots(fs_info, tree_root);
    if (ret)
    goto recovery_tree_root;
    --- a/fs/btrfs/inode-map.c
    +++ b/fs/btrfs/inode-map.c
    @@ -515,7 +515,7 @@ out:
    return ret;
    }

    -static int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid)
    +int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid)
    {
    struct btrfs_path *path;
    int ret;
    @@ -555,13 +555,6 @@ int btrfs_find_free_objectid(struct btrf
    int ret;
    mutex_lock(&root->objectid_mutex);

    - if (unlikely(root->highest_objectid < BTRFS_FIRST_FREE_OBJECTID)) {
    - ret = btrfs_find_highest_objectid(root,
    - &root->highest_objectid);
    - if (ret)
    - goto out;
    - }
    -
    if (unlikely(root->highest_objectid >= BTRFS_LAST_FREE_OBJECTID)) {
    ret = -ENOSPC;
    goto out;
    --- a/fs/btrfs/inode-map.h
    +++ b/fs/btrfs/inode-map.h
    @@ -9,5 +9,6 @@ int btrfs_save_ino_cache(struct btrfs_ro
    struct btrfs_trans_handle *trans);

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

    #endif
    --- a/fs/btrfs/ioctl.c
    +++ b/fs/btrfs/ioctl.c
    @@ -568,6 +568,10 @@ static noinline int create_subvol(struct
    goto fail;
    }

    + mutex_lock(&new_root->objectid_mutex);
    + new_root->highest_objectid = new_dirid;
    + mutex_unlock(&new_root->objectid_mutex);
    +
    /*
    * insert the directory item
    */
    \
     
     \ /
      Last update: 2016-03-02 02:41    [W:4.232 / U:0.056 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site