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
Unified · Split
| @@ -3657,7 +3657,7 @@ L: linux-btrfs@vger.kernel.org · 3656 unmodified lines | |||
| 3657 | S: Maintained | 3657 | S: Maintained |
| 3658 | W: http://btrfs.wiki.kernel.org/ | 3658 | W: http://btrfs.wiki.kernel.org/ |
| 3659 | Q: http://patchwork.kernel.org/project/linux-btrfs/list/ | 3659 | 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 |
| 3661 | F: Documentation/filesystems/btrfs.rst | 3661 | F: Documentation/filesystems/btrfs.rst |
| 3662 | F: fs/btrfs/ | 3662 | F: fs/btrfs/ |
| 3663 | F: include/linux/btrfs* | 3663 | F: include/linux/btrfs* |
| @@ -391,7 +391,7 @@ static int is_shared_data_backref(struct preftrees *preftrees, u64 bytenr) · 390 unmodified lines | |||
| 391 | struct rb_node **p = &preftrees->direct.root.rb_root.rb_node; | 391 | struct rb_node **p = &preftrees->direct.root.rb_root.rb_node; |
| 392 | struct rb_node *parent = NULL; | 392 | struct rb_node *parent = NULL; |
| 393 | struct prelim_ref *ref = NULL; | 393 | struct prelim_ref *ref = NULL; |
| 394 | struct prelim_ref target = {0}; | 394 | struct prelim_ref target = {}; |
| 395 | int result; | 395 | int result; |
| 396 | 396 | ||
| 397 | target.parent = bytenr; | 397 | target.parent = bytenr; |
| @@ -662,10 +662,19 @@ again: · 661 unmodified lines | |||
| 662 | } | 662 | } |
| 663 | 663 | ||
| 664 | got_it: | 664 | got_it: |
| 665 | btrfs_record_root_in_trans(h, root); | ||
| 666 | |||
| 667 | if (!current->journal_info) | 665 | if (!current->journal_info) |
| 668 | current->journal_info = h; | 666 | 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 | |||
| 669 | return h; | 678 | return h; |
| 670 | 679 | ||
| 671 | join_fail: | 680 | join_fail: |
| @@ -4226,6 +4226,9 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans, · 4225 unmodified lines | |||
| 4226 | const u64 ino = btrfs_ino(inode); | 4226 | const u64 ino = btrfs_ino(inode); |
| 4227 | struct btrfs_path *dst_path = NULL; | 4227 | struct btrfs_path *dst_path = NULL; |
| 4228 | bool dropped_extents = false; | 4228 | bool dropped_extents = false; |
| 4229 | u64 truncate_offset = i_size; | ||
| 4230 | struct extent_buffer *leaf; | ||
| 4231 | int slot; | ||
| 4229 | int ins_nr = 0; | 4232 | int ins_nr = 0; |
| 4230 | int start_slot; | 4233 | int start_slot; |
| 4231 | int ret; | 4234 | int ret; |
| @@ -4240,9 +4243,43 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans, · 8 unmodified lines | |||
| 4240 | if (ret < 0) | 4243 | if (ret < 0) |
| 4241 | goto out; | 4244 | goto out; |
| 4242 | 4245 | ||
| 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 | |||
| 4243 | while (true) { | 4280 | while (true) { |
| 4244 | struct extent_buffer *leaf = path->nodes[0]; | 4281 | leaf = path->nodes[0]; |
| 4245 | int slot = path->slots[0]; | 4282 | slot = path->slots[0]; |
| 4246 | 4283 | ||
| 4247 | if (slot >= btrfs_header_nritems(leaf)) { | 4284 | if (slot >= btrfs_header_nritems(leaf)) { |
| 4248 | if (ins_nr > 0) { | 4285 | if (ins_nr > 0) { |
| @@ -4280,7 +4317,7 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans, · 31 unmodified lines | |||
| 4280 | ret = btrfs_truncate_inode_items(trans, | 4317 | ret = btrfs_truncate_inode_items(trans, |
| 4281 | root->log_root, | 4318 | root->log_root, |
| 4282 | &inode->vfs_inode, | 4319 | &inode->vfs_inode, |
| 4283 | i_size, | 4320 | truncate_offset, |
| 4284 | BTRFS_EXTENT_DATA_KEY); | 4321 | BTRFS_EXTENT_DATA_KEY); |
| 4285 | } while (ret == -EAGAIN); | 4322 | } while (ret == -EAGAIN); |
| 4286 | if (ret) | 4323 | if (ret) |