22 Jul, 2020

1 commit

  • At btrfs_find_all_roots_safe() we allocate a ulist and set the **roots
    argument to point to it. However if later we fail due to an error returned
    by find_parent_nodes(), we free that ulist but leave a dangling pointer in
    the **roots argument. Upon receiving the error, a caller of this function
    can attempt to free the same ulist again, resulting in an invalid memory
    access.

    One such scenario is during qgroup accounting:

    btrfs_qgroup_account_extents()

    --> calls btrfs_find_all_roots() passes &new_roots (a stack allocated
    pointer) to btrfs_find_all_roots()

    --> btrfs_find_all_roots() just calls btrfs_find_all_roots_safe()
    passing &new_roots to it

    --> allocates ulist and assigns its address to **roots (which
    points to new_roots from btrfs_qgroup_account_extents())

    --> find_parent_nodes() returns an error, so we free the ulist
    and leave **roots pointing to it after returning

    --> btrfs_qgroup_account_extents() sees btrfs_find_all_roots() returned
    an error and jumps to the label 'cleanup', which just tries to
    free again the same ulist

    Stack trace example:

    ------------[ cut here ]------------
    BTRFS: tree first key check failed
    WARNING: CPU: 1 PID: 1763215 at fs/btrfs/disk-io.c:422 btrfs_verify_level_key+0xe0/0x180 [btrfs]
    Modules linked in: dm_snapshot dm_thin_pool (...)
    CPU: 1 PID: 1763215 Comm: fsstress Tainted: G W 5.8.0-rc3-btrfs-next-64 #1
    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014
    RIP: 0010:btrfs_verify_level_key+0xe0/0x180 [btrfs]
    Code: 28 5b 5d (...)
    RSP: 0018:ffffb89b473779a0 EFLAGS: 00010286
    RAX: 0000000000000000 RBX: ffff90397759bf08 RCX: 0000000000000000
    RDX: 0000000000000001 RSI: 0000000000000027 RDI: 00000000ffffffff
    RBP: ffff9039a419c000 R08: 0000000000000000 R09: 0000000000000000
    R10: 0000000000000000 R11: ffffb89b43301000 R12: 000000000000005e
    R13: ffffb89b47377a2e R14: ffffb89b473779af R15: 0000000000000000
    FS: 00007fc47e1e1000(0000) GS:ffff9039ac200000(0000) knlGS:0000000000000000
    CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    CR2: 00007fc47e1df000 CR3: 00000003d9e4e001 CR4: 00000000003606e0
    DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
    DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
    Call Trace:
    read_block_for_search+0xf6/0x350 [btrfs]
    btrfs_next_old_leaf+0x242/0x650 [btrfs]
    resolve_indirect_refs+0x7cf/0x9e0 [btrfs]
    find_parent_nodes+0x4ea/0x12c0 [btrfs]
    btrfs_find_all_roots_safe+0xbf/0x130 [btrfs]
    btrfs_qgroup_account_extents+0x9d/0x390 [btrfs]
    btrfs_commit_transaction+0x4f7/0xb20 [btrfs]
    btrfs_sync_file+0x3d4/0x4d0 [btrfs]
    do_fsync+0x38/0x70
    __x64_sys_fdatasync+0x13/0x20
    do_syscall_64+0x5c/0xe0
    entry_SYSCALL_64_after_hwframe+0x44/0xa9
    RIP: 0033:0x7fc47e2d72e3
    Code: Bad RIP value.
    RSP: 002b:00007fffa32098c8 EFLAGS: 00000246 ORIG_RAX: 000000000000004b
    RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007fc47e2d72e3
    RDX: 00007fffa3209830 RSI: 00007fffa3209830 RDI: 0000000000000003
    RBP: 000000000000072e R08: 0000000000000001 R09: 0000000000000003
    R10: 0000000000000000 R11: 0000000000000246 R12: 00000000000003e8
    R13: 0000000051eb851f R14: 00007fffa3209970 R15: 00005607c4ac8b50
    irq event stamp: 0
    hardirqs last enabled at (0): [] 0x0
    hardirqs last disabled at (0): [] copy_process+0x755/0x1eb0
    softirqs last enabled at (0): [] copy_process+0x755/0x1eb0
    softirqs last disabled at (0): [] 0x0
    ---[ end trace 8639237550317b48 ]---
    BTRFS error (device sdc): tree first key mismatch detected, bytenr=62324736 parent_transid=94 key expected=(262,108,1351680) has=(259,108,1921024)
    general protection fault, probably for non-canonical address 0x6b6b6b6b6b6b6b6b: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI
    CPU: 2 PID: 1763215 Comm: fsstress Tainted: G W 5.8.0-rc3-btrfs-next-64 #1
    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014
    RIP: 0010:ulist_release+0x14/0x60 [btrfs]
    Code: c7 07 00 (...)
    RSP: 0018:ffffb89b47377d60 EFLAGS: 00010282
    RAX: 6b6b6b6b6b6b6b6b RBX: ffff903959b56b90 RCX: 0000000000000000
    RDX: 0000000000000001 RSI: 0000000000270024 RDI: ffff9036e2adc840
    RBP: ffff9036e2adc848 R08: 0000000000000000 R09: 0000000000000000
    R10: 0000000000000000 R11: 0000000000000000 R12: ffff9036e2adc840
    R13: 0000000000000015 R14: ffff9039a419ccf8 R15: ffff90395d605840
    FS: 00007fc47e1e1000(0000) GS:ffff9039ac600000(0000) knlGS:0000000000000000
    CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    CR2: 00007f8c1c0a51c8 CR3: 00000003d9e4e004 CR4: 00000000003606e0
    DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
    DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
    Call Trace:
    ulist_free+0x13/0x20 [btrfs]
    btrfs_qgroup_account_extents+0xf3/0x390 [btrfs]
    btrfs_commit_transaction+0x4f7/0xb20 [btrfs]
    btrfs_sync_file+0x3d4/0x4d0 [btrfs]
    do_fsync+0x38/0x70
    __x64_sys_fdatasync+0x13/0x20
    do_syscall_64+0x5c/0xe0
    entry_SYSCALL_64_after_hwframe+0x44/0xa9
    RIP: 0033:0x7fc47e2d72e3
    Code: Bad RIP value.
    RSP: 002b:00007fffa32098c8 EFLAGS: 00000246 ORIG_RAX: 000000000000004b
    RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007fc47e2d72e3
    RDX: 00007fffa3209830 RSI: 00007fffa3209830 RDI: 0000000000000003
    RBP: 000000000000072e R08: 0000000000000001 R09: 0000000000000003
    R10: 0000000000000000 R11: 0000000000000246 R12: 00000000000003e8
    R13: 0000000051eb851f R14: 00007fffa3209970 R15: 00005607c4ac8b50
    Modules linked in: dm_snapshot dm_thin_pool (...)
    ---[ end trace 8639237550317b49 ]---
    RIP: 0010:ulist_release+0x14/0x60 [btrfs]
    Code: c7 07 00 (...)
    RSP: 0018:ffffb89b47377d60 EFLAGS: 00010282
    RAX: 6b6b6b6b6b6b6b6b RBX: ffff903959b56b90 RCX: 0000000000000000
    RDX: 0000000000000001 RSI: 0000000000270024 RDI: ffff9036e2adc840
    RBP: ffff9036e2adc848 R08: 0000000000000000 R09: 0000000000000000
    R10: 0000000000000000 R11: 0000000000000000 R12: ffff9036e2adc840
    R13: 0000000000000015 R14: ffff9039a419ccf8 R15: ffff90395d605840
    FS: 00007fc47e1e1000(0000) GS:ffff9039ad200000(0000) knlGS:0000000000000000
    CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    CR2: 00007f6a776f7d40 CR3: 00000003d9e4e002 CR4: 00000000003606e0
    DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
    DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400

    Fix this by making btrfs_find_all_roots_safe() set *roots to NULL after
    it frees the ulist.

    Fixes: 8da6d5815c592b ("Btrfs: added btrfs_find_all_roots()")
    CC: stable@vger.kernel.org # 4.4+
    Reviewed-by: Josef Bacik
    Signed-off-by: Filipe Manana
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Filipe Manana
     

25 May, 2020

13 commits

  • The main function to lookup a root by its id btrfs_get_fs_root takes the
    whole key, while only using the objectid. The value of offset is preset
    to (u64)-1 but not actually used until btrfs_find_root that does the
    actual search.

    Switch btrfs_get_fs_root to use only objectid and remove all local
    variables that existed just for the lookup. The actual key for search is
    set up in btrfs_get_fs_root, reusing another key variable.

    Signed-off-by: David Sterba

    David Sterba
     
  • The name BTRFS_ROOT_REF_COWS is not very clear about the meaning.

    In fact, that bit can only be set to those trees:

    - Subvolume roots
    - Data reloc root
    - Reloc roots for above roots

    All other trees won't get this bit set. So just by the result, it is
    obvious that, roots with this bit set can have tree blocks shared with
    other trees. Either shared by snapshots, or by reloc roots (an special
    snapshot created by relocation).

    This patch will rename BTRFS_ROOT_REF_COWS to BTRFS_ROOT_SHAREABLE to
    make it easier to understand, and update all comment mentioning
    "reference counted" to follow the rename.

    Signed-off-by: Qu Wenruo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Qu Wenruo
     
  • For relocation tree detection, relocation backref cache uses
    btrfs_should_ignore_reloc_root() which uses relocation-specific checks
    like checking the DEAD_RELOC_ROOT bit.

    However for general purpose backref cache, we can rely on that check, as
    it's possible that relocation is also running.

    For generic purposed backref cache, we detect reloc root by
    SHARED_BLOCK_REF item. Only reloc root node has its parent bytenr
    pointing back to itself.

    And in that case, backref cache will mark the reloc root node useless,
    dropping any child orphan nodes.

    So only call btrfs_should_ignore_reloc_root() if the backref cache is
    for relocation.

    Signed-off-by: Qu Wenruo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Qu Wenruo
     
  • The error cleanup will be extracted as a new function,
    btrfs_backref_error_cleanup(), and moved to backref.c and exported for
    later usage.

    Signed-off-by: Qu Wenruo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Qu Wenruo
     
  • This the the 2nd major part of generic backref cache. Move it to
    backref.c so we can reuse it.

    Signed-off-by: Qu Wenruo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Qu Wenruo
     
  • This function is the major part of backref cache build process, move it
    to backref.c so we can reuse it later.

    Signed-off-by: Qu Wenruo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Qu Wenruo
     
  • Since we're releasing all existing nodes/edges, other than cleanup the
    mess after error, "release" is a more proper naming here.

    Signed-off-by: Qu Wenruo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Qu Wenruo
     
  • Also add comment explaining the cleanup progress, to differ it from
    btrfs_backref_drop_node().

    Signed-off-by: Qu Wenruo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Qu Wenruo
     
  • Signed-off-by: Qu Wenruo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Qu Wenruo
     
  • Signed-off-by: Qu Wenruo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Qu Wenruo
     
  • Signed-off-by: Qu Wenruo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Qu Wenruo
     
  • This function will go to the next inline/keyed backref for
    btrfs_backref_iter infrastructure.

    Reviewed-by: Johannes Thumshirn
    Reviewed-by: Josef Bacik
    Signed-off-by: Qu Wenruo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Qu Wenruo
     
  • Due to the complex nature of btrfs extent tree, when we want to iterate
    all backrefs of one extent, this involves quite a lot of work, like
    searching the EXTENT_ITEM/METADATA_ITEM, iteration through inline and keyed
    backrefs.

    Normally this would result in a complex code, something like:

    btrfs_search_slot()
    /* Ensure we are at EXTENT_ITEM/METADATA_ITEM */
    while (1) { /* Loop for extent tree items */
    while (ptr < end) { /* Loop for inlined items */
    /* Real work here */
    }
    next:
    ret = btrfs_next_item()
    /* Ensure we're still at keyed item for specified bytenr */
    }

    The idea of btrfs_backref_iter is to avoid such complex and hard to
    read code structure, but something like the following:

    iter = btrfs_backref_iter_alloc();
    ret = btrfs_backref_iter_start(iter, bytenr);
    if (ret < 0)
    goto out;
    for (; ; ret = btrfs_backref_iter_next(iter)) {
    /* Real work here */
    }
    out:
    btrfs_backref_iter_free(iter);

    This patch is just the skeleton + btrfs_backref_iter_start() code.

    Reviewed-by: Johannes Thumshirn
    Reviewed-by: Josef Bacik
    Signed-off-by: Qu Wenruo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Qu Wenruo
     

30 Apr, 2020

1 commit

  • Some older compilers like gcc-4.8 warn about mismatched curly braces in
    a initializer:

    fs/btrfs/backref.c: In function 'is_shared_data_backref':
    fs/btrfs/backref.c:394:9: error: missing braces around
    initializer [-Werror=missing-braces]
    struct prelim_ref target = {0};
    ^
    fs/btrfs/backref.c:394:9: error: (near initialization for
    'target.rbnode') [-Werror=missing-braces]

    Use the GNU empty initializer extension to avoid this.

    Fixes: ed58f2e66e84 ("btrfs: backref, don't add refs from shared block when resolving normal backref")
    Reviewed-by: Qu Wenruo
    Signed-off-by: Arnd Bergmann
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Arnd Bergmann
     

24 Mar, 2020

10 commits

  • Zygo reported a deadlock where a task was stuck in the inode logical
    resolve code. The deadlock looks like this

    Task 1
    btrfs_ioctl_logical_to_ino
    ->iterate_inodes_from_logical
    ->iterate_extent_inodes
    ->path->search_commit_root isn't set, so a transaction is started
    ->resolve_indirect_ref for a root that's being deleted
    ->search for our key, attempt to lock a node, DEADLOCK

    Task 2
    btrfs_drop_snapshot
    ->walk down to a leaf, lock it, walk up, lock node
    ->end transaction
    ->start transaction
    -> wait_cur_trans

    Task 3
    btrfs_commit_transaction
    ->wait_event(cur_trans->write_wait, num_writers == 1) DEADLOCK

    We are holding a transaction open in btrfs_ioctl_logical_to_ino while we
    try to resolve our references. btrfs_drop_snapshot() holds onto its
    locks while it stops and starts transaction handles, because it assumes
    nobody is going to touch the root now. Commit just does what commit
    does, waiting for the writers to finish, blocking any new trans handles
    from starting.

    Fix this by making the backref code not try to resolve backrefs of roots
    that are currently being deleted. This will keep us from walking into a
    snapshot that's currently being deleted.

    This problem was harder to hit before because we rarely broke out of the
    snapshot delete halfway through, but with my delayed ref throttling code
    it happened much more often. However we've always been able to do this,
    so it's not a new problem.

    Fixes: 8da6d5815c59 ("Btrfs: added btrfs_find_all_roots()")
    Signed-off-by: Josef Bacik
    Signed-off-by: David Sterba

    Josef Bacik
     
  • Now that we have proper root ref counting everywhere we can kill the
    subvol_srcu.

    * removal of fs_info::subvol_srcu reduces size of fs_info by 1176 bytes

    * the refcount_t used for the references checks for accidental 0->1
    in cases where the root lifetime would not be properly protected

    * there's a leak detector for roots to catch unfreed roots at umount
    time

    * SRCU served us well over the years but is was not a proper
    synchronization mechanism for some cases

    Signed-off-by: Josef Bacik
    Reviewed-by: David Sterba
    [ update changelog ]
    Signed-off-by: David Sterba

    Josef Bacik
     
  • In relocation, we need to locate all parent tree leaves referring to one
    data extent, thus we have a complex mechanism to iterate throught extent
    tree and subvolume trees to locate the related leaves.

    However this is already done in backref.c, we have
    btrfs_find_all_leafs(), which can return a ulist containing all leaves
    referring to that data extent.

    Use btrfs_find_all_leafs() to replace find_data_references().

    There is a special handling for v1 space cache data extents, where we
    need to delete the v1 space cache data extents, to avoid those data
    extents to hang the data relocation.

    In this patch, the special handling is done by re-iterating the root
    tree leaf. Although it's a little less efficient than the old handling,
    considering we can reuse a lot of code, it should be acceptable.

    Signed-off-by: Qu Wenruo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Qu Wenruo
     
  • With the following patches:

    - btrfs: backref, only collect file extent items matching backref offset
    - btrfs: backref, not adding refs from shared block when resolving normal backref
    - btrfs: backref, only search backref entries from leaves of the same root

    we only collect the normal data refs we want, so the imprecise upper
    bound total_refs of that EXTENT_ITEM could now be changed to the count
    of the normal backref entry we want to search.

    Background and how the patches fit together:

    Btrfs has two types of data backref.
    For BTRFS_EXTENT_DATA_REF_KEY type of backref, we don't have the
    exact block number. Therefore, we need to call resolve_indirect_refs.
    It uses btrfs_search_slot to locate the leaf block. Then
    we need to walk through the leaves to search for the EXTENT_DATA items
    that have disk bytenr matching the extent item (add_all_parents).

    When resolving indirect refs, we could take entries that don't
    belong to the backref entry we are searching for right now.
    For that reason when searching backref entry, we always use total
    refs of that EXTENT_ITEM rather than individual count.

    For example:
    item 11 key (40831553536 EXTENT_ITEM 4194304) itemoff 15460 itemsize
    extent refs 24 gen 7302 flags DATA
    shared data backref parent 394985472 count 10 #1
    extent data backref root 257 objectid 260 offset 1048576 count 3 #2
    extent data backref root 256 objectid 260 offset 65536 count 6 #3
    extent data backref root 257 objectid 260 offset 65536 count 5 #4

    For example, when searching backref entry #4, we'll use total_refs
    24, a very loose loop ending condition, instead of total_refs = 5.

    But using total_refs = 24 is not accurate. Sometimes, we'll never find
    all the refs from specific root. As a result, the loop keeps on going
    until we reach the end of that inode.

    The first 3 patches, handle 3 different types refs we might encounter.
    These refs do not belong to the normal backref we are searching, and
    hence need to be skipped.

    This patch changes the total_refs to correct number so that we could
    end loop as soon as we find all the refs we want.

    btrfs send uses backref to find possible clone sources, the following
    is a simple test to compare the results with and without this patch:

    $ btrfs subvolume create /sub1
    $ for i in `seq 1 163840`; do
    dd if=/dev/zero of=/sub1/file bs=64K count=1 seek=$((i-1)) conv=notrunc oflag=direct
    done
    $ btrfs subvolume snapshot /sub1 /sub2
    $ for i in `seq 1 163840`; do
    dd if=/dev/zero of=/sub1/file bs=4K count=1 seek=$(((i-1)*16+10)) conv=notrunc oflag=direct
    done
    $ btrfs subvolume snapshot -r /sub1 /snap1
    $ time btrfs send /snap1 | btrfs receive /volume2

    Without this patch:

    real 69m48.124s
    user 0m50.199s
    sys 70m15.600s

    With this patch:

    real 1m59.683s
    user 0m35.421s
    sys 2m42.684s

    Reviewed-by: Josef Bacik
    Reviewed-by: Johannes Thumshirn
    Signed-off-by: ethanwu
    [ add patchset cover letter with background and numbers ]
    Signed-off-by: David Sterba

    ethanwu
     
  • We could have some nodes/leaves in subvolume whose owner are not the
    that subvolume. In this way, when we resolve normal backrefs of that
    subvolume, we should avoid collecting those references from these blocks.

    Reviewed-by: Josef Bacik
    Reviewed-by: Johannes Thumshirn
    Signed-off-by: ethanwu
    Signed-off-by: David Sterba

    ethanwu
     
  • All references from the block of SHARED_DATA_REF belong to that shared
    block backref.

    For example:

    item 11 key (40831553536 EXTENT_ITEM 4194304) itemoff 15460 itemsize 95
    extent refs 24 gen 7302 flags DATA
    extent data backref root 257 objectid 260 offset 65536 count 5
    extent data backref root 258 objectid 265 offset 0 count 9
    shared data backref parent 394985472 count 10

    Block 394985472 might be leaf from root 257, and the item obejctid and
    (file_pos - file_extent_item::offset) in that leaf just happens to be
    260 and 65536 which is equal to the first extent data backref entry.

    Before this patch, when we resolve backref:

    root 257 objectid 260 offset 65536

    we will add those refs in block 394985472 and wrongly treat those as the
    refs we want.

    Fix this by checking if the leaf we are processing is shared data
    backref, if so, just skip this leaf.

    Shared data refs added into preftrees.direct have all entry value = 0
    (root_id = 0, key = NULL, level = 0) except parent entry.

    Other refs from indirect tree will have key value and root id != 0, and
    these values won't be changed when their parent is resolved and added to
    preftrees.direct. Therefore, we could reuse the preftrees.direct and
    search ref with all values = 0 except parent is set to avoid getting
    those resolved refs block.

    Reviewed-by: Josef Bacik
    Reviewed-by: Johannes Thumshirn
    Signed-off-by: ethanwu
    Signed-off-by: David Sterba

    ethanwu
     
  • When resolving one backref of type EXTENT_DATA_REF, we collect all
    references that simply reference the EXTENT_ITEM even though their
    (file_pos - file_extent_item::offset) are not the same as the
    btrfs_extent_data_ref::offset we are searching for.

    This patch adds additional check so that we only collect references whose
    (file_pos - file_extent_item::offset) == btrfs_extent_data_ref::offset.

    Reviewed-by: Josef Bacik
    Reviewed-by: Johannes Thumshirn
    Signed-off-by: ethanwu
    Signed-off-by: David Sterba

    ethanwu
     
  • We are now using these for all roots, rename them to btrfs_put_root()
    and btrfs_grab_root();

    Reviewed-by: Nikolay Borisov
    Signed-off-by: Josef Bacik
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Josef Bacik
     
  • Now that all callers of btrfs_get_fs_root are subsequently calling
    btrfs_grab_fs_root and handling dropping the ref when they are done
    appropriately, go ahead and push btrfs_grab_fs_root up into
    btrfs_get_fs_root.

    Signed-off-by: Josef Bacik
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Josef Bacik
     
  • We're looking up a random root, we need to hold a ref on it while we're
    using it.

    Reviewed-by: David Sterba
    Signed-off-by: Josef Bacik
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Josef Bacik
     

31 Jul, 2019

1 commit

  • The fiemap handler locks a file range that can have unflushed delalloc,
    and after locking the range, it tries to attach to a running transaction.
    If the running transaction started its commit, that is, it is in state
    TRANS_STATE_COMMIT_START, and either the filesystem was mounted with the
    flushoncommit option or the transaction is creating a snapshot for the
    subvolume that contains the file that fiemap is operating on, we end up
    deadlocking. This happens because fiemap is blocked on the transaction,
    waiting for it to complete, and the transaction is waiting for the flushed
    dealloc to complete, which requires locking the file range that the fiemap
    task already locked. The following stack traces serve as an example of
    when this deadlock happens:

    (...)
    [404571.515510] Workqueue: btrfs-endio-write btrfs_endio_write_helper [btrfs]
    [404571.515956] Call Trace:
    [404571.516360] ? __schedule+0x3ae/0x7b0
    [404571.516730] schedule+0x3a/0xb0
    [404571.517104] lock_extent_bits+0x1ec/0x2a0 [btrfs]
    [404571.517465] ? remove_wait_queue+0x60/0x60
    [404571.517832] btrfs_finish_ordered_io+0x292/0x800 [btrfs]
    [404571.518202] normal_work_helper+0xea/0x530 [btrfs]
    [404571.518566] process_one_work+0x21e/0x5c0
    [404571.518990] worker_thread+0x4f/0x3b0
    [404571.519413] ? process_one_work+0x5c0/0x5c0
    [404571.519829] kthread+0x103/0x140
    [404571.520191] ? kthread_create_worker_on_cpu+0x70/0x70
    [404571.520565] ret_from_fork+0x3a/0x50
    [404571.520915] kworker/u8:6 D 0 31651 2 0x80004000
    [404571.521290] Workqueue: btrfs-flush_delalloc btrfs_flush_delalloc_helper [btrfs]
    (...)
    [404571.537000] fsstress D 0 13117 13115 0x00004000
    [404571.537263] Call Trace:
    [404571.537524] ? __schedule+0x3ae/0x7b0
    [404571.537788] schedule+0x3a/0xb0
    [404571.538066] wait_current_trans+0xc8/0x100 [btrfs]
    [404571.538349] ? remove_wait_queue+0x60/0x60
    [404571.538680] start_transaction+0x33c/0x500 [btrfs]
    [404571.539076] btrfs_check_shared+0xa3/0x1f0 [btrfs]
    [404571.539513] ? extent_fiemap+0x2ce/0x650 [btrfs]
    [404571.539866] extent_fiemap+0x2ce/0x650 [btrfs]
    [404571.540170] do_vfs_ioctl+0x526/0x6f0
    [404571.540436] ksys_ioctl+0x70/0x80
    [404571.540734] __x64_sys_ioctl+0x16/0x20
    [404571.540997] do_syscall_64+0x60/0x1d0
    [404571.541279] entry_SYSCALL_64_after_hwframe+0x49/0xbe
    (...)
    [404571.543729] btrfs D 0 14210 14208 0x00004000
    [404571.544023] Call Trace:
    [404571.544275] ? __schedule+0x3ae/0x7b0
    [404571.544526] ? wait_for_completion+0x112/0x1a0
    [404571.544795] schedule+0x3a/0xb0
    [404571.545064] schedule_timeout+0x1ff/0x390
    [404571.545351] ? lock_acquire+0xa6/0x190
    [404571.545638] ? wait_for_completion+0x49/0x1a0
    [404571.545890] ? wait_for_completion+0x112/0x1a0
    [404571.546228] wait_for_completion+0x131/0x1a0
    [404571.546503] ? wake_up_q+0x70/0x70
    [404571.546775] btrfs_wait_ordered_extents+0x27c/0x400 [btrfs]
    [404571.547159] btrfs_commit_transaction+0x3b0/0xae0 [btrfs]
    [404571.547449] ? btrfs_mksubvol+0x4a4/0x640 [btrfs]
    [404571.547703] ? remove_wait_queue+0x60/0x60
    [404571.547969] btrfs_mksubvol+0x605/0x640 [btrfs]
    [404571.548226] ? __sb_start_write+0xd4/0x1c0
    [404571.548512] ? mnt_want_write_file+0x24/0x50
    [404571.548789] btrfs_ioctl_snap_create_transid+0x169/0x1a0 [btrfs]
    [404571.549048] btrfs_ioctl_snap_create_v2+0x11d/0x170 [btrfs]
    [404571.549307] btrfs_ioctl+0x133f/0x3150 [btrfs]
    [404571.549549] ? mem_cgroup_charge_statistics+0x4c/0xd0
    [404571.549792] ? mem_cgroup_commit_charge+0x84/0x4b0
    [404571.550064] ? __handle_mm_fault+0xe3e/0x11f0
    [404571.550306] ? do_raw_spin_unlock+0x49/0xc0
    [404571.550608] ? _raw_spin_unlock+0x24/0x30
    [404571.550976] ? __handle_mm_fault+0xedf/0x11f0
    [404571.551319] ? do_vfs_ioctl+0xa2/0x6f0
    [404571.551659] ? btrfs_ioctl_get_supported_features+0x30/0x30 [btrfs]
    [404571.552087] do_vfs_ioctl+0xa2/0x6f0
    [404571.552355] ksys_ioctl+0x70/0x80
    [404571.552621] __x64_sys_ioctl+0x16/0x20
    [404571.552864] do_syscall_64+0x60/0x1d0
    [404571.553104] entry_SYSCALL_64_after_hwframe+0x49/0xbe
    (...)

    If we were joining the transaction instead of attaching to it, we would
    not risk a deadlock because a join only blocks if the transaction is in a
    state greater then or equals to TRANS_STATE_COMMIT_DOING, and the delalloc
    flush performed by a transaction is done before it reaches that state,
    when it is in the state TRANS_STATE_COMMIT_START. However a transaction
    join is intended for use cases where we do modify the filesystem, and
    fiemap only needs to peek at delayed references from the current
    transaction in order to determine if extents are shared, and, besides
    that, when there is no current transaction or when it blocks to wait for
    a current committing transaction to complete, it creates a new transaction
    without reserving any space. Such unnecessary transactions, besides doing
    unnecessary IO, can cause transaction aborts (-ENOSPC) and unnecessary
    rotation of the precious backup roots.

    So fix this by adding a new transaction join variant, named join_nostart,
    which behaves like the regular join, but it does not create a transaction
    when none currently exists or after waiting for a committing transaction
    to complete.

    Fixes: 03628cdbc64db6 ("Btrfs: do not start a transaction during fiemap")
    Signed-off-by: Filipe Manana
    Signed-off-by: David Sterba

    Filipe Manana
     

01 Jul, 2019

1 commit

  • btrfs_check_shared looks up parents of a given extent and uses ulists
    for that. These are allocated and freed repeatedly. Preallocation in the
    caller will avoid the overhead and also allow us to use the GFP_KERNEL
    as it is happens before the extent locks are taken.

    Reviewed-by: Nikolay Borisov
    Reviewed-by: Filipe Manana
    Signed-off-by: David Sterba

    David Sterba
     

30 Apr, 2019

3 commits

  • During fiemap, for regular extents (non inline) we need to check if they
    are shared and if they are, set the shared bit. Checking if an extent is
    shared requires checking the delayed references of the currently running
    transaction, since some reference might have not yet hit the extent tree
    and be only in the in-memory delayed references.

    However we were using a transaction join for this, which creates a new
    transaction when there is no transaction currently running. That means
    that two more potential failures can happen: creating the transaction and
    committing it. Further, if no write activity is currently happening in the
    system, and fiemap calls keep being done, we end up creating and
    committing transactions that do nothing.

    In some extreme cases this can result in the commit of the transaction
    created by fiemap to fail with ENOSPC when updating the root item of a
    subvolume tree because a join does not reserve any space, leading to a
    trace like the following:

    heisenberg kernel: ------------[ cut here ]------------
    heisenberg kernel: BTRFS: Transaction aborted (error -28)
    heisenberg kernel: WARNING: CPU: 0 PID: 7137 at fs/btrfs/root-tree.c:136 btrfs_update_root+0x22b/0x320 [btrfs]
    (...)
    heisenberg kernel: CPU: 0 PID: 7137 Comm: btrfs-transacti Not tainted 4.19.0-4-amd64 #1 Debian 4.19.28-2
    heisenberg kernel: Hardware name: FUJITSU LIFEBOOK U757/FJNB2A5, BIOS Version 1.21 03/19/2018
    heisenberg kernel: RIP: 0010:btrfs_update_root+0x22b/0x320 [btrfs]
    (...)
    heisenberg kernel: RSP: 0018:ffffb5448828bd40 EFLAGS: 00010286
    heisenberg kernel: RAX: 0000000000000000 RBX: ffff8ed56bccef50 RCX: 0000000000000006
    heisenberg kernel: RDX: 0000000000000007 RSI: 0000000000000092 RDI: ffff8ed6bda166a0
    heisenberg kernel: RBP: 00000000ffffffe4 R08: 00000000000003df R09: 0000000000000007
    heisenberg kernel: R10: 0000000000000000 R11: 0000000000000001 R12: ffff8ed63396a078
    heisenberg kernel: R13: ffff8ed092d7c800 R14: ffff8ed64f5db028 R15: ffff8ed6bd03d068
    heisenberg kernel: FS: 0000000000000000(0000) GS:ffff8ed6bda00000(0000) knlGS:0000000000000000
    heisenberg kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    heisenberg kernel: CR2: 00007f46f75f8000 CR3: 0000000310a0a002 CR4: 00000000003606f0
    heisenberg kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
    heisenberg kernel: DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
    heisenberg kernel: Call Trace:
    heisenberg kernel: commit_fs_roots+0x166/0x1d0 [btrfs]
    heisenberg kernel: ? _cond_resched+0x15/0x30
    heisenberg kernel: ? btrfs_run_delayed_refs+0xac/0x180 [btrfs]
    heisenberg kernel: btrfs_commit_transaction+0x2bd/0x870 [btrfs]
    heisenberg kernel: ? start_transaction+0x9d/0x3f0 [btrfs]
    heisenberg kernel: transaction_kthread+0x147/0x180 [btrfs]
    heisenberg kernel: ? btrfs_cleanup_transaction+0x530/0x530 [btrfs]
    heisenberg kernel: kthread+0x112/0x130
    heisenberg kernel: ? kthread_bind+0x30/0x30
    heisenberg kernel: ret_from_fork+0x35/0x40
    heisenberg kernel: ---[ end trace 05de912e30e012d9 ]---

    Since fiemap (and btrfs_check_shared()) is a read-only operation, do not do
    a transaction join to avoid the overhead of creating a new transaction (if
    there is currently no running transaction) and introducing a potential
    point of failure when the new transaction gets committed, instead use a
    transaction attach to grab a handle for the currently running transaction
    if any.

    Reported-by: Christoph Anton Mitterer
    Link: https://lore.kernel.org/linux-btrfs/b2a668d7124f1d3e410367f587926f622b3f03a4.camel@scientia.net/
    Fixes: afce772e87c36c ("btrfs: fix check_shared for fiemap ioctl")
    CC: stable@vger.kernel.org # 4.14+
    Reviewed-by: Qu Wenruo
    Signed-off-by: Filipe Manana
    Signed-off-by: David Sterba

    Filipe Manana
     
  • When finding out which inodes have references on a particular extent, done
    by backref.c:iterate_extent_inodes(), from the BTRFS_IOC_LOGICAL_INO (both
    v1 and v2) ioctl and from scrub we use the transaction join API to grab a
    reference on the currently running transaction, since in order to give
    accurate results we need to inspect the delayed references of the currently
    running transaction.

    However, if there is currently no running transaction, the join operation
    will create a new transaction. This is inefficient as the transaction will
    eventually be committed, doing unnecessary IO and introducing a potential
    point of failure that will lead to a transaction abort due to -ENOSPC, as
    recently reported [1].

    That's because the join, creates the transaction but does not reserve any
    space, so when attempting to update the root item of the root passed to
    btrfs_join_transaction(), during the transaction commit, we can end up
    failling with -ENOSPC. Users of a join operation are supposed to actually
    do some filesystem changes and reserve space by some means, which is not
    the case of iterate_extent_inodes(), it is a read-only operation for all
    contextes from which it is called.

    The reported [1] -ENOSPC failure stack trace is the following:

    heisenberg kernel: ------------[ cut here ]------------
    heisenberg kernel: BTRFS: Transaction aborted (error -28)
    heisenberg kernel: WARNING: CPU: 0 PID: 7137 at fs/btrfs/root-tree.c:136 btrfs_update_root+0x22b/0x320 [btrfs]
    (...)
    heisenberg kernel: CPU: 0 PID: 7137 Comm: btrfs-transacti Not tainted 4.19.0-4-amd64 #1 Debian 4.19.28-2
    heisenberg kernel: Hardware name: FUJITSU LIFEBOOK U757/FJNB2A5, BIOS Version 1.21 03/19/2018
    heisenberg kernel: RIP: 0010:btrfs_update_root+0x22b/0x320 [btrfs]
    (...)
    heisenberg kernel: RSP: 0018:ffffb5448828bd40 EFLAGS: 00010286
    heisenberg kernel: RAX: 0000000000000000 RBX: ffff8ed56bccef50 RCX: 0000000000000006
    heisenberg kernel: RDX: 0000000000000007 RSI: 0000000000000092 RDI: ffff8ed6bda166a0
    heisenberg kernel: RBP: 00000000ffffffe4 R08: 00000000000003df R09: 0000000000000007
    heisenberg kernel: R10: 0000000000000000 R11: 0000000000000001 R12: ffff8ed63396a078
    heisenberg kernel: R13: ffff8ed092d7c800 R14: ffff8ed64f5db028 R15: ffff8ed6bd03d068
    heisenberg kernel: FS: 0000000000000000(0000) GS:ffff8ed6bda00000(0000) knlGS:0000000000000000
    heisenberg kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    heisenberg kernel: CR2: 00007f46f75f8000 CR3: 0000000310a0a002 CR4: 00000000003606f0
    heisenberg kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
    heisenberg kernel: DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
    heisenberg kernel: Call Trace:
    heisenberg kernel: commit_fs_roots+0x166/0x1d0 [btrfs]
    heisenberg kernel: ? _cond_resched+0x15/0x30
    heisenberg kernel: ? btrfs_run_delayed_refs+0xac/0x180 [btrfs]
    heisenberg kernel: btrfs_commit_transaction+0x2bd/0x870 [btrfs]
    heisenberg kernel: ? start_transaction+0x9d/0x3f0 [btrfs]
    heisenberg kernel: transaction_kthread+0x147/0x180 [btrfs]
    heisenberg kernel: ? btrfs_cleanup_transaction+0x530/0x530 [btrfs]
    heisenberg kernel: kthread+0x112/0x130
    heisenberg kernel: ? kthread_bind+0x30/0x30
    heisenberg kernel: ret_from_fork+0x35/0x40
    heisenberg kernel: ---[ end trace 05de912e30e012d9 ]---

    So fix that by using the attach API, which does not create a transaction
    when there is currently no running transaction.

    [1] https://lore.kernel.org/linux-btrfs/b2a668d7124f1d3e410367f587926f622b3f03a4.camel@scientia.net/

    Reported-by: Zygo Blaxell
    CC: stable@vger.kernel.org # 4.4+
    Signed-off-by: Filipe Manana
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Filipe Manana
     
  • BUG_ON(1) leads to bogus warnings from clang when
    CONFIG_PROFILE_ANNOTATED_BRANCHES is set:

    fs/btrfs/volumes.c:5041:3: error: variable 'max_chunk_size' is used uninitialized whenever 'if' condition is false
    [-Werror,-Wsometimes-uninitialized]
    BUG_ON(1);
    ^~~~~~~~~
    include/asm-generic/bug.h:61:36: note: expanded from macro 'BUG_ON'
    #define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
    ^~~~~~~~~~~~~~~~~~~
    include/linux/compiler.h:48:23: note: expanded from macro 'unlikely'
    # define unlikely(x) (__branch_check__(x, 0, __builtin_constant_p(x)))
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    fs/btrfs/volumes.c:5046:9: note: uninitialized use occurs here
    max_chunk_size);
    ^~~~~~~~~~~~~~
    include/linux/kernel.h:860:36: note: expanded from macro 'min'
    #define min(x, y) __careful_cmp(x, y,
    Reviewed-by: David Sterba
    Signed-off-by: Arnd Bergmann
    Signed-off-by: David Sterba

    Arnd Bergmann
     

25 Feb, 2019

2 commits

  • Qgroups will do the old roots lookup at delayed ref time, which could be
    while walking down the extent root while running a delayed ref. This
    should be fine, except we specifically lock eb's in the backref walking
    code irrespective of path->skip_locking, which deadlocks the system.
    Fix up the backref code to honor path->skip_locking, nobody will be
    modifying the commit_root when we're searching so it's completely safe
    to do.

    This happens since fb235dc06fac ("btrfs: qgroup: Move half of the qgroup
    accounting time out of commit trans"), kernel may lockup with quota
    enabled.

    There is one backref trace triggered by snapshot dropping along with
    write operation in the source subvolume. The example can be reliably
    reproduced:

    btrfs-cleaner D 0 4062 2 0x80000000
    Call Trace:
    schedule+0x32/0x90
    btrfs_tree_read_lock+0x93/0x130 [btrfs]
    find_parent_nodes+0x29b/0x1170 [btrfs]
    btrfs_find_all_roots_safe+0xa8/0x120 [btrfs]
    btrfs_find_all_roots+0x57/0x70 [btrfs]
    btrfs_qgroup_trace_extent_post+0x37/0x70 [btrfs]
    btrfs_qgroup_trace_leaf_items+0x10b/0x140 [btrfs]
    btrfs_qgroup_trace_subtree+0xc8/0xe0 [btrfs]
    do_walk_down+0x541/0x5e3 [btrfs]
    walk_down_tree+0xab/0xe7 [btrfs]
    btrfs_drop_snapshot+0x356/0x71a [btrfs]
    btrfs_clean_one_deleted_snapshot+0xb8/0xf0 [btrfs]
    cleaner_kthread+0x12b/0x160 [btrfs]
    kthread+0x112/0x130
    ret_from_fork+0x27/0x50

    When dropping snapshots with qgroup enabled, we will trigger backref
    walk.

    However such backref walk at that timing is pretty dangerous, as if one
    of the parent nodes get WRITE locked by other thread, we could cause a
    dead lock.

    For example:

    FS 260 FS 261 (Dropped)
    node A node B
    / \ / \
    node C node D node E
    / \ / \ / \
    leaf F|leaf G|leaf H|leaf I|leaf J|leaf K

    The lock sequence would be:

    Thread A (cleaner) | Thread B (other writer)
    -----------------------------------------------------------------------
    write_lock(B) |
    write_lock(D) |
    ^^^ called by walk_down_tree() |
    | write_lock(A)
    | write_lock(D) << Stall
    read_lock(H) << for backref walk |
    read_lock(D) << lock owner is |
    the same thread A |
    so read lock is OK |
    read_lock(A) << Stall |

    So thread A hold write lock D, and needs read lock A to unlock.
    While thread B holds write lock A, while needs lock D to unlock.

    This will cause a deadlock.

    This is not only limited to snapshot dropping case. As the backref
    walk, even only happens on commit trees, is breaking the normal top-down
    locking order, makes it deadlock prone.

    Fixes: fb235dc06fac ("btrfs: qgroup: Move half of the qgroup accounting time out of commit trans")
    CC: stable@vger.kernel.org # 4.14+
    Reported-and-tested-by: David Sterba
    Reported-by: Filipe Manana
    Reviewed-by: Qu Wenruo
    Signed-off-by: Josef Bacik
    Reviewed-by: Filipe Manana
    [ rebase to latest branch and fix lock assert bug in btrfs/007 ]
    Signed-off-by: Qu Wenruo
    [ copy logs and deadlock analysis from Qu's patch ]
    Signed-off-by: David Sterba

    Josef Bacik
     
  • We can use the right helper where the lock type is a fixed parameter.

    Reviewed-by: Johannes Thumshirn
    Signed-off-by: David Sterba

    David Sterba
     

17 Dec, 2018

3 commits

  • The typos accumulate over time so once in a while time they get fixed in
    a large patch.

    Signed-off-by: Andrea Gelmini
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Andrea Gelmini
     
  • In iterate_inode_exrefs the eb is cloned via btrfs_clone_extent_buffer
    which creates a private extent buffer with the dummy flag set and ref
    count of 1. Then this buffer is locked for reading and its ref count is
    incremented by 1. Finally it's fed to the passed iterate_irefs_t
    function. The actual iterate call back is inode_to_path (coming from
    paths_from_inode) which feeds the eb to btrfs_ref_to_path. In this final
    function the passed eb is only read by first assigning it to the local
    eb variable. This variable is only modified in the case another eb was
    referenced from the passed path that is eb != eb_in check triggers.

    Considering this there is no point in locking the cloned eb in
    iterate_inode_refs since it's never being modified and is not published
    anywhere. Furthermore the cloned eb is completely fine having its ref
    count be 1.

    Signed-off-by: Nikolay Borisov
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Nikolay Borisov
     
  • In iterate_inode_refs the eb is cloned via btrfs_clone_extent_buffer
    which creates a private extent buffer with the dummy flag set and ref
    count of 1. Then this buffer is locked for reading and its ref count is
    incremented by 1. Finally it's fed to the passed iterate_irefs_t
    function. The actual iterate call back is inode_to_path (coming from
    paths_from_inode) which feeds the eb to btrfs_ref_to_path. In this final
    function the passed eb is only read by first assigning it to the local
    eb variable. This variable is only modified in the case another eb was
    referenced from the passed path that is eb != eb_in check triggers.

    Considering this there is no point in locking the cloned eb in
    iterate_inode_refs since it's never being modified and is not published
    anywhere. Furthermore the cloned eb is completely fine having its ref
    count be 1.

    Signed-off-by: Nikolay Borisov
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Nikolay Borisov
     

15 Oct, 2018

3 commits

  • rb_first_cached() trades an extra pointer "leftmost" for doing the same
    job as rb_first() but in O(1).

    While resolving indirect refs and missing refs, it always looks for the
    first rb entry in a while loop, it's helpful to use rb_first_cached
    instead.

    For more details about the optimization see patch "Btrfs: delayed-refs:
    use rb_first_cached for href_root".

    Tested-by: Holger Hoffstätte
    Signed-off-by: Liu Bo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Liu Bo
     
  • rb_first_cached() trades an extra pointer "leftmost" for doing the same
    job as rb_first() but in O(1).

    Functions manipulating href->ref_tree need to get the first entry, this
    converts href->ref_tree to use rb_first_cached().

    For more details about the optimization see patch "Btrfs: delayed-refs:
    use rb_first_cached for href_root".

    Tested-by: Holger Hoffstätte
    Signed-off-by: Liu Bo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Liu Bo
     
  • There are two members in struct btrfs_root which indicate root's
    objectid: objectid and root_key.objectid.

    They are both set to the same value in __setup_root():

    static void __setup_root(struct btrfs_root *root,
    struct btrfs_fs_info *fs_info,
    u64 objectid)
    {
    ...
    root->objectid = objectid;
    ...
    root->root_key.objectid = objecitd;
    ...
    }

    and not changed to other value after initialization.

    grep in btrfs directory shows both are used in many places:
    $ grep -rI "root->root_key.objectid" | wc -l
    133
    $ grep -rI "root->objectid" | wc -l
    55
    (4.17, inc. some noise)

    It is confusing to have two similar variable names and it seems
    that there is no rule about which should be used in a certain case.

    Since ->root_key itself is needed for tree reloc tree, let's remove
    'objecitd' member and unify code to use ->root_key.objectid in all places.

    Signed-off-by: Misono Tomohiro
    Reviewed-by: Qu Wenruo
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Misono Tomohiro
     

06 Aug, 2018

2 commits