for-6.19-rc1-tag

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAmlATDcACgkQxWXV+ddt
 WDvWIA/7BP1o+7bGSY/HIwnVIwNyEd1YCpUrLZAd61C7t2OEZKCO13HtM9cZSIRb
 z++k8iCkNl5Z3uZH/cQfUcCuA2sip9HSGaVrfeQ3qVnB/s3DMGb/mu1yBCKUo9/f
 nCxpsIC7BD6cTaiAzCJ6JgvCjOSieG111s0/LGjDcjlM7YQoA8p/Jan1nlvfc8It
 sTQ+ZCsuO/xHViQnfmT/XIyy5bSuSABb5LR78wp8wumngTL3ooBXGwWifrNT/egi
 E06Hhnqopg1PjBDtQtmInJ1gh1E0capQ5j1Z6TDeMYCPeUOuPpRqLVrRP3bIM4jN
 vDu5dZpM9r542Wpj/vZvs/UqmhczUmbQfjLfWdr+KORrl6RA9pkHXyFTFIsTKhGi
 vtAsmMnu5FwKSlnZU1i/EuvcF89KEPx4jKRGQWiKUPwAuBUAkVa4xhsI/mAUmwv5
 +Z+hQxPuIAdmcbLblsI0mnhCGjMTx+qUQQdhY2r7U2bOKhEds+XekABb9KBrjOdj
 k8UEQZJwwWkcPSunYsOpBYBI1SIV8UeHtp8d2xrat90+Ome7feL1VFEjV/rOKc6w
 f7hUeYZPVNQMcXdfNRkoXHK/zqKxpMF5lz9Tq3mzfF6XoseC+gSW44dWQnHPnI8X
 kCj0bpg7o2WgGuc3UWIXrVXZmSEWhn30Go6UfsGqHT7xiULQvSc=
 =lAhb
 -----END PGP SIGNATURE-----

Merge tag 'for-6.19-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

Pull btrfs fixes from David Sterba:

 - fix missing btrfs_path release after printing a relocation error
   message

 - fix extent changeset leak on mmap write after failure to reserve
   metadata

 - fix fs devices list structure freeing, it could be potentially leaked
   under some circumstances

 - tree log fixes:
     - fix incremental directory logging where inodes for new dentries
       were incorrectly skipped
     - don't log conflicting inode if it's a directory moved in the
       current transaction

 - regression fixes:
     - fix incorrect btrfs_path freeing when it's auto-cleaned
     - revert commit simplifying preallocation of temporary structures
       in qgroup functions, some cases were not handled properly

* tag 'for-6.19-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix changeset leak on mmap write after failure to reserve metadata
  btrfs: fix memory leak of fs_devices in degraded seed device path
  btrfs: fix a potential path leak in print_data_reloc_error()
  Revert "btrfs: add ASSERTs on prealloc in qgroup functions"
  btrfs: do not skip logging new dentries when logging a new name
  btrfs: don't log conflicting inode if it's a dir moved in the current transaction
  btrfs: tests: fix double btrfs_path free in remove_extent_ref()
master
Linus Torvalds 2025-12-16 19:28:20 +12:00
commit 115fada16b
6 changed files with 46 additions and 33 deletions

View File

@ -2019,13 +2019,14 @@ out:
else
btrfs_delalloc_release_space(inode, data_reserved, page_start,
reserved_space, true);
extent_changeset_free(data_reserved);
out_noreserve:
if (only_release_metadata)
btrfs_check_nocow_unlock(inode);
sb_end_pagefault(inode->vfs_inode.i_sb);
extent_changeset_free(data_reserved);
if (ret < 0)
return vmf_error(ret);

View File

@ -256,6 +256,7 @@ static void print_data_reloc_error(const struct btrfs_inode *inode, u64 file_off
if (ret < 0) {
btrfs_err_rl(fs_info, "failed to lookup extent item for logical %llu: %d",
logical, ret);
btrfs_release_path(&path);
return;
}
eb = path.nodes[0];

View File

@ -1243,14 +1243,7 @@ out:
btrfs_end_transaction(trans);
else if (trans)
ret = btrfs_end_transaction(trans);
/*
* At this point we either failed at allocating prealloc, or we
* succeeded and passed the ownership to it to add_qgroup_rb(). In any
* case, this needs to be NULL or there is something wrong.
*/
ASSERT(prealloc == NULL);
kfree(prealloc);
return ret;
}
@ -1682,12 +1675,7 @@ int btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup);
out:
mutex_unlock(&fs_info->qgroup_ioctl_lock);
/*
* At this point we either failed at allocating prealloc, or we
* succeeded and passed the ownership to it to add_qgroup_rb(). In any
* case, this needs to be NULL or there is something wrong.
*/
ASSERT(prealloc == NULL);
kfree(prealloc);
return ret;
}
@ -3279,7 +3267,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
struct btrfs_root *quota_root;
struct btrfs_qgroup *srcgroup;
struct btrfs_qgroup *dstgroup;
struct btrfs_qgroup *prealloc = NULL;
struct btrfs_qgroup *prealloc;
struct btrfs_qgroup_list **qlist_prealloc = NULL;
bool free_inherit = false;
bool need_rescan = false;
@ -3520,14 +3508,7 @@ out:
}
if (free_inherit)
kfree(inherit);
/*
* At this point we either failed at allocating prealloc, or we
* succeeded and passed the ownership to it to add_qgroup_rb(). In any
* case, this needs to be NULL or there is something wrong.
*/
ASSERT(prealloc == NULL);
kfree(prealloc);
return ret;
}

View File

@ -187,7 +187,6 @@ static int remove_extent_ref(struct btrfs_root *root, u64 bytenr,
ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
if (ret) {
test_err("couldn't find backref %d", ret);
btrfs_free_path(path);
return ret;
}
btrfs_del_item(&trans, root, path);

View File

@ -5865,14 +5865,6 @@ static int log_new_dir_dentries(struct btrfs_trans_handle *trans,
struct btrfs_inode *curr_inode = start_inode;
int ret = 0;
/*
* If we are logging a new name, as part of a link or rename operation,
* don't bother logging new dentries, as we just want to log the names
* of an inode and that any new parents exist.
*/
if (ctx->logging_new_name)
return 0;
path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
@ -6051,6 +6043,33 @@ static int conflicting_inode_is_dir(struct btrfs_root *root, u64 ino,
return ret;
}
static bool can_log_conflicting_inode(const struct btrfs_trans_handle *trans,
const struct btrfs_inode *inode)
{
if (!S_ISDIR(inode->vfs_inode.i_mode))
return true;
if (inode->last_unlink_trans < trans->transid)
return true;
/*
* If this is a directory and its unlink_trans is not from a past
* transaction then we must fallback to a transaction commit in order
* to avoid getting a directory with 2 hard links after log replay.
*
* This happens if a directory A is renamed, moved from one parent
* directory to another one, a new file is created in the old parent
* directory with the old name of our directory A, the new file is
* fsynced, then we moved the new file to some other parent directory
* and fsync again the new file. This results in a log tree where we
* logged that directory A existed, with the INODE_REF item for the
* new location but without having logged its old parent inode, so
* that on log replay we add a new link for the new location but the
* old link remains, resulting in a link count of 2.
*/
return false;
}
static int add_conflicting_inode(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_path *path,
@ -6154,6 +6173,11 @@ static int add_conflicting_inode(struct btrfs_trans_handle *trans,
return 0;
}
if (!can_log_conflicting_inode(trans, inode)) {
btrfs_add_delayed_iput(inode);
return BTRFS_LOG_FORCE_COMMIT;
}
btrfs_add_delayed_iput(inode);
ino_elem = kmalloc(sizeof(*ino_elem), GFP_NOFS);
@ -6218,6 +6242,12 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
break;
}
if (!can_log_conflicting_inode(trans, inode)) {
btrfs_add_delayed_iput(inode);
ret = BTRFS_LOG_FORCE_COMMIT;
break;
}
/*
* Always log the directory, we cannot make this
* conditional on need_log_inode() because the directory

View File

@ -7128,6 +7128,7 @@ static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info,
fs_devices->seeding = true;
fs_devices->opened = 1;
list_add(&fs_devices->seed_list, &fs_info->fs_devices->seed_list);
return fs_devices;
}