Skip to content

Commit 262f7a6

Browse files
committed
Merge tag 'for-5.7-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/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
2 parents ea91593 + eb91db6 commit 262f7a6

File tree

4 files changed

+53
-7
lines changed

4 files changed

+53
-7
lines changed

MAINTAINERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3657,7 +3657,7 @@ L: [email protected]
36573657
S: Maintained
36583658
W: http://btrfs.wiki.kernel.org/
36593659
Q: http://patchwork.kernel.org/project/linux-btrfs/list/
3660-
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git
3660+
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git
36613661
F: Documentation/filesystems/btrfs.rst
36623662
F: fs/btrfs/
36633663
F: include/linux/btrfs*

fs/btrfs/backref.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ static int is_shared_data_backref(struct preftrees *preftrees, u64 bytenr)
391391
struct rb_node **p = &preftrees->direct.root.rb_root.rb_node;
392392
struct rb_node *parent = NULL;
393393
struct prelim_ref *ref = NULL;
394-
struct prelim_ref target = {0};
394+
struct prelim_ref target = {};
395395
int result;
396396

397397
target.parent = bytenr;

fs/btrfs/transaction.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -662,10 +662,19 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
662662
}
663663

664664
got_it:
665-
btrfs_record_root_in_trans(h, root);
666-
667665
if (!current->journal_info)
668666
current->journal_info = h;
667+
668+
/*
669+
* btrfs_record_root_in_trans() needs to alloc new extents, and may
670+
* call btrfs_join_transaction() while we're also starting a
671+
* transaction.
672+
*
673+
* Thus it need to be called after current->journal_info initialized,
674+
* or we can deadlock.
675+
*/
676+
btrfs_record_root_in_trans(h, root);
677+
669678
return h;
670679

671680
join_fail:

fs/btrfs/tree-log.c

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4226,6 +4226,9 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans,
42264226
const u64 ino = btrfs_ino(inode);
42274227
struct btrfs_path *dst_path = NULL;
42284228
bool dropped_extents = false;
4229+
u64 truncate_offset = i_size;
4230+
struct extent_buffer *leaf;
4231+
int slot;
42294232
int ins_nr = 0;
42304233
int start_slot;
42314234
int ret;
@@ -4240,9 +4243,43 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans,
42404243
if (ret < 0)
42414244
goto out;
42424245

4246+
/*
4247+
* We must check if there is a prealloc extent that starts before the
4248+
* i_size and crosses the i_size boundary. This is to ensure later we
4249+
* truncate down to the end of that extent and not to the i_size, as
4250+
* otherwise we end up losing part of the prealloc extent after a log
4251+
* replay and with an implicit hole if there is another prealloc extent
4252+
* that starts at an offset beyond i_size.
4253+
*/
4254+
ret = btrfs_previous_item(root, path, ino, BTRFS_EXTENT_DATA_KEY);
4255+
if (ret < 0)
4256+
goto out;
4257+
4258+
if (ret == 0) {
4259+
struct btrfs_file_extent_item *ei;
4260+
4261+
leaf = path->nodes[0];
4262+
slot = path->slots[0];
4263+
ei = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
4264+
4265+
if (btrfs_file_extent_type(leaf, ei) ==
4266+
BTRFS_FILE_EXTENT_PREALLOC) {
4267+
u64 extent_end;
4268+
4269+
btrfs_item_key_to_cpu(leaf, &key, slot);
4270+
extent_end = key.offset +
4271+
btrfs_file_extent_num_bytes(leaf, ei);
4272+
4273+
if (extent_end > i_size)
4274+
truncate_offset = extent_end;
4275+
}
4276+
} else {
4277+
ret = 0;
4278+
}
4279+
42434280
while (true) {
4244-
struct extent_buffer *leaf = path->nodes[0];
4245-
int slot = path->slots[0];
4281+
leaf = path->nodes[0];
4282+
slot = path->slots[0];
42464283

42474284
if (slot >= btrfs_header_nritems(leaf)) {
42484285
if (ins_nr > 0) {
@@ -4280,7 +4317,7 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans,
42804317
ret = btrfs_truncate_inode_items(trans,
42814318
root->log_root,
42824319
&inode->vfs_inode,
4283-
i_size,
4320+
truncate_offset,
42844321
BTRFS_EXTENT_DATA_KEY);
42854322
} while (ret == -EAGAIN);
42864323
if (ret)

0 commit comments

Comments
 (0)