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