diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2018-11-01 16:31:39 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2018-11-01 16:31:39 -0400 |
commit | d47748e5ae5af6572e520cc9767bbe70c22ea498 (patch) | |
tree | ae33bdfffaaa6c1e9297d33f39dff2ddee4ddb24 | |
parent | 5e1275808630ea3b2c97c776f40e475017535f72 (diff) |
ovl: automatically enable redirect_dir on metacopy=on
Current behavior is to automatically disable metacopy if redirect_dir is
not enabled and proceed with the mount.
If "metacopy=on" mount option was given, then this behavior can confuse the
user: no mount failure, yet metacopy is disabled.
This patch makes metacopy=on imply redirect_dir=on.
The converse is also true: turning off full redirect with redirect_dir=
{off|follow|nofollow} will disable metacopy.
If both metacopy=on and redirect_dir={off|follow|nofollow} is specified,
then mount will fail, since there's no way to correctly resolve the
conflict.
Reported-by: Daniel Walsh <dwalsh@redhat.com>
Fixes: d5791044d2e5 ("ovl: Provide a mount option metacopy=on/off...")
Cc: <stable@vger.kernel.org> # v4.19
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r-- | Documentation/filesystems/overlayfs.txt | 6 | ||||
-rw-r--r-- | fs/overlayfs/super.c | 36 |
2 files changed, 35 insertions, 7 deletions
diff --git a/Documentation/filesystems/overlayfs.txt b/Documentation/filesystems/overlayfs.txt index 51c136c821bf..eef7d9d259e8 100644 --- a/Documentation/filesystems/overlayfs.txt +++ b/Documentation/filesystems/overlayfs.txt | |||
@@ -286,6 +286,12 @@ pointed by REDIRECT. This should not be possible on local system as setting | |||
286 | "trusted." xattrs will require CAP_SYS_ADMIN. But it should be possible | 286 | "trusted." xattrs will require CAP_SYS_ADMIN. But it should be possible |
287 | for untrusted layers like from a pen drive. | 287 | for untrusted layers like from a pen drive. |
288 | 288 | ||
289 | Note: redirect_dir={off|nofollow|follow(*)} conflicts with metacopy=on, and | ||
290 | results in an error. | ||
291 | |||
292 | (*) redirect_dir=follow only conflicts with metacopy=on if upperdir=... is | ||
293 | given. | ||
294 | |||
289 | Sharing and copying layers | 295 | Sharing and copying layers |
290 | -------------------------- | 296 | -------------------------- |
291 | 297 | ||
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 22ffb23ea44d..0116735cc321 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
@@ -472,6 +472,7 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) | |||
472 | { | 472 | { |
473 | char *p; | 473 | char *p; |
474 | int err; | 474 | int err; |
475 | bool metacopy_opt = false, redirect_opt = false; | ||
475 | 476 | ||
476 | config->redirect_mode = kstrdup(ovl_redirect_mode_def(), GFP_KERNEL); | 477 | config->redirect_mode = kstrdup(ovl_redirect_mode_def(), GFP_KERNEL); |
477 | if (!config->redirect_mode) | 478 | if (!config->redirect_mode) |
@@ -516,6 +517,7 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) | |||
516 | config->redirect_mode = match_strdup(&args[0]); | 517 | config->redirect_mode = match_strdup(&args[0]); |
517 | if (!config->redirect_mode) | 518 | if (!config->redirect_mode) |
518 | return -ENOMEM; | 519 | return -ENOMEM; |
520 | redirect_opt = true; | ||
519 | break; | 521 | break; |
520 | 522 | ||
521 | case OPT_INDEX_ON: | 523 | case OPT_INDEX_ON: |
@@ -548,6 +550,7 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) | |||
548 | 550 | ||
549 | case OPT_METACOPY_ON: | 551 | case OPT_METACOPY_ON: |
550 | config->metacopy = true; | 552 | config->metacopy = true; |
553 | metacopy_opt = true; | ||
551 | break; | 554 | break; |
552 | 555 | ||
553 | case OPT_METACOPY_OFF: | 556 | case OPT_METACOPY_OFF: |
@@ -572,13 +575,32 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) | |||
572 | if (err) | 575 | if (err) |
573 | return err; | 576 | return err; |
574 | 577 | ||
575 | /* metacopy feature with upper requires redirect_dir=on */ | 578 | /* |
576 | if (config->upperdir && config->metacopy && !config->redirect_dir) { | 579 | * This is to make the logic below simpler. It doesn't make any other |
577 | pr_warn("overlayfs: metadata only copy up requires \"redirect_dir=on\", falling back to metacopy=off.\n"); | 580 | * difference, since config->redirect_dir is only used for upper. |
578 | config->metacopy = false; | 581 | */ |
579 | } else if (config->metacopy && !config->redirect_follow) { | 582 | if (!config->upperdir && config->redirect_follow) |
580 | pr_warn("overlayfs: metadata only copy up requires \"redirect_dir=follow\" on non-upper mount, falling back to metacopy=off.\n"); | 583 | config->redirect_dir = true; |
581 | config->metacopy = false; | 584 | |
585 | /* Resolve metacopy -> redirect_dir dependency */ | ||
586 | if (config->metacopy && !config->redirect_dir) { | ||
587 | if (metacopy_opt && redirect_opt) { | ||
588 | pr_err("overlayfs: conflicting options: metacopy=on,redirect_dir=%s\n", | ||
589 | config->redirect_mode); | ||
590 | return -EINVAL; | ||
591 | } | ||
592 | if (redirect_opt) { | ||
593 | /* | ||
594 | * There was an explicit redirect_dir=... that resulted | ||
595 | * in this conflict. | ||
596 | */ | ||
597 | pr_info("overlayfs: disabling metacopy due to redirect_dir=%s\n", | ||
598 | config->redirect_mode); | ||
599 | config->metacopy = false; | ||
600 | } else { | ||
601 | /* Automatically enable redirect otherwise. */ | ||
602 | config->redirect_follow = config->redirect_dir = true; | ||
603 | } | ||
582 | } | 604 | } |
583 | 605 | ||
584 | return 0; | 606 | return 0; |