Commit 667b1d41 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:

 - regression fix: dirty extents tracked in xarray for qgroups must be
   adjusted for 32bit platforms

 - fix potentially freeing uninitialized name in fscrypt structure

 - fix warning about unneeded variable in a send callback

* tag 'for-6.12-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix uninitialized pointer free on read_alloc_one_name() error
  btrfs: send: cleanup unneeded return variable in changed_verity()
  btrfs: fix uninitialized pointer free in add_inode_ref()
  btrfs: use sector numbers as keys for the dirty extents xarray
parents 9f635d44 2ab5e243
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -849,6 +849,7 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
		     struct btrfs_qgroup_extent_record *qrecord,
		     int action, bool *qrecord_inserted_ret)
{
	struct btrfs_fs_info *fs_info = trans->fs_info;
	struct btrfs_delayed_ref_head *existing;
	struct btrfs_delayed_ref_root *delayed_refs;
	bool qrecord_inserted = false;
@@ -859,11 +860,11 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
	if (qrecord) {
		int ret;

		ret = btrfs_qgroup_trace_extent_nolock(trans->fs_info,
						       delayed_refs, qrecord);
		ret = btrfs_qgroup_trace_extent_nolock(fs_info, delayed_refs, qrecord);
		if (ret) {
			/* Clean up if insertion fails or item exists. */
			xa_release(&delayed_refs->dirty_extents, qrecord->bytenr);
			xa_release(&delayed_refs->dirty_extents,
				   qrecord->bytenr >> fs_info->sectorsize_bits);
			/* Caller responsible for freeing qrecord on error. */
			if (ret < 0)
				return ERR_PTR(ret);
@@ -873,7 +874,7 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
		}
	}

	trace_add_delayed_ref_head(trans->fs_info, head_ref, action);
	trace_add_delayed_ref_head(fs_info, head_ref, action);

	existing = htree_insert(&delayed_refs->href_root,
				&head_ref->href_node);
@@ -895,8 +896,7 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
		if (head_ref->is_data && head_ref->ref_mod < 0) {
			delayed_refs->pending_csums += head_ref->num_bytes;
			trans->delayed_ref_csum_deletions +=
				btrfs_csum_bytes_to_leaves(trans->fs_info,
							   head_ref->num_bytes);
				btrfs_csum_bytes_to_leaves(fs_info, head_ref->num_bytes);
		}
		delayed_refs->num_heads++;
		delayed_refs->num_heads_ready++;
@@ -1030,7 +1030,8 @@ static int add_delayed_ref(struct btrfs_trans_handle *trans,
			goto free_head_ref;
		}
		if (xa_reserve(&trans->transaction->delayed_refs.dirty_extents,
			       generic_ref->bytenr, GFP_NOFS)) {
			       generic_ref->bytenr >> fs_info->sectorsize_bits,
			       GFP_NOFS)) {
			ret = -ENOMEM;
			goto free_record;
		}
+9 −1
Original line number Diff line number Diff line
@@ -202,7 +202,15 @@ struct btrfs_delayed_ref_root {
	/* head ref rbtree */
	struct rb_root_cached href_root;

	/* Track dirty extent records. */
	/*
	 * Track dirty extent records.
	 * The keys correspond to the logical address of the extent ("bytenr")
	 * right shifted by fs_info->sectorsize_bits. This is both to get a more
	 * dense index space (optimizes xarray structure) and because indexes in
	 * xarrays are of "unsigned long" type, meaning they are 32 bits wide on
	 * 32 bits platforms, limiting the extent range to 4G which is too low
	 * and makes it unusable (truncated index values) on 32 bits platforms.
	 */
	struct xarray dirty_extents;

	/* this spin lock protects the rbtree and the entries inside */
+16 −5
Original line number Diff line number Diff line
@@ -2005,16 +2005,26 @@ int btrfs_qgroup_trace_extent_nolock(struct btrfs_fs_info *fs_info,
				struct btrfs_qgroup_extent_record *record)
{
	struct btrfs_qgroup_extent_record *existing, *ret;
	unsigned long bytenr = record->bytenr;
	const unsigned long index = (record->bytenr >> fs_info->sectorsize_bits);

	if (!btrfs_qgroup_full_accounting(fs_info))
		return 1;

#if BITS_PER_LONG == 32
	if (record->bytenr >= MAX_LFS_FILESIZE) {
		btrfs_err_rl(fs_info,
"qgroup record for extent at %llu is beyond 32bit page cache and xarray index limit",
			     record->bytenr);
		btrfs_err_32bit_limit(fs_info);
		return -EOVERFLOW;
	}
#endif

	lockdep_assert_held(&delayed_refs->lock);
	trace_btrfs_qgroup_trace_extent(fs_info, record);

	xa_lock(&delayed_refs->dirty_extents);
	existing = xa_load(&delayed_refs->dirty_extents, bytenr);
	existing = xa_load(&delayed_refs->dirty_extents, index);
	if (existing) {
		if (record->data_rsv && !existing->data_rsv) {
			existing->data_rsv = record->data_rsv;
@@ -2024,7 +2034,7 @@ int btrfs_qgroup_trace_extent_nolock(struct btrfs_fs_info *fs_info,
		return 1;
	}

	ret = __xa_store(&delayed_refs->dirty_extents, record->bytenr, record, GFP_ATOMIC);
	ret = __xa_store(&delayed_refs->dirty_extents, index, record, GFP_ATOMIC);
	xa_unlock(&delayed_refs->dirty_extents);
	if (xa_is_err(ret)) {
		qgroup_mark_inconsistent(fs_info);
@@ -2129,6 +2139,7 @@ int btrfs_qgroup_trace_extent(struct btrfs_trans_handle *trans, u64 bytenr,
	struct btrfs_fs_info *fs_info = trans->fs_info;
	struct btrfs_qgroup_extent_record *record;
	struct btrfs_delayed_ref_root *delayed_refs;
	const unsigned long index = (bytenr >> fs_info->sectorsize_bits);
	int ret;

	if (!btrfs_qgroup_full_accounting(fs_info) || bytenr == 0 || num_bytes == 0)
@@ -2137,7 +2148,7 @@ int btrfs_qgroup_trace_extent(struct btrfs_trans_handle *trans, u64 bytenr,
	if (!record)
		return -ENOMEM;

	if (xa_reserve(&trans->transaction->delayed_refs.dirty_extents, bytenr, GFP_NOFS)) {
	if (xa_reserve(&trans->transaction->delayed_refs.dirty_extents, index, GFP_NOFS)) {
		kfree(record);
		return -ENOMEM;
	}
@@ -2152,7 +2163,7 @@ int btrfs_qgroup_trace_extent(struct btrfs_trans_handle *trans, u64 bytenr,
	spin_unlock(&delayed_refs->lock);
	if (ret) {
		/* Clean up if insertion fails or item exists. */
		xa_release(&delayed_refs->dirty_extents, record->bytenr);
		xa_release(&delayed_refs->dirty_extents, index);
		kfree(record);
		return 0;
	}
+1 −3
Original line number Diff line number Diff line
@@ -7190,13 +7190,11 @@ static int changed_extent(struct send_ctx *sctx,

static int changed_verity(struct send_ctx *sctx, enum btrfs_compare_tree_result result)
{
	int ret = 0;

	if (!sctx->cur_inode_new_gen && !sctx->cur_inode_deleted) {
		if (result == BTRFS_COMPARE_TREE_NEW)
			sctx->cur_inode_needs_verity = true;
	}
	return ret;
	return 0;
}

static int dir_changed(struct send_ctx *sctx, u64 dir)
+3 −3
Original line number Diff line number Diff line
@@ -1374,7 +1374,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
	struct inode *inode = NULL;
	unsigned long ref_ptr;
	unsigned long ref_end;
	struct fscrypt_str name;
	struct fscrypt_str name = { 0 };
	int ret;
	int log_ref_ver = 0;
	u64 parent_objectid;
@@ -1845,7 +1845,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
				    struct btrfs_dir_item *di,
				    struct btrfs_key *key)
{
	struct fscrypt_str name;
	struct fscrypt_str name = { 0 };
	struct btrfs_dir_item *dir_dst_di;
	struct btrfs_dir_item *index_dst_di;
	bool dir_dst_matches = false;
@@ -2125,7 +2125,7 @@ static noinline int check_item_in_log(struct btrfs_trans_handle *trans,
	struct extent_buffer *eb;
	int slot;
	struct btrfs_dir_item *di;
	struct fscrypt_str name;
	struct fscrypt_str name = { 0 };
	struct inode *inode = NULL;
	struct btrfs_key location;