From d5791044d2e5749ef4de84161cec5532e2111540 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Fri, 11 May 2018 11:49:27 -0400 Subject: ovl: Provide a mount option metacopy=on/off for metadata copyup By default metadata only copy up is disabled. Provide a mount option so that users can choose one way or other. Also provide a kernel config and module option to enable/disable metacopy feature. metacopy feature requires redirect_dir=on when upper is present. Otherwise, it requires redirect_dir=follow atleast. As of now, metacopy does not work with nfs_export=on. So if both metacopy=on and nfs_export=on then nfs_export is disabled. Signed-off-by: Vivek Goyal Reviewed-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/Kconfig | 19 +++++++++++++++++++ fs/overlayfs/ovl_entry.h | 1 + fs/overlayfs/super.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 63 insertions(+), 3 deletions(-) (limited to 'fs/overlayfs') diff --git a/fs/overlayfs/Kconfig b/fs/overlayfs/Kconfig index 9384164253ac..2ef91be2a04e 100644 --- a/fs/overlayfs/Kconfig +++ b/fs/overlayfs/Kconfig @@ -64,6 +64,7 @@ config OVERLAY_FS_NFS_EXPORT bool "Overlayfs: turn on NFS export feature by default" depends on OVERLAY_FS depends on OVERLAY_FS_INDEX + depends on !OVERLAY_FS_METACOPY help If this config option is enabled then overlay filesystems will use the index directory to decode overlay NFS file handles by default. @@ -103,3 +104,21 @@ config OVERLAY_FS_XINO_AUTO For more information, see Documentation/filesystems/overlayfs.txt If unsure, say N. + +config OVERLAY_FS_METACOPY + bool "Overlayfs: turn on metadata only copy up feature by default" + depends on OVERLAY_FS + select OVERLAY_FS_REDIRECT_DIR + help + If this config option is enabled then overlay filesystems will + copy up only metadata where appropriate and data copy up will + happen when a file is opened for WRITE operation. It is still + possible to turn off this feature globally with the "metacopy=off" + module option or on a filesystem instance basis with the + "metacopy=off" mount option. + + Note, that this feature is not backward compatible. That is, + mounting an overlay which has metacopy only inodes on a kernel + that doesn't support this feature will have unexpected results. + + If unsure, say N. diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h index 41655a7d6894..ea4134e97d0d 100644 --- a/fs/overlayfs/ovl_entry.h +++ b/fs/overlayfs/ovl_entry.h @@ -19,6 +19,7 @@ struct ovl_config { bool index; bool nfs_export; int xino; + bool metacopy; }; struct ovl_sb { diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 0e84593af84e..d4caeee051ee 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -64,6 +64,11 @@ static void ovl_entry_stack_free(struct ovl_entry *oe) dput(oe->lowerstack[i].dentry); } +static bool ovl_metacopy_def = IS_ENABLED(CONFIG_OVERLAY_FS_METACOPY); +module_param_named(metacopy, ovl_metacopy_def, bool, 0644); +MODULE_PARM_DESC(ovl_metacopy_def, + "Default to on or off for the metadata only copy up feature"); + static void ovl_dentry_release(struct dentry *dentry) { struct ovl_entry *oe = dentry->d_fsdata; @@ -347,6 +352,9 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry) "on" : "off"); if (ofs->config.xino != ovl_xino_def()) seq_printf(m, ",xino=%s", ovl_xino_str[ofs->config.xino]); + if (ofs->config.metacopy != ovl_metacopy_def) + seq_printf(m, ",metacopy=%s", + ofs->config.metacopy ? "on" : "off"); return 0; } @@ -384,6 +392,8 @@ enum { OPT_XINO_ON, OPT_XINO_OFF, OPT_XINO_AUTO, + OPT_METACOPY_ON, + OPT_METACOPY_OFF, OPT_ERR, }; @@ -400,6 +410,8 @@ static const match_table_t ovl_tokens = { {OPT_XINO_ON, "xino=on"}, {OPT_XINO_OFF, "xino=off"}, {OPT_XINO_AUTO, "xino=auto"}, + {OPT_METACOPY_ON, "metacopy=on"}, + {OPT_METACOPY_OFF, "metacopy=off"}, {OPT_ERR, NULL} }; @@ -452,6 +464,7 @@ static int ovl_parse_redirect_mode(struct ovl_config *config, const char *mode) static int ovl_parse_opt(char *opt, struct ovl_config *config) { char *p; + int err; config->redirect_mode = kstrdup(ovl_redirect_mode_def(), GFP_KERNEL); if (!config->redirect_mode) @@ -526,6 +539,14 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) config->xino = OVL_XINO_AUTO; break; + case OPT_METACOPY_ON: + config->metacopy = true; + break; + + case OPT_METACOPY_OFF: + config->metacopy = false; + break; + default: pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p); return -EINVAL; @@ -540,7 +561,20 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) config->workdir = NULL; } - return ovl_parse_redirect_mode(config, config->redirect_mode); + err = ovl_parse_redirect_mode(config, config->redirect_mode); + if (err) + return err; + + /* metacopy feature with upper requires redirect_dir=on */ + if (config->upperdir && config->metacopy && !config->redirect_dir) { + pr_warn("overlayfs: metadata only copy up requires \"redirect_dir=on\", falling back to metacopy=off.\n"); + config->metacopy = false; + } else if (config->metacopy && !config->redirect_follow) { + pr_warn("overlayfs: metadata only copy up requires \"redirect_dir=follow\" on non-upper mount, falling back to metacopy=off.\n"); + config->metacopy = false; + } + + return 0; } #define OVL_WORKDIR_NAME "work" @@ -1013,7 +1047,8 @@ static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath) if (err) { ofs->noxattr = true; ofs->config.index = false; - pr_warn("overlayfs: upper fs does not support xattr, falling back to index=off.\n"); + ofs->config.metacopy = false; + pr_warn("overlayfs: upper fs does not support xattr, falling back to index=off and metacopy=off.\n"); err = 0; } else { vfs_removexattr(ofs->workdir, OVL_XATTR_OPAQUE); @@ -1035,7 +1070,6 @@ static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath) pr_warn("overlayfs: NFS export requires \"index=on\", falling back to nfs_export=off.\n"); ofs->config.nfs_export = false; } - out: mnt_drop_write(mnt); return err; @@ -1346,6 +1380,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) ofs->config.index = ovl_index_def; ofs->config.nfs_export = ovl_nfs_export_def; ofs->config.xino = ovl_xino_def(); + ofs->config.metacopy = ovl_metacopy_def; err = ovl_parse_opt((char *) data, &ofs->config); if (err) goto out_err; @@ -1416,6 +1451,11 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) } } + if (ofs->config.metacopy && ofs->config.nfs_export) { + pr_warn("overlayfs: NFS export is not supported with metadata only copy up, falling back to nfs_export=off.\n"); + ofs->config.nfs_export = false; + } + if (ofs->config.nfs_export) sb->s_export_op = &ovl_export_operations; -- cgit v1.2.3-55-g7522