Skip to content

Commit b0504bf

Browse files
committed
ovl: add support for unique fsid per instance
The legacy behavior of ovl_statfs() reports the f_fsid filled by underlying upper fs. This fsid is not unique among overlayfs instances on the same upper fs. With mount option uuid=on, generate a non-persistent uuid per overlayfs instance and use it as the seed for f_fsid, similar to tmpfs. This is useful for reporting fanotify events with fid info from different instances of overlayfs over the same upper fs. The old behavior of null uuid and upper fs fsid is retained with the mount option uuid=null, which is the default. The mount option uuid=off that disables uuid checks in underlying layers also retains the legacy behavior. Signed-off-by: Amir Goldstein <amir73il@gmail.com>
1 parent 16aac5a commit b0504bf

File tree

7 files changed

+69
-13
lines changed

7 files changed

+69
-13
lines changed

Documentation/filesystems/overlayfs.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,22 @@ can be useful in case the underlying disk is copied and the UUID of this copy
657657
is changed. This is only applicable if all lower/upper/work directories are on
658658
the same filesystem, otherwise it will fallback to normal behaviour.
659659

660+
661+
UUID and fsid
662+
-------------
663+
664+
The UUID of overlayfs instance itself and the fsid reported by statfs(2) are
665+
controlled by the "uuid" mount option, which supports these values:
666+
667+
- "null": (default)
668+
UUID of overlayfs is null. fsid is taken from upper most filesystem.
669+
- "off":
670+
UUID of overlayfs is null. fsid is taken from upper most filesystem.
671+
UUID of underlying layers is ignored.
672+
- "on":
673+
UUID of overlayfs is generated and used to report a unique fsid.
674+
675+
660676
Volatile mount
661677
--------------
662678

fs/overlayfs/copy_up.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real,
416416
if (is_upper)
417417
fh->fb.flags |= OVL_FH_FLAG_PATH_UPPER;
418418
fh->fb.len = sizeof(fh->fb) + buflen;
419-
if (ofs->config.uuid)
419+
if (ovl_origin_uuid(ofs))
420420
fh->fb.uuid = *uuid;
421421

422422
return fh;

fs/overlayfs/namei.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,9 @@ struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
171171
* layer where file handle will be decoded.
172172
* In case of uuid=off option just make sure that stored uuid is null.
173173
*/
174-
if (ofs->config.uuid ? !uuid_equal(&fh->fb.uuid, &mnt->mnt_sb->s_uuid) :
175-
!uuid_is_null(&fh->fb.uuid))
174+
if (ovl_origin_uuid(ofs) ?
175+
!uuid_equal(&fh->fb.uuid, &mnt->mnt_sb->s_uuid) :
176+
!uuid_is_null(&fh->fb.uuid))
176177
return NULL;
177178

178179
bytes = (fh->fb.len - offsetof(struct ovl_fb, fid));

fs/overlayfs/overlayfs.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ enum {
6767
OVL_REDIRECT_ON,
6868
};
6969

70+
enum {
71+
OVL_UUID_OFF,
72+
OVL_UUID_NULL,
73+
OVL_UUID_ON,
74+
};
75+
7076
enum {
7177
OVL_XINO_OFF,
7278
OVL_XINO_AUTO,
@@ -534,6 +540,16 @@ static inline bool ovl_redirect_dir(struct ovl_fs *ofs)
534540
return ofs->config.redirect_mode == OVL_REDIRECT_ON;
535541
}
536542

543+
static inline bool ovl_origin_uuid(struct ovl_fs *ofs)
544+
{
545+
return ofs->config.uuid != OVL_UUID_OFF;
546+
}
547+
548+
static inline bool ovl_has_fsid(struct ovl_fs *ofs)
549+
{
550+
return ofs->config.uuid == OVL_UUID_ON;
551+
}
552+
537553
/*
538554
* With xino=auto, we do best effort to keep all inodes on same st_dev and
539555
* d_ino consistent with st_ino.

fs/overlayfs/ovl_entry.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ struct ovl_config {
1212
int redirect_mode;
1313
int verity_mode;
1414
bool index;
15-
bool uuid;
15+
int uuid;
1616
bool nfs_export;
1717
int xino;
1818
bool metacopy;

fs/overlayfs/params.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,23 @@ static const struct constant_table ovl_parameter_bool[] = {
6565
{}
6666
};
6767

68+
static const struct constant_table ovl_parameter_uuid[] = {
69+
{ "off", OVL_UUID_OFF },
70+
{ "null", OVL_UUID_NULL },
71+
{ "on", OVL_UUID_ON },
72+
{}
73+
};
74+
75+
static const char *ovl_uuid_mode(struct ovl_config *config)
76+
{
77+
return ovl_parameter_uuid[config->uuid].name;
78+
}
79+
80+
static int ovl_uuid_def(void)
81+
{
82+
return OVL_UUID_NULL;
83+
}
84+
6885
static const struct constant_table ovl_parameter_xino[] = {
6986
{ "off", OVL_XINO_OFF },
7087
{ "auto", OVL_XINO_AUTO },
@@ -129,7 +146,7 @@ const struct fs_parameter_spec ovl_parameter_spec[] = {
129146
fsparam_flag("default_permissions", Opt_default_permissions),
130147
fsparam_enum("redirect_dir", Opt_redirect_dir, ovl_parameter_redirect_dir),
131148
fsparam_enum("index", Opt_index, ovl_parameter_bool),
132-
fsparam_enum("uuid", Opt_uuid, ovl_parameter_bool),
149+
fsparam_enum("uuid", Opt_uuid, ovl_parameter_uuid),
133150
fsparam_enum("nfs_export", Opt_nfs_export, ovl_parameter_bool),
134151
fsparam_flag("userxattr", Opt_userxattr),
135152
fsparam_enum("xino", Opt_xino, ovl_parameter_xino),
@@ -701,7 +718,7 @@ int ovl_init_fs_context(struct fs_context *fc)
701718

702719
ofs->config.redirect_mode = ovl_redirect_mode_def();
703720
ofs->config.index = ovl_index_def;
704-
ofs->config.uuid = true;
721+
ofs->config.uuid = ovl_uuid_def();
705722
ofs->config.nfs_export = ovl_nfs_export_def;
706723
ofs->config.xino = ovl_xino_def();
707724
ofs->config.metacopy = ovl_metacopy_def;
@@ -947,8 +964,8 @@ int ovl_show_options(struct seq_file *m, struct dentry *dentry)
947964
ovl_redirect_mode(&ofs->config));
948965
if (ofs->config.index != ovl_index_def)
949966
seq_printf(m, ",index=%s", ofs->config.index ? "on" : "off");
950-
if (!ofs->config.uuid)
951-
seq_puts(m, ",uuid=off");
967+
if (ofs->config.uuid != ovl_uuid_def())
968+
seq_printf(m, ",uuid=%s", ovl_uuid_mode(&ofs->config));
952969
if (ofs->config.nfs_export != ovl_nfs_export_def)
953970
seq_printf(m, ",nfs_export=%s", ofs->config.nfs_export ?
954971
"on" : "off");

fs/overlayfs/super.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,9 @@ static int ovl_sync_fs(struct super_block *sb, int wait)
242242
*/
243243
static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf)
244244
{
245-
struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
246-
struct dentry *root_dentry = dentry->d_sb->s_root;
245+
struct super_block *sb = dentry->d_sb;
246+
struct ovl_fs *ofs = OVL_FS(sb);
247+
struct dentry *root_dentry = sb->s_root;
247248
struct path path;
248249
int err;
249250

@@ -253,6 +254,8 @@ static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf)
253254
if (!err) {
254255
buf->f_namelen = ofs->namelen;
255256
buf->f_type = OVERLAYFS_SUPER_MAGIC;
257+
if (ovl_has_fsid(ofs))
258+
buf->f_fsid = uuid_to_fsid(sb->s_uuid.b);
256259
}
257260

258261
return err;
@@ -1421,9 +1424,12 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
14211424
if (!ovl_upper_mnt(ofs))
14221425
sb->s_flags |= SB_RDONLY;
14231426

1424-
if (!ofs->config.uuid && ofs->numfs > 1) {
1425-
pr_warn("The uuid=off requires a single fs for lower and upper, falling back to uuid=on.\n");
1426-
ofs->config.uuid = true;
1427+
if (!ovl_origin_uuid(ofs) && ofs->numfs > 1) {
1428+
pr_warn("The uuid=off requires a single fs for lower and upper, falling back to uuid=null.\n");
1429+
ofs->config.uuid = OVL_UUID_NULL;
1430+
} else if (ovl_has_fsid(ofs)) {
1431+
/* Use per instance uuid/fsid */
1432+
uuid_gen(&sb->s_uuid);
14271433
}
14281434

14291435
if (!ovl_force_readonly(ofs) && ofs->config.index) {

0 commit comments

Comments
 (0)