30 Jun, 2017

1 commit

  • Dave Jones hit a WARN_ON(nr < 0) in btrfs_wait_ordered_roots() with
    v4.12-rc6. This was because commit 70e7af244 made it possible for
    calc_reclaim_items_nr() to return a negative number. It's not really a
    bug in that commit, it just didn't go far enough down the stack to find
    all the possible 64->32 bit overflows.

    This switches calc_reclaim_items_nr() to return a u64 and changes everyone
    that uses the results of that math to u64 as well.

    Reported-by: Dave Jones
    Fixes: 70e7af2 ("Btrfs: fix delalloc accounting leak caused by u32 overflow")
    Signed-off-by: Chris Mason
    Reviewed-by: David Sterba
    Signed-off-by: David Sterba

    Chris Mason
     

18 Apr, 2017

2 commits


28 Feb, 2017

1 commit


14 Feb, 2017

3 commits

  • Since we have a good helper entry_end, use it for ordered extent.

    Signed-off-by: Liu Bo
    Reviewed-by: David Sterba
    [ whitespace reformatting ]
    Signed-off-by: David Sterba

    Liu Bo
     
  • btrfs_ordered_update_i_size can be called by truncate and endio, but
    only endio takes ordered_extent which contains the completed IO.

    while truncating down a file, if there are some in-flight IOs,
    btrfs_ordered_update_i_size in endio will set disk_i_size to
    @orig_offset that is zero. If truncating-down fails somehow, we try to
    recover in memory isize with this zero'd disk_i_size.

    Fix it by only updating disk_i_size with @orig_offset when
    btrfs_ordered_update_i_size is not called from endio while truncating
    down and waiting for in-flight IOs completing their work before recover
    in-memory size.

    Besides fixing the above issue, add an assertion for last_size to double
    check we truncate down to the desired size.

    Signed-off-by: Liu Bo
    Signed-off-by: David Sterba

    Liu Bo
     
  • Signed-off-by: Nikolay Borisov
    Signed-off-by: David Sterba

    Nikolay Borisov
     

06 Dec, 2016

2 commits


27 Sep, 2016

1 commit

  • CodingStyle chapter 2:
    "[...] never break user-visible strings such as printk messages,
    because that breaks the ability to grep for them."

    This patch unsplits user-visible strings.

    Signed-off-by: Jeff Mahoney
    Signed-off-by: David Sterba

    Jeff Mahoney
     

26 Jul, 2016

1 commit

  • BTRFS is using a variety of slab caches to satisfy internal needs.
    Those slab caches are always allocated with the SLAB_RECLAIM_ACCOUNT,
    meaning allocations from the caches are going to be accounted as
    SReclaimable. At the same time btrfs is not registering any shrinkers
    whatsoever, thus preventing memory from the slabs to be shrunk. This
    means those caches are not in fact reclaimable.

    To fix this remove the SLAB_RECLAIM_ACCOUNT on all caches apart from the
    inode cache, since this one is being freed by the generic VFS super_block
    shrinker. Also set the transaction related caches as SLAB_TEMPORARY,
    to better document the lifetime of the objects (it just translates
    to SLAB_RECLAIM_ACCOUNT).

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

    Nikolay Borisov
     

24 Jun, 2016

1 commit

  • When doing truncate operation, btrfs_setsize() will first call
    truncate_setsize() to set new inode->i_size, but if later
    btrfs_truncate() fails, btrfs_setsize() will call
    "i_size_write(inode, BTRFS_I(inode)->disk_i_size)" to reset the
    inmemory inode size, now bug occurs. It's because for truncate
    case btrfs_ordered_update_i_size() directly uses inode->i_size
    to update BTRFS_I(inode)->disk_i_size, indeed we should use the
    "offset" argument to update disk_i_size. Here is the call graph:
    ==>btrfs_truncate()
    ====>btrfs_truncate_inode_items()
    ======>btrfs_ordered_update_i_size(inode, last_size, NULL);
    Here btrfs_ordered_update_i_size()'s offset argument is last_size.

    And below test case can reveal this bug:

    dd if=/dev/zero of=fs.img bs=$((1024*1024)) count=100
    dev=$(losetup --show -f fs.img)
    mkdir -p /mnt/mntpoint
    mkfs.btrfs -f $dev
    mount $dev /mnt/mntpoint
    cd /mnt/mntpoint

    echo "workdir is: /mnt/mntpoint"
    blocksize=$((128 * 1024))
    dd if=/dev/zero of=testfile bs=$blocksize count=1
    sync
    count=$((17*1024*1024*1024/blocksize))
    echo "file size is:" $((count*blocksize))
    for ((i = 1; i /dev/null
    done
    sync

    truncate --size 0 testfile
    ls -l testfile
    du -sh testfile
    exit

    In this case, truncate operation will fail for enospc reason and
    "du -sh testfile" returns value greater than 0, but testfile's
    size is 0, we need to reflect correct inode->i_size.

    Signed-off-by: Wang Xiaoguang
    Signed-off-by: David Sterba
    Signed-off-by: Chris Mason

    Wang Xiaoguang
     

30 May, 2016

1 commit

  • When we do a device replace, for each device extent we find from the
    source device, we set the corresponding block group to readonly mode to
    prevent writes into it from happening while we are copying the device
    extent from the source to the target device. However just before we set
    the block group to readonly mode some concurrent task might have already
    allocated an extent from it or decided it could perform a nocow write
    into one of its extents, which can make the device replace process to
    miss copying an extent since it uses the extent tree's commit root to
    search for extents and only once it finishes searching for all extents
    belonging to the block group it does set the left cursor to the logical
    end address of the block group - this is a problem if the respective
    ordered extents finish while we are searching for extents using the
    extent tree's commit root and no transaction commit happens while we
    are iterating the tree, since it's the delayed references created by the
    ordered extents (when they complete) that insert the extent items into
    the extent tree (using the non-commit root of course).
    Example:

    CPU 1 CPU 2

    btrfs_dev_replace_start()
    btrfs_scrub_dev()
    scrub_enumerate_chunks()
    --> finds device extent belonging
    to block group X

    starts buffered write
    against some inode

    writepages is run against
    that inode forcing dellaloc
    to run

    btrfs_writepages()
    extent_writepages()
    extent_write_cache_pages()
    __extent_writepage()
    writepage_delalloc()
    run_delalloc_range()
    cow_file_range()
    btrfs_reserve_extent()
    --> allocates an extent
    from block group X
    (which is not yet
    in RO mode)
    btrfs_add_ordered_extent()
    --> creates ordered extent Y
    flush_epd_write_bio()
    --> bio against the extent from
    block group X is submitted

    btrfs_inc_block_group_ro(bg X)
    --> sets block group X to readonly

    scrub_chunk(bg X)
    scrub_stripe(device extent from srcdev)
    --> keeps searching for extent items
    belonging to the block group using
    the extent tree's commit root
    --> it never blocks due to
    fs_info->scrub_pause_req as no
    one tries to commit transaction N
    --> copies all extents found from the
    source device into the target device
    --> finishes search loop

    bio completes

    ordered extent Y completes
    and creates delayed data
    reference which will add an
    extent item to the extent
    tree when run (typically
    at transaction commit time)

    --> so the task doing the
    scrub/device replace
    at CPU 1 misses this
    and does not copy this
    extent into the new/target
    device

    btrfs_dec_block_group_ro(bg X)
    --> turns block group X back to RW mode

    dev_replace->cursor_left is set to the
    logical end offset of block group X

    So fix this by waiting for all cow and nocow writes after setting a block
    group to readonly mode.

    Signed-off-by: Filipe Manana
    Reviewed-by: Josef Bacik

    Filipe Manana
     

13 May, 2016

1 commit

  • Before the relocation process of a block group starts, it sets the block
    group to readonly mode, then flushes all delalloc writes and then finally
    it waits for all ordered extents to complete. This last step includes
    waiting for ordered extents destinated at extents allocated in other block
    groups, making us waste unecessary time.

    So improve this by waiting only for ordered extents that fall into the
    block group's range.

    Signed-off-by: Filipe Manana
    Reviewed-by: Josef Bacik
    Reviewed-by: Liu Bo

    Filipe Manana
     

14 Mar, 2016

1 commit


12 Mar, 2016

1 commit


18 Feb, 2016

1 commit


22 Oct, 2015

1 commit

  • We have a mechanism to make sure we don't lose updates for ordered extents that
    were logged in the transaction that is currently running. We add the ordered
    extent to a transaction list and then the transaction waits on all the ordered
    extents in that list. However are substantially large file systems this list
    can be extremely large, and can give us soft lockups, since the ordered extents
    don't remove themselves from the list when they do complete.

    To fix this we simply add a counter to the transaction that is incremented any
    time we have a logged extent that needs to be completed in the current
    transaction. Then when the ordered extent finally completes it decrements the
    per transaction counter and wakes up the transaction if we are the last ones.
    This will eliminate the softlockup. Thanks,

    Signed-off-by: Josef Bacik
    Signed-off-by: Chris Mason

    Josef Bacik
     

11 Oct, 2015

1 commit


02 Jul, 2015

1 commit

  • If we fail to submit a bio for a direct IO request, we were grabbing the
    corresponding ordered extent and decrementing its reference count twice,
    once for our lookup reference and once for the ordered tree reference.
    This was a problem because it caused the ordered extent to be freed
    without removing it from the ordered tree and any lists it might be
    attached to, leaving dangling pointers to the ordered extent around.
    Example trace with CONFIG_DEBUG_PAGEALLOC=y:

    [161779.858707] BUG: unable to handle kernel paging request at 0000000087654330
    [161779.859983] IP: [] rb_prev+0x22/0x3b
    [161779.860636] PGD 34d818067 PUD 0
    [161779.860636] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC
    (...)
    [161779.860636] Call Trace:
    [161779.860636] [] __tree_search+0xd9/0xf9 [btrfs]
    [161779.860636] [] tree_search+0x42/0x63 [btrfs]
    [161779.860636] [] ? btrfs_lookup_ordered_range+0x2d/0xa5 [btrfs]
    [161779.860636] [] btrfs_lookup_ordered_range+0x38/0xa5 [btrfs]
    [161779.860636] [] btrfs_get_blocks_direct+0x11b/0x615 [btrfs]
    [161779.860636] [] do_blockdev_direct_IO+0x5ff/0xb43
    [161779.860636] [] ? btrfs_page_exists_in_range+0x1ad/0x1ad [btrfs]
    [161779.860636] [] ? btrfs_get_extent_fiemap+0x1bc/0x1bc [btrfs]
    [161779.860636] [] __blockdev_direct_IO+0x32/0x34
    [161779.860636] [] ? btrfs_get_extent_fiemap+0x1bc/0x1bc [btrfs]
    [161779.860636] [] btrfs_direct_IO+0x198/0x21f [btrfs]
    [161779.860636] [] ? btrfs_get_extent_fiemap+0x1bc/0x1bc [btrfs]
    [161779.860636] [] generic_file_direct_write+0xb3/0x128
    [161779.860636] [] ? btrfs_file_write_iter+0x15f/0x3e0 [btrfs]
    [161779.860636] [] btrfs_file_write_iter+0x201/0x3e0 [btrfs]
    (...)

    We were also not freeing the btrfs_dio_private we allocated previously,
    which kmemleak reported with the following trace in its sysfs file:

    unreferenced object 0xffff8803f553bf80 (size 96):
    comm "xfs_io", pid 4501, jiffies 4295039588 (age 173.936s)
    hex dump (first 32 bytes):
    88 6c 9b f5 02 88 ff ff 00 00 00 00 00 00 00 00 .l..............
    00 00 00 00 00 00 00 00 00 00 c4 00 00 00 00 00 ................
    backtrace:
    [] create_object+0x172/0x29a
    [] kmemleak_alloc+0x25/0x41
    [] kmemleak_alloc_recursive.constprop.40+0x16/0x18
    [] kmem_cache_alloc_trace+0xfb/0x148
    [] btrfs_submit_direct+0x65/0x16a [btrfs]
    [] dio_bio_submit+0x62/0x8f
    [] do_blockdev_direct_IO+0x97e/0xb43
    [] __blockdev_direct_IO+0x32/0x34
    [] btrfs_direct_IO+0x198/0x21f [btrfs]
    [] generic_file_direct_write+0xb3/0x128
    [] btrfs_file_write_iter+0x201/0x3e0 [btrfs]
    [] __vfs_write+0x7c/0xa5
    [] vfs_write+0xa0/0xe4
    [] SyS_pwrite64+0x64/0x82
    [] system_call_fastpath+0x12/0x6f
    [] 0xffffffffffffffff

    For read requests we weren't doing any cleanup either (none of the work
    done by btrfs_endio_direct_read()), so a failure submitting a bio for a
    read request would leave a range in the inode's io_tree locked forever,
    blocking any future operations (both reads and writes) against that range.

    So fix this by making sure we do the same cleanup that we do for the case
    where the bio submission succeeds.

    Signed-off-by: Filipe Manana
    Signed-off-by: Chris Mason

    Filipe Manana
     

10 Jun, 2015

2 commits

  • We don't need to attach ordered extents that have completed to the current
    transaction. Doing so only makes us hold memory for longer than necessary
    and delaying the iput of the inode until the transaction is committed (for
    each created ordered extent we do an igrab and then schedule an asynchronous
    iput when the ordered extent's reference count drops to 0), preventing the
    inode from being evictable until the transaction commits.

    Signed-off-by: Filipe Manana
    Signed-off-by: Chris Mason

    Filipe Manana
     
  • Commit 3a8b36f37806 ("Btrfs: fix data loss in the fast fsync path") added
    a performance regression for that causes an unnecessary sync of the log
    trees (fs/subvol and root log trees) when 2 consecutive fsyncs are done
    against a file, without no writes or any metadata updates to the inode in
    between them and if a transaction is committed before the second fsync is
    called.

    Huang Ying reported this to lkml (https://lkml.org/lkml/2015/3/18/99)
    after a test sysbench test that measured a -62% decrease of file io
    requests per second for that tests' workload.

    The test is:

    echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
    echo performance > /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor
    echo performance > /sys/devices/system/cpu/cpu2/cpufreq/scaling_governor
    echo performance > /sys/devices/system/cpu/cpu3/cpufreq/scaling_governor
    mkfs -t btrfs /dev/sda2
    mount -t btrfs /dev/sda2 /fs/sda2
    cd /fs/sda2
    for ((i = 0; i < 1024; i++)); do fallocate -l 67108864 testfile.$i; done
    sysbench --test=fileio --max-requests=0 --num-threads=4 --max-time=600 \
    --file-test-mode=rndwr --file-total-size=68719476736 --file-io-mode=sync \
    --file-num=1024 run

    A test on kvm guest, running a debug kernel gave me the following results:

    Without 3a8b36f378060d: 16.01 reqs/sec
    With 3a8b36f378060d: 3.39 reqs/sec
    With 3a8b36f378060d and this patch: 16.04 reqs/sec

    Reported-by: Huang Ying
    Tested-by: Huang, Ying
    Signed-off-by: Filipe Manana
    Signed-off-by: Chris Mason

    Filipe Manana
     

03 Jun, 2015

1 commit

  • After commit 8407f553268a
    ("Btrfs: fix data corruption after fast fsync and writeback error"),
    during wait_ordered_extents(), we wait for ordered extent setting
    BTRFS_ORDERED_IO_DONE or BTRFS_ORDERED_IOERR, at which point we've
    already got checksum information, so we don't need to check
    (csum_bytes_left == 0) in the whole logging path.

    Signed-off-by: Liu Bo
    Signed-off-by: Chris Mason

    Liu Bo
     

11 May, 2015

1 commit

  • When waiting for the writeback of block group cache we returned
    immediately if there was an error during writeback without waiting
    for the ordered extent to complete. This left a short time window
    where if some other task attempts to start the writeout for the same
    block group cache it can attempt to add a new ordered extent, starting
    at the same offset (0) before the previous one is removed from the
    ordered tree, causing an ordered tree panic (calls BUG()).

    This normally doesn't happen in other write paths, such as buffered
    writes or direct IO writes for regular files, since before marking
    page ranges dirty we lock the ranges and wait for any ordered extents
    within the range to complete first.

    Fix this by making btrfs_wait_ordered_range() not return immediately
    if it gets an error from the writeback, waiting for all ordered extents
    to complete first.

    This issue happened often when running the fstest btrfs/088 and it's
    easy to trigger it by running in a loop until the panic happens:

    for ((i = 1; i ] btrfs_add_ordered_extent+0x12/0x14 [btrfs]
    [17156.864052] [] run_delalloc_nocow+0x5bf/0x747 [btrfs]
    [17156.864052] [] run_delalloc_range+0x95/0x353 [btrfs]
    [17156.864052] [] writepage_delalloc.isra.16+0xb9/0x13f [btrfs]
    [17156.864052] [] __extent_writepage+0x129/0x1f7 [btrfs]
    [17156.864052] [] extent_write_cache_pages.isra.15.constprop.28+0x231/0x2f4 [btrfs]
    [17156.864052] [] ? __module_text_address+0x12/0x59
    [17156.864052] [] ? trace_hardirqs_on+0xd/0xf
    [17156.864052] [] extent_writepages+0x4b/0x5c [btrfs]
    [17156.864052] [] ? kmem_cache_free+0x9b/0xce
    [17156.864052] [] ? btrfs_submit_direct+0x3fc/0x3fc [btrfs]
    [17156.864052] [] ? free_extent_state+0x8c/0xc1 [btrfs]
    [17156.864052] [] btrfs_writepages+0x28/0x2a [btrfs]
    [17156.864052] [] do_writepages+0x23/0x2c
    [17156.864052] [] __filemap_fdatawrite_range+0x5a/0x61
    [17156.864052] [] filemap_fdatawrite_range+0x13/0x15
    [17156.864052] [] btrfs_fdatawrite_range+0x21/0x48 [btrfs]
    [17156.864052] [] __btrfs_write_out_cache.isra.14+0x2d9/0x3a7 [btrfs]
    [17156.864052] [] ? btrfs_write_out_cache+0x41/0xdc [btrfs]
    [17156.864052] [] btrfs_write_out_cache+0x93/0xdc [btrfs]
    [17156.864052] [] ? btrfs_start_dirty_block_groups+0x13a/0x2b2 [btrfs]
    [17156.864052] [] btrfs_start_dirty_block_groups+0x1d9/0x2b2 [btrfs]
    [17156.864052] [] ? trace_hardirqs_on+0xd/0xf
    [17156.864052] [] btrfs_commit_transaction+0x130/0x9c9 [btrfs]
    [17156.864052] [] btrfs_sync_fs+0xe1/0x12d [btrfs]

    Signed-off-by: Filipe Manana
    Signed-off-by: Chris Mason

    Filipe Manana
     

03 Mar, 2015

1 commit

  • We can have multiple fsync operations against the same file during the
    same transaction and they can collect the same ordered extents while they
    don't complete (still accessible from the inode's ordered tree). If this
    happens, those ordered extents will never get their reference counts
    decremented to 0, leading to memory leaks and inode leaks (an iput for an
    ordered extent's inode is scheduled only when the ordered extent's refcount
    drops to 0). The following sequence diagram explains this race:

    CPU 1 CPU 2

    btrfs_sync_file()

    btrfs_sync_file()

    mutex_lock(inode->i_mutex)
    btrfs_log_inode()
    btrfs_get_logged_extents()
    --> collects ordered extent X
    --> increments ordered
    extent X's refcount
    btrfs_submit_logged_extents()
    mutex_unlock(inode->i_mutex)

    mutex_lock(inode->i_mutex)
    btrfs_sync_log()
    btrfs_wait_logged_extents()
    --> list_del_init(&ordered->log_list)
    btrfs_log_inode()
    btrfs_get_logged_extents()
    --> Adds ordered extent X
    to logged_list because
    at this point:
    list_empty(&ordered->log_list)
    && test_bit(BTRFS_ORDERED_LOGGED,
    &ordered->flags) == 0
    --> Increments ordered extent
    X's refcount
    --> check if ordered extent's io is
    finished or not, start it if
    necessary and wait for it to finish
    --> sets bit BTRFS_ORDERED_LOGGED
    on ordered extent X's flags
    and adds it to trans->ordered
    btrfs_sync_log() finishes

    btrfs_submit_logged_extents()
    btrfs_log_inode() finishes
    mutex_unlock(inode->i_mutex)

    btrfs_sync_file() finishes

    btrfs_sync_log()
    btrfs_wait_logged_extents()
    --> Sees ordered extent X has the
    bit BTRFS_ORDERED_LOGGED set in
    its flags
    --> X's refcount is untouched
    btrfs_sync_log() finishes

    btrfs_sync_file() finishes

    btrfs_commit_transaction()
    --> called by transaction kthread for e.g.
    btrfs_wait_pending_ordered()
    --> waits for ordered extent X to
    complete
    --> decrements ordered extent X's
    refcount by 1 only, corresponding
    to the increment done by the fsync
    task ran by CPU 1

    In the scenario of the above diagram, after the transaction commit,
    the ordered extent will remain with a refcount of 1 forever, leaking
    the ordered extent structure and preventing the i_count of its inode
    from ever decreasing to 0, since the delayed iput is scheduled only
    when the ordered extent's refcount drops to 0, preventing the inode
    from ever being evicted by the VFS.

    Fix this by using the flag BTRFS_ORDERED_LOGGED differently. Use it to
    mean that an ordered extent is already being processed by an fsync call,
    which will attach it to the current transaction, preventing it from being
    collected by subsequent fsync operations against the same inode.

    This race was introduced with the following change (added in 3.19 and
    backported to stable 3.18 and 3.17):

    Btrfs: make sure logged extents complete in the current transaction V3
    commit 50d9aa99bd35c77200e0e3dd7a72274f8304701f

    I ran into this issue while running xfstests/generic/113 in a loop, which
    failed about 1 out of 10 runs with the following warning in dmesg:

    [ 2612.440038] WARNING: CPU: 4 PID: 22057 at fs/btrfs/disk-io.c:3558 free_fs_root+0x36/0x133 [btrfs]()
    [ 2612.442810] Modules linked in: btrfs crc32c_generic xor raid6_pq nfsd auth_rpcgss oid_registry nfs_acl nfs lockd grace fscache sunrpc loop processor parport_pc parport psmouse therma
    l_sys i2c_piix4 serio_raw pcspkr evdev microcode button i2c_core ext4 crc16 jbd2 mbcache sd_mod sg sr_mod cdrom virtio_scsi ata_generic virtio_pci ata_piix virtio_ring libata virtio flo
    ppy e1000 scsi_mod [last unloaded: btrfs]
    [ 2612.452711] CPU: 4 PID: 22057 Comm: umount Tainted: G W 3.19.0-rc5-btrfs-next-4+ #1
    [ 2612.454921] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
    [ 2612.457709] 0000000000000009 ffff8801342c3c78 ffffffff8142425e ffff88023ec8f2d8
    [ 2612.459829] 0000000000000000 ffff8801342c3cb8 ffffffff81045308 ffff880046460000
    [ 2612.461564] ffffffffa036da56 ffff88003d07b000 ffff880046460000 ffff880046460068
    [ 2612.463163] Call Trace:
    [ 2612.463719] [] dump_stack+0x4c/0x65
    [ 2612.464789] [] warn_slowpath_common+0xa1/0xbb
    [ 2612.466026] [] ? free_fs_root+0x36/0x133 [btrfs]
    [ 2612.467247] [] warn_slowpath_null+0x1a/0x1c
    [ 2612.468416] [] free_fs_root+0x36/0x133 [btrfs]
    [ 2612.469625] [] btrfs_drop_and_free_fs_root+0x93/0x9b [btrfs]
    [ 2612.471251] [] btrfs_free_fs_roots+0xa4/0xd6 [btrfs]
    [ 2612.472536] [] ? wait_for_completion+0x24/0x26
    [ 2612.473742] [] close_ctree+0x1f3/0x33c [btrfs]
    [ 2612.475477] [] ? destroy_workqueue+0x148/0x1ba
    [ 2612.476695] [] btrfs_put_super+0x19/0x1b [btrfs]
    [ 2612.477911] [] generic_shutdown_super+0x73/0xef
    [ 2612.479106] [] kill_anon_super+0x13/0x1e
    [ 2612.480226] [] btrfs_kill_super+0x17/0x23 [btrfs]
    [ 2612.481471] [] deactivate_locked_super+0x3b/0x50
    [ 2612.482686] [] deactivate_super+0x3f/0x43
    [ 2612.483791] [] cleanup_mnt+0x59/0x78
    [ 2612.484842] [] __cleanup_mnt+0x12/0x14
    [ 2612.485900] [] task_work_run+0x8f/0xbc
    [ 2612.486960] [] do_notify_resume+0x5a/0x6b
    [ 2612.488083] [] ? trace_hardirqs_on_thunk+0x3a/0x3f
    [ 2612.489333] [] int_signal+0x12/0x17
    [ 2612.490353] ---[ end trace 54a960a6bdcb8d93 ]---
    [ 2612.557253] VFS: Busy inodes after unmount of sdb. Self-destruct in 5 seconds. Have a nice day...

    Kmemleak confirmed the ordered extent leak (and btrfs inode specific
    structures such as delayed nodes):

    $ cat /sys/kernel/debug/kmemleak
    unreferenced object 0xffff880154290db0 (size 576):
    comm "btrfsck", pid 21980, jiffies 4295542503 (age 1273.412s)
    hex dump (first 32 bytes):
    01 40 00 00 01 00 00 00 b0 1d f1 4e 01 88 ff ff .@.........N....
    00 00 00 00 00 00 00 00 c8 0d 29 54 01 88 ff ff ..........)T....
    backtrace:
    [] kmemleak_update_trace+0x4c/0x6a
    [] radix_tree_node_alloc+0x6d/0x83
    [] __radix_tree_create+0x109/0x190
    [] radix_tree_insert+0x30/0xac
    [] btrfs_get_or_create_delayed_node+0x130/0x187 [btrfs]
    [] btrfs_delayed_delete_inode_ref+0x32/0xac [btrfs]
    [] __btrfs_unlink_inode+0xee/0x288 [btrfs]
    [] btrfs_unlink_inode+0x1e/0x40 [btrfs]
    [] btrfs_unlink+0x60/0x9b [btrfs]
    [] vfs_unlink+0x9c/0xed
    [] do_unlinkat+0x12c/0x1fa
    [] SyS_unlinkat+0x29/0x2b
    [] system_call_fastpath+0x12/0x17
    [] 0xffffffffffffffff
    unreferenced object 0xffff88014ef11db0 (size 576):
    comm "rm", pid 22009, jiffies 4295542593 (age 1273.052s)
    hex dump (first 32 bytes):
    02 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
    00 00 00 00 00 00 00 00 c8 1d f1 4e 01 88 ff ff ...........N....
    backtrace:
    [] kmemleak_update_trace+0x4c/0x6a
    [] radix_tree_node_alloc+0x6d/0x83
    [] __radix_tree_create+0x109/0x190
    [] radix_tree_insert+0x30/0xac
    [] btrfs_get_or_create_delayed_node+0x130/0x187 [btrfs]
    [] btrfs_delayed_delete_inode_ref+0x32/0xac [btrfs]
    [] __btrfs_unlink_inode+0xee/0x288 [btrfs]
    [] btrfs_unlink_inode+0x1e/0x40 [btrfs]
    [] btrfs_unlink+0x60/0x9b [btrfs]
    [] vfs_unlink+0x9c/0xed
    [] do_unlinkat+0x12c/0x1fa
    [] SyS_unlinkat+0x29/0x2b
    [] system_call_fastpath+0x12/0x17
    [] 0xffffffffffffffff
    unreferenced object 0xffff8800336feda8 (size 584):
    comm "aio-stress", pid 22031, jiffies 4295543006 (age 1271.400s)
    hex dump (first 32 bytes):
    00 40 3e 00 00 00 00 00 00 00 8f 42 00 00 00 00 .@>........B....
    00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 00 ................
    backtrace:
    [] create_object+0x172/0x29a
    [] kmemleak_alloc+0x25/0x41
    [] kmemleak_alloc_recursive.constprop.52+0x16/0x18
    [] kmem_cache_alloc+0xf7/0x198
    [] __btrfs_add_ordered_extent+0x43/0x309 [btrfs]
    [] btrfs_add_ordered_extent_dio+0x12/0x14 [btrfs]
    [] btrfs_get_blocks_direct+0x3ef/0x571 [btrfs]
    [] do_blockdev_direct_IO+0x62a/0xb47
    [] __blockdev_direct_IO+0x34/0x36
    [] btrfs_direct_IO+0x16a/0x1e8 [btrfs]
    [] generic_file_direct_write+0xb8/0x12d
    [] btrfs_file_write_iter+0x24b/0x42f [btrfs]
    [] aio_run_iocb+0x2b7/0x32e
    [] do_io_submit+0x26e/0x2ff
    [] SyS_io_submit+0x10/0x12
    [] system_call_fastpath+0x12/0x17

    CC: # 3.19, 3.18 and 3.17
    Signed-off-by: Filipe Manana
    Signed-off-by: Chris Mason

    Filipe Manana
     

22 Nov, 2014

2 commits

  • Instead of collecting all ordered extents from the inode's ordered tree
    and then wait for all of them to complete, just collect the ones that
    overlap the fsync range.

    Signed-off-by: Filipe Manana
    Signed-off-by: Chris Mason

    Filipe Manana
     
  • Liu Bo pointed out that my previous fix would lose the generation update in the
    scenario I described. It is actually much worse than that, we could lose the
    entire extent if we lose power right after the transaction commits. Consider
    the following

    write extent 0-4k
    log extent in log tree
    commit transaction
    < power fail happens here
    ordered extent completes

    We would lose the 0-4k extent because it hasn't updated the actual fs tree, and
    the transaction commit will reset the log so it isn't replayed. If we lose
    power before the transaction commit we are save, otherwise we are not.

    Fix this by keeping track of all extents we logged in this transaction. Then
    when we go to commit the transaction make sure we wait for all of those ordered
    extents to complete before proceeding. This will make sure that if we lose
    power after the transaction commit we still have our data. This also fixes the
    problem of the improperly updated extent generation. Thanks,

    cc: stable@vger.kernel.org
    Signed-off-by: Josef Bacik
    Signed-off-by: Chris Mason

    Josef Bacik
     

21 Nov, 2014

1 commit


24 Aug, 2014

1 commit

  • This has been reported and discussed for a long time, and this hang occurs in
    both 3.15 and 3.16.

    Btrfs now migrates to use kernel workqueue, but it introduces this hang problem.

    Btrfs has a kind of work queued as an ordered way, which means that its
    ordered_func() must be processed in the way of FIFO, so it usually looks like --

    normal_work_helper(arg)
    work = container_of(arg, struct btrfs_work, normal_work);

    work->func() ordered_list
    ordered_work->ordered_func()
    ordered_work->ordered_free()

    The hang is a rare case, first when we find free space, we get an uncached block
    group, then we go to read its free space cache inode for free space information,
    so it will

    file a readahead request
    btrfs_readpages()
    for page that is not in page cache
    __do_readpage()
    submit_extent_page()
    btrfs_submit_bio_hook()
    btrfs_bio_wq_end_io()
    submit_bio()
    end_workqueue_bio() current_work = arg; normal_work
    worker->current_func(arg)
    normal_work_helper(arg)
    A = container_of(arg, struct btrfs_work, normal_work);

    A->func()
    A->ordered_func()
    A->ordered_free() ordered_func()
    submit_compressed_extents()
    find_free_extent()
    load_free_space_inode()
    ... ordered_free()

    As if work A has a high priority in wq->ordered_list and there are more ordered
    works queued after it, such as B->ordered_func(), its memory could have been
    freed before normal_work_helper() returns, which means that kernel workqueue
    code worker_thread() still has worker->current_work pointer to be work
    A->normal_work's, ie. arg's address.

    Meanwhile, work C is allocated after work A is freed, work C->normal_work
    and work A->normal_work are likely to share the same address(I confirmed this
    with ftrace output, so I'm not just guessing, it's rare though).

    When another kthread picks up work C->normal_work to process, and finds our
    kthread is processing it(see find_worker_executing_work()), it'll think
    work C as a collision and skip then, which ends up nobody processing work C.

    So the situation is that our kthread is waiting forever on work C.

    Besides, there're other cases that can lead to deadlock, but the real problem
    is that all btrfs workqueue shares one work->func, -- normal_work_helper,
    so this makes each workqueue to have its own helper function, but only a
    wraper pf normal_work_helper.

    With this patch, I no long hit the above hang.

    Signed-off-by: Liu Bo
    Signed-off-by: Chris Mason

    Liu Bo
     

15 Aug, 2014

1 commit

  • Truncates and renames are often used to replace old versions of a file
    with new versions. Applications often expect this to be an atomic
    replacement, even if they haven't done anything to make sure the new
    version is fully on disk.

    Btrfs has strict flushing in place to make sure that renaming over an
    old file with a new file will fully flush out the new file before
    allowing the transaction commit with the rename to complete.

    This ordering means the commit code needs to be able to lock file pages,
    and there are a few paths in the filesystem where we will try to end a
    transaction with the page lock held. It's rare, but these things can
    deadlock.

    This patch removes the ordered flushes and switches to a best effort
    filemap_flush like ext4 uses. It's not perfect, but it should fix the
    deadlocks.

    Signed-off-by: Chris Mason

    Chris Mason
     

20 Jul, 2014

1 commit

  • xfstests generic/127 detected this problem.

    With commit 7fc34a62ca4434a79c68e23e70ed26111b7a4cf8, now fsync will only flush
    data within the passed range. This is the cause of the above problem,
    -- btrfs's fsync has a stage called 'sync log' which will wait for all the
    ordered extents it've recorded to finish.

    In xfstests/generic/127, with mixed operations such as truncate, fallocate,
    punch hole, and mapwrite, we get some pre-allocated extents, and mapwrite will
    mmap, and then msync. And I find that msync will wait for quite a long time
    (about 20s in my case), thanks to ftrace, it turns out that the previous
    fallocate calls 'btrfs_wait_ordered_range()' to flush dirty pages, but as the
    range of dirty pages may be larger than 'btrfs_wait_ordered_range()' wants,
    there can be some ordered extents created but not getting corresponding pages
    flushed, then they're left in memory until we fsync which runs into the
    stage 'sync log', and fsync will just wait for the system writeback thread
    to flush those pages and get ordered extents finished, so the latency is
    inevitable.

    This adds a flush similar to btrfs_start_ordered_extent() in
    btrfs_wait_logged_extents() to fix that.

    Reviewed-by: Miao Xie
    Signed-off-by: Liu Bo
    Signed-off-by: Chris Mason

    Liu Bo
     

10 Jun, 2014

1 commit


11 Mar, 2014

6 commits

  • When we create a snapshot, we just need wait the ordered extents in
    the source fs/file root, but because we use the global mutex to protect
    this ordered extents list of the source fs/file root to avoid accessing
    a empty list, if someone got the mutex to access the ordered extents list
    of the other fs/file root, we had to wait.

    This patch splits the above global mutex, now every fs/file root has
    its own mutex to protect its own list.

    Signed-off-by: Miao Xie
    Signed-off-by: Josef Bacik

    Miao Xie
     
  • The tasks that wait for the IO_DONE flag just care about the io of the dirty
    pages, so it is better to wake up them immediately after all the pages are
    written, not the whole process of the io completes.

    Signed-off-by: Miao Xie
    Signed-off-by: Josef Bacik

    Miao Xie
     
  • btrfs_wait_ordered_roots() moves all the list entries to a new list,
    and then deals with them one by one. But if the other task invokes this
    function at that time, it would get a empty list. It makes the enospc
    error happens more early. Fix it.

    Signed-off-by: Miao Xie
    Signed-off-by: Josef Bacik

    Miao Xie
     
  • Since the "_struct" suffix is mainly used for distinguish the differnt
    btrfs_work between the original and the newly created one,
    there is no need using the suffix since all btrfs_workers are changed
    into btrfs_workqueue.

    Also this patch fixed some codes whose code style is changed due to the
    too long "_struct" suffix.

    Signed-off-by: Qu Wenruo
    Tested-by: David Sterba
    Signed-off-by: Josef Bacik

    Qu Wenruo
     
  • Replace the fs_info->submit_workers with the newly created
    btrfs_workqueue.

    Signed-off-by: Qu Wenruo
    Tested-by: David Sterba
    Signed-off-by: Josef Bacik

    Qu Wenruo
     
  • There was a problem in the old code:
    If we failed to log the csum, we would free all the ordered extents in the log list
    including those ordered extents that were logged successfully, it would make the
    log committer not to wait for the completion of the ordered extents.

    This patch doesn't insert the ordered extents that is about to be logged into
    a global list, instead, we insert them into a local list. If we log the ordered
    extents successfully, we splice them with the global list, or we will throw them
    away, then do full sync. It can also reduce the lock contention and the traverse
    time of list.

    Signed-off-by: Miao Xie
    Signed-off-by: Josef Bacik

    Miao Xie
     

29 Jan, 2014

2 commits

  • Convert all applicable cases of printk and pr_* to the btrfs_* macros.

    Fix all uses of the BTRFS prefix.

    Signed-off-by: Frank Holton
    Signed-off-by: Josef Bacik
    Signed-off-by: Chris Mason

    Frank Holton
     
  • After an ordered extent completes, don't blindly reset the
    inode's ordered tree last accessed ordered extent pointer.

    While running the xfstests I noticed that about 29% of the
    time the ordered extent to which tree->last pointed was not
    the same as our just completed ordered extent. After that I
    ran the following sysbench test (after a prepare phase) and
    noticed that about 68% of the time tree->last pointed to
    a different ordered extent too.

    sysbench --test=fileio --file-num=32 --file-total-size=4G \
    --file-test-mode=rndwr --num-threads=512 \
    --file-block-size=32768 --max-time=60 --max-requests=0 run

    Therefore reset tree->last on ordered extent removal only if
    it pointed to the ordered extent we're removing from the tree.

    Results from 4 runs of the following test before and after
    applying this patch:

    $ sysbench --test=fileio --file-num=32 --file-total-size=4G \
    --file-test-mode=seqwr --num-threads=512 \
    --file-block-size=32768 --max-time=60 --file-io-mode=sync prepare
    $ sysbench --test=fileio --file-num=32 --file-total-size=4G \
    --file-test-mode=seqwr --num-threads=512 \
    --file-block-size=32768 --max-time=60 --file-io-mode=sync run

    Before this path:

    run 1 - 64.049Mb/sec
    run 2 - 63.455Mb/sec
    run 3 - 64.656Mb/sec
    run 4 - 63.833Mb/sec

    After this patch:

    run 1 - 66.149Mb/sec
    run 2 - 68.459Mb/sec
    run 3 - 66.338Mb/sec
    run 4 - 66.176Mb/sec

    With random writes (--file-test-mode=rndwr) I had huge fluctuations
    on the results (+- 35% easily).

    Signed-off-by: Filipe David Borba Manana
    Signed-off-by: Josef Bacik
    Signed-off-by: Chris Mason

    Filipe David Borba Manana