With index=on, overlayfs instances are non-migratable, meaning that the layers cannot be copied without breaking the index. So when indexdir exists, store a persistent uuid in xattr on the indexdir to give the overlayfs instance a persistent identifier. This also makes f_fsid persistent and more reliable for reporting fid info in fanotify events. With mount option uuid=nogen, a persistent uuid is not be initialized on indexdir, but if a persistent uuid already exists, it will be used. Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> --- fs/overlayfs/overlayfs.h | 3 +++ fs/overlayfs/super.c | 7 +++++++ fs/overlayfs/util.c | 41 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index dcdb02d0ddf8..9927472a3aaa 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -36,6 +36,7 @@ enum ovl_xattr { OVL_XATTR_IMPURE, OVL_XATTR_NLINK, OVL_XATTR_UPPER, + OVL_XATTR_UUID, OVL_XATTR_METACOPY, OVL_XATTR_PROTATTR, }; @@ -431,6 +432,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, + struct dentry *upperdentry, bool set); static inline bool ovl_check_origin_xattr(struct ovl_fs *ofs, struct dentry *upperdentry) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index ad2250f98b38..8364620e8722 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -1535,6 +1535,9 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs, if (err) pr_err("failed to verify index dir 'upper' xattr\n"); + /* Best effort get or set persistent uuid */ + ovl_init_uuid_xattr(sb, ofs, ofs->indexdir, true); + /* Cleanup bad/stale/orphan index entries */ if (!err) err = ovl_indexdir_cleanup(ofs); @@ -2052,6 +2055,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) ovl_uuid_str[ofs->config.uuid]); } + /* + * This uuid may be overridden by a persistent uuid stored in xattr on + * index dir and it may be persisted in xattr on first index=on mount. + */ if (ovl_want_uuid_gen(ofs)) uuid_gen(&sb->s_uuid); diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 923d66d131c1..8902db4b2975 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -589,6 +589,45 @@ 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, possibly overriding + * the random generated value in s_uuid. + * Otherwise, if @set is true and s_uuid contains a valid value, store this + * value in xattr. + */ +bool ovl_init_uuid_xattr(struct super_block *sb, struct ovl_fs *ofs, + struct dentry *upperdentry, bool set) +{ + struct path path = { + .dentry = upperdentry, + .mnt = ovl_upper_mnt(ofs), + }; + uuid_t uuid; + int res; + + res = ovl_path_getxattr(ofs, &path, OVL_XATTR_UUID, uuid.b, UUID_SIZE); + if (res == UUID_SIZE) { + uuid_copy(&sb->s_uuid, &uuid); + return true; + } + + if (res == -ENODATA) { + if (!set || uuid_is_null(&sb->s_uuid)) + return false; + + res = ovl_setxattr(ofs, upperdentry, OVL_XATTR_UUID, + sb->s_uuid.b, UUID_SIZE); + if (res == 0) + return true; + } else { + set = false; + } + + pr_warn("failed to %s uuid (%pd2, err=%i)\n", + set ? "set" : "get", upperdentry, res); + return false; +} + bool ovl_path_check_dir_xattr(struct ovl_fs *ofs, const struct path *path, enum ovl_xattr ox) { @@ -611,6 +650,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" @@ -625,6 +665,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), }; -- 2.34.1