sfrench/cifs-2.6.git
4 years agobtrfs: get fs_info from device in btrfs_rm_dev_item
David Sterba [Wed, 20 Mar 2019 15:31:53 +0000 (16:31 +0100)]
btrfs: get fs_info from device in btrfs_rm_dev_item

We can read fs_info from the device and can drop it from the parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from eb in __push_leaf_left
David Sterba [Wed, 20 Mar 2019 13:40:41 +0000 (14:40 +0100)]
btrfs: get fs_info from eb in __push_leaf_left

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from eb in __push_leaf_right
David Sterba [Wed, 20 Mar 2019 13:39:45 +0000 (14:39 +0100)]
btrfs: get fs_info from eb in __push_leaf_right

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Remove bio_offset argument from submit_bio_hook
Nikolay Borisov [Wed, 10 Apr 2019 16:46:04 +0000 (19:46 +0300)]
btrfs: Remove bio_offset argument from submit_bio_hook

None of the implementers of the submit_bio_hook use the bio_offset
parameter, simply remove it. No functional changes.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Always pass 0 bio_offset for btree_submit_bio_start
Nikolay Borisov [Wed, 10 Apr 2019 14:24:42 +0000 (17:24 +0300)]
btrfs: Always pass 0 bio_offset for btree_submit_bio_start

The btree submit hook queues the async csum and forwards the bio_offset
parameter passed to btree_submit_bio_hook. This is redundant since
btree_submit_bio_start calls btree_csum_one_bio which doesn't use the
offset at all. No functional changes.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Pass 0 for bio_offset to btrfs_wq_submit_bio
Nikolay Borisov [Wed, 10 Apr 2019 14:24:41 +0000 (17:24 +0300)]
btrfs: Pass 0 for bio_offset to btrfs_wq_submit_bio

Buffered writeback always calls btrfs_csum_one_bio with the last 2
arguments being 0 irrespective of what the bio_offset has been passed to
btrfs_submit_bio_start. Make this apparent by explicitly passing 0 for
bio_offset when calling btrfs_wq_submit_bio from btrfs_submit_bio_hook.
This will allow for further simplifications down the line. No functional
changes.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Remove 'tree' argument from read_extent_buffer_pages
Nikolay Borisov [Wed, 10 Apr 2019 14:24:40 +0000 (17:24 +0300)]
btrfs: Remove 'tree' argument from read_extent_buffer_pages

This function always uses the btree inode's io_tree. Stop taking the
tree as a function argument and instead access it internally from
read_extent_buffer_pages. No functional changes.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Change submit_bio_hook to taking an inode directly
Nikolay Borisov [Wed, 10 Apr 2019 14:24:39 +0000 (17:24 +0300)]
btrfs: Change submit_bio_hook to taking an inode directly

The only possible 'private_data' that is passed to this function is
actually an inode. Make that explicit by changing the signature of the
call back. No functional changes.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Define submit_bio_hook's type directly
Nikolay Borisov [Wed, 10 Apr 2019 14:24:38 +0000 (17:24 +0300)]
btrfs: Define submit_bio_hook's type directly

There is no need to use a typedef to define the type of the function and
then use that to define the respective member in extent_io_ops.  Define
struct's member directly. No functional changes.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from block group in search_free_space_info
David Sterba [Wed, 20 Mar 2019 13:11:21 +0000 (14:11 +0100)]
btrfs: get fs_info from block group in search_free_space_info

We can read fs_info from the block group cache structure and can drop it
from the parameters.  Though the transaction is also availabe, it's not
guaranteed to be non-NULL.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from block group in btrfs_find_space_cluster
David Sterba [Wed, 20 Mar 2019 12:53:49 +0000 (13:53 +0100)]
btrfs: get fs_info from block group in btrfs_find_space_cluster

We can read fs_info from the block group cache structure and can drop it
from the parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from block group in write_pinned_extent_entries
David Sterba [Wed, 20 Mar 2019 12:49:09 +0000 (13:49 +0100)]
btrfs: get fs_info from block group in write_pinned_extent_entries

We can read fs_info from the block group cache structure and can drop it
from the parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from block group in load_free_space_cache
David Sterba [Wed, 20 Mar 2019 12:47:15 +0000 (13:47 +0100)]
btrfs: get fs_info from block group in load_free_space_cache

We can read fs_info from the block group cache structure and can drop it
from the parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from block group in lookup_free_space_inode
David Sterba [Wed, 20 Mar 2019 12:40:19 +0000 (13:40 +0100)]
btrfs: get fs_info from block group in lookup_free_space_inode

We can read fs_info from the block group cache structure and can drop it
from the parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from block group in pin_down_extent
David Sterba [Wed, 20 Mar 2019 11:12:32 +0000 (12:12 +0100)]
btrfs: get fs_info from block group in pin_down_extent

We can read fs_info from the block group cache structure and can drop it
from the parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from block group in next_block_group
David Sterba [Wed, 20 Mar 2019 11:01:07 +0000 (12:01 +0100)]
btrfs: get fs_info from block group in next_block_group

We can read fs_info from the block group cache structure and can drop it
from the parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agoBtrfs: remove no longer used function to run delayed refs asynchronously
Filipe Manana [Wed, 17 Apr 2019 09:28:47 +0000 (10:28 +0100)]
Btrfs: remove no longer used function to run delayed refs asynchronously

It used to be called from only two places (truncate path and releasing a
transaction handle), but commits 28bad2125767c5 ("btrfs: fix truncate
throttling") and db2462a6ad3dc4 ("btrfs: don't run delayed refs in the end
transaction logic") removed their calls to this function, so it's not used
anymore. Just remove it and all its helpers.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: cleanup btrfs_setxattr_trans and drop transaction parameter
Anand Jain [Fri, 12 Apr 2019 08:02:59 +0000 (16:02 +0800)]
btrfs: cleanup btrfs_setxattr_trans and drop transaction parameter

Previous patch made sure that btrfs_setxattr_trans() is called only when
transaction NULL.  Clean up btrfs_setxattr_trans() and drop the
parameter.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: split btrfs_setxattr calls regarding transaction
Anand Jain [Fri, 12 Apr 2019 08:02:58 +0000 (16:02 +0800)]
btrfs: split btrfs_setxattr calls regarding transaction

When the caller has already created the transaction handle,
btrfs_setxattr() will use it. Also adds assert in btrfs_setxattr().

Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: remove redundant readonly root check in btrfs_setxattr_trans
Anand Jain [Fri, 12 Apr 2019 08:02:57 +0000 (16:02 +0800)]
btrfs: remove redundant readonly root check in btrfs_setxattr_trans

btrfs_setxattr_trans() is called by 5 functions as below and all of them
do updates. None of them would be roun on a read-only root.
So its ok to remove the readonly root check here as it's a high-level
conditon.

1.
  __btrfs_set_acl()
    btrfs_init_acl()
      btrfs_init_inode_security()

2.
  __btrfs_set_acl()
    btrfs_set_acl()

3.
  btrfs_set_prop()
    btrfs_set_prop_trans()
      /                       \
      btrfs_ioctl_setflags()   btrfs_xattr_handler_set_prop()

4.
  btrfs_xattr_handler_set()

5.
  btrfs_initxattrs()
    btrfs_xattr_security_init()
      btrfs_init_inode_security()

Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: export btrfs_setxattr
Anand Jain [Fri, 12 Apr 2019 08:02:56 +0000 (16:02 +0800)]
btrfs: export btrfs_setxattr

Preparatory patch, as we are going split the calls with and without
transaction to use the respective btrfs_setxattr() and
btrfs_setxattr_trans() functions. Export btrfs_setxattr() for calls
outside of xattr.c.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: rename do_setxattr to btrfs_setxattr
Anand Jain [Fri, 12 Apr 2019 08:02:55 +0000 (16:02 +0800)]
btrfs: rename do_setxattr to btrfs_setxattr

When trans is not NULL btrfs_setxattr() calls do_setxattr() directly
with a check for readonly root. Rename do_setxattr() btrfs_setxattr() in
preparation to call do_setxattr() directly instead.  Preparatory patch,
no functional changes.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: rename btrfs_setxattr to btrfs_setxattr_trans
Anand Jain [Fri, 12 Apr 2019 08:02:54 +0000 (16:02 +0800)]
btrfs: rename btrfs_setxattr to btrfs_setxattr_trans

Rename btrfs_setxattr() to btrfs_setxattr_trans(), so that do_setxattr()
can be renamed to btrfs_setxattr().
Preparatory patch, no functional changes.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: trace: Introduce trace events for all btrfs tree locking events
Qu Wenruo [Mon, 15 Apr 2019 13:15:25 +0000 (21:15 +0800)]
btrfs: trace: Introduce trace events for all btrfs tree locking events

Unlike btrfs_tree_lock() and btrfs_tree_read_lock(), the remaining
functions in locking.c will not sleep, thus doesn't make much sense to
record their execution time.

Those events are introduced mainly for user space tool to audit and
detect lock leakage or dead lock.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: trace: Introduce trace events for sleepable tree lock
Qu Wenruo [Mon, 15 Apr 2019 13:15:24 +0000 (21:15 +0800)]
btrfs: trace: Introduce trace events for sleepable tree lock

There are two tree lock events which can sleep:
- btrfs_tree_read_lock()
- btrfs_tree_lock()

Sometimes we may need to look into the concurrency picture of the fs.
For that case, we need the execution time of above two functions and the
owner of @eb.

Here we introduce a trace events for user space tools like bcc, to get
the execution time of above two functions, and get detailed owner info
where eBPF code can't.

All the overhead is hidden behind the trace events, so if events are not
enabled, there is no overhead.

These trace events also output bytenr and generation, allow them to be
pared with unlock events to pin down deadlock.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agoBtrfs: remove no longer used member num_dirty_bgs from transaction
Filipe Manana [Mon, 15 Apr 2019 08:29:19 +0000 (09:29 +0100)]
Btrfs: remove no longer used member num_dirty_bgs from transaction

The member num_dirty_bgs of struct btrfs_transaction is not used anymore,
it is set and incremented but nothing reads its value anymore. Its last
read use was removed by commit 64403612b73a94 ("btrfs: rework
btrfs_check_space_for_delayed_refs"). So just remove that member.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in btrfs_run_dev_replace
David Sterba [Wed, 20 Mar 2019 15:51:44 +0000 (16:51 +0100)]
btrfs: get fs_info from trans in btrfs_run_dev_replace

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in btrfs_run_dev_stats
David Sterba [Wed, 20 Mar 2019 15:50:38 +0000 (16:50 +0100)]
btrfs: get fs_info from trans in btrfs_run_dev_stats

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in btrfs_finish_sprout
David Sterba [Wed, 20 Mar 2019 15:36:39 +0000 (16:36 +0100)]
btrfs: get fs_info from trans in btrfs_finish_sprout

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in init_first_rw_device
David Sterba [Wed, 20 Mar 2019 15:29:13 +0000 (16:29 +0100)]
btrfs: get fs_info from trans in init_first_rw_device

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in copy_for_split
David Sterba [Wed, 20 Mar 2019 13:42:33 +0000 (14:42 +0100)]
btrfs: get fs_info from trans in copy_for_split

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in insert_ptr
David Sterba [Wed, 20 Mar 2019 13:32:45 +0000 (14:32 +0100)]
btrfs: get fs_info from trans in insert_ptr

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in balance_node_right
David Sterba [Wed, 20 Mar 2019 13:18:06 +0000 (14:18 +0100)]
btrfs: get fs_info from trans in balance_node_right

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in push_node_left
David Sterba [Wed, 20 Mar 2019 13:16:45 +0000 (14:16 +0100)]
btrfs: get fs_info from trans in push_node_left

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in btrfs_write_out_cache
David Sterba [Wed, 20 Mar 2019 12:51:56 +0000 (13:51 +0100)]
btrfs: get fs_info from trans in btrfs_write_out_cache

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in create_free_space_inode
David Sterba [Wed, 20 Mar 2019 12:42:57 +0000 (13:42 +0100)]
btrfs: get fs_info from trans in create_free_space_inode

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in btrfs_set_log_full_commit
David Sterba [Wed, 20 Mar 2019 12:28:05 +0000 (13:28 +0100)]
btrfs: get fs_info from trans in btrfs_set_log_full_commit

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in btrfs_need_log_full_commit
David Sterba [Wed, 20 Mar 2019 12:25:34 +0000 (13:25 +0100)]
btrfs: get fs_info from trans in btrfs_need_log_full_commit

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in btrfs_create_tree
David Sterba [Wed, 20 Mar 2019 12:20:49 +0000 (13:20 +0100)]
btrfs: get fs_info from trans in btrfs_create_tree

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in update_block_group
David Sterba [Wed, 20 Mar 2019 11:10:15 +0000 (12:10 +0100)]
btrfs: get fs_info from trans in update_block_group

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in btrfs_write_dirty_block_groups
David Sterba [Wed, 20 Mar 2019 11:04:08 +0000 (12:04 +0100)]
btrfs: get fs_info from trans in btrfs_write_dirty_block_groups

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in btrfs_setup_space_cache
David Sterba [Wed, 20 Mar 2019 11:02:55 +0000 (12:02 +0100)]
btrfs: get fs_info from trans in btrfs_setup_space_cache

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from trans in write_one_cache_group
David Sterba [Wed, 20 Mar 2019 10:57:46 +0000 (11:57 +0100)]
btrfs: get fs_info from trans in write_one_cache_group

We can read fs_info from the transaction and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Remove redundant inode argument from btrfs_add_ordered_sum
Nikolay Borisov [Wed, 10 Apr 2019 13:16:11 +0000 (16:16 +0300)]
btrfs: Remove redundant inode argument from btrfs_add_ordered_sum

Ordered csums are keyed off of a btrfs_ordered_extent, which already has
a reference to the inode. This implies that an explicit inode argument
is redundant. So remove it.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Do mandatory tree block check before submitting bio
Qu Wenruo [Thu, 4 Apr 2019 03:47:08 +0000 (11:47 +0800)]
btrfs: Do mandatory tree block check before submitting bio

There are at least 2 reports about a memory bit flip sneaking into
on-disk data.

Currently we only have a relaxed check triggered at
btrfs_mark_buffer_dirty() time, as it's not mandatory and only for
CONFIG_BTRFS_FS_CHECK_INTEGRITY enabled build, it doesn't help users to
detect such problem.

This patch will address the hole by triggering comprehensive check on
tree blocks before writing it back to disk.

The design points are:

- Timing of the check: Tree block write hook
  This timing is chosen to reduce the overhead.
  The comprehensive check should be as expensive as a checksum
  calculation.
  Doing full check at btrfs_mark_buffer_dirty() is too expensive for end
  user.

- Loose empty leaf check
  Originally for an empty leaf, tree-checker will report error if it's
  not a tree root.

  The problem for such check at write time is:
  * False alert for tree root created in current transaction
    In that case, the commit root still needs to be written to disk.
    And since current root can differ from commit root, then it will
    cause false alert.
    This happens for log tree.

  * False alert for relocated tree block
    Relocated tree block can be written to disk due to memory pressure,
    in that case an empty csum tree root can be written to disk and
    cause false alert, since csum root node hasn't been updated.

  Previous patch of removing comprehensive empty leaf owner check has
  paved the way for this patch.

The example error output will be something like:

  BTRFS critical (device dm-3): corrupt leaf: root=2 block=1350630375424 slot=68, bad key order, prev (10510212874240 169 0) current (1714119868416 169 0)
  BTRFS error (device dm-3): block=1350630375424 write time tree block corruption detected
  BTRFS: error (device dm-3) in btrfs_commit_transaction:2220: errno=-5 IO failure (Error while writing out transaction)
  BTRFS info (device dm-3): forced readonly
  BTRFS warning (device dm-3): Skipping commit of aborted transaction.
  BTRFS: error (device dm-3) in cleanup_transaction:1839: errno=-5 IO failure
  BTRFS info (device dm-3): delayed_refs has NO entry

Reported-by: Leonard Lausen <leonard@lausen.nl>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: Remove comprehensive root owner check
Qu Wenruo [Thu, 4 Apr 2019 03:47:07 +0000 (11:47 +0800)]
btrfs: tree-checker: Remove comprehensive root owner check

Commit 1ba98d086fe3 ("Btrfs: detect corruption when non-root leaf has
zero item") introduced comprehensive root owner checker.

However it's pretty expensive tree search to locate the owner root,
especially when it get reused by mandatory read and write time
tree-checker.

This patch will remove that check, and completely rely on owner based
empty leaf check, which is much faster and still works fine for most
case.

And since we skip the old root owner check, now write time tree check
can be merged with btrfs_check_leaf_full().

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agoBtrfs: fix data bytes_may_use underflow with fallocate due to failed quota reserve
Robbie Ko [Tue, 26 Mar 2019 03:56:11 +0000 (11:56 +0800)]
Btrfs: fix data bytes_may_use underflow with fallocate due to failed quota reserve

When doing fallocate, we first add the range to the reserve_list and
then reserve the quota.  If quota reservation fails, we'll release all
reserved parts of reserve_list.

However, cur_offset is not updated to indicate that this range is
already been inserted into the list.  Therefore, the same range is freed
twice.  Once at list_for_each_entry loop, and once at the end of the
function.  This will result in WARN_ON on bytes_may_use when we free the
remaining space.

At the end, under the 'out' label we have a call to:

   btrfs_free_reserved_data_space(inode, data_reserved, alloc_start, alloc_end - cur_offset);

The start offset, third argument, should be cur_offset.

Everything from alloc_start to cur_offset was freed by the
list_for_each_entry_safe_loop.

Fixes: 18513091af94 ("btrfs: update btrfs_space_info's bytes_may_use timely")
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Robbie Ko <robbieko@synology.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from eb in read_one_dev
David Sterba [Wed, 20 Mar 2019 15:45:15 +0000 (16:45 +0100)]
btrfs: get fs_info from eb in read_one_dev

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from eb in read_one_chunk
David Sterba [Wed, 20 Mar 2019 15:43:07 +0000 (16:43 +0100)]
btrfs: get fs_info from eb in read_one_chunk

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from eb in btrfs_check_chunk_valid
David Sterba [Wed, 20 Mar 2019 15:40:48 +0000 (16:40 +0100)]
btrfs: get fs_info from eb in btrfs_check_chunk_valid

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from eb in should_balance_chunk
David Sterba [Wed, 20 Mar 2019 15:38:52 +0000 (16:38 +0100)]
btrfs: get fs_info from eb in should_balance_chunk

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from eb in btrfs_check_node
David Sterba [Wed, 20 Mar 2019 15:25:00 +0000 (16:25 +0100)]
btrfs: get fs_info from eb in btrfs_check_node

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from eb in btrfs_check_leaf_relaxed
David Sterba [Wed, 20 Mar 2019 15:24:18 +0000 (16:24 +0100)]
btrfs: get fs_info from eb in btrfs_check_leaf_relaxed

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from eb in btrfs_check_leaf_full
David Sterba [Wed, 20 Mar 2019 15:23:29 +0000 (16:23 +0100)]
btrfs: get fs_info from eb in btrfs_check_leaf_full

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Switch btrfs_trim_free_extents to find_first_clear_extent_bit
Nikolay Borisov [Wed, 27 Mar 2019 12:24:18 +0000 (14:24 +0200)]
btrfs: Switch btrfs_trim_free_extents to find_first_clear_extent_bit

Instead of always calling the allocator to search for a free extent,
that satisfies the input criteria, switch btrfs_trim_free_extents to
using find_first_clear_extent_bit. With this change it's no longer
necessary to read the device tree in order to figure out holes in
the devices.

Now the code always searches in-memory data structure to figure out the
space range which contains the requested which should result in speed
improvements.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Implement find_first_clear_extent_bit
Nikolay Borisov [Wed, 27 Mar 2019 12:24:17 +0000 (14:24 +0200)]
btrfs: Implement find_first_clear_extent_bit

This function is very similar to find_first_extent_bit except that it
locates the first contiguous span of space which does not have bits set.
It's intended use is in the freespace trimming code.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Optimize unallocated chunks discard
Nikolay Borisov [Wed, 27 Mar 2019 12:24:16 +0000 (14:24 +0200)]
btrfs: Optimize unallocated chunks discard

Currently unallocated chunks are always trimmed. For example
2 consecutive trims on large storage would trim freespace twice
irrespective of whether the space was actually allocated or not between
those trims.

Optimise this behavior by exploiting the newly introduced alloc_state
tree of btrfs_device. A new CHUNK_TRIMMED bit is used to mark
those unallocated chunks which have been trimmed and have not been
allocated afterwards. On chunk allocation the respective underlying devices'
physical space will have its CHUNK_TRIMMED flag cleared. This avoids
submitting discards for space which hasn't been changed since the last
time discard was issued.

This applies to the single mount period of the filesystem as the
information is not stored permanently.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Factor out in_range macro
Nikolay Borisov [Wed, 27 Mar 2019 12:24:15 +0000 (14:24 +0200)]
btrfs: Factor out in_range macro

This is used in more than one places so let's factor it out in ctree.h.
No functional changes.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Remove 'trans' argument from find_free_dev_extent(_start)
Nikolay Borisov [Wed, 27 Mar 2019 12:24:14 +0000 (14:24 +0200)]
btrfs: Remove 'trans' argument from find_free_dev_extent(_start)

Now that these functions no longer require a handle to transaction to
inspect pending/pinned chunks the argument can be removed. At the same
time also remove any surrounding code which acquired the handle.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: replace pending/pinned chunks lists with io tree
Jeff Mahoney [Wed, 27 Mar 2019 12:24:12 +0000 (14:24 +0200)]
btrfs: replace pending/pinned chunks lists with io tree

The pending chunks list contains chunks that are allocated in the
current transaction but haven't been created yet. The pinned chunks
list contains chunks that are being released in the current transaction.
Both describe chunks that are not reflected on disk as in use but are
unavailable just the same.

The pending chunks list is anchored by the transaction handle, which
means that we need to hold a reference to a transaction when working
with the list.

The way we use them is by iterating over both lists to perform
comparisons on the stripes they describe for each device. This is
backwards and requires that we keep a transaction handle open while
we're trimming.

This patchset adds an extent_io_tree to btrfs_device that maintains
the allocation state of the device.  Extents are set dirty when
chunks are first allocated -- when the extent maps are added to the
mapping tree. They're cleared when last removed -- when the extent
maps are removed from the mapping tree. This matches the lifespan
of the pending and pinned chunks list and allows us to do trims
on unallocated space safely without pinning the transaction for what
may be a lengthy operation. We can also use this io tree to mark
which chunks have already been trimmed so we don't repeat the operation.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Transpose btrfs_close_devices/btrfs_mapping_tree_free in close_ctree
Nikolay Borisov [Tue, 12 Feb 2019 14:13:14 +0000 (16:13 +0200)]
btrfs: Transpose btrfs_close_devices/btrfs_mapping_tree_free in close_ctree

Following the introduction of the alloc_state tree, some of the callees
of btrfs_mapping_tree_free will have to interact with the btrfs_device
of the constituent devices. Enable this by moving the code responsible
for freeing devices after the last user (btrfs_mapping_tree_free).
Otherwise the kernel could crash due to use-after-free.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Stop using call_rcu for device freeing
Nikolay Borisov [Wed, 27 Mar 2019 12:24:11 +0000 (14:24 +0200)]
btrfs: Stop using call_rcu for device freeing

btrfs_device structs are freed from RCU context since device iteration
is protected by RCU. Currently this is achieved by using call_rcu since
no blocking functions are called within btrfs_free_device. Future
refactoring of pending/pinned chunks will require calling sleeping
functions.

This patch is in preparation for these changes by simply switching from
RCU callbacks to explicit calls of synchronize_rcu and calling
btrfs_free_device directly. This is functionally equivalent, making sure
that there are no readers at that time.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Implement set_extent_bits_nowait
Nikolay Borisov [Wed, 27 Mar 2019 12:24:10 +0000 (14:24 +0200)]
btrfs: Implement set_extent_bits_nowait

It will be used in a future patch that will require modifying an
extent_io_tree struct under a spinlock.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Introduce new bits for device allocation tree
Nikolay Borisov [Mon, 25 Mar 2019 12:31:26 +0000 (14:31 +0200)]
btrfs: Introduce new bits for device allocation tree

Rather than hijacking the existing defines let's just define new bits,
with more descriptive names. Instead of using yet more (currently at 18)
bits for the new flags, use the fact those flags will be specific to
the device allocation tree so define them using existing EXTENT_* flags.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Populate ->orig_block_len during read_one_chunk
Nikolay Borisov [Mon, 25 Mar 2019 12:31:25 +0000 (14:31 +0200)]
btrfs: Populate ->orig_block_len during read_one_chunk

Chunks read from disk currently don't get their ->orig_block_len member
set, in contrast when a new chunk is allocated, the respective
extent_map's ->orig_block_len is assigned the size of the stripe of this
chunk.

Let's apply the same strategy for chunks which are read from
disk, not only does this codify the invariant that ->orig_block_len
always contains the size of the stripe for a chunk (when the em belongs
to the mapping tree). But it's also a preparatory patch for further work
around tracking chunk allocation in an extent tree rather than
pinned/pending lists.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Rename and export clear_btree_io_tree
Nikolay Borisov [Mon, 25 Mar 2019 12:31:24 +0000 (14:31 +0200)]
btrfs: Rename and export clear_btree_io_tree

This function is going to be used to clear out the device extent
allocation information. Give it a more generic name and export it. This
is in preparation to replacing the pending/pinned chunk lists with an
extent tree. No functional changes.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Handle pending/pinned chunks before blockgroup relocation during device shrink
Nikolay Borisov [Mon, 25 Mar 2019 12:31:23 +0000 (14:31 +0200)]
btrfs: Handle pending/pinned chunks before blockgroup relocation during device shrink

During device shrink pinned/pending chunks (i.e. those which have been
deleted/created respectively, in the current transaction and haven't
touched disk) need to be accounted when doing device shrink. Presently
this happens after the main relocation loop in btrfs_shrink_device,
which could lead to making another go in the body of the function.

Since there is no hard requirement to perform pinned/pending chunks
handling after the relocation loop, move the code before it. This leads
to simplifying the code flow around - i.e. no need to use 'goto again'.

A notable side effect of this change is that modification of the
device's size requires a transaction to be started and committed before
the relocation loop starts. This is necessary to ensure that relocation
process sees the shrunk device size.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: combine device update operations during transaction commit
Nikolay Borisov [Mon, 25 Mar 2019 12:31:22 +0000 (14:31 +0200)]
btrfs: combine device update operations during transaction commit

We currently overload the pending_chunks list to handle updating
btrfs_device->commit_bytes used.  We don't actually care about the
extent mapping or even the device mapping for the chunk - we just need
the device, and we can end up processing it multiple times.  The
fs_devices->resized_list does more or less the same thing, but with the
disk size.  They are called consecutively during commit and have more or
less the same purpose.

We can combine the two lists into a single list that attaches to the
transaction and contains a list of devices that need updating.  Since we
always add the device to a list when we change bytes_used or
disk_total_size, there's no harm in copying both values at once.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Honour FITRIM range constraints during free space trim
Nikolay Borisov [Mon, 25 Mar 2019 12:31:21 +0000 (14:31 +0200)]
btrfs: Honour FITRIM range constraints during free space trim

Up until now trimming the freespace was done irrespective of what the
arguments of the FITRIM ioctl were. For example fstrim's -o/-l arguments
will be entirely ignored. Fix it by correctly handling those paramter.
This requires breaking if the found freespace extent is after the end of
the passed range as well as completing trim after trimming
fstrim_range::len bytes.

Fixes: 499f377f49f0 ("btrfs: iterate over unused chunk space in FITRIM")
CC: stable@vger.kernel.org # 4.4+
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agoBtrfs: send, improve clone range
Robbie Ko [Fri, 29 Mar 2019 10:03:27 +0000 (18:03 +0800)]
Btrfs: send, improve clone range

Improve clone_range in two scenarios.

1. Remove the limit of inode size when find clone inodes We can do
   partial clone, so there is no need to limit the size of the candidate
   inode.  When clone a range, we clone the legal range only by bytenr,
   offset, len, inode size.

2. In the scenarios of rewrite or clone_range, data_offset rarely
   matches exactly, so the chance of a clone is missed.

e.g.
    1. Write a 1M file
        dd if=/dev/zero of=1M bs=1M count=1

    2. Clone 1M file
       cp --reflink 1M clone

    3. Rewrite 4k on the clone file
       dd if=/dev/zero of=clone bs=4k count=1 conv=notrunc

    The disk layout is as follows:
    item 16 key (257 EXTENT_DATA 0) itemoff 15353 itemsize 53
extent data disk byte 1103101952 nr 1048576
extent data offset 0 nr 1048576 ram 1048576
extent compression(none)
    ...
    item 22 key (258 EXTENT_DATA 0) itemoff 14959 itemsize 53
extent data disk byte 1104150528 nr 4096
extent data offset 0 nr 4096 ram 4096
extent compression(none)
    item 23 key (258 EXTENT_DATA 4096) itemoff 14906 itemsize 53
extent data disk byte 1103101952 nr 1048576
extent data offset 4096 nr 1044480 ram 1048576
extent compression(none)

When send, inode 258 file offset 4096~1048576 (item 23) has a chance to
clone_range, but because data_offset does not match inode 257 (item 16),
it causes missed clone and can only transfer actual data.

Improve the problem by judging whether the current data_offset has
overlap with the file extent item, and if so, adjusting offset and
extent_len so that we can clone correctly.

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Robbie Ko <robbieko@synology.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: prop: open code btrfs_set_prop in inherit_prop
Anand Jain [Tue, 2 Apr 2019 10:07:41 +0000 (18:07 +0800)]
btrfs: prop: open code btrfs_set_prop in inherit_prop

When an inode inherits property from its parent, we call btrfs_set_prop().
btrfs_set_prop() does an elaborate checks, which is not required in the
context of inheriting a property. Instead just open-code only the required
items from btrfs_set_prop() and then call btrfs_setxattr() directly. So
now the only user of btrfs_set_prop() is gone, (except for the wraper
function btrfs_set_prop_trans()).

Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: drop unused parameter in mount_subvol
Anand Jain [Fri, 29 Mar 2019 06:03:17 +0000 (14:03 +0800)]
btrfs: drop unused parameter in mount_subvol

@device_name in mount_subvol() is not used, drop it.  Also see:
5bedc48a8f9e ("btrfs: drop unused parameters from mount_subvol").

Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: get fs_info from eb in check_inode_item
David Sterba [Wed, 20 Mar 2019 15:22:58 +0000 (16:22 +0100)]
btrfs: tree-checker: get fs_info from eb in check_inode_item

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: get fs_info from eb in check_dev_item
David Sterba [Wed, 20 Mar 2019 15:22:58 +0000 (16:22 +0100)]
btrfs: tree-checker: get fs_info from eb in check_dev_item

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: get fs_info from eb in dev_item_err
David Sterba [Wed, 20 Mar 2019 15:22:58 +0000 (16:22 +0100)]
btrfs: tree-checker: get fs_info from eb in dev_item_err

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: get fs_info from eb in chunk_err
David Sterba [Wed, 20 Mar 2019 15:22:58 +0000 (16:22 +0100)]
btrfs: tree-checker: get fs_info from eb in chunk_err

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: get fs_info from eb in check_leaf
David Sterba [Wed, 20 Mar 2019 15:22:58 +0000 (16:22 +0100)]
btrfs: tree-checker: get fs_info from eb in check_leaf

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: get fs_info from eb in check_leaf_item
David Sterba [Wed, 20 Mar 2019 15:22:00 +0000 (16:22 +0100)]
btrfs: tree-checker: get fs_info from eb in check_leaf_item

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: get fs_info from eb in check_extent_data_item
David Sterba [Wed, 20 Mar 2019 15:21:10 +0000 (16:21 +0100)]
btrfs: tree-checker: get fs_info from eb in check_extent_data_item

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: get fs_info from eb in check_block_group_item
David Sterba [Wed, 20 Mar 2019 15:19:31 +0000 (16:19 +0100)]
btrfs: tree-checker: get fs_info from eb in check_block_group_item

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: get fs_info from eb in block_group_err
David Sterba [Wed, 20 Mar 2019 15:18:57 +0000 (16:18 +0100)]
btrfs: tree-checker: get fs_info from eb in block_group_err

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: get fs_info from eb in check_dir_item
David Sterba [Wed, 20 Mar 2019 15:17:46 +0000 (16:17 +0100)]
btrfs: tree-checker: get fs_info from eb in check_dir_item

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: get fs_info from eb in dir_item_err
David Sterba [Wed, 20 Mar 2019 15:07:27 +0000 (16:07 +0100)]
btrfs: tree-checker: get fs_info from eb in dir_item_err

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: get fs_info from eb in check_csum_item
David Sterba [Wed, 20 Mar 2019 15:02:56 +0000 (16:02 +0100)]
btrfs: tree-checker: get fs_info from eb in check_csum_item

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: get fs_info from eb in file_extent_err
David Sterba [Wed, 20 Mar 2019 14:32:46 +0000 (15:32 +0100)]
btrfs: tree-checker: get fs_info from eb in file_extent_err

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: get fs_info from eb in generic_err
David Sterba [Wed, 20 Mar 2019 14:31:28 +0000 (15:31 +0100)]
btrfs: tree-checker: get fs_info from eb in generic_err

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: inode: Verify inode mode to avoid NULL pointer dereference
Qu Wenruo [Wed, 13 Mar 2019 05:55:11 +0000 (13:55 +0800)]
btrfs: inode: Verify inode mode to avoid NULL pointer dereference

[BUG]
When accessing a file on a crafted image, btrfs can crash in block layer:

  BUG: unable to handle kernel NULL pointer dereference at 0000000000000008
  PGD 136501067 P4D 136501067 PUD 124519067 PMD 0
  CPU: 3 PID: 0 Comm: swapper/3 Not tainted 5.0.0-rc8-default #252
  RIP: 0010:end_bio_extent_readpage+0x144/0x700
  Call Trace:
   <IRQ>
   blk_update_request+0x8f/0x350
   blk_mq_end_request+0x1a/0x120
   blk_done_softirq+0x99/0xc0
   __do_softirq+0xc7/0x467
   irq_exit+0xd1/0xe0
   call_function_single_interrupt+0xf/0x20
   </IRQ>
  RIP: 0010:default_idle+0x1e/0x170

[CAUSE]
The crafted image has a tricky corruption, the INODE_ITEM has a
different type against its parent dir:

        item 20 key (268 INODE_ITEM 0) itemoff 2808 itemsize 160
                generation 13 transid 13 size 1048576 nbytes 1048576
                block group 0 mode 121644 links 1 uid 0 gid 0 rdev 0
                sequence 9 flags 0x0(none)

This mode number 0120000 means it's a symlink.

But the dir item think it's still a regular file:

        item 8 key (264 DIR_INDEX 5) itemoff 3707 itemsize 32
                location key (268 INODE_ITEM 0) type FILE
                transid 13 data_len 0 name_len 2
                name: f4
        item 40 key (264 DIR_ITEM 51821248) itemoff 1573 itemsize 32
                location key (268 INODE_ITEM 0) type FILE
                transid 13 data_len 0 name_len 2
                name: f4

For symlink, we don't set BTRFS_I(inode)->io_tree.ops and leave it
empty, as symlink is only designed to have inlined extent, all handled
by tree block read.  Thus no need to trigger btrfs_submit_bio_hook() for
inline file extent.

However end_bio_extent_readpage() expects tree->ops populated, as it's
reading regular data extent.  This causes NULL pointer dereference.

[FIX]
This patch fixes the problem in two ways:

- Verify inode mode against its dir item when looking up inode
  So in btrfs_lookup_dentry() if we find inode mode mismatch with dir
  item, we error out so that corrupted inode will not be accessed.

- Verify inode mode when getting extent mapping
  Only regular file should have regular or preallocated extent.
  If we found regular/preallocated file extent for symlink or
  the rest, we error out before submitting the read bio.

With this fix that crafted image can be rejected gracefully:

  BTRFS critical (device loop0): inode mode mismatch with dir: inode mode=0121644 btrfs type=7 dir type=1

Reported-by: Yoon Jungyeon <jungyeon@gatech.edu>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=202763
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: Verify inode item
Qu Wenruo [Wed, 13 Mar 2019 06:31:35 +0000 (14:31 +0800)]
btrfs: tree-checker: Verify inode item

There is a report in kernel bugzilla about mismatch file type in dir
item and inode item.

This inspires us to check inode mode in inode item.

This patch will check the following members:

- inode key objectid
  Should be ROOT_DIR_DIR or [256, (u64)-256] or FREE_INO.

- inode key offset
  Should be 0

- inode item generation
- inode item transid
  No newer than sb generation + 1.
  The +1 is for log tree.

- inode item mode
  No unknown bits.
  No invalid S_IF* bit.
  NOTE: S_IFMT check is not enough, need to check every know type.

- inode item nlink
  Dir should have no more link than 1.

- inode item flags

Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: Enhance chunk checker to validate chunk profile
Qu Wenruo [Wed, 13 Mar 2019 04:17:50 +0000 (12:17 +0800)]
btrfs: tree-checker: Enhance chunk checker to validate chunk profile

Btrfs-progs already have a comprehensive type checker, to ensure there
is only 0 (SINGLE profile) or 1 (DUP/RAID0/1/5/6/10) bit set for chunk
profile bits.

Do the same work for kernel.

Reported-by: Yoon Jungyeon <jungyeon@gatech.edu>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=202765
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: Verify dev item
Qu Wenruo [Fri, 8 Mar 2019 06:20:03 +0000 (14:20 +0800)]
btrfs: tree-checker: Verify dev item

[BUG]
For fuzzed image whose DEV_ITEM has invalid total_bytes as 0, then
kernel will just panic:
  BUG: unable to handle kernel NULL pointer dereference at 0000000000000098
  #PF error: [normal kernel read fault]
  PGD 800000022b2bd067 P4D 800000022b2bd067 PUD 22b2bc067 PMD 0
  Oops: 0000 [#1] SMP PTI
  CPU: 0 PID: 1106 Comm: mount Not tainted 5.0.0-rc8+ #9
  RIP: 0010:btrfs_verify_dev_extents+0x2a5/0x5a0
  Call Trace:
   open_ctree+0x160d/0x2149
   btrfs_mount_root+0x5b2/0x680

[CAUSE]
If device extent verification finds a deivce with 0 total_bytes, then it
assumes it's a seed dummy, then search for seed devices.

But in this case, there is no seed device at all, causing NULL pointer.

[FIX]
Since this is caused by fuzzed image, let's go the tree-check way, just
add a new verification for device item.

Reported-by: Yoon Jungyeon <jungyeon@gatech.edu>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=202691
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: Check chunk item at tree block read time
Qu Wenruo [Wed, 20 Mar 2019 05:42:33 +0000 (13:42 +0800)]
btrfs: tree-checker: Check chunk item at tree block read time

Since we have btrfs_check_chunk_valid() in tree-checker, let's do
chunk item verification in tree-checker too.

Since the tree-checker is run at endio time, if one chunk leaf fails
chunk verification, we can still retry the other copy, making btrfs more
robust to fuzzed image as we may still get a good chunk item.

Also since we have done chunk verification in tree block read time, skip
the btrfs_check_chunk_valid() call in read_one_chunk() if we're reading
chunk items from leaf.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: Make btrfs_check_chunk_valid() return EUCLEAN instead of EIO
Qu Wenruo [Wed, 20 Mar 2019 05:39:14 +0000 (13:39 +0800)]
btrfs: tree-checker: Make btrfs_check_chunk_valid() return EUCLEAN instead of EIO

To follow the standard behavior of tree-checker.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: tree-checker: Make chunk item checker messages more readable
Qu Wenruo [Wed, 20 Mar 2019 05:36:06 +0000 (13:36 +0800)]
btrfs: tree-checker: Make chunk item checker messages more readable

Old error message would be something like:
  BTRFS error (device dm-3): invalid chunk num_stipres: 0

New error message would be:
  Btrfs critical (device dm-3): corrupt superblock syschunk array: chunk_start=2097152, invalid chunk num_stripes: 0
Or
  Btrfs critical (device dm-3): corrupt leaf: root=3 block=8388608 slot=3 chunk_start=2097152, invalid chunk num_stripes: 0

And for certain error message, also output expected value.

The error message levels are changed from error to critical.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: Move btrfs_check_chunk_valid() to tree-check.[ch] and export it
Qu Wenruo [Wed, 20 Mar 2019 05:16:42 +0000 (13:16 +0800)]
btrfs: Move btrfs_check_chunk_valid() to tree-check.[ch] and export it

By function, chunk item verification is more suitable to be done inside
tree-checker.

So move btrfs_check_chunk_valid() to tree-checker.c and export it.

And since it's now moved to tree-checker, also add a better comment for
what this function is doing.

Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: qgroup: remove obsolete fs_info members
David Sterba [Wed, 27 Mar 2019 15:55:26 +0000 (16:55 +0100)]
btrfs: qgroup: remove obsolete fs_info members

The commit fcebe4562dec ("Btrfs: rework qgroup accounting") reworked
qgroups and added some new structures. Another rework of qgroup
mechanics e69bcee37692 ("btrfs: qgroup: Cleanup the old
ref_node-oriented mechanism.") stopped using them and left uncleaned.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from eb in btrfs_verify_level_key
David Sterba [Wed, 20 Mar 2019 13:58:13 +0000 (14:58 +0100)]
btrfs: get fs_info from eb in btrfs_verify_level_key

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from eb in btree_read_extent_buffer_pages
David Sterba [Wed, 20 Mar 2019 13:56:39 +0000 (14:56 +0100)]
btrfs: get fs_info from eb in btree_read_extent_buffer_pages

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from eb in read_node_slot
David Sterba [Wed, 20 Mar 2019 13:54:01 +0000 (14:54 +0100)]
btrfs: get fs_info from eb in read_node_slot

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from eb in btrfs_leaf_free_space
David Sterba [Wed, 20 Mar 2019 13:36:46 +0000 (14:36 +0100)]
btrfs: get fs_info from eb in btrfs_leaf_free_space

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>
4 years agobtrfs: get fs_info from eb in clean_tree_block
David Sterba [Wed, 20 Mar 2019 13:30:02 +0000 (14:30 +0100)]
btrfs: get fs_info from eb in clean_tree_block

We can read fs_info from extent buffer and can drop it from the
parameters.

Signed-off-by: David Sterba <dsterba@suse.com>