Commit 262f7a6b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents ea915933 eb91db63
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -3657,7 +3657,7 @@ L: linux-btrfs@vger.kernel.org
S:	Maintained
S:	Maintained
W:	http://btrfs.wiki.kernel.org/
W:	http://btrfs.wiki.kernel.org/
Q:	http://patchwork.kernel.org/project/linux-btrfs/list/
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:	Documentation/filesystems/btrfs.rst
F:	fs/btrfs/
F:	fs/btrfs/
F:	include/linux/btrfs*
F:	include/linux/btrfs*
+1 −1
Original line number Original line Diff line number Diff line
@@ -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 **p = &preftrees->direct.root.rb_root.rb_node;
	struct rb_node *parent = NULL;
	struct rb_node *parent = NULL;
	struct prelim_ref *ref = NULL;
	struct prelim_ref *ref = NULL;
	struct prelim_ref target = {0};
	struct prelim_ref target = {};
	int result;
	int result;


	target.parent = bytenr;
	target.parent = bytenr;
+11 −2
Original line number Original line Diff line number Diff line
@@ -662,10 +662,19 @@ again:
	}
	}


got_it:
got_it:
	btrfs_record_root_in_trans(h, root);

	if (!current->journal_info)
	if (!current->journal_info)
		current->journal_info = h;
		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;
	return h;


join_fail:
join_fail:
+40 −3
Original line number Original line Diff line number Diff line
@@ -4226,6 +4226,9 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans,
	const u64 ino = btrfs_ino(inode);
	const u64 ino = btrfs_ino(inode);
	struct btrfs_path *dst_path = NULL;
	struct btrfs_path *dst_path = NULL;
	bool dropped_extents = false;
	bool dropped_extents = false;
	u64 truncate_offset = i_size;
	struct extent_buffer *leaf;
	int slot;
	int ins_nr = 0;
	int ins_nr = 0;
	int start_slot;
	int start_slot;
	int ret;
	int ret;
@@ -4240,9 +4243,43 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans,
	if (ret < 0)
	if (ret < 0)
		goto out;
		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) {
	while (true) {
		struct extent_buffer *leaf = path->nodes[0];
		leaf = path->nodes[0];
		int slot = path->slots[0];
		slot = path->slots[0];


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