1. 14 Mar, 2018 2 commits
    • Edmund Nadolski's avatar
      btrfs: add missing initialization in btrfs_check_shared · 18bf591b
      Edmund Nadolski authored
      This patch addresses an issue that causes fiemap to falsely
      report a shared extent.  The test case is as follows:
      
      xfs_io -f -d -c "pwrite -b 16k 0 64k" -c "fiemap -v" /media/scratch/file5
      sync
      xfs_io  -c "fiemap -v" /media/scratch/file5
      
      which gives the resulting output:
      
      wrote 65536/65536 bytes at offset 0
      64 KiB, 4 ops; 0.0000 sec (121.359 MiB/sec and 7766.9903 ops/sec)
      /media/scratch/file5:
       EXT: FILE-OFFSET      BLOCK-RANGE      TOTAL FLAGS
         0: [0..127]:        24576..24703       128 0x2001
      /media/scratch/file5:
       EXT: FILE-OFFSET      BLOCK-RANGE      TOTAL FLAGS
         0: [0..127]:        24576..24703       128   0x1
      
      This is because btrfs_check_shared calls find_parent_nodes
      repeatedly in a loop, passing a share_check struct to report
      the count of shared extent. But btrfs_check_shared does not
      re-initialize the count value to zero for subsequent calls
      from the loop, resulting in a false share count value. This
      is a regressive behavior from 4.13.
      
      With proper re-initialization the test result is as follows:
      
      wrote 65536/65536 bytes at offset 0
      64 KiB, 4 ops; 0.0000 sec (110.035 MiB/sec and 7042.2535 ops/sec)
      /media/scratch/file5:
       EXT: FILE-OFFSET      BLOCK-RANGE      TOTAL FLAGS
         0: [0..127]:        24576..24703       128   0x1
      /media/scratch/file5:
       EXT: FILE-OFFSET      BLOCK-RANGE      TOTAL FLAGS
         0: [0..127]:        24576..24703       128   0x1
      
      which corrects the regression.
      
      Fixes: 3ec4d323 ("btrfs: allow backref search checks for shared extents")
      Signed-off-by: default avatarEdmund Nadolski <enadolski@suse.com>
      [ add text from cover letter to changelog ]
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      18bf591b
    • Dmitriy Gorokh's avatar
      btrfs: Fix NULL pointer exception in find_bio_stripe · 047fdea6
      Dmitriy Gorokh authored
      On detaching of a disk which is a part of a RAID6 filesystem, the
      following kernel OOPS may happen:
      
      [63122.680461] BTRFS error (device sdo): bdev /dev/sdo errs: wr 0, rd 0, flush 1, corrupt 0, gen 0
      [63122.719584] BTRFS warning (device sdo): lost page write due to IO error on /dev/sdo
      [63122.719587] BTRFS error (device sdo): bdev /dev/sdo errs: wr 1, rd 0, flush 1, corrupt 0, gen 0
      [63122.803516] BTRFS warning (device sdo): lost page write due to IO error on /dev/sdo
      [63122.803519] BTRFS error (device sdo): bdev /dev/sdo errs: wr 2, rd 0, flush 1, corrupt 0, gen 0
      [63122.863902] BTRFS critical (device sdo): fatal error on device /dev/sdo
      [63122.935338] BUG: unable to handle kernel NULL pointer dereference at 0000000000000080
      [63122.946554] IP: fail_bio_stripe+0x58/0xa0 [btrfs]
      [63122.958185] PGD 9ecda067 P4D 9ecda067 PUD b2b37067 PMD 0
      [63122.971202] Oops: 0000 [#1] SMP
      [63123.006760] CPU: 0 PID: 3979 Comm: kworker/u8:9 Tainted: G W 4.14.2-16-scst34x+ #8
      [63123.007091] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
      [63123.007402] Workqueue: btrfs-worker btrfs_worker_helper [btrfs]
      [63123.007595] task: ffff880036ea4040 task.stack: ffffc90006384000
      [63123.007796] RIP: 0010:fail_bio_stripe+0x58/0xa0 [btrfs]
      [63123.007968] RSP: 0018:ffffc90006387ad8 EFLAGS: 00010287
      [63123.008140] RAX: 0000000000000002 RBX: ffff88004beaa0b8 RCX: ffff8800b2bd5690
      [63123.008359] RDX: 0000000000000000 RSI: ffff88007bb43500 RDI: ffff88004beaa000
      [63123.008621] RBP: ffffc90006387ae8 R08: 0000000099100000 R09: ffff8800b2bd5600
      [63123.008840] R10: 0000000000000004 R11: 0000000000010000 R12: ffff88007bb43500
      [63123.009059] R13: 00000000fffffffb R14: ffff880036fc5180 R15: 0000000000000004
      [63123.009278] FS: 0000000000000000(0000) GS:ffff8800b7000000(0000) knlGS:0000000000000000
      [63123.009564] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
      [63123.009748] CR2: 0000000000000080 CR3: 00000000b0866000 CR4: 00000000000406f0
      [63123.009969] Call Trace:
      [63123.010085] raid_write_end_io+0x7e/0x80 [btrfs]
      [63123.010251] bio_endio+0xa1/0x120
      [63123.010378] generic_make_request+0x218/0x270
      [63123.010921] submit_bio+0x66/0x130
      [63123.011073] finish_rmw+0x3fc/0x5b0 [btrfs]
      [63123.011245] full_stripe_write+0x96/0xc0 [btrfs]
      [63123.011428] raid56_parity_write+0x117/0x170 [btrfs]
      [63123.011604] btrfs_map_bio+0x2ec/0x320 [btrfs]
      [63123.011759] ? ___cache_free+0x1c5/0x300
      [63123.011909] __btrfs_submit_bio_done+0x26/0x50 [btrfs]
      [63123.012087] run_one_async_done+0x9c/0xc0 [btrfs]
      [63123.012257] normal_work_helper+0x19e/0x300 [btrfs]
      [63123.012429] btrfs_worker_helper+0x12/0x20 [btrfs]
      [63123.012656] process_one_work+0x14d/0x350
      [63123.012888] worker_thread+0x4d/0x3a0
      [63123.013026] ? _raw_spin_unlock_irqrestore+0x15/0x20
      [63123.013192] kthread+0x109/0x140
      [63123.013315] ? process_scheduled_works+0x40/0x40
      [63123.013472] ? kthread_stop+0x110/0x110
      [63123.013610] ret_from_fork+0x25/0x30
      [63123.014469] RIP: fail_bio_stripe+0x58/0xa0 [btrfs] RSP: ffffc90006387ad8
      [63123.014678] CR2: 0000000000000080
      [63123.016590] ---[ end trace a295ea7259c17880 ]—
      
      This is reproducible in a cycle, where a series of writes is followed by
      SCSI device delete command. The test may take up to few minutes.
      
      Fixes: 74d46992 ("block: replace bi_bdev with a gendisk pointer and partitions index")
      [ no signed-off-by provided ]
      Author: Dmitriy Gorokh <Dmitriy.Gorokh@wdc.com>
      Reviewed-by: default avatarLiu Bo <bo.li.liu@oracle.com>
      Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      047fdea6
  2. 01 Mar, 2018 8 commits
    • Filipe Manana's avatar
      Btrfs: fix log replay failure after unlink and link combination · 1f250e92
      Filipe Manana authored
      If we have a file with 2 (or more) hard links in the same directory,
      remove one of the hard links, create a new file (or link an existing file)
      in the same directory with the name of the removed hard link, and then
      finally fsync the new file, we end up with a log that fails to replay,
      causing a mount failure.
      
      Example:
      
        $ mkfs.btrfs -f /dev/sdb
        $ mount /dev/sdb /mnt
      
        $ mkdir /mnt/testdir
        $ touch /mnt/testdir/foo
        $ ln /mnt/testdir/foo /mnt/testdir/bar
      
        $ sync
      
        $ unlink /mnt/testdir/bar
        $ touch /mnt/testdir/bar
        $ xfs_io -c "fsync" /mnt/testdir/bar
      
        <power failure>
      
        $ mount /dev/sdb /mnt
        mount: mount(2) failed: /mnt: No such file or directory
      
      When replaying the log, for that example, we also see the following in
      dmesg/syslog:
      
        [71813.671307] BTRFS info (device dm-0): failed to delete reference to bar, inode 258 parent 257
        [71813.674204] ------------[ cut here ]------------
        [71813.675694] BTRFS: Transaction aborted (error -2)
        [71813.677236] WARNING: CPU: 1 PID: 13231 at fs/btrfs/inode.c:4128 __btrfs_unlink_inode+0x17b/0x355 [btrfs]
        [71813.679669] Modules linked in: btrfs xfs f2fs dm_flakey dm_mod dax ghash_clmulni_intel ppdev pcbc aesni_intel aes_x86_64 crypto_simd cryptd glue_helper evdev psmouse i2c_piix4 parport_pc i2c_core pcspkr sg serio_raw parport button sunrpc loop autofs4 ext4 crc16 mbcache jbd2 zstd_decompress zstd_compress xxhash raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor raid6_pq libcrc32c crc32c_generic raid1 raid0 multipath linear md_mod ata_generic sd_mod virtio_scsi ata_piix libata virtio_pci virtio_ring crc32c_intel floppy virtio e1000 scsi_mod [last unloaded: btrfs]
        [71813.679669] CPU: 1 PID: 13231 Comm: mount Tainted: G        W        4.15.0-rc9-btrfs-next-56+ #1
        [71813.679669] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.10.2-0-g5f4c7b1-prebuilt.qemu-project.org 04/01/2014
        [71813.679669] RIP: 0010:__btrfs_unlink_inode+0x17b/0x355 [btrfs]
        [71813.679669] RSP: 0018:ffffc90001cef738 EFLAGS: 00010286
        [71813.679669] RAX: 0000000000000025 RBX: ffff880217ce4708 RCX: 0000000000000001
        [71813.679669] RDX: 0000000000000000 RSI: ffffffff81c14bae RDI: 00000000ffffffff
        [71813.679669] RBP: ffffc90001cef7c0 R08: 0000000000000001 R09: 0000000000000001
        [71813.679669] R10: ffffc90001cef5e0 R11: ffffffff8343f007 R12: ffff880217d474c8
        [71813.679669] R13: 00000000fffffffe R14: ffff88021ccf1548 R15: 0000000000000101
        [71813.679669] FS:  00007f7cee84c480(0000) GS:ffff88023fc80000(0000) knlGS:0000000000000000
        [71813.679669] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
        [71813.679669] CR2: 00007f7cedc1abf9 CR3: 00000002354b4003 CR4: 00000000001606e0
        [71813.679669] Call Trace:
        [71813.679669]  btrfs_unlink_inode+0x17/0x41 [btrfs]
        [71813.679669]  drop_one_dir_item+0xfa/0x131 [btrfs]
        [71813.679669]  add_inode_ref+0x71e/0x851 [btrfs]
        [71813.679669]  ? __lock_is_held+0x39/0x71
        [71813.679669]  ? replay_one_buffer+0x53/0x53a [btrfs]
        [71813.679669]  replay_one_buffer+0x4a4/0x53a [btrfs]
        [71813.679669]  ? rcu_read_unlock+0x3a/0x57
        [71813.679669]  ? __lock_is_held+0x39/0x71
        [71813.679669]  walk_up_log_tree+0x101/0x1d2 [btrfs]
        [71813.679669]  walk_log_tree+0xad/0x188 [btrfs]
        [71813.679669]  btrfs_recover_log_trees+0x1fa/0x31e [btrfs]
        [71813.679669]  ? replay_one_extent+0x544/0x544 [btrfs]
        [71813.679669]  open_ctree+0x1cf6/0x2209 [btrfs]
        [71813.679669]  btrfs_mount_root+0x368/0x482 [btrfs]
        [71813.679669]  ? trace_hardirqs_on_caller+0x14c/0x1a6
        [71813.679669]  ? __lockdep_init_map+0x176/0x1c2
        [71813.679669]  ? mount_fs+0x64/0x10b
        [71813.679669]  mount_fs+0x64/0x10b
        [71813.679669]  vfs_kern_mount+0x68/0xce
        [71813.679669]  btrfs_mount+0x13e/0x772 [btrfs]
        [71813.679669]  ? trace_hardirqs_on_caller+0x14c/0x1a6
        [71813.679669]  ? __lockdep_init_map+0x176/0x1c2
        [71813.679669]  ? mount_fs+0x64/0x10b
        [71813.679669]  mount_fs+0x64/0x10b
        [71813.679669]  vfs_kern_mount+0x68/0xce
        [71813.679669]  do_mount+0x6e5/0x973
        [71813.679669]  ? memdup_user+0x3e/0x5c
        [71813.679669]  SyS_mount+0x72/0x98
        [71813.679669]  entry_SYSCALL_64_fastpath+0x1e/0x8b
        [71813.679669] RIP: 0033:0x7f7cedf150ba
        [71813.679669] RSP: 002b:00007ffca71da688 EFLAGS: 00000206
        [71813.679669] Code: 7f a0 e8 51 0c fd ff 48 8b 43 50 f0 0f ba a8 30 2c 00 00 02 72 17 41 83 fd fb 74 11 44 89 ee 48 c7 c7 7d 11 7f a0 e8 38 f5 8d e0 <0f> ff 44 89 e9 ba 20 10 00 00 eb 4d 48 8b 4d b0 48 8b 75 88 4c
        [71813.679669] ---[ end trace 83bd473fc5b4663b ]---
        [71813.854764] BTRFS: error (device dm-0) in __btrfs_unlink_inode:4128: errno=-2 No such entry
        [71813.886994] BTRFS: error (device dm-0) in btrfs_replay_log:2307: errno=-2 No such entry (Failed to recover log tree)
        [71813.903357] BTRFS error (device dm-0): cleaner transaction attach returned -30
        [71814.128078] BTRFS error (device dm-0): open_ctree failed
      
      This happens because the log has inode reference items for both inode 258
      (the first file we created) and inode 259 (the second file created), and
      when processing the reference item for inode 258, we replace the
      corresponding item in the subvolume tree (which has two names, "foo" and
      "bar") witht he one in the log (which only has one name, "foo") without
      removing the corresponding dir index keys from the parent directory.
      Later, when processing the inode reference item for inode 259, which has
      a name of "bar" associated to it, we notice that dir index entries exist
      for that name and for a different inode, so we attempt to unlink that
      name, which fails because the inode reference item for inode 258 no longer
      has the name "bar" associated to it, making a call to btrfs_unlink_inode()
      fail with a -ENOENT error.
      
      Fix this by unlinking all the names in an inode reference item from a
      subvolume tree that are not present in the inode reference item found in
      the log tree, before overwriting it with the item from the log tree.
      Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      1f250e92
    • Filipe Manana's avatar
      Btrfs: fix log replay failure after linking special file and fsync · 9a6509c4
      Filipe Manana authored
      If in the same transaction we rename a special file (fifo, character/block
      device or symbolic link), create a hard link for it having its old name
      then sync the log, we will end up with a log that can not be replayed and
      at when attempting to replay it, an EEXIST error is returned and mounting
      the filesystem fails. Example scenario:
      
        $ mkfs.btrfs -f /dev/sdc
        $ mount /dev/sdc /mnt
        $ mkdir /mnt/testdir
        $ mkfifo /mnt/testdir/foo
        # Make sure everything done so far is durably persisted.
        $ sync
      
        # Create some unrelated file and fsync it, this is just to create a log
        # tree. The file must be in the same directory as our special file.
        $ touch /mnt/testdir/f1
        $ xfs_io -c "fsync" /mnt/testdir/f1
      
        # Rename our special file and then create a hard link with its old name.
        $ mv /mnt/testdir/foo /mnt/testdir/bar
        $ ln /mnt/testdir/bar /mnt/testdir/foo
      
        # Create some other unrelated file and fsync it, this is just to persist
        # the log tree which was modified by the previous rename and link
        # operations. Alternatively we could have modified file f1 and fsync it.
        $ touch /mnt/f2
        $ xfs_io -c "fsync" /mnt/f2
      
        <power failure>
      
        $ mount /dev/sdc /mnt
        mount: mount /dev/sdc on /mnt failed: File exists
      
      This happens because when both the log tree and the subvolume's tree have
      an entry in the directory "testdir" with the same name, that is, there
      is one key (258 INODE_REF 257) in the subvolume tree and another one in
      the log tree (where 258 is the inode number of our special file and 257
      is the inode for directory "testdir"). Only the data of those two keys
      differs, in the subvolume tree the index field for inode reference has
      a value of 3 while the log tree it has a value of 5. Because the same key
      exists in both trees, but have different index, the log replay fails with
      an -EEXIST error when attempting to replay the inode reference from the
      log tree.
      
      Fix this by setting the last_unlink_trans field of the inode (our special
      file) to the current transaction id when a hard link is created, as this
      forces logging the parent directory inode, solving the conflict at log
      replay time.
      
      A new generic test case for fstests was also submitted.
      Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      9a6509c4
    • Filipe Manana's avatar
      Btrfs: send, fix issuing write op when processing hole in no data mode · d4dfc0f4
      Filipe Manana authored
      When doing an incremental send of a filesystem with the no-holes feature
      enabled, we end up issuing a write operation when using the no data mode
      send flag, instead of issuing an update extent operation. Fix this by
      issuing the update extent operation instead.
      
      Trivial reproducer:
      
        $ mkfs.btrfs -f -O no-holes /dev/sdc
        $ mkfs.btrfs -f /dev/sdd
        $ mount /dev/sdc /mnt/sdc
        $ mount /dev/sdd /mnt/sdd
      
        $ xfs_io -f -c "pwrite -S 0xab 0 32K" /mnt/sdc/foobar
        $ btrfs subvolume snapshot -r /mnt/sdc /mnt/sdc/snap1
      
        $ xfs_io -c "fpunch 8K 8K" /mnt/sdc/foobar
        $ btrfs subvolume snapshot -r /mnt/sdc /mnt/sdc/snap2
      
        $ btrfs send /mnt/sdc/snap1 | btrfs receive /mnt/sdd
        $ btrfs send --no-data -p /mnt/sdc/snap1 /mnt/sdc/snap2 \
             | btrfs receive -vv /mnt/sdd
      
      Before this change the output of the second receive command is:
      
        receiving snapshot snap2 uuid=f6922049-8c22-e544-9ff9-fc6755918447...
        utimes
        write foobar, offset 8192, len 8192
        utimes foobar
        BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=f6922049-8c22-e544-9ff9-...
      
      After this change it is:
      
        receiving snapshot snap2 uuid=564d36a3-ebc8-7343-aec9-bf6fda278e64...
        utimes
        update_extent foobar: offset=8192, len=8192
        utimes foobar
        BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=564d36a3-ebc8-7343-aec9-bf6fda278e64...
      Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      d4dfc0f4
    • Anand Jain's avatar
      btrfs: use proper endianness accessors for super_copy · 3c181c12
      Anand Jain authored
      The fs_info::super_copy is a byte copy of the on-disk structure and all
      members must use the accessor macros/functions to obtain the right
      value.  This was missing in update_super_roots and in sysfs readers.
      
      Moving between opposite endianness hosts will report bogus numbers in
      sysfs, and mount may fail as the root will not be restored correctly. If
      the filesystem is always used on a same endian host, this will not be a
      problem.
      
      Fix this by using the btrfs_set_super...() functions to set
      fs_info::super_copy values, and for the sysfs, use the cached
      fs_info::nodesize/sectorsize values.
      
      CC: stable@vger.kernel.org
      Fixes: df93589a ("btrfs: export more from FS_INFO to sysfs")
      Signed-off-by: default avatarAnand Jain <anand.jain@oracle.com>
      Reviewed-by: default avatarLiu Bo <bo.li.liu@oracle.com>
      Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
      [ update changelog ]
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      3c181c12
    • Hans van Kranenburg's avatar
      btrfs: alloc_chunk: fix DUP stripe size handling · 92e222df
      Hans van Kranenburg authored
      In case of using DUP, we search for enough unallocated disk space on a
      device to hold two stripes.
      
      The devices_info[ndevs-1].max_avail that holds the amount of unallocated
      space found is directly assigned to stripe_size, while it's actually
      twice the stripe size.
      
      Later on in the code, an unconditional division of stripe_size by
      dev_stripes corrects the value, but in the meantime there's a check to
      see if the stripe_size does not exceed max_chunk_size. Since during this
      check stripe_size is twice the amount as intended, the check will reduce
      the stripe_size to max_chunk_size if the actual correct to be used
      stripe_size is more than half the amount of max_chunk_size.
      
      The unconditional division later tries to correct stripe_size, but will
      actually make sure we can't allocate more than half the max_chunk_size.
      
      Fix this by moving the division by dev_stripes before the max chunk size
      check, so it always contains the right value, instead of putting a duct
      tape division in further on to get it fixed again.
      
      Since in all other cases than DUP, dev_stripes is 1, this change only
      affects DUP.
      
      Other attempts in the past were made to fix this:
      * 37db63a4 "Btrfs: fix max chunk size check in chunk allocator" tried
      to fix the same problem, but still resulted in part of the code acting
      on a wrongly doubled stripe_size value.
      * 86db2578 "Btrfs: fix max chunk size on raid5/6" unintentionally
      broke this fix again.
      
      The real problem was already introduced with the rest of the code in
      73c5de00.
      
      The user visible result however will be that the max chunk size for DUP
      will suddenly double, while it's actually acting according to the limits
      in the code again like it was 5 years ago.
      Reported-by: default avatarNaohiro Aota <naohiro.aota@wdc.com>
      Link: https://www.spinics.net/lists/linux-btrfs/msg69752.html
      Fixes: 73c5de00 ("btrfs: quasi-round-robin for chunk allocation")
      Fixes: 86db2578 ("Btrfs: fix max chunk size on raid5/6")
      Signed-off-by: default avatarHans van Kranenburg <hans.van.kranenburg@mendix.com>
      Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
      [ update comment ]
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      92e222df
    • Nikolay Borisov's avatar
      btrfs: Handle btrfs_set_extent_delalloc failure in relocate_file_extent_cluster · 765f3ceb
      Nikolay Borisov authored
      Essentially duplicate the error handling from the above block which
      handles the !PageUptodate(page) case and additionally clear
      EXTENT_BOUNDARY.
      Signed-off-by: default avatarNikolay Borisov <nborisov@suse.com>
      Reviewed-by: default avatarJosef Bacik <jbacik@fb.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      765f3ceb
    • Nikolay Borisov's avatar
      btrfs: handle failure of add_pending_csums · ac01f26a
      Nikolay Borisov authored
      add_pending_csums was added as part of the new data=ordered
      implementation in e6dcd2dc ("Btrfs: New data=ordered
      implementation"). Even back then it called the btrfs_csum_file_blocks
      which can fail but it never bothered handling the failure. In ENOMEM
      situation this could lead to the filesystem failing to write the
      checksums for a particular extent and not detect this. On read this
      could lead to the filesystem erroring out due to crc mismatch. Fix it by
      propagating failure from add_pending_csums and handling them.
      Signed-off-by: default avatarNikolay Borisov <nborisov@suse.com>
      Reviewed-by: default avatarJosef Bacik <jbacik@fb.com>
      Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      ac01f26a
    • Jeff Mahoney's avatar
      btrfs: use kvzalloc to allocate btrfs_fs_info · a8fd1f71
      Jeff Mahoney authored
      The srcu_struct in btrfs_fs_info scales in size with NR_CPUS.  On
      kernels built with NR_CPUS=8192, this can result in kmalloc failures
      that prevent mounting.
      
      There is work in progress to try to resolve this for every user of
      srcu_struct but using kvzalloc will work around the failures until
      that is complete.
      
      As an example with NR_CPUS=512 on x86_64: the overall size of
      subvol_srcu is 3460 bytes, fs_info is 6496.
      Signed-off-by: default avatarJeff Mahoney <jeffm@suse.com>
      Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      a8fd1f71
  3. 05 Feb, 2018 1 commit
  4. 02 Feb, 2018 9 commits
    • Filipe Manana's avatar
      Btrfs: fix null pointer dereference when replacing missing device · 627e0873
      Filipe Manana authored
      When we are replacing a missing device we mount the filesystem with the
      degraded mode option in which case we are allowed to have a btrfs device
      structure without a backing device member (its bdev member is NULL) and
      therefore we can't dereference that member. Commit 38b5f68e
      ("btrfs: drop btrfs_device::can_discard to query directly") started to
      dereference that member when discarding extents, resulting in a null
      pointer dereference:
      
       [ 3145.322257] BTRFS warning (device sdf): devid 2 uuid 4d922414-58eb-4880-8fed-9c3840f6c5d5 is missing
       [ 3145.364116] BTRFS info (device sdf): dev_replace from <missing disk> (devid 2) to /dev/sdg started
       [ 3145.413489] BUG: unable to handle kernel NULL pointer dereference at 00000000000000e0
       [ 3145.415085] IP: btrfs_discard_extent+0x6a/0xf8 [btrfs]
       [ 3145.415085] PGD 0 P4D 0
       [ 3145.415085] Oops: 0000 [#1] PREEMPT SMP PTI
       [ 3145.415085] Modules linked in: ppdev ghash_clmulni_intel pcbc aesni_intel aes_x86_64 crypto_simd cryptd glue_helper evdev psmouse parport_pc serio_raw i2c_piix4 i2
       [ 3145.415085] CPU: 0 PID: 11989 Comm: btrfs Tainted: G        W        4.15.0-rc9-btrfs-next-55+ #1
       [ 3145.415085] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.10.2-0-g5f4c7b1-prebuilt.qemu-project.org 04/01/2014
       [ 3145.415085] RIP: 0010:btrfs_discard_extent+0x6a/0xf8 [btrfs]
       [ 3145.415085] RSP: 0018:ffffc90004813c60 EFLAGS: 00010293
       [ 3145.415085] RAX: ffff88020d39cc00 RBX: ffff88020c4ea2a0 RCX: 0000000000000002
       [ 3145.415085] RDX: 0000000000000000 RSI: ffff88020c4ea240 RDI: 0000000000000000
       [ 3145.415085] RBP: 0000000000000000 R08: 0000000000004000 R09: 0000000000000000
       [ 3145.415085] R10: ffffc90004813ae8 R11: 0000000000000000 R12: 0000000000000000
       [ 3145.415085] R13: ffff88020c418000 R14: 0000000000000000 R15: 0000000000000000
       [ 3145.415085] FS:  00007f565681f8c0(0000) GS:ffff88023fc00000(0000) knlGS:0000000000000000
       [ 3145.415085] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
       [ 3145.415085] CR2: 00000000000000e0 CR3: 000000020d208006 CR4: 00000000001606f0
       [ 3145.415085] Call Trace:
       [ 3145.415085]  btrfs_finish_extent_commit+0x9a/0x1be [btrfs]
       [ 3145.415085]  btrfs_commit_transaction+0x649/0x7a0 [btrfs]
       [ 3145.415085]  ? start_transaction+0x2b0/0x3b3 [btrfs]
       [ 3145.415085]  btrfs_dev_replace_start+0x274/0x30c [btrfs]
       [ 3145.415085]  btrfs_dev_replace_by_ioctl+0x45/0x59 [btrfs]
       [ 3145.415085]  btrfs_ioctl+0x1a91/0x1d62 [btrfs]
       [ 3145.415085]  ? lock_acquire+0x16a/0x1af
       [ 3145.415085]  ? vfs_ioctl+0x1b/0x28
       [ 3145.415085]  ? trace_hardirqs_on_caller+0x14c/0x1a6
       [ 3145.415085]  vfs_ioctl+0x1b/0x28
       [ 3145.415085]  do_vfs_ioctl+0x5a9/0x5e0
       [ 3145.415085]  ? _raw_spin_unlock_irq+0x34/0x46
       [ 3145.415085]  ? entry_SYSCALL_64_fastpath+0x5/0x8b
       [ 3145.415085]  ? trace_hardirqs_on_caller+0x14c/0x1a6
       [ 3145.415085]  SyS_ioctl+0x52/0x76
       [ 3145.415085]  entry_SYSCALL_64_fastpath+0x1e/0x8b
       [ 3145.415085] RIP: 0033:0x7f56558b3c47
       [ 3145.415085] RSP: 002b:00007ffdcfac4c58 EFLAGS: 00000202
       [ 3145.415085] Code: be 02 00 00 00 4c 89 ef e8 b9 e7 03 00 85 c0 89 c5 75 75 48 8b 44 24 08 45 31 f6 48 8d 58 60 eb 52 48 8b 03 48 8b b8 a0 00 00 00 <48> 8b 87 e0 00
       [ 3145.415085] RIP: btrfs_discard_extent+0x6a/0xf8 [btrfs] RSP: ffffc90004813c60
       [ 3145.415085] CR2: 00000000000000e0
       [ 3145.458185] ---[ end trace 06302e7ac31902bf ]---
      
      This is trivially reproduced by running the test btrfs/027 from fstests
      like this:
      
        $ MOUNT_OPTIONS="-o discard" ./check btrfs/027
      
      Fix this by skipping devices without a backing device before attempting
      to discard.
      
      Fixes: 38b5f68e ("btrfs: drop btrfs_device::can_discard to query directly")
      Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      627e0873
    • Zygo Blaxell's avatar
      btrfs: remove spurious WARN_ON(ref->count < 0) in find_parent_nodes · c8195a7b
      Zygo Blaxell authored
      Until v4.14, this warning was very infrequent:
      
      	WARNING: CPU: 3 PID: 18172 at fs/btrfs/backref.c:1391 find_parent_nodes+0xc41/0x14e0
      	Modules linked in: [...]
      	CPU: 3 PID: 18172 Comm: bees Tainted: G      D W    L  4.11.9-zb64+ #1
      	Hardware name: System manufacturer System Product Name/M5A78L-M/USB3, BIOS 2101    12/02/2014
      	Call Trace:
      	 dump_stack+0x85/0xc2
      	 __warn+0xd1/0xf0
      	 warn_slowpath_null+0x1d/0x20
      	 find_parent_nodes+0xc41/0x14e0
      	 __btrfs_find_all_roots+0xad/0x120
      	 ? extent_same_check_offsets+0x70/0x70
      	 iterate_extent_inodes+0x168/0x300
      	 iterate_inodes_from_logical+0x87/0xb0
      	 ? iterate_inodes_from_logical+0x87/0xb0
      	 ? extent_same_check_offsets+0x70/0x70
      	 btrfs_ioctl+0x8ac/0x2820
      	 ? lock_acquire+0xc2/0x200
      	 do_vfs_ioctl+0x91/0x700
      	 ? __fget+0x112/0x200
      	 SyS_ioctl+0x79/0x90
      	 entry_SYSCALL_64_fastpath+0x23/0xc6
      	 ? trace_hardirqs_off_caller+0x1f/0x140
      
      Starting with v4.14 (specifically 86d5f994 ("btrfs: convert prelimary
      reference tracking to use rbtrees")) the WARN_ON occurs three orders of
      magnitude more frequently--almost once per second while running workloads
      like bees.
      
      Replace the WARN_ON() with a comment rationale for its removal.
      The rationale is paraphrased from an explanation by Edmund Nadolski
      <enadolski@suse.de> on the linux-btrfs mailing list.
      
      Fixes: 8da6d581 ("Btrfs: added btrfs_find_all_roots()")
      Signed-off-by: default avatarZygo Blaxell <ce3g8jdj@umail.furryterror.org>
      Reviewed-by: default avatarLu Fengqi <lufq.fnst@cn.fujitsu.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      c8195a7b
    • Nikolay Borisov's avatar
      btrfs: Ignore errors from btrfs_qgroup_trace_extent_post · 952bd3db
      Nikolay Borisov authored
      Running generic/019 with qgroups on the scratch device enabled is almost
      guaranteed to trigger the BUG_ON in btrfs_free_tree_block. It's supposed
      to trigger only on -ENOMEM, in reality, however, it's possible to get
      -EIO from btrfs_qgroup_trace_extent_post. This function just finds the
      roots of the extent being tracked and sets the qrecord->old_roots list.
      If this operation fails nothing critical happens except the quota
      accounting can be considered wrong. In such case just set the
      INCONSISTENT flag for the quota and print a warning, rather than killing
      off the system. Additionally, it's possible to trigger a BUG_ON in
      btrfs_truncate_inode_items as well.
      Signed-off-by: default avatarNikolay Borisov <nborisov@suse.com>
      Reviewed-by: default avatarQu Wenruo <wqu@suse.com>
      [ error message adjustments ]
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      952bd3db
    • Liu Bo's avatar
      Btrfs: fix unexpected -EEXIST when creating new inode · 900c9981
      Liu Bo authored
      The highest objectid, which is assigned to new inode, is decided at
      the time of initializing fs roots.  However, in cases where log replay
      gets processed, the btree which fs root owns might be changed, so we
      have to search it again for the highest objectid, otherwise creating
      new inode would end up with -EEXIST.
      
      cc: <stable@vger.kernel.org> v4.4-rc6+
      Fixes: f32e48e9 ("Btrfs: Initialize btrfs_root->highest_objectid when loading tree root and subvolume roots")
      Signed-off-by: default avatarLiu Bo <bo.li.liu@oracle.com>
      Reviewed-by: default avatarJosef Bacik <jbacik@fb.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      900c9981
    • Liu Bo's avatar
      Btrfs: fix use-after-free on root->orphan_block_rsv · 1a932ef4
      Liu Bo authored
      I got these from running generic/475,
      
      WARNING: CPU: 0 PID: 26384 at fs/btrfs/inode.c:3326 btrfs_orphan_commit_root+0x1ac/0x2b0 [btrfs]
      BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
      IP: btrfs_block_rsv_release+0x1c/0x70 [btrfs]
      Call Trace:
        btrfs_orphan_release_metadata+0x9f/0x200 [btrfs]
        btrfs_orphan_del+0x10d/0x170 [btrfs]
        btrfs_setattr+0x500/0x640 [btrfs]
        notify_change+0x7ae/0x870
        do_truncate+0xca/0x130
        vfs_truncate+0x2ee/0x3d0
        do_sys_truncate+0xaf/0xf0
        SyS_truncate+0xe/0x10
        entry_SYSCALL_64_fastpath+0x1f/0x96
      
      The race is between btrfs_orphan_commit_root and btrfs_orphan_del,
              t1                                        t2
      btrfs_orphan_commit_root                     btrfs_orphan_del
         spin_lock
         check (&root->orphan_inodes)
         root->orphan_block_rsv = NULL;
         spin_unlock
                                                   atomic_dec(&root->orphan_inodes);
                                                   access root->orphan_block_rsv
      
      Accessing root->orphan_block_rsv must be done before decreasing
      root->orphan_inodes.
      
      cc: <stable@vger.kernel.org> v3.12+
      Fixes: 703c88e0 ("Btrfs: fix tracking of orphan inode count")
      Signed-off-by: default avatarLiu Bo <bo.li.liu@oracle.com>
      Reviewed-by: default avatarJosef Bacik <jbacik@fb.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      1a932ef4
    • Liu Bo's avatar
      Btrfs: fix btrfs_evict_inode to handle abnormal inodes correctly · e8f1bc14
      Liu Bo authored
      This regression is introduced in
      commit 3d48d981 ("btrfs: Handle uninitialised inode eviction").
      
      There are two problems,
      
      a) it is ->destroy_inode() that does the final free on inode, not
         ->evict_inode(),
      b) clear_inode() must be called before ->evict_inode() returns.
      
      This could end up hitting BUG_ON(inode->i_state != (I_FREEING | I_CLEAR));
      in evict() because I_CLEAR is set in clear_inode().
      
      Fixes: commit 3d48d981 ("btrfs: Handle uninitialised inode eviction")
      Cc: <stable@vger.kernel.org> # v4.7-rc6+
      Signed-off-by: default avatarLiu Bo <bo.li.liu@oracle.com>
      Reviewed-by: default avatarNikolay Borisov <nborisov@suse.com>
      Reviewed-by: default avatarJosef Bacik <jbacik@fb.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      e8f1bc14
    • Liu Bo's avatar
      Btrfs: fix extent state leak from tree log · 55237a5f
      Liu Bo authored
      It's possible that btrfs_sync_log() bails out after one of the two
      btrfs_write_marked_extents() which convert extent state's state bit into
      EXTENT_NEED_WAIT from EXTENT_DIRTY/EXTENT_NEW, however only EXTENT_DIRTY
      and EXTENT_NEW are searched by free_log_tree() so that those extent states
      with EXTENT_NEED_WAIT lead to memory leak.
      
      cc: <stable@vger.kernel.org>
      Signed-off-by: default avatarLiu Bo <bo.li.liu@oracle.com>
      Reviewed-by: default avatarJosef Bacik <jbacik@fb.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      55237a5f
    • Liu Bo's avatar
      Btrfs: fix crash due to not cleaning up tree log block's dirty bits · 1846430c
      Liu Bo authored
      In cases that the whole fs flips into readonly status due to failures in
      critical sections, then log tree's blocks are still dirty, and this leads
      to a crash during umount time, the crash is about use-after-free,
      
      umount
       -> close_ctree
          -> stop workers
          -> iput(btree_inode)
             -> iput_final
                -> write_inode_now
      	     -> ...
      	       -> queue job on stop'd workers
      
      cc: <stable@vger.kernel.org> v3.12+
      Fixes: 681ae509 ("Btrfs: cleanup reserved space when freeing tree log on error")
      Signed-off-by: default avatarLiu Bo <bo.li.liu@oracle.com>
      Reviewed-by: default avatarJosef Bacik <jbacik@fb.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      1846430c
    • Liu Bo's avatar
      Btrfs: fix deadlock in run_delalloc_nocow · e8916699
      Liu Bo authored
      @cur_offset is not set back to what it should be (@cow_start) if
      btrfs_next_leaf() returns something wrong, and the range [cow_start,
      cur_offset) remains locked forever.
      
      cc: <stable@vger.kernel.org>
      Signed-off-by: default avatarLiu Bo <bo.li.liu@oracle.com>
      Reviewed-by: default avatarJosef Bacik <jbacik@fb.com>
      Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
      e8916699
  5. 29 Jan, 2018 2 commits
  6. 22 Jan, 2018 18 commits