Re: [PATCH 4/4] ovl: add support for appending lowerdirs one by one

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Oct 30, 2023 at 2:04 PM Amir Goldstein <amir73il@xxxxxxxxx> wrote:
>
> Add new mount options lowerdir+ and datadir+ that can be used to add
> layers to lower layers stack one by one.
>
> Unlike the legacy lowerdir mount option, special characters (i.e. colons
> and cammas) are not unescaped with these new mount options.
>
> The new mount options can be repeated to compose a large stack of lower
> layers, but they may not be mixed with the lagacy lowerdir mount option,
> because for displaying lower layers in mountinfo, we do not want to mix
> escaped with unescaped lower layers path syntax.
>
> Similar to data-only layer rules with the lowerdir mount option, the
> datadir+ option must follow at least one lowerdir+ option and the
> lowerdir+ option must not follow the datadir+ option.
>
> If the legacy lowerdir mount option follows lowerdir+ and datadir+
> mount options, it overrides them.  Sepcifically, calling:
>
>   fsconfig(FSCONFIG_SET_STRING, "lowerdir", "", 0);
>
> can be used to reset previously setup lower layers.
>
> Suggested-by: Miklos Szeredi <miklos@xxxxxxxxxx>
> Link: https://lore.kernel.org/r/CAJfpegt7VC94KkRtb1dfHG8+4OzwPBLYqhtc8=QFUxpFJE+=RQ@xxxxxxxxxxxxxx/
> Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx>
> ---
>  fs/overlayfs/params.c | 78 +++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 76 insertions(+), 2 deletions(-)
>
> diff --git a/fs/overlayfs/params.c b/fs/overlayfs/params.c
> index 9a9238eac730..1c390e93d060 100644
> --- a/fs/overlayfs/params.c
> +++ b/fs/overlayfs/params.c
> @@ -45,6 +45,8 @@ MODULE_PARM_DESC(metacopy,
>
>  enum ovl_opt {
>         Opt_lowerdir,
> +       Opt_lowerdir_add,
> +       Opt_datadir_add,
>         Opt_upperdir,
>         Opt_workdir,
>         Opt_default_permissions,
> @@ -140,8 +142,11 @@ static int ovl_verity_mode_def(void)
>  #define fsparam_string_empty(NAME, OPT) \
>         __fsparam(fs_param_is_string, NAME, OPT, fs_param_can_be_empty, NULL)
>
> +
>  const struct fs_parameter_spec ovl_parameter_spec[] = {
>         fsparam_string_empty("lowerdir",    Opt_lowerdir),
> +       fsparam_string("lowerdir+",         Opt_lowerdir_add),
> +       fsparam_string("datadir+",          Opt_datadir_add),
>         fsparam_string("upperdir",          Opt_upperdir),
>         fsparam_string("workdir",           Opt_workdir),
>         fsparam_flag("default_permissions", Opt_default_permissions),
> @@ -273,6 +278,8 @@ static int ovl_mount_dir(const char *name, struct path *path)
>  static int ovl_mount_dir_check(struct fs_context *fc, const struct path *path,
>                                enum ovl_opt layer, const char *name, bool upper)
>  {
> +       struct ovl_fs_context *ctx = fc->fs_private;
> +
>         if (ovl_dentry_weird(path->dentry))
>                 return invalfc(fc, "filesystem on %s not supported", name);
>
> @@ -289,16 +296,44 @@ static int ovl_mount_dir_check(struct fs_context *fc, const struct path *path,
>                         return invalfc(fc, "filesystem not supported as %s", name);
>                 if (__mnt_is_readonly(path->mnt))
>                         return invalfc(fc, "%s is read-only", name);
> +       } else {
> +               if (ctx->lowerdir_all)
> +                       return invalfc(fc, "%s cannot follow lowerdir mount option", name);
> +               if (ctx->nr_data && layer == Opt_lowerdir_add)
> +                       return invalfc(fc, "regular lower layers cannot follow data layers");
> +               if (ctx->nr == OVL_MAX_STACK)
> +                       return invalfc(fc, "too many lower directories, limit is %d",
> +                                      OVL_MAX_STACK);
>         }
>         return 0;
>  }
>
> +static int ovl_ctx_realloc_lower(struct fs_context *fc)
> +{
> +       struct ovl_fs_context *ctx = fc->fs_private;
> +       struct ovl_fs_context_layer *l;
> +       size_t nr;
> +
> +       if (ctx->nr < ctx->capacity)
> +               return 0;
> +
> +       nr = min(max(4096 / sizeof(*l), ctx->capacity * 2), (size_t) OVL_MAX_STACK);
> +       l = krealloc_array(ctx->lower, nr, sizeof(*l), GFP_KERNEL_ACCOUNT);
> +       if (!l)
> +               return -ENOMEM;
> +
> +       ctx->lower = l;
> +       ctx->capacity = nr;
> +       return 0;
> +}
> +
>  static void ovl_add_layer(struct fs_context *fc, enum ovl_opt layer,
>                          struct path *path, char **pname)
>  {
>         struct ovl_fs *ofs = fc->s_fs_info;
>         struct ovl_config *config = &ofs->config;
>         struct ovl_fs_context *ctx = fc->fs_private;
> +       struct ovl_fs_context_layer *l;
>
>         switch (layer) {
>         case Opt_workdir:
> @@ -309,6 +344,16 @@ static void ovl_add_layer(struct fs_context *fc, enum ovl_opt layer,
>                 swap(config->upperdir, *pname);
>                 swap(ctx->upper, *path);
>                 break;
> +       case Opt_datadir_add:
> +               ctx->nr_data++;
> +               fallthrough;
> +       case Opt_lowerdir_add:
> +               WARN_ON(ctx->nr >= ctx->capacity);
> +               l = &ctx->lower[ctx->nr++];
> +               memset(l, 0, sizeof(*l));
> +               swap(l->name, *pname);
> +               swap(l->path, *path);
> +               break;
>         default:
>                 WARN_ON(1);
>         }
> @@ -324,7 +369,10 @@ static int ovl_parse_layer(struct fs_context *fc, struct fs_parameter *param,
>         if (!name)
>                 return -ENOMEM;
>
> -       err = ovl_mount_dir(name, &path);
> +       if (upper)
> +               err = ovl_mount_dir(name, &path);
> +       else
> +               err = ovl_mount_dir_noesc(name, &path);
>         if (err)
>                 goto out_free;
>
> @@ -332,6 +380,12 @@ static int ovl_parse_layer(struct fs_context *fc, struct fs_parameter *param,
>         if (err)
>                 goto out_put;
>
> +       if (!upper) {
> +               err = ovl_ctx_realloc_lower(fc);
> +               if (err)
> +                       goto out_put;
> +       }
> +
>         /* Store the user provided path string in ctx to show in mountinfo */
>         ovl_add_layer(fc, layer, &path, &name);
>
> @@ -514,6 +568,10 @@ static int ovl_parse_param(struct fs_context *fc, struct fs_parameter *param)
>         case Opt_lowerdir:
>                 err = ovl_parse_param_lowerdir(param->string, fc);
>                 break;
> +       case Opt_lowerdir_add:
> +       case Opt_datadir_add:
> +               err = ovl_parse_layer(fc, param, opt, false);
> +               break;
>         case Opt_upperdir:
>         case Opt_workdir:
>                 err = ovl_parse_layer(fc, param, opt, true);

Sorry, ovl_parse_layer() doesn't need bool upper arg.
Your POC didn't have it.

I removed that and pushed to overlayfs-next.

Thanks,
Amir.




[Index of Archives]     [Linux Filesystems Devel]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux