Skip to content

Commit

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

Pull btrfs fixes from David Sterba:
 "These are fixes that were found during testing with help of error
  injection, plus some other stable material.

  There's a fixup to patch added to rc1 causing locking in wrong context
  warnings, tests found one more deadlock scenario. The patches are
  tagged for stable, two of them now in the queue but we'd like all
  three released at the same time.

  I'm not happy about fixes to fixes in such a fast succession during
  rcs, but I hope we found all the fallouts of commit 28553fa
  ('Btrfs: fix race between shrinking truncate and fiemap')"

* tag 'for-5.6-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  Btrfs: fix deadlock during fast fsync when logging prealloc extents beyond eof
  Btrfs: fix btrfs_wait_ordered_range() so that it waits for all ordered extents
  btrfs: fix bytes_may_use underflow in prealloc error condtition
  btrfs: handle logged extent failure properly
  btrfs: do not check delayed items are empty for single transaction cleanup
  btrfs: reset fs_root to NULL on error in open_ctree
  btrfs: destroy qgroup extent records on transaction abort
  • Loading branch information
torvalds committed Feb 23, 2020
2 parents a3163ca + a5ae50d commit d2eee25
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 10 deletions.
3 changes: 2 additions & 1 deletion fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -3200,6 +3200,7 @@ int __cold open_ctree(struct super_block *sb,
if (IS_ERR(fs_info->fs_root)) {
err = PTR_ERR(fs_info->fs_root);
btrfs_warn(fs_info, "failed to read fs tree: %d", err);
fs_info->fs_root = NULL;
goto fail_qgroup;
}

Expand Down Expand Up @@ -4276,6 +4277,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
cond_resched();
spin_lock(&delayed_refs->lock);
}
btrfs_qgroup_destroy_extent_records(trans);

spin_unlock(&delayed_refs->lock);

Expand Down Expand Up @@ -4501,7 +4503,6 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
wake_up(&fs_info->transaction_wait);

btrfs_destroy_delayed_inodes(fs_info);
btrfs_assert_delayed_root_empty(fs_info);

btrfs_destroy_marked_extents(fs_info, &cur_trans->dirty_pages,
EXTENT_DIRTY);
Expand Down
2 changes: 2 additions & 0 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -4430,6 +4430,8 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,

ret = alloc_reserved_file_extent(trans, 0, root_objectid, 0, owner,
offset, ins, 1);
if (ret)
btrfs_pin_extent(fs_info, ins->objectid, ins->offset, 1);
btrfs_put_block_group(block_group);
return ret;
}
Expand Down
26 changes: 18 additions & 8 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -4103,8 +4103,9 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
return -ENOMEM;
path->reada = READA_BACK;

lock_extent_bits(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
&cached_state);
if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
lock_extent_bits(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
&cached_state);

/*
* We want to drop from the next block forward in case this new size is
Expand Down Expand Up @@ -4368,11 +4369,10 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
if (!ret && last_size > new_size)
last_size = new_size;
btrfs_ordered_update_i_size(inode, last_size, NULL);
unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start,
(u64)-1, &cached_state);
}

unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
&cached_state);

btrfs_free_path(path);
return ret;
}
Expand Down Expand Up @@ -9824,6 +9824,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_key ins;
u64 cur_offset = start;
u64 clear_offset = start;
u64 i_size;
u64 cur_bytes;
u64 last_alloc = (u64)-1;
Expand Down Expand Up @@ -9858,6 +9859,15 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
btrfs_end_transaction(trans);
break;
}

/*
* We've reserved this space, and thus converted it from
* ->bytes_may_use to ->bytes_reserved. Any error that happens
* from here on out we will only need to clear our reservation
* for the remaining unreserved area, so advance our
* clear_offset by our extent size.
*/
clear_offset += ins.offset;
btrfs_dec_block_group_reservations(fs_info, ins.objectid);

last_alloc = ins.offset;
Expand Down Expand Up @@ -9937,9 +9947,9 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
if (own_trans)
btrfs_end_transaction(trans);
}
if (cur_offset < end)
btrfs_free_reserved_data_space(inode, NULL, cur_offset,
end - cur_offset + 1);
if (clear_offset < end)
btrfs_free_reserved_data_space(inode, NULL, clear_offset,
end - clear_offset + 1);
return ret;
}

Expand Down
7 changes: 6 additions & 1 deletion fs/btrfs/ordered-data.c
Original file line number Diff line number Diff line change
Expand Up @@ -679,10 +679,15 @@ int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len)
}
btrfs_start_ordered_extent(inode, ordered, 1);
end = ordered->file_offset;
/*
* If the ordered extent had an error save the error but don't
* exit without waiting first for all other ordered extents in
* the range to complete.
*/
if (test_bit(BTRFS_ORDERED_IOERR, &ordered->flags))
ret = -EIO;
btrfs_put_ordered_extent(ordered);
if (ret || end == 0 || end == start)
if (end == 0 || end == start)
break;
end--;
}
Expand Down
13 changes: 13 additions & 0 deletions fs/btrfs/qgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -4002,3 +4002,16 @@ int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans,
}
return ret;
}

void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans)
{
struct btrfs_qgroup_extent_record *entry;
struct btrfs_qgroup_extent_record *next;
struct rb_root *root;

root = &trans->delayed_refs.dirty_extent_root;
rbtree_postorder_for_each_entry_safe(entry, next, root, node) {
ulist_free(entry->old_roots);
kfree(entry);
}
}
1 change: 1 addition & 0 deletions fs/btrfs/qgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -414,5 +414,6 @@ int btrfs_qgroup_add_swapped_blocks(struct btrfs_trans_handle *trans,
u64 last_snapshot);
int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct extent_buffer *eb);
void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans);

#endif
2 changes: 2 additions & 0 deletions fs/btrfs/transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ void btrfs_put_transaction(struct btrfs_transaction *transaction)
BUG_ON(!list_empty(&transaction->list));
WARN_ON(!RB_EMPTY_ROOT(
&transaction->delayed_refs.href_root.rb_root));
WARN_ON(!RB_EMPTY_ROOT(
&transaction->delayed_refs.dirty_extent_root));
if (transaction->delayed_refs.pending_csums)
btrfs_err(transaction->fs_info,
"pending csums is %llu",
Expand Down

0 comments on commit d2eee25

Please sign in to comment.