Skip to content

Commit

Permalink
Merge tag 'for-4.20-part2-tag' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/kdave/linux

Pull more btrfs updates from David Sterba:
 "This contains a few minor updates and fixes that were under testing or
  arrived shortly after the merge window freeze, mostly stable material"

* tag 'for-4.20-part2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  Btrfs: fix use-after-free when dumping free space
  Btrfs: fix use-after-free during inode eviction
  btrfs: move the dio_sem higher up the callchain
  btrfs: don't run delayed_iputs in commit
  btrfs: fix insert_reserved error handling
  btrfs: only free reserved extent if we didn't insert it
  btrfs: don't use ctl->free_space for max_extent_size
  btrfs: set max_extent_size properly
  btrfs: reset max_extent_size properly
  MAINTAINERS: update my email address for btrfs
  btrfs: delayed-ref: extract find_first_ref_head from find_ref_head
  Btrfs: fix deadlock when writing out free space caches
  Btrfs: fix assertion on fsync of regular file when using no-holes feature
  Btrfs: fix null pointer dereference on compressed write path error
  • Loading branch information
torvalds committed Oct 30, 2018
2 parents 11743c5 + 9084cb6 commit 85b5d4b
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 68 deletions.
2 changes: 1 addition & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -3160,7 +3160,7 @@ F: drivers/gpio/gpio-bt8xx.c

BTRFS FILE SYSTEM
M: Chris Mason <[email protected]>
M: Josef Bacik <jbacik@fb.com>
M: Josef Bacik <josef@toxicpanda.com>
M: David Sterba <[email protected]>
L: [email protected]
W: http://btrfs.wiki.kernel.org/
Expand Down
17 changes: 17 additions & 0 deletions fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1014,9 +1014,26 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
if ((root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && parent)
parent_start = parent->start;

/*
* If we are COWing a node/leaf from the extent, chunk or device trees,
* make sure that we do not finish block group creation of pending block
* groups. We do this to avoid a deadlock.
* COWing can result in allocation of a new chunk, and flushing pending
* block groups (btrfs_create_pending_block_groups()) can be triggered
* when finishing allocation of a new chunk. Creation of a pending block
* group modifies the extent, chunk and device trees, therefore we could
* deadlock with ourselves since we are holding a lock on an extent
* buffer that btrfs_create_pending_block_groups() may try to COW later.
*/
if (root == fs_info->extent_root ||
root == fs_info->chunk_root ||
root == fs_info->dev_root)
trans->can_flush_pending_bgs = false;

cow = btrfs_alloc_tree_block(trans, root, parent_start,
root->root_key.objectid, &disk_key, level,
search_start, empty_size);
trans->can_flush_pending_bgs = true;
if (IS_ERR(cow))
return PTR_ERR(cow);

Expand Down
50 changes: 27 additions & 23 deletions fs/btrfs/delayed-ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,14 +164,27 @@ static struct btrfs_delayed_ref_node* tree_insert(struct rb_root_cached *root,
return NULL;
}

static struct btrfs_delayed_ref_head *find_first_ref_head(
struct btrfs_delayed_ref_root *dr)
{
struct rb_node *n;
struct btrfs_delayed_ref_head *entry;

n = rb_first_cached(&dr->href_root);
if (!n)
return NULL;

entry = rb_entry(n, struct btrfs_delayed_ref_head, href_node);

return entry;
}

/*
* find an head entry based on bytenr. This returns the delayed ref
* head if it was able to find one, or NULL if nothing was in that spot.
* If return_bigger is given, the next bigger entry is returned if no exact
* match is found. But if no bigger one is found then the first node of the
* ref head tree will be returned.
* Find a head entry based on bytenr. This returns the delayed ref head if it
* was able to find one, or NULL if nothing was in that spot. If return_bigger
* is given, the next bigger entry is returned if no exact match is found.
*/
static struct btrfs_delayed_ref_head* find_ref_head(
static struct btrfs_delayed_ref_head *find_ref_head(
struct btrfs_delayed_ref_root *dr, u64 bytenr,
bool return_bigger)
{
Expand All @@ -195,10 +208,9 @@ static struct btrfs_delayed_ref_head* find_ref_head(
if (bytenr > entry->bytenr) {
n = rb_next(&entry->href_node);
if (!n)
n = rb_first_cached(&dr->href_root);
return NULL;
entry = rb_entry(n, struct btrfs_delayed_ref_head,
href_node);
return entry;
}
return entry;
}
Expand Down Expand Up @@ -355,33 +367,25 @@ struct btrfs_delayed_ref_head *btrfs_select_ref_head(
struct btrfs_delayed_ref_root *delayed_refs)
{
struct btrfs_delayed_ref_head *head;
u64 start;
bool loop = false;

again:
start = delayed_refs->run_delayed_start;
head = find_ref_head(delayed_refs, start, true);
if (!head && !loop) {
head = find_ref_head(delayed_refs, delayed_refs->run_delayed_start,
true);
if (!head && delayed_refs->run_delayed_start != 0) {
delayed_refs->run_delayed_start = 0;
start = 0;
loop = true;
head = find_ref_head(delayed_refs, start, true);
if (!head)
return NULL;
} else if (!head && loop) {
return NULL;
head = find_first_ref_head(delayed_refs);
}
if (!head)
return NULL;

while (head->processing) {
struct rb_node *node;

node = rb_next(&head->href_node);
if (!node) {
if (loop)
if (delayed_refs->run_delayed_start == 0)
return NULL;
delayed_refs->run_delayed_start = 0;
start = 0;
loop = true;
goto again;
}
head = rb_entry(node, struct btrfs_delayed_ref_head,
Expand Down
37 changes: 17 additions & 20 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,9 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
insert_reserved);
else
BUG();
if (ret && insert_reserved)
btrfs_pin_extent(trans->fs_info, node->bytenr,
node->num_bytes, 1);
return ret;
}

Expand Down Expand Up @@ -2954,7 +2957,6 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
struct btrfs_delayed_ref_head *head;
int ret;
int run_all = count == (unsigned long)-1;
bool can_flush_pending_bgs = trans->can_flush_pending_bgs;

/* We'll clean this up in btrfs_cleanup_transaction */
if (trans->aborted)
Expand All @@ -2971,7 +2973,6 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
#ifdef SCRAMBLE_DELAYED_REFS
delayed_refs->run_delayed_start = find_middle(&delayed_refs->root);
#endif
trans->can_flush_pending_bgs = false;
ret = __btrfs_run_delayed_refs(trans, count);
if (ret < 0) {
btrfs_abort_transaction(trans, ret);
Expand Down Expand Up @@ -3002,7 +3003,6 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
goto again;
}
out:
trans->can_flush_pending_bgs = can_flush_pending_bgs;
return 0;
}

Expand Down Expand Up @@ -4568,6 +4568,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags,
goto out;
} else {
ret = 1;
space_info->max_extent_size = 0;
}

space_info->force_alloc = CHUNK_ALLOC_NO_FORCE;
Expand All @@ -4589,11 +4590,9 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags,
* the block groups that were made dirty during the lifetime of the
* transaction.
*/
if (trans->can_flush_pending_bgs &&
trans->chunk_bytes_reserved >= (u64)SZ_2M) {
if (trans->chunk_bytes_reserved >= (u64)SZ_2M)
btrfs_create_pending_block_groups(trans);
btrfs_trans_release_chunk_metadata(trans);
}

return ret;
}

Expand Down Expand Up @@ -6464,6 +6463,7 @@ static void btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache,
space_info->bytes_readonly += num_bytes;
cache->reserved -= num_bytes;
space_info->bytes_reserved -= num_bytes;
space_info->max_extent_size = 0;

if (delalloc)
cache->delalloc_bytes -= num_bytes;
Expand Down Expand Up @@ -7260,6 +7260,7 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *block_group = NULL;
u64 search_start = 0;
u64 max_extent_size = 0;
u64 max_free_space = 0;
u64 empty_cluster = 0;
struct btrfs_space_info *space_info;
int loop = 0;
Expand Down Expand Up @@ -7555,8 +7556,8 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info,
spin_lock(&ctl->tree_lock);
if (ctl->free_space <
num_bytes + empty_cluster + empty_size) {
if (ctl->free_space > max_extent_size)
max_extent_size = ctl->free_space;
max_free_space = max(max_free_space,
ctl->free_space);
spin_unlock(&ctl->tree_lock);
goto loop;
}
Expand Down Expand Up @@ -7723,6 +7724,8 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info,
}
out:
if (ret == -ENOSPC) {
if (!max_extent_size)
max_extent_size = max_free_space;
spin_lock(&space_info->lock);
space_info->max_extent_size = max_extent_size;
spin_unlock(&space_info->lock);
Expand Down Expand Up @@ -8004,21 +8007,14 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
}

path = btrfs_alloc_path();
if (!path) {
btrfs_free_and_pin_reserved_extent(fs_info,
extent_key.objectid,
fs_info->nodesize);
if (!path)
return -ENOMEM;
}

path->leave_spinning = 1;
ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path,
&extent_key, size);
if (ret) {
btrfs_free_path(path);
btrfs_free_and_pin_reserved_extent(fs_info,
extent_key.objectid,
fs_info->nodesize);
return ret;
}

Expand Down Expand Up @@ -10132,9 +10128,10 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans)
struct btrfs_block_group_item item;
struct btrfs_key key;
int ret = 0;
bool can_flush_pending_bgs = trans->can_flush_pending_bgs;

trans->can_flush_pending_bgs = false;
if (!trans->can_flush_pending_bgs)
return;

while (!list_empty(&trans->new_bgs)) {
block_group = list_first_entry(&trans->new_bgs,
struct btrfs_block_group_cache,
Expand All @@ -10159,7 +10156,7 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans)
next:
list_del_init(&block_group->bg_list);
}
trans->can_flush_pending_bgs = can_flush_pending_bgs;
btrfs_trans_release_chunk_metadata(trans);
}

int btrfs_make_block_group(struct btrfs_trans_handle *trans, u64 bytes_used,
Expand Down
12 changes: 12 additions & 0 deletions fs/btrfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -2078,6 +2078,14 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
goto out;

inode_lock(inode);

/*
* We take the dio_sem here because the tree log stuff can race with
* lockless dio writes and get an extent map logged for an extent we
* never waited on. We need it this high up for lockdep reasons.
*/
down_write(&BTRFS_I(inode)->dio_sem);

atomic_inc(&root->log_batch);

/*
Expand All @@ -2086,6 +2094,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
*/
ret = btrfs_wait_ordered_range(inode, start, len);
if (ret) {
up_write(&BTRFS_I(inode)->dio_sem);
inode_unlock(inode);
goto out;
}
Expand All @@ -2109,6 +2118,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
* checked called fsync.
*/
ret = filemap_check_wb_err(inode->i_mapping, file->f_wb_err);
up_write(&BTRFS_I(inode)->dio_sem);
inode_unlock(inode);
goto out;
}
Expand All @@ -2127,6 +2137,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
trans = btrfs_start_transaction(root, 0);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
up_write(&BTRFS_I(inode)->dio_sem);
inode_unlock(inode);
goto out;
}
Expand All @@ -2148,6 +2159,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
* file again, but that will end up using the synchronization
* inside btrfs_sync_log to keep things safe.
*/
up_write(&BTRFS_I(inode)->dio_sem);
inode_unlock(inode);

/*
Expand Down
32 changes: 22 additions & 10 deletions fs/btrfs/free-space-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1772,6 +1772,13 @@ static int search_bitmap(struct btrfs_free_space_ctl *ctl,
return -1;
}

static inline u64 get_max_extent_size(struct btrfs_free_space *entry)
{
if (entry->bitmap)
return entry->max_extent_size;
return entry->bytes;
}

/* Cache the size of the max extent in bytes */
static struct btrfs_free_space *
find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes,
Expand All @@ -1793,8 +1800,8 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes,
for (node = &entry->offset_index; node; node = rb_next(node)) {
entry = rb_entry(node, struct btrfs_free_space, offset_index);
if (entry->bytes < *bytes) {
if (entry->bytes > *max_extent_size)
*max_extent_size = entry->bytes;
*max_extent_size = max(get_max_extent_size(entry),
*max_extent_size);
continue;
}

Expand All @@ -1812,8 +1819,8 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes,
}

if (entry->bytes < *bytes + align_off) {
if (entry->bytes > *max_extent_size)
*max_extent_size = entry->bytes;
*max_extent_size = max(get_max_extent_size(entry),
*max_extent_size);
continue;
}

Expand All @@ -1825,8 +1832,10 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes,
*offset = tmp;
*bytes = size;
return entry;
} else if (size > *max_extent_size) {
*max_extent_size = size;
} else {
*max_extent_size =
max(get_max_extent_size(entry),
*max_extent_size);
}
continue;
}
Expand Down Expand Up @@ -2449,6 +2458,7 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group,
struct rb_node *n;
int count = 0;

spin_lock(&ctl->tree_lock);
for (n = rb_first(&ctl->free_space_offset); n; n = rb_next(n)) {
info = rb_entry(n, struct btrfs_free_space, offset_index);
if (info->bytes >= bytes && !block_group->ro)
Expand All @@ -2457,6 +2467,7 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group,
info->offset, info->bytes,
(info->bitmap) ? "yes" : "no");
}
spin_unlock(&ctl->tree_lock);
btrfs_info(fs_info, "block group has cluster?: %s",
list_empty(&block_group->cluster_list) ? "no" : "yes");
btrfs_info(fs_info,
Expand Down Expand Up @@ -2685,8 +2696,8 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group,

err = search_bitmap(ctl, entry, &search_start, &search_bytes, true);
if (err) {
if (search_bytes > *max_extent_size)
*max_extent_size = search_bytes;
*max_extent_size = max(get_max_extent_size(entry),
*max_extent_size);
return 0;
}

Expand Down Expand Up @@ -2723,8 +2734,9 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,

entry = rb_entry(node, struct btrfs_free_space, offset_index);
while (1) {
if (entry->bytes < bytes && entry->bytes > *max_extent_size)
*max_extent_size = entry->bytes;
if (entry->bytes < bytes)
*max_extent_size = max(get_max_extent_size(entry),
*max_extent_size);

if (entry->bytes < bytes ||
(!entry->bitmap && entry->offset < min_start)) {
Expand Down
Loading

0 comments on commit 85b5d4b

Please sign in to comment.