Skip to content

Commit

Permalink
Merge tag 'for-5.7-rc3-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 more btrfs fixes from David Sterba:
 "A few more stability fixes, minor build warning fixes and git url
  fixup:

   - fix partial loss of prealloc extent past i_size after fsync

   - fix potential deadlock due to wrong transaction handle passing via
     journal_info

   - fix gcc 4.8 struct intialization warning

   - update git URL in MAINTAINERS entry"

* tag 'for-5.7-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  MAINTAINERS: btrfs: fix git repo URL
  btrfs: fix gcc-4.8 build warning for struct initializer
  btrfs: transaction: Avoid deadlock due to bad initialization timing of fs_info::journal_info
  btrfs: fix partial loss of prealloc extent past i_size after fsync
  • Loading branch information
torvalds committed May 3, 2020
2 parents ea91593 + eb91db6 commit 262f7a6
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 7 deletions.
2 changes: 1 addition & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -3657,7 +3657,7 @@ L: [email protected]
S: Maintained
W: http://btrfs.wiki.kernel.org/
Q: http://patchwork.kernel.org/project/linux-btrfs/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git
F: Documentation/filesystems/btrfs.rst
F: fs/btrfs/
F: include/linux/btrfs*
Expand Down
2 changes: 1 addition & 1 deletion fs/btrfs/backref.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ static int is_shared_data_backref(struct preftrees *preftrees, u64 bytenr)
struct rb_node **p = &preftrees->direct.root.rb_root.rb_node;
struct rb_node *parent = NULL;
struct prelim_ref *ref = NULL;
struct prelim_ref target = {0};
struct prelim_ref target = {};
int result;

target.parent = bytenr;
Expand Down
13 changes: 11 additions & 2 deletions fs/btrfs/transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,10 +662,19 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
}

got_it:
btrfs_record_root_in_trans(h, root);

if (!current->journal_info)
current->journal_info = h;

/*
* btrfs_record_root_in_trans() needs to alloc new extents, and may
* call btrfs_join_transaction() while we're also starting a
* transaction.
*
* Thus it need to be called after current->journal_info initialized,
* or we can deadlock.
*/
btrfs_record_root_in_trans(h, root);

return h;

join_fail:
Expand Down
43 changes: 40 additions & 3 deletions fs/btrfs/tree-log.c
Original file line number Diff line number Diff line change
Expand Up @@ -4226,6 +4226,9 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans,
const u64 ino = btrfs_ino(inode);
struct btrfs_path *dst_path = NULL;
bool dropped_extents = false;
u64 truncate_offset = i_size;
struct extent_buffer *leaf;
int slot;
int ins_nr = 0;
int start_slot;
int ret;
Expand All @@ -4240,9 +4243,43 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans,
if (ret < 0)
goto out;

/*
* We must check if there is a prealloc extent that starts before the
* i_size and crosses the i_size boundary. This is to ensure later we
* truncate down to the end of that extent and not to the i_size, as
* otherwise we end up losing part of the prealloc extent after a log
* replay and with an implicit hole if there is another prealloc extent
* that starts at an offset beyond i_size.
*/
ret = btrfs_previous_item(root, path, ino, BTRFS_EXTENT_DATA_KEY);
if (ret < 0)
goto out;

if (ret == 0) {
struct btrfs_file_extent_item *ei;

leaf = path->nodes[0];
slot = path->slots[0];
ei = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);

if (btrfs_file_extent_type(leaf, ei) ==
BTRFS_FILE_EXTENT_PREALLOC) {
u64 extent_end;

btrfs_item_key_to_cpu(leaf, &key, slot);
extent_end = key.offset +
btrfs_file_extent_num_bytes(leaf, ei);

if (extent_end > i_size)
truncate_offset = extent_end;
}
} else {
ret = 0;
}

while (true) {
struct extent_buffer *leaf = path->nodes[0];
int slot = path->slots[0];
leaf = path->nodes[0];
slot = path->slots[0];

if (slot >= btrfs_header_nritems(leaf)) {
if (ins_nr > 0) {
Expand Down Expand Up @@ -4280,7 +4317,7 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans,
ret = btrfs_truncate_inode_items(trans,
root->log_root,
&inode->vfs_inode,
i_size,
truncate_offset,
BTRFS_EXTENT_DATA_KEY);
} while (ret == -EAGAIN);
if (ret)
Expand Down

0 comments on commit 262f7a6

Please sign in to comment.