ovl: store persistent uuid/fsid with uuid=on
authorAmir Goldstein <amir73il@gmail.com>
Fri, 7 Jul 2023 08:20:41 +0000 (11:20 +0300)
committerAmir Goldstein <amir73il@gmail.com>
Sat, 12 Aug 2023 16:02:50 +0000 (19:02 +0300)
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: Amir Goldstein <amir73il@gmail.com>
Documentation/filesystems/overlayfs.rst
fs/overlayfs/overlayfs.h
fs/overlayfs/params.c
fs/overlayfs/super.c
fs/overlayfs/util.c

index d55381d..8275ed7 100644 (file)
@@ -671,6 +671,9 @@ controlled by the "uuid" mount option, which supports these values:
     UUID of underlying layers is ignored.
 - "on":
     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
index 000dd89..8b026d7 100644 (file)
@@ -37,6 +37,7 @@ enum ovl_xattr {
        OVL_XATTR_IMPURE,
        OVL_XATTR_NLINK,
        OVL_XATTR_UPPER,
+       OVL_XATTR_UUID,
        OVL_XATTR_METACOPY,
        OVL_XATTR_PROTATTR,
 };
@@ -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,
                              enum ovl_xattr ox);
 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,
                                          struct dentry *upperdentry)
index 1ff9346..5a59c87 100644 (file)
@@ -801,6 +801,11 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
                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 */
        if (config->verity_mode && !config->metacopy) {
                /* Don't allow explicit specified conflicting combinations */
index c2bab61..9107e54 100644 (file)
@@ -777,6 +777,10 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
                        ofs->config.index = false;
                        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.
                 * 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)
        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)) {
-               /* Use per instance uuid/fsid */
-               uuid_gen(&sb->s_uuid);
+       } else if (ovl_has_fsid(ofs) && ovl_upper_mnt(ofs)) {
+               /* Use per instance persistent uuid/fsid */
+               ovl_init_uuid_xattr(sb, ofs, &ctx->upper);
        }
 
        if (!ovl_force_readonly(ofs) && ofs->config.index) {
index 500133f..8602982 100644 (file)
@@ -676,6 +676,43 @@ bool ovl_path_check_origin_xattr(struct ovl_fs *ofs, const struct path *path)
        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,
                               enum ovl_xattr ox)
 {
@@ -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_NLINK_POSTFIX                "nlink"
 #define OVL_XATTR_UPPER_POSTFIX                "upper"
+#define OVL_XATTR_UUID_POSTFIX         "uuid"
 #define OVL_XATTR_METACOPY_POSTFIX     "metacopy"
 #define OVL_XATTR_PROTATTR_POSTFIX     "protattr"
 
@@ -712,6 +750,7 @@ const char *const ovl_xattr_table[][2] = {
        OVL_XATTR_TAB_ENTRY(OVL_XATTR_IMPURE),
        OVL_XATTR_TAB_ENTRY(OVL_XATTR_NLINK),
        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_PROTATTR),
 };