mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-03 19:55:31 +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
|
rightmost one and going left. In the above example lower1 will be the
|
||||||
top, lower2 the middle and lower3 the bottom layer.
|
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
|
Metadata only copy up
|
||||||
---------------------
|
---------------------
|
||||||
|
@ -192,7 +192,8 @@ static ssize_t ovl_parse_param_split_lowerdirs(char *str)
|
|||||||
|
|
||||||
for (s = d = str;; s++, d++) {
|
for (s = d = str;; s++, d++) {
|
||||||
if (*s == '\\') {
|
if (*s == '\\') {
|
||||||
s++;
|
/* keep esc chars in split lowerdir */
|
||||||
|
*d++ = *s++;
|
||||||
} else if (*s == ':') {
|
} else if (*s == ':') {
|
||||||
bool next_colon = (*(s + 1) == ':');
|
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;
|
int err = -ENOMEM;
|
||||||
char *tmp = kstrdup(name, GFP_KERNEL);
|
char *tmp = kstrdup(name, GFP_KERNEL);
|
||||||
@ -276,7 +277,7 @@ static int ovl_mount_dir(const char *name, struct path *path)
|
|||||||
ovl_unescape(tmp);
|
ovl_unescape(tmp);
|
||||||
err = ovl_mount_dir_noesc(tmp, path);
|
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",
|
pr_err("filesystem on '%s' not supported as upperdir\n",
|
||||||
tmp);
|
tmp);
|
||||||
path_put_init(path);
|
path_put_init(path);
|
||||||
@ -297,7 +298,7 @@ static int ovl_parse_param_upperdir(const char *name, struct fs_context *fc,
|
|||||||
struct path path;
|
struct path path;
|
||||||
char *dup;
|
char *dup;
|
||||||
|
|
||||||
err = ovl_mount_dir(name, &path);
|
err = ovl_mount_dir(name, &path, true);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -500,7 +501,7 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
|
|||||||
l = &ctx->lower[nr];
|
l = &ctx->lower[nr];
|
||||||
memset(l, 0, sizeof(*l));
|
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)
|
if (err)
|
||||||
goto out_put;
|
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 super_block *sb = dentry->d_sb;
|
||||||
struct ovl_fs *ofs = OVL_FS(sb);
|
struct ovl_fs *ofs = OVL_FS(sb);
|
||||||
size_t nr, nr_merged_lower = ofs->numlayer - ofs->numdatalayer;
|
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]);
|
* lowerdirs[] starts from offset 1, then
|
||||||
/* dump regular lower layers */
|
* >= 0 regular lower layers prefixed with : and
|
||||||
for (nr = 2; nr < nr_merged_lower; nr++)
|
* >= 0 data-only lower layers prefixed with ::
|
||||||
seq_printf(m, ":%s", ofs->config.lowerdirs[nr]);
|
*
|
||||||
/* dump data lower layers */
|
* we need to escase comma and space like seq_show_option() does and
|
||||||
for (nr = 0; nr < ofs->numdatalayer; nr++)
|
* we also need to escape the colon separator from lowerdir paths.
|
||||||
seq_printf(m, "::%s", lowerdatadirs[nr]);
|
*/
|
||||||
|
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) {
|
if (ofs->config.upperdir) {
|
||||||
seq_show_option(m, "upperdir", ofs->config.upperdir);
|
seq_show_option(m, "upperdir", ofs->config.upperdir);
|
||||||
seq_show_option(m, "workdir", ofs->config.workdir);
|
seq_show_option(m, "workdir", ofs->config.workdir);
|
||||||
|
Loading…
Reference in New Issue
Block a user