From: Anand Jain <anajain.sg@gmail.com>
To: linux-btrfs@vger.kernel.org, dsterba@suse.com
Cc: Anand Jain <asj@kernel.org>
Subject: Re: [PATCH v3 2/2] btrfs: derive f_fsid from on-disk fsuuid and dev_t
Date: Mon, 4 May 2026 22:28:58 +0800 [thread overview]
Message-ID: <d1a3223f-489a-4769-ab0e-7620dedc3274@gmail.com> (raw)
In-Reply-To: <1420378f88b69562c4c77fe72bc7286408d995d2.1777281686.git.asj@kernel.org>
On 27/4/26 18:18, Anand Jain wrote:
> f_fsid depends on fs_devices->fsid and subvol root id.
>
> For cloned devices either same as the source or dynamical generated
> at mount won't suite because tools like fanotify and ima depends on it.
>
> Switch to a stable derivation using the persistent on-disk fsuuid +
> root id + devt of the block device for the single device filesystem
> when temp_fsid is active.
> This is consistent as long as the device remains unchanged/replace
> (excludes btrfs device replace secnario for now).
>
David,
The changelog was inaccurate per Sashiko. I missed updating it to
reflect the final implementation.
I have corrected it below to match the current code changes.
I hope below change log can be used during merge.
-----------
btrfs: derive f_fsid from on-disk fsid and dev_t
The f_fsid was originally derived from fs_devices->fsid and the
subvolume root ID. However, when temp_fsid is active, fs_devices->fsid
is randomized, making the standard derivation inconsistent.
Since metadata_uuid is optional, it is not a reliable alternative.
This patch instead retrieves the on-disk UUID from
fs_info->super_copy->fsid.
To prevent f_fsid collisions between original and cloned filesystems,
this implementation hashes the dev_t for single-device btrfs
filesystems to ensure uniqueness. This is limited to single-device
filesystems as cloned mounts are currently only supported for that
configuration. Note that f_fsid will change if the device is replaced.
Additionally, since the kernel cannot distinguish between the
original and the cloned filesystem, this new f_fsid derivation
is applied to both.
---------------
Thanks
Anand
> Signed-off-by: Anand Jain <asj@kernel.org>
> ---
> fs/btrfs/super.c | 41 +++++++++++++++++++++++++++++++++--------
> 1 file changed, 33 insertions(+), 8 deletions(-)
>
> diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
> index a63ad6bd89f6..00eff951917c 100644
> --- a/fs/btrfs/super.c
> +++ b/fs/btrfs/super.c
> @@ -1732,12 +1732,13 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
> u64 total_free_data = 0;
> u64 total_free_meta = 0;
> u32 bits = fs_info->sectorsize_bits;
> - __be32 *fsid = (__be32 *)fs_info->fs_devices->fsid;
> + __be32 *fsid;
> unsigned factor = 1;
> struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
> int ret;
> u64 thresh = 0;
> int mixed = 0;
> + __kernel_fsid_t f_fsid;
>
> list_for_each_entry(found, &fs_info->space_info, list) {
> if (found->flags & BTRFS_BLOCK_GROUP_DATA) {
> @@ -1818,14 +1819,38 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
> buf->f_bsize = fs_info->sectorsize;
> buf->f_namelen = BTRFS_NAME_LEN;
>
> - /* We treat it as constant endianness (it doesn't matter _which_)
> - because we want the fsid to come out the same whether mounted
> - on a big-endian or little-endian host */
> - buf->f_fsid.val[0] = be32_to_cpu(fsid[0]) ^ be32_to_cpu(fsid[2]);
> - buf->f_fsid.val[1] = be32_to_cpu(fsid[1]) ^ be32_to_cpu(fsid[3]);
> + /*
> + * fs_devices->fsid is dynamically generated when temp_fsid is active
> + * to support cloned filesystems. Use the original on-disk fsid instead,
> + * as it remains consistent across mount cycles.
> + */
> + if (fs_info->fs_devices->temp_fsid)
> + fsid = (__be32 *)fs_info->super_copy->fsid;
> + else
> + fsid = (__be32 *)fs_info->fs_devices->fsid;
> +
> + /*
> + * We treat it as constant endianness (it doesn't matter _which_)
> + * because we want the fsid to come out the same whether mounted
> + * on a big-endian or little-endian host.
> + */
> + f_fsid.val[0] = be32_to_cpu(fsid[0]) ^ be32_to_cpu(fsid[2]);
> + f_fsid.val[1] = be32_to_cpu(fsid[1]) ^ be32_to_cpu(fsid[3]);
> +
> /* Mask in the root object ID too, to disambiguate subvols */
> - buf->f_fsid.val[0] ^= btrfs_root_id(BTRFS_I(d_inode(dentry))->root) >> 32;
> - buf->f_fsid.val[1] ^= btrfs_root_id(BTRFS_I(d_inode(dentry))->root);
> + f_fsid.val[0] ^= btrfs_root_id(BTRFS_I(d_inode(dentry))->root) >> 32;
> + f_fsid.val[1] ^= btrfs_root_id(BTRFS_I(d_inode(dentry))->root);
> +
> + /* Hash dev_t to avoid f_fsid collision with cloned filesystems. */
> + if (fs_info->fs_devices->total_devices == 1) {
> + __kernel_fsid_t dev_fsid = \
> + u64_to_fsid(huge_encode_dev(fs_info->fs_devices->latest_dev->bdev->bd_dev));
> +
> + f_fsid.val[0] ^= dev_fsid.val[1];
> + f_fsid.val[1] ^= dev_fsid.val[0];
> + }
> +
> + memcpy(&buf->f_fsid, &f_fsid, sizeof(f_fsid));
>
> return 0;
> }
prev parent reply other threads:[~2026-05-04 14:29 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-27 10:18 [PATCH v3 0/2] fix s_uuid and f_fsid consistency for cloned filesystems Anand Jain
2026-04-27 10:18 ` [PATCH v3 1/2] btrfs: use on-disk uuid for s_uuid in temp_fsid mounts Anand Jain
2026-04-27 10:18 ` [PATCH v3 2/2] btrfs: derive f_fsid from on-disk fsuuid and dev_t Anand Jain
2026-05-04 14:28 ` Anand Jain [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d1a3223f-489a-4769-ab0e-7620dedc3274@gmail.com \
--to=anajain.sg@gmail.com \
--cc=asj@kernel.org \
--cc=dsterba@suse.com \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox