for-6.12-rc3-tag
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAmcPxtAACgkQxWXV+ddt WDu9lA//WfB88fwEKnqBYDRo6aiSMIAzLDuXkJ9i8d7rcjZO1OIZkEnMOsxhvTcZ KxgjNjkgzoTyUwoAUlG+ZpvMeSNMhBdr2NFkXmYzN9oanFE4zplpZiWx6tGSApRU 0ilngjXBsr8p03HmB88Yb05DVYQ2elMP6Jx3VETDBa0CNyp4//tGKzusNhZdA7KM XLZmkKRk3ZKabNo+p2J5t8UGJCl2L18U0o/EphfSkODKadUnsBbAPZUt2EGQCZwv uZhDFAUkgTFBkeRO7JwTfDrNi51M4zwmh+kEduzg4Ny4TdFb1UapU7K1N330WMru 4Qa953Met9I4NB/kKI+fZP1lN4NGuD2qEU6yoZVSy4UiqRp1gEg8kOUfVGFbNJa1 VFYcwdrBad0I4PjnQc5bpZVjzqJT5wWiZxjlWrB7VyIfdmnvQxe5h4DBwBhN5FJr +MEtuY2QNFygjDAZ5z0Ss8hegqI+FYi562Cjy9QRLhb3qGD8STF2BIChaILIn3oA UVJUlUP6CUmCu1RZRMFB4/WkeHO46FmZxJErGfFeXqJInThf0/rdSZOQgIP0JsUq N8FINEgXFAMCkK1PT7MNvAYkSP0tR7B0JjGKcSlGS3v3F0URCNGvHSiqbLedAtXT lc1MdXTZxub8h6xhIvgY1j7HRAFGrunn7LD6MIKRWX1SZPWwAGI= =DEUA -----END PGP SIGNATURE----- Merge tag 'for-6.12-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux 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
This commit is contained in:
commit
667b1d41b2
@ -849,6 +849,7 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
|
|||||||
struct btrfs_qgroup_extent_record *qrecord,
|
struct btrfs_qgroup_extent_record *qrecord,
|
||||||
int action, bool *qrecord_inserted_ret)
|
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_head *existing;
|
||||||
struct btrfs_delayed_ref_root *delayed_refs;
|
struct btrfs_delayed_ref_root *delayed_refs;
|
||||||
bool qrecord_inserted = false;
|
bool qrecord_inserted = false;
|
||||||
@ -859,11 +860,11 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
|
|||||||
if (qrecord) {
|
if (qrecord) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = btrfs_qgroup_trace_extent_nolock(trans->fs_info,
|
ret = btrfs_qgroup_trace_extent_nolock(fs_info, delayed_refs, qrecord);
|
||||||
delayed_refs, qrecord);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/* Clean up if insertion fails or item exists. */
|
/* 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. */
|
/* Caller responsible for freeing qrecord on error. */
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ERR_PTR(ret);
|
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,
|
existing = htree_insert(&delayed_refs->href_root,
|
||||||
&head_ref->href_node);
|
&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) {
|
if (head_ref->is_data && head_ref->ref_mod < 0) {
|
||||||
delayed_refs->pending_csums += head_ref->num_bytes;
|
delayed_refs->pending_csums += head_ref->num_bytes;
|
||||||
trans->delayed_ref_csum_deletions +=
|
trans->delayed_ref_csum_deletions +=
|
||||||
btrfs_csum_bytes_to_leaves(trans->fs_info,
|
btrfs_csum_bytes_to_leaves(fs_info, head_ref->num_bytes);
|
||||||
head_ref->num_bytes);
|
|
||||||
}
|
}
|
||||||
delayed_refs->num_heads++;
|
delayed_refs->num_heads++;
|
||||||
delayed_refs->num_heads_ready++;
|
delayed_refs->num_heads_ready++;
|
||||||
@ -1030,7 +1030,8 @@ static int add_delayed_ref(struct btrfs_trans_handle *trans,
|
|||||||
goto free_head_ref;
|
goto free_head_ref;
|
||||||
}
|
}
|
||||||
if (xa_reserve(&trans->transaction->delayed_refs.dirty_extents,
|
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;
|
ret = -ENOMEM;
|
||||||
goto free_record;
|
goto free_record;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -202,7 +202,15 @@ struct btrfs_delayed_ref_root {
|
|||||||
/* head ref rbtree */
|
/* head ref rbtree */
|
||||||
struct rb_root_cached href_root;
|
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;
|
struct xarray dirty_extents;
|
||||||
|
|
||||||
/* this spin lock protects the rbtree and the entries inside */
|
/* this spin lock protects the rbtree and the entries inside */
|
||||||
|
|||||||
@ -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 *record)
|
||||||
{
|
{
|
||||||
struct btrfs_qgroup_extent_record *existing, *ret;
|
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))
|
if (!btrfs_qgroup_full_accounting(fs_info))
|
||||||
return 1;
|
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);
|
lockdep_assert_held(&delayed_refs->lock);
|
||||||
trace_btrfs_qgroup_trace_extent(fs_info, record);
|
trace_btrfs_qgroup_trace_extent(fs_info, record);
|
||||||
|
|
||||||
xa_lock(&delayed_refs->dirty_extents);
|
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 (existing) {
|
||||||
if (record->data_rsv && !existing->data_rsv) {
|
if (record->data_rsv && !existing->data_rsv) {
|
||||||
existing->data_rsv = record->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;
|
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);
|
xa_unlock(&delayed_refs->dirty_extents);
|
||||||
if (xa_is_err(ret)) {
|
if (xa_is_err(ret)) {
|
||||||
qgroup_mark_inconsistent(fs_info);
|
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_fs_info *fs_info = trans->fs_info;
|
||||||
struct btrfs_qgroup_extent_record *record;
|
struct btrfs_qgroup_extent_record *record;
|
||||||
struct btrfs_delayed_ref_root *delayed_refs;
|
struct btrfs_delayed_ref_root *delayed_refs;
|
||||||
|
const unsigned long index = (bytenr >> fs_info->sectorsize_bits);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!btrfs_qgroup_full_accounting(fs_info) || bytenr == 0 || num_bytes == 0)
|
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)
|
if (!record)
|
||||||
return -ENOMEM;
|
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);
|
kfree(record);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
@ -2152,7 +2163,7 @@ int btrfs_qgroup_trace_extent(struct btrfs_trans_handle *trans, u64 bytenr,
|
|||||||
spin_unlock(&delayed_refs->lock);
|
spin_unlock(&delayed_refs->lock);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/* Clean up if insertion fails or item exists. */
|
/* 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);
|
kfree(record);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
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 (!sctx->cur_inode_new_gen && !sctx->cur_inode_deleted) {
|
||||||
if (result == BTRFS_COMPARE_TREE_NEW)
|
if (result == BTRFS_COMPARE_TREE_NEW)
|
||||||
sctx->cur_inode_needs_verity = true;
|
sctx->cur_inode_needs_verity = true;
|
||||||
}
|
}
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dir_changed(struct send_ctx *sctx, u64 dir)
|
static int dir_changed(struct send_ctx *sctx, u64 dir)
|
||||||
|
|||||||
@ -1374,7 +1374,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
|
|||||||
struct inode *inode = NULL;
|
struct inode *inode = NULL;
|
||||||
unsigned long ref_ptr;
|
unsigned long ref_ptr;
|
||||||
unsigned long ref_end;
|
unsigned long ref_end;
|
||||||
struct fscrypt_str name;
|
struct fscrypt_str name = { 0 };
|
||||||
int ret;
|
int ret;
|
||||||
int log_ref_ver = 0;
|
int log_ref_ver = 0;
|
||||||
u64 parent_objectid;
|
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_dir_item *di,
|
||||||
struct btrfs_key *key)
|
struct btrfs_key *key)
|
||||||
{
|
{
|
||||||
struct fscrypt_str name;
|
struct fscrypt_str name = { 0 };
|
||||||
struct btrfs_dir_item *dir_dst_di;
|
struct btrfs_dir_item *dir_dst_di;
|
||||||
struct btrfs_dir_item *index_dst_di;
|
struct btrfs_dir_item *index_dst_di;
|
||||||
bool dir_dst_matches = false;
|
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;
|
struct extent_buffer *eb;
|
||||||
int slot;
|
int slot;
|
||||||
struct btrfs_dir_item *di;
|
struct btrfs_dir_item *di;
|
||||||
struct fscrypt_str name;
|
struct fscrypt_str name = { 0 };
|
||||||
struct inode *inode = NULL;
|
struct inode *inode = NULL;
|
||||||
struct btrfs_key location;
|
struct btrfs_key location;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user