mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
ovl: fix regression in showing lowerdir mount option
Before commitb36a5780cb
("ovl: modify layer parameter parsing"), spaces and commas in lowerdir mount option value used to be escaped using seq_show_option(). In current upstream, when lowerdir value has a space, it is not escaped in /proc/mounts, e.g.: none /mnt overlay rw,relatime,lowerdir=l l,upperdir=u,workdir=w 0 0 which results in broken output of the mount utility: none on /mnt type overlay (rw,relatime,lowerdir=l) Store the original lowerdir mount options before unescaping and show them using the same escaping used for seq_show_option() in addition to escaping the colon separator character. Fixes:b36a5780cb
("ovl: modify layer parameter parsing") Signed-off-by: Amir Goldstein <amir73il@gmail.com>
This commit is contained in:
parent
c34706acf4
commit
32db510708
@ -339,6 +339,18 @@ The specified lower directories will be stacked beginning from the
|
||||
rightmost one and going left. In the above example lower1 will be the
|
||||
top, lower2 the middle and lower3 the bottom layer.
|
||||
|
||||
Note: directory names containing colons can be provided as lower layer by
|
||||
escaping the colons with a single backslash. For example:
|
||||
|
||||
mount -t overlay overlay -olowerdir=/a\:lower\:\:dir /merged
|
||||
|
||||
Since kernel version v6.5, directory names containing colons can also
|
||||
be provided as lower layer using the fsconfig syscall from new mount api:
|
||||
|
||||
fsconfig(fs_fd, FSCONFIG_SET_STRING, "lowerdir", "/a:lower::dir", 0);
|
||||
|
||||
In the latter case, colons in lower layer directory names will be escaped
|
||||
as an octal characters (\072) when displayed in /proc/self/mountinfo.
|
||||
|
||||
Metadata only copy up
|
||||
---------------------
|
||||
|
@ -192,7 +192,8 @@ static ssize_t ovl_parse_param_split_lowerdirs(char *str)
|
||||
|
||||
for (s = d = str;; s++, d++) {
|
||||
if (*s == '\\') {
|
||||
s++;
|
||||
/* keep esc chars in split lowerdir */
|
||||
*d++ = *s++;
|
||||
} else if (*s == ':') {
|
||||
bool next_colon = (*(s + 1) == ':');
|
||||
|
||||
@ -267,7 +268,7 @@ static void ovl_unescape(char *s)
|
||||
}
|
||||
}
|
||||
|
||||
static int ovl_mount_dir(const char *name, struct path *path)
|
||||
static int ovl_mount_dir(const char *name, struct path *path, bool upper)
|
||||
{
|
||||
int err = -ENOMEM;
|
||||
char *tmp = kstrdup(name, GFP_KERNEL);
|
||||
@ -276,7 +277,7 @@ static int ovl_mount_dir(const char *name, struct path *path)
|
||||
ovl_unescape(tmp);
|
||||
err = ovl_mount_dir_noesc(tmp, path);
|
||||
|
||||
if (!err && path->dentry->d_flags & DCACHE_OP_REAL) {
|
||||
if (!err && upper && path->dentry->d_flags & DCACHE_OP_REAL) {
|
||||
pr_err("filesystem on '%s' not supported as upperdir\n",
|
||||
tmp);
|
||||
path_put_init(path);
|
||||
@ -297,7 +298,7 @@ static int ovl_parse_param_upperdir(const char *name, struct fs_context *fc,
|
||||
struct path path;
|
||||
char *dup;
|
||||
|
||||
err = ovl_mount_dir(name, &path);
|
||||
err = ovl_mount_dir(name, &path, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -500,7 +501,7 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
|
||||
l = &ctx->lower[nr];
|
||||
memset(l, 0, sizeof(*l));
|
||||
|
||||
err = ovl_mount_dir_noesc(dup_iter, &l->path);
|
||||
err = ovl_mount_dir(dup_iter, &l->path, false);
|
||||
if (err)
|
||||
goto out_put;
|
||||
|
||||
@ -979,16 +980,23 @@ int ovl_show_options(struct seq_file *m, struct dentry *dentry)
|
||||
struct super_block *sb = dentry->d_sb;
|
||||
struct ovl_fs *ofs = OVL_FS(sb);
|
||||
size_t nr, nr_merged_lower = ofs->numlayer - ofs->numdatalayer;
|
||||
char **lowerdatadirs = &ofs->config.lowerdirs[nr_merged_lower];
|
||||
|
||||
/* lowerdirs[] starts from offset 1 */
|
||||
seq_printf(m, ",lowerdir=%s", ofs->config.lowerdirs[1]);
|
||||
/* dump regular lower layers */
|
||||
for (nr = 2; nr < nr_merged_lower; nr++)
|
||||
seq_printf(m, ":%s", ofs->config.lowerdirs[nr]);
|
||||
/* dump data lower layers */
|
||||
for (nr = 0; nr < ofs->numdatalayer; nr++)
|
||||
seq_printf(m, "::%s", lowerdatadirs[nr]);
|
||||
/*
|
||||
* lowerdirs[] starts from offset 1, then
|
||||
* >= 0 regular lower layers prefixed with : and
|
||||
* >= 0 data-only lower layers prefixed with ::
|
||||
*
|
||||
* we need to escase comma and space like seq_show_option() does and
|
||||
* we also need to escape the colon separator from lowerdir paths.
|
||||
*/
|
||||
seq_puts(m, ",lowerdir=");
|
||||
for (nr = 1; nr < ofs->numlayer; nr++) {
|
||||
if (nr > 1)
|
||||
seq_putc(m, ':');
|
||||
if (nr >= nr_merged_lower)
|
||||
seq_putc(m, ':');
|
||||
seq_escape(m, ofs->config.lowerdirs[nr], ":, \t\n\\");
|
||||
}
|
||||
if (ofs->config.upperdir) {
|
||||
seq_show_option(m, "upperdir", ofs->config.upperdir);
|
||||
seq_show_option(m, "workdir", ofs->config.workdir);
|
||||
|
Loading…
Reference in New Issue
Block a user