History

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

Linus Torvalds committed 6 years ago

Commit 262f7a62 parents ea91593 eb91db64 files · +53 −7Browse files

Unified · Split

4 files
  1. MAINTAINERS +1 −1
  2. fs/btrfs/backref.c +1 −1
  3. fs/btrfs/transaction.c +11 −2
  4. fs/btrfs/tree-log.c +40 −3
MAINTAINERS+1−1
@@ -3657,7 +3657,7 @@ L: linux-btrfs@vger.kernel.org · 3656 unmodified lines
3657S: Maintained3657S: Maintained
3658W: http://btrfs.wiki.kernel.org/3658W: http://btrfs.wiki.kernel.org/
3659Q: http://patchwork.kernel.org/project/linux-btrfs/list/3659Q: http://patchwork.kernel.org/project/linux-btrfs/list/
3660T: git git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git3660T: git git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git
3661F: Documentation/filesystems/btrfs.rst3661F: Documentation/filesystems/btrfs.rst
3662F: fs/btrfs/3662F: fs/btrfs/
3663F: include/linux/btrfs*3663F: include/linux/btrfs*
fs/btrfs/backref.c+1−1
@@ -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;
fs/btrfs/transaction.c+11−2
@@ -662,10 +662,19 @@ again: · 661 unmodified lines
662 }662 }
663 663
664got_it:664got_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
671join_fail:680join_fail:
fs/btrfs/tree-log.c+40−3
@@ -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)