From 65dda3f24e1e990d98c2073ab4623671dff5cbe8 Mon Sep 17 00:00:00 2001 From: Yoichi Umezawa Date: Wed, 25 Nov 2015 15:34:58 +0900 Subject: [PATCH] mcoverlayfs: support mount options(nocopyupw, nofscheck) --- executer/kernel/mcoverlayfs/inode.c | 26 ++++---- executer/kernel/mcoverlayfs/overlayfs.h | 1 + executer/kernel/mcoverlayfs/super.c | 86 +++++++++++++++++++------ 3 files changed, 82 insertions(+), 31 deletions(-) diff --git a/executer/kernel/mcoverlayfs/inode.c b/executer/kernel/mcoverlayfs/inode.c index 04f12488..5b0c8ee8 100644 --- a/executer/kernel/mcoverlayfs/inode.c +++ b/executer/kernel/mcoverlayfs/inode.c @@ -345,20 +345,22 @@ static int ovl_dentry_open(struct dentry *dentry, struct file *file, bool want_write = false; type = ovl_path_real(dentry, &realpath); - if (ovl_open_need_copy_up(file->f_flags, type, realpath.dentry)) { - want_write = true; - err = ovl_want_write(dentry); - if (err) - goto out; + if (!ovl_is_nocopyupw(dentry)) { + if (ovl_open_need_copy_up(file->f_flags, type, realpath.dentry)) { + want_write = true; + err = ovl_want_write(dentry); + if (err) + goto out; - if (file->f_flags & O_TRUNC) - err = ovl_copy_up_last(dentry, NULL, true); - else - err = ovl_copy_up(dentry); - if (err) - goto out_drop_write; + if (file->f_flags & O_TRUNC) + err = ovl_copy_up_last(dentry, NULL, true); + else + err = ovl_copy_up(dentry); + if (err) + goto out_drop_write; - ovl_path_upper(dentry, &realpath); + ovl_path_upper(dentry, &realpath); + } } err = vfs_open(&realpath, file, cred); diff --git a/executer/kernel/mcoverlayfs/overlayfs.h b/executer/kernel/mcoverlayfs/overlayfs.h index 17ac5afc..f2b7e6d1 100644 --- a/executer/kernel/mcoverlayfs/overlayfs.h +++ b/executer/kernel/mcoverlayfs/overlayfs.h @@ -131,6 +131,7 @@ static inline int ovl_do_whiteout(struct inode *dir, struct dentry *dentry) return err; } +bool ovl_is_nocopyupw(struct dentry *dentry); enum ovl_path_type ovl_path_type(struct dentry *dentry); u64 ovl_dentry_version_get(struct dentry *dentry); void ovl_dentry_version_inc(struct dentry *dentry); diff --git a/executer/kernel/mcoverlayfs/super.c b/executer/kernel/mcoverlayfs/super.c index bf8537c7..ddabb641 100644 --- a/executer/kernel/mcoverlayfs/super.c +++ b/executer/kernel/mcoverlayfs/super.c @@ -24,12 +24,22 @@ MODULE_AUTHOR("Miklos Szeredi "); MODULE_DESCRIPTION("Overlay filesystem"); MODULE_LICENSE("GPL"); -#define OVERLAYFS_SUPER_MAGIC 0x794c7630 +#define MCOVERLAYFS_SUPER_MAGIC 0x4d634f56 + +enum ovl_opt_bit { + __OVL_OPT_DEFAULT = 0, + __OVL_OPT_NOCOPYUPW = (1 << 0), + __OVL_OPT_NOFSCHECK = (1 << 1), +}; + +#define OVL_OPT_NOCOPYUPW(opt) ((opt) & __OVL_OPT_NOCOPYUPW) +#define OVL_OPT_NOFSCHECK(opt) ((opt) & __OVL_OPT_NOFSCHECK) struct ovl_config { char *lowerdir; char *upperdir; char *workdir; + unsigned opt; }; /* private information held for overlayfs's superblock */ @@ -62,6 +72,16 @@ struct ovl_entry { #define OVL_MAX_STACK 500 +bool ovl_is_nocopyupw(struct dentry *dentry) +{ + struct ovl_fs *ofs = dentry->d_sb->s_fs_info; + + if (OVL_OPT_NOCOPYUPW(ofs->config.opt)) + return true; + + return false; +} + static struct dentry *__ovl_dentry_lower(struct ovl_entry *oe) { return oe->numlower ? oe->lowerstack[0].dentry : NULL; @@ -500,7 +520,7 @@ static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf) err = vfs_statfs(&path, buf); if (!err) { buf->f_namelen = max(buf->f_namelen, ofs->lower_namelen); - buf->f_type = OVERLAYFS_SUPER_MAGIC; + buf->f_type = MCOVERLAYFS_SUPER_MAGIC; } return err; @@ -522,6 +542,12 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry) seq_printf(m, ",upperdir=%s", ufs->config.upperdir); seq_printf(m, ",workdir=%s", ufs->config.workdir); } + if (OVL_OPT_NOCOPYUPW(ufs->config.opt)) { + seq_printf(m, ",nocopyupw"); + } + if (OVL_OPT_NOFSCHECK(ufs->config.opt)) { + seq_printf(m, ",nofscheck"); + } return 0; } @@ -546,6 +572,8 @@ enum { OPT_LOWERDIR, OPT_UPPERDIR, OPT_WORKDIR, + OPT_NOCOPYUPW, + OPT_NOFSCHECK, OPT_ERR, }; @@ -553,6 +581,8 @@ static const match_table_t ovl_tokens = { {OPT_LOWERDIR, "lowerdir=%s"}, {OPT_UPPERDIR, "upperdir=%s"}, {OPT_WORKDIR, "workdir=%s"}, + {OPT_NOCOPYUPW, "nocopyupw"}, + {OPT_NOFSCHECK, "nofscheck"}, {OPT_ERR, NULL} }; @@ -583,6 +613,8 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) { char *p; + config->opt = __OVL_OPT_DEFAULT; + while ((p = ovl_next_opt(&opt)) != NULL) { int token; substring_t args[MAX_OPT_ARGS]; @@ -613,6 +645,14 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) return -ENOMEM; break; + case OPT_NOCOPYUPW: + config->opt = config->opt | __OVL_OPT_NOCOPYUPW; + break; + + case OPT_NOFSCHECK: + config->opt = config->opt | __OVL_OPT_NOFSCHECK; + break; + default: pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p); return -EINVAL; @@ -713,7 +753,7 @@ static bool ovl_is_allowed_fs_type(struct dentry *root) return true; } -static int ovl_mount_dir_noesc(const char *name, struct path *path) +static int ovl_mount_dir_noesc(const char *name, struct path *path, unsigned opt) { int err = -EINVAL; @@ -727,9 +767,11 @@ static int ovl_mount_dir_noesc(const char *name, struct path *path) goto out; } err = -EINVAL; - if (!ovl_is_allowed_fs_type(path->dentry)) { - pr_err("overlayfs: filesystem on '%s' not supported\n", name); - goto out_put; + if (!OVL_OPT_NOFSCHECK(opt)) { + if (!ovl_is_allowed_fs_type(path->dentry)) { + pr_err("overlayfs: filesystem on '%s' not supported\n", name); + goto out_put; + } } if (!S_ISDIR(path->dentry->d_inode->i_mode)) { pr_err("overlayfs: '%s' not a directory\n", name); @@ -743,26 +785,26 @@ out: return err; } -static int ovl_mount_dir(const char *name, struct path *path) +static int ovl_mount_dir(const char *name, struct path *path, unsigned opt) { int err = -ENOMEM; char *tmp = kstrdup(name, GFP_KERNEL); if (tmp) { ovl_unescape(tmp); - err = ovl_mount_dir_noesc(tmp, path); + err = ovl_mount_dir_noesc(tmp, path, opt); kfree(tmp); } return err; } static int ovl_lower_dir(const char *name, struct path *path, long *namelen, - int *stack_depth) + int *stack_depth, unsigned opt) { int err; struct kstatfs statfs; - err = ovl_mount_dir_noesc(name, path); + err = ovl_mount_dir_noesc(name, path, opt); if (err) goto out; @@ -851,7 +893,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) goto out_free_config; } - err = ovl_mount_dir(ufs->config.upperdir, &upperpath); + err = ovl_mount_dir(ufs->config.upperdir, &upperpath, ufs->config.opt); if (err) goto out_free_config; @@ -862,7 +904,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) goto out_put_upperpath; } - err = ovl_mount_dir(ufs->config.workdir, &workpath); + err = ovl_mount_dir(ufs->config.workdir, &workpath, ufs->config.opt); if (err) goto out_put_upperpath; @@ -900,7 +942,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) lower = lowertmp; for (numlower = 0; numlower < stacklen; numlower++) { err = ovl_lower_dir(lower, &stack[numlower], - &ufs->lower_namelen, &sb->s_stack_depth); + &ufs->lower_namelen, &sb->s_stack_depth, + ufs->config.opt); if (err) goto out_put_lowerpath; @@ -948,15 +991,20 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) * Make lower_mnt R/O. That way fchmod/fchown on lower file * will fail instead of modifying lower fs. */ - mnt->mnt_flags |= MNT_READONLY; + if (!OVL_OPT_NOCOPYUPW(ufs->config.opt)) { + mnt->mnt_flags |= MNT_READONLY; + } ufs->lower_mnt[ufs->numlower] = mnt; ufs->numlower++; } /* If the upper fs is nonexistent, we mark overlayfs r/o too */ - if (!ufs->upper_mnt) - sb->s_flags |= MS_RDONLY; + if (!ufs->upper_mnt) { + if (!OVL_OPT_NOCOPYUPW(ufs->config.opt)) { + sb->s_flags |= MS_RDONLY; + } + } sb->s_d_op = &ovl_dentry_operations; @@ -983,7 +1031,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) root_dentry->d_fsdata = oe; - sb->s_magic = OVERLAYFS_SUPER_MAGIC; + sb->s_magic = MCOVERLAYFS_SUPER_MAGIC; sb->s_op = &ovl_super_operations; sb->s_root = root_dentry; sb->s_fs_info = ufs; @@ -1026,11 +1074,11 @@ static struct dentry *ovl_mount(struct file_system_type *fs_type, int flags, static struct file_system_type ovl_fs_type = { .owner = THIS_MODULE, - .name = "overlay", + .name = "mcoverlay", .mount = ovl_mount, .kill_sb = kill_anon_super, }; -MODULE_ALIAS_FS("overlay"); +MODULE_ALIAS_FS("mcoverlay"); static int __init ovl_init(void) {