read-write mount and will result in an error.
Note: the mount option uuid=off can be used to replace UUID of the underlying
-filesystem in file handles with null, and effectively disable UUID checks. This
+filesystem in file handles with null, in order to relax the UUID checks. This
can be useful in case the underlying disk is copied and the UUID of this copy
-is changed. This is only applicable if all lower/upper/work directories are on
+is changed. This is only applicable if all lower directories are on
the same filesystem, otherwise it will fallback to normal behaviour.
UUID of overlayfs is null. fsid is taken from upper most filesystem.
- "off":
UUID of overlayfs is null. fsid is taken from upper most filesystem.
- UUID of underlying layers is ignored.
+ UUID of underlying layers is ignored and null used instead.
- "on":
UUID of overlayfs is generated and used to report a unique fsid.
UUID is stored in xattr "trusted.overlay.uuid", making overlayfs fsid
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)
{
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));
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,
* 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;
}
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;
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;
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));
}
}
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);
}