Commit d9544c1b authored by Amir Goldstein's avatar Amir Goldstein

ovl: store persistent uuid/fsid with uuid=on

With uuid=on, store a persistent uuid in xattr on the upper dir to
give the overlayfs instance a persistent identifier.

This also makes f_fsid persistent and more reliable for reporting
fid info in fanotify events.

uuid=on is not supported on non-upper overlayfs or with upper fs
that does not support xattrs.
Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
parent b0504bfe
...@@ -671,6 +671,9 @@ controlled by the "uuid" mount option, which supports these values: ...@@ -671,6 +671,9 @@ controlled by the "uuid" mount option, which supports these values:
UUID of underlying layers is ignored. UUID of underlying layers is ignored.
- "on": - "on":
UUID of overlayfs is generated and used to report a unique fsid. UUID of overlayfs is generated and used to report a unique fsid.
UUID is stored in xattr "trusted.overlay.uuid", making overlayfs fsid
unique and persistent. This option requires an overlayfs with upper
filesystem that supports xattrs.
Volatile mount Volatile mount
......
...@@ -37,6 +37,7 @@ enum ovl_xattr { ...@@ -37,6 +37,7 @@ enum ovl_xattr {
OVL_XATTR_IMPURE, OVL_XATTR_IMPURE,
OVL_XATTR_NLINK, OVL_XATTR_NLINK,
OVL_XATTR_UPPER, OVL_XATTR_UPPER,
OVL_XATTR_UUID,
OVL_XATTR_METACOPY, OVL_XATTR_METACOPY,
OVL_XATTR_PROTATTR, OVL_XATTR_PROTATTR,
}; };
...@@ -465,6 +466,8 @@ bool ovl_already_copied_up(struct dentry *dentry, int flags); ...@@ -465,6 +466,8 @@ bool ovl_already_copied_up(struct dentry *dentry, int flags);
bool ovl_path_check_dir_xattr(struct ovl_fs *ofs, const struct path *path, bool ovl_path_check_dir_xattr(struct ovl_fs *ofs, const struct path *path,
enum ovl_xattr ox); enum ovl_xattr ox);
bool ovl_path_check_origin_xattr(struct ovl_fs *ofs, const struct path *path); bool ovl_path_check_origin_xattr(struct ovl_fs *ofs, const struct path *path);
bool ovl_init_uuid_xattr(struct super_block *sb, struct ovl_fs *ofs,
const struct path *upperpath);
static inline bool ovl_check_origin_xattr(struct ovl_fs *ofs, static inline bool ovl_check_origin_xattr(struct ovl_fs *ofs,
struct dentry *upperdentry) struct dentry *upperdentry)
......
...@@ -801,6 +801,11 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx, ...@@ -801,6 +801,11 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
config->ovl_volatile = false; config->ovl_volatile = false;
} }
if (!config->upperdir && config->uuid == OVL_UUID_ON) {
pr_info("option \"uuid=on\" requires an upper fs, falling back to uuid=null.\n");
config->uuid = OVL_UUID_NULL;
}
/* Resolve verity -> metacopy dependency */ /* Resolve verity -> metacopy dependency */
if (config->verity_mode && !config->metacopy) { if (config->verity_mode && !config->metacopy) {
/* Don't allow explicit specified conflicting combinations */ /* Don't allow explicit specified conflicting combinations */
......
...@@ -777,6 +777,10 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs, ...@@ -777,6 +777,10 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
ofs->config.index = false; ofs->config.index = false;
pr_warn("...falling back to index=off.\n"); pr_warn("...falling back to index=off.\n");
} }
if (ovl_has_fsid(ofs)) {
ofs->config.uuid = OVL_UUID_NULL;
pr_warn("...falling back to uuid=null.\n");
}
/* /*
* xattr support is required for persistent st_ino. * xattr support is required for persistent st_ino.
* Without persistent st_ino, xino=auto falls back to xino=off. * Without persistent st_ino, xino=auto falls back to xino=off.
...@@ -1427,9 +1431,9 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc) ...@@ -1427,9 +1431,9 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
if (!ovl_origin_uuid(ofs) && ofs->numfs > 1) { 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"); 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; ofs->config.uuid = OVL_UUID_NULL;
} else if (ovl_has_fsid(ofs)) { } else if (ovl_has_fsid(ofs) && ovl_upper_mnt(ofs)) {
/* Use per instance uuid/fsid */ /* Use per instance persistent uuid/fsid */
uuid_gen(&sb->s_uuid); ovl_init_uuid_xattr(sb, ofs, &ctx->upper);
} }
if (!ovl_force_readonly(ofs) && ofs->config.index) { if (!ovl_force_readonly(ofs) && ofs->config.index) {
......
...@@ -676,6 +676,43 @@ bool ovl_path_check_origin_xattr(struct ovl_fs *ofs, const struct path *path) ...@@ -676,6 +676,43 @@ bool ovl_path_check_origin_xattr(struct ovl_fs *ofs, const struct path *path)
return false; return false;
} }
/*
* Load persistent uuid from xattr into s_uuid if found, or store a new
* random generated value in s_uuid and in xattr.
*/
bool ovl_init_uuid_xattr(struct super_block *sb, struct ovl_fs *ofs,
const struct path *upperpath)
{
bool set = false;
int res;
/* Try to load existing persistent uuid */
res = ovl_path_getxattr(ofs, upperpath, OVL_XATTR_UUID, sb->s_uuid.b,
UUID_SIZE);
if (res == UUID_SIZE)
return true;
if (res != -ENODATA)
goto fail;
/* Generate overlay instance uuid */
uuid_gen(&sb->s_uuid);
/* Try to store persistent uuid */
set = true;
res = ovl_setxattr(ofs, upperpath->dentry, OVL_XATTR_UUID, sb->s_uuid.b,
UUID_SIZE);
if (res == 0)
return true;
fail:
memset(sb->s_uuid.b, 0, UUID_SIZE);
ofs->config.uuid = OVL_UUID_NULL;
pr_warn("failed to %s uuid (%pd2, err=%i); falling back to uuid=null.\n",
set ? "set" : "get", upperpath->dentry, res);
return false;
}
bool ovl_path_check_dir_xattr(struct ovl_fs *ofs, const struct path *path, bool ovl_path_check_dir_xattr(struct ovl_fs *ofs, const struct path *path,
enum ovl_xattr ox) enum ovl_xattr ox)
{ {
...@@ -698,6 +735,7 @@ bool ovl_path_check_dir_xattr(struct ovl_fs *ofs, const struct path *path, ...@@ -698,6 +735,7 @@ bool ovl_path_check_dir_xattr(struct ovl_fs *ofs, const struct path *path,
#define OVL_XATTR_IMPURE_POSTFIX "impure" #define OVL_XATTR_IMPURE_POSTFIX "impure"
#define OVL_XATTR_NLINK_POSTFIX "nlink" #define OVL_XATTR_NLINK_POSTFIX "nlink"
#define OVL_XATTR_UPPER_POSTFIX "upper" #define OVL_XATTR_UPPER_POSTFIX "upper"
#define OVL_XATTR_UUID_POSTFIX "uuid"
#define OVL_XATTR_METACOPY_POSTFIX "metacopy" #define OVL_XATTR_METACOPY_POSTFIX "metacopy"
#define OVL_XATTR_PROTATTR_POSTFIX "protattr" #define OVL_XATTR_PROTATTR_POSTFIX "protattr"
...@@ -712,6 +750,7 @@ const char *const ovl_xattr_table[][2] = { ...@@ -712,6 +750,7 @@ const char *const ovl_xattr_table[][2] = {
OVL_XATTR_TAB_ENTRY(OVL_XATTR_IMPURE), OVL_XATTR_TAB_ENTRY(OVL_XATTR_IMPURE),
OVL_XATTR_TAB_ENTRY(OVL_XATTR_NLINK), OVL_XATTR_TAB_ENTRY(OVL_XATTR_NLINK),
OVL_XATTR_TAB_ENTRY(OVL_XATTR_UPPER), OVL_XATTR_TAB_ENTRY(OVL_XATTR_UPPER),
OVL_XATTR_TAB_ENTRY(OVL_XATTR_UUID),
OVL_XATTR_TAB_ENTRY(OVL_XATTR_METACOPY), OVL_XATTR_TAB_ENTRY(OVL_XATTR_METACOPY),
OVL_XATTR_TAB_ENTRY(OVL_XATTR_PROTATTR), OVL_XATTR_TAB_ENTRY(OVL_XATTR_PROTATTR),
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment