Skip to content

Commit 795939a

Browse files
amir73ilMiklos Szeredi
authored andcommitted
ovl: add support for "xino" mount and config options
With mount option "xino=on", mounter declares that there are enough free high bits in underlying fs to hold the layer fsid. If overlayfs does encounter underlying inodes using the high xino bits reserved for layer fsid, a warning will be emitted and the original inode number will be used. The mount option name "xino" goes after a similar meaning mount option of aufs, but in overlayfs case, the mapping is stateless. An example for a use case of "xino=on" is when upper/lower is on an xfs filesystem. xfs uses 64bit inode numbers, but it currently never uses the upper 8bit for inode numbers exposed via stat(2) and that is not likely to change in the future without user opting-in for a new xfs feature. The actual number of unused upper bit is much larger and determined by the xfs filesystem geometry (64 - agno_log - agblklog - inopblog). That means that for all practical purpose, there are enough unused bits in xfs inode numbers for more than OVL_MAX_STACK unique fsid's. Another use case of "xino=on" is when upper/lower is on tmpfs. tmpfs inode numbers are allocated sequentially since boot, so they will practially never use the high inode number bits. For compatibility with applications that expect 32bit inodes, the feature can be disabled with "xino=off". The option "xino=auto" automatically detects underlying filesystem that use 32bit inodes and enables the feature. The Kconfig option OVERLAY_FS_XINO_AUTO and module parameter of the same name, determine if the default mode for overlayfs mount is "xino=auto" or "xino=off". Signed-off-by: Amir Goldstein <[email protected]> Signed-off-by: Miklos Szeredi <[email protected]>
1 parent adbf4f7 commit 795939a

File tree

3 files changed

+88
-3
lines changed

3 files changed

+88
-3
lines changed

fs/overlayfs/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,20 @@ config OVERLAY_FS_NFS_EXPORT
8686
case basis with the "nfs_export=on" mount option.
8787

8888
Say N unless you fully understand the consequences.
89+
90+
config OVERLAY_FS_XINO_AUTO
91+
bool "Overlayfs: auto enable inode number mapping"
92+
default n
93+
depends on OVERLAY_FS
94+
help
95+
If this config option is enabled then overlay filesystems will use
96+
unused high bits in undelying filesystem inode numbers to map all
97+
inodes to a unified address space. The mapped 64bit inode numbers
98+
might not be compatible with applications that expect 32bit inodes.
99+
100+
If compatibility with applications that expect 32bit inodes is not an
101+
issue, then it is safe and recommended to say Y here.
102+
103+
For more information, see Documentation/filesystems/overlayfs.txt
104+
105+
If unsure, say N.

fs/overlayfs/ovl_entry.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ struct ovl_config {
1818
const char *redirect_mode;
1919
bool index;
2020
bool nfs_export;
21+
int xino;
2122
};
2223

2324
struct ovl_sb {

fs/overlayfs/super.c

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ module_param_named(nfs_export, ovl_nfs_export_def, bool, 0644);
5151
MODULE_PARM_DESC(ovl_nfs_export_def,
5252
"Default to on or off for the NFS export feature");
5353

54+
static bool ovl_xino_auto_def = IS_ENABLED(CONFIG_OVERLAY_FS_XINO_AUTO);
55+
module_param_named(xino_auto, ovl_xino_auto_def, bool, 0644);
56+
MODULE_PARM_DESC(ovl_xino_auto_def,
57+
"Auto enable xino feature");
58+
5459
static void ovl_entry_stack_free(struct ovl_entry *oe)
5560
{
5661
unsigned int i;
@@ -327,6 +332,23 @@ static const char *ovl_redirect_mode_def(void)
327332
return ovl_redirect_dir_def ? "on" : "off";
328333
}
329334

335+
enum {
336+
OVL_XINO_OFF,
337+
OVL_XINO_AUTO,
338+
OVL_XINO_ON,
339+
};
340+
341+
static const char * const ovl_xino_str[] = {
342+
"off",
343+
"auto",
344+
"on",
345+
};
346+
347+
static inline int ovl_xino_def(void)
348+
{
349+
return ovl_xino_auto_def ? OVL_XINO_AUTO : OVL_XINO_OFF;
350+
}
351+
330352
/**
331353
* ovl_show_options
332354
*
@@ -352,6 +374,8 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
352374
if (ofs->config.nfs_export != ovl_nfs_export_def)
353375
seq_printf(m, ",nfs_export=%s", ofs->config.nfs_export ?
354376
"on" : "off");
377+
if (ofs->config.xino != ovl_xino_def())
378+
seq_printf(m, ",xino=%s", ovl_xino_str[ofs->config.xino]);
355379
return 0;
356380
}
357381

@@ -386,6 +410,9 @@ enum {
386410
OPT_INDEX_OFF,
387411
OPT_NFS_EXPORT_ON,
388412
OPT_NFS_EXPORT_OFF,
413+
OPT_XINO_ON,
414+
OPT_XINO_OFF,
415+
OPT_XINO_AUTO,
389416
OPT_ERR,
390417
};
391418

@@ -399,6 +426,9 @@ static const match_table_t ovl_tokens = {
399426
{OPT_INDEX_OFF, "index=off"},
400427
{OPT_NFS_EXPORT_ON, "nfs_export=on"},
401428
{OPT_NFS_EXPORT_OFF, "nfs_export=off"},
429+
{OPT_XINO_ON, "xino=on"},
430+
{OPT_XINO_OFF, "xino=off"},
431+
{OPT_XINO_AUTO, "xino=auto"},
402432
{OPT_ERR, NULL}
403433
};
404434

@@ -513,6 +543,18 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
513543
config->nfs_export = false;
514544
break;
515545

546+
case OPT_XINO_ON:
547+
config->xino = OVL_XINO_ON;
548+
break;
549+
550+
case OPT_XINO_OFF:
551+
config->xino = OVL_XINO_OFF;
552+
break;
553+
554+
case OPT_XINO_AUTO:
555+
config->xino = OVL_XINO_AUTO;
556+
break;
557+
516558
default:
517559
pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p);
518560
return -EINVAL;
@@ -1197,9 +1239,31 @@ static int ovl_get_lower_layers(struct ovl_fs *ofs, struct path *stack,
11971239
ofs->numlower++;
11981240
}
11991241

1200-
/* When all layers on same fs, overlay can use real inode numbers */
1201-
if (!ofs->numlowerfs || (ofs->numlowerfs == 1 && !ofs->upper_mnt))
1242+
/*
1243+
* When all layers on same fs, overlay can use real inode numbers.
1244+
* With mount option "xino=on", mounter declares that there are enough
1245+
* free high bits in underlying fs to hold the unique fsid.
1246+
* If overlayfs does encounter underlying inodes using the high xino
1247+
* bits reserved for fsid, it emits a warning and uses the original
1248+
* inode number.
1249+
*/
1250+
if (!ofs->numlowerfs || (ofs->numlowerfs == 1 && !ofs->upper_mnt)) {
12021251
ofs->xino_bits = 0;
1252+
ofs->config.xino = OVL_XINO_OFF;
1253+
} else if (ofs->config.xino == OVL_XINO_ON && !ofs->xino_bits) {
1254+
/*
1255+
* This is a roundup of number of bits needed for numlowerfs+1
1256+
* (i.e. ilog2(numlowerfs+1 - 1) + 1). fsid 0 is reserved for
1257+
* upper fs even with non upper overlay.
1258+
*/
1259+
BUILD_BUG_ON(ilog2(OVL_MAX_STACK) > 31);
1260+
ofs->xino_bits = ilog2(ofs->numlowerfs) + 1;
1261+
}
1262+
1263+
if (ofs->xino_bits) {
1264+
pr_info("overlayfs: \"xino\" feature enabled using %d upper inode bits.\n",
1265+
ofs->xino_bits);
1266+
}
12031267

12041268
err = 0;
12051269
out:
@@ -1311,6 +1375,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
13111375

13121376
ofs->config.index = ovl_index_def;
13131377
ofs->config.nfs_export = ovl_nfs_export_def;
1378+
ofs->config.xino = ovl_xino_def();
13141379
err = ovl_parse_opt((char *) data, &ofs->config);
13151380
if (err)
13161381
goto out_err;
@@ -1325,7 +1390,9 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
13251390
sb->s_stack_depth = 0;
13261391
sb->s_maxbytes = MAX_LFS_FILESIZE;
13271392
/* Assume underlaying fs uses 32bit inodes unless proven otherwise */
1328-
ofs->xino_bits = BITS_PER_LONG - 32;
1393+
if (ofs->config.xino != OVL_XINO_OFF)
1394+
ofs->xino_bits = BITS_PER_LONG - 32;
1395+
13291396
if (ofs->config.upperdir) {
13301397
if (!ofs->config.workdir) {
13311398
pr_err("overlayfs: missing 'workdir'\n");

0 commit comments

Comments
 (0)