Merge tag 'ovl-update-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs

Pull overlayfs update from Amir Goldstein:
 "Relax the semantics of uuid=off to cater to a use case of overlayfs
  lower layers on btrfs clones, whose UUID are ephemeral and an upper
  layer on a different filesystem"

* tag 'ovl-update-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs:
  ovl: relax requirement for uuid=off,index=on
This commit is contained in:
Linus Torvalds
2026-02-17 15:08:24 -08:00
4 changed files with 24 additions and 20 deletions

View File

@@ -159,6 +159,18 @@ invalid:
goto out;
}
bool ovl_uuid_match(struct ovl_fs *ofs, const struct super_block *sb,
const uuid_t *uuid)
{
/*
* Make sure that the stored uuid matches the uuid of the lower
* layer where file handle will be decoded.
* In case of uuid=off option just make sure that stored uuid is null.
*/
return ovl_origin_uuid(ofs) ? uuid_equal(uuid, &sb->s_uuid) :
uuid_is_null(uuid);
}
struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
struct vfsmount *mnt, bool connected)
{
@@ -168,14 +180,7 @@ struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
if (!capable(CAP_DAC_READ_SEARCH))
return NULL;
/*
* Make sure that the stored uuid matches the uuid of the lower
* layer where file handle will be decoded.
* In case of uuid=off option just make sure that stored uuid is null.
*/
if (ovl_origin_uuid(ofs) ?
!uuid_equal(&fh->fb.uuid, &mnt->mnt_sb->s_uuid) :
!uuid_is_null(&fh->fb.uuid))
if (!ovl_uuid_match(ofs, mnt->mnt_sb, &fh->fb.uuid))
return NULL;
bytes = (fh->fb.len - offsetof(struct ovl_fb, fid));

View File

@@ -710,6 +710,8 @@ static inline int ovl_check_fh_len(struct ovl_fh *fh, int fh_len)
return ovl_check_fb_len(&fh->fb, fh_len - OVL_FH_WIRE_OFFSET);
}
bool ovl_uuid_match(struct ovl_fs *ofs, const struct super_block *sb,
const uuid_t *uuid);
struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
struct vfsmount *mnt, bool connected);
int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected,

View File

@@ -940,7 +940,7 @@ static bool ovl_lower_uuid_ok(struct ovl_fs *ofs, const uuid_t *uuid)
* disable lower file handle decoding on all of them.
*/
if (ofs->fs[i].is_lower &&
uuid_equal(&ofs->fs[i].sb->s_uuid, uuid)) {
ovl_uuid_match(ofs, ofs->fs[i].sb, uuid)) {
ofs->fs[i].bad_uuid = true;
return false;
}
@@ -952,6 +952,7 @@ static bool ovl_lower_uuid_ok(struct ovl_fs *ofs, const uuid_t *uuid)
static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
{
struct super_block *sb = path->mnt->mnt_sb;
const uuid_t *uuid = ovl_origin_uuid(ofs) ? &sb->s_uuid : &uuid_null;
unsigned int i;
dev_t dev;
int err;
@@ -963,7 +964,7 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
return i;
}
if (!ovl_lower_uuid_ok(ofs, &sb->s_uuid)) {
if (!ovl_lower_uuid_ok(ofs, uuid)) {
bad_uuid = true;
if (ofs->config.xino == OVL_XINO_AUTO) {
ofs->config.xino = OVL_XINO_OFF;
@@ -975,9 +976,8 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
warn = true;
}
if (warn) {
pr_warn("%s uuid detected in lower fs '%pd2', falling back to xino=%s,index=off,nfs_export=off.\n",
uuid_is_null(&sb->s_uuid) ? "null" :
"conflicting",
pr_warn("%s uuid in non-single lower fs '%pd2', falling back to xino=%s,index=off,nfs_export=off.\n",
uuid_is_null(uuid) ? "null" : "conflicting",
path->dentry, ovl_xino_mode(&ofs->config));
}
}
@@ -1469,10 +1469,7 @@ static int ovl_fill_super_creds(struct fs_context *fc, struct super_block *sb)
if (!ovl_upper_mnt(ofs))
sb->s_flags |= SB_RDONLY;
if (!ovl_origin_uuid(ofs) && ofs->numfs > 1) {
pr_warn("The uuid=off requires a single fs for lower and upper, falling back to uuid=null.\n");
ofs->config.uuid = OVL_UUID_NULL;
} else if (ovl_has_fsid(ofs) && ovl_upper_mnt(ofs)) {
if (ovl_has_fsid(ofs) && ovl_upper_mnt(ofs)) {
/* Use per instance persistent uuid/fsid */
ovl_init_uuid_xattr(sb, ofs, &ctx->upper);
}