Re: [PATCH v3 2/3] ovl: port to new mount api

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

 



On Tue, Jun 13, 2023 at 5:49 PM Christian Brauner <brauner@xxxxxxxxxx> wrote:
>
> We recently ported util-linux to the new mount api. Now the mount(8)
> tool will by default use the new mount api. While trying hard to fall
> back to the old mount api gracefully there are still cases where we run
> into issues that are difficult to handle nicely.
>
> Now with mount(8) and libmount supporting the new mount api I expect an
> increase in the number of bug reports and issues we're going to see with
> filesystems that don't yet support the new mount api. So it's time we
> rectify this.
>
> Signed-off-by: Christian Brauner <brauner@xxxxxxxxxx>
> ---
>  fs/overlayfs/ovl_entry.h |   2 +-
>  fs/overlayfs/super.c     | 557 ++++++++++++++++++++++++++---------------------
>  2 files changed, 305 insertions(+), 254 deletions(-)
>
> diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
> index e5207c4bf5b8..c72433c06006 100644
> --- a/fs/overlayfs/ovl_entry.h
> +++ b/fs/overlayfs/ovl_entry.h
> @@ -12,7 +12,7 @@ struct ovl_config {
>         bool default_permissions;
>         bool redirect_dir;
>         bool redirect_follow;
> -       const char *redirect_mode;
> +       unsigned redirect_mode;

I have a separate patch to get rid of redirect_dir and redirect_follow
leaving only redirect_mode enum.

I've already rebased your patches over this change in my branch.

https://github.com/amir73il/linux/commits/fs-overlayfs-mount_api


>         bool index;
>         bool uuid;
>         bool nfs_export;
> diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
> index d9be5d318e1b..3392dc5d2082 100644
> --- a/fs/overlayfs/super.c
> +++ b/fs/overlayfs/super.c
> @@ -16,6 +16,8 @@
>  #include <linux/posix_acl_xattr.h>
>  #include <linux/exportfs.h>
>  #include <linux/file.h>
> +#include <linux/fs_context.h>
> +#include <linux/fs_parser.h>
>  #include "overlayfs.h"
>
>  MODULE_AUTHOR("Miklos Szeredi <miklos@xxxxxxxxxx>");
> @@ -59,6 +61,79 @@ module_param_named(metacopy, ovl_metacopy_def, bool, 0644);
>  MODULE_PARM_DESC(metacopy,
>                  "Default to on or off for the metadata only copy up feature");
>
> +enum {
> +       Opt_lowerdir,
> +       Opt_upperdir,
> +       Opt_workdir,
> +       Opt_default_permissions,
> +       Opt_redirect_dir,
> +       Opt_index,
> +       Opt_uuid,
> +       Opt_nfs_export,
> +       Opt_userxattr,
> +       Opt_xino,
> +       Opt_metacopy,
> +       Opt_volatile,
> +};

Renaming all those enums to lower case creates unneeded churn.
I undid that in my branch, so now the mount api porting patch is a
lot smaller.

> +
> +static const struct constant_table ovl_parameter_bool[] = {
> +       { "on",         true  },
> +       { "off",        false },
> +       {}
> +};
> +
> +static const struct constant_table ovl_parameter_xino[] = {
> +       { "on",         OVL_XINO_ON   },
> +       { "off",        OVL_XINO_OFF  },
> +       { "auto",       OVL_XINO_AUTO },
> +       {}
> +};
> +
> +enum {
> +       OVL_REDIRECT_DIR_ON,
> +       OVL_REDIRECT_DIR_OFF,
> +       OVL_REDIRECT_DIR_FOLLOW,
> +       OVL_REDIRECT_DIR_NOFOLLOW,
> +};
> +
> +static const struct constant_table ovl_parameter_redirect_dir[] = {
> +       { "on",         OVL_REDIRECT_DIR_ON       },
> +       { "off",        OVL_REDIRECT_DIR_OFF      },
> +       { "follow",     OVL_REDIRECT_DIR_FOLLOW   },
> +       { "nofollow",   OVL_REDIRECT_DIR_NOFOLLOW },
> +       {}
> +};
> +
> +static const char *ovl_redirect_mode(struct ovl_config *config)
> +{
> +       return ovl_parameter_redirect_dir[config->redirect_mode].name;
> +}
> +
> +static const struct fs_parameter_spec ovl_parameter_spec[] = {
> +       fsparam_string("lowerdir",          Opt_lowerdir),
> +       fsparam_string("upperdir",          Opt_upperdir),
> +       fsparam_string("workdir",           Opt_workdir),
> +       fsparam_flag("default_permissions", Opt_default_permissions),
> +       fsparam_enum("redirect_dir",        Opt_redirect_dir, ovl_parameter_redirect_dir),
> +       fsparam_enum("index",               Opt_index, ovl_parameter_bool),
> +       fsparam_enum("uuid",                Opt_uuid, ovl_parameter_bool),
> +       fsparam_enum("nfs_export",          Opt_nfs_export, ovl_parameter_bool),
> +       fsparam_flag("userxattr",           Opt_userxattr),
> +       fsparam_enum("xino",                Opt_xino, ovl_parameter_xino),
> +       fsparam_enum("metacopy",            Opt_metacopy, ovl_parameter_bool),
> +       fsparam_flag("volatile",            Opt_volatile),
> +       {}
> +};
> +
> +#define OVL_METACOPY_SET       BIT(0)
> +#define OVL_REDIRECT_SET       BIT(1)
> +#define OVL_NFS_EXPORT_SET     BIT(2)
> +#define OVL_INDEX_SET          BIT(3)
> +
> +struct ovl_fs_context {
> +       u8 set;
> +};
> +
>  static struct dentry *ovl_d_real(struct dentry *dentry,
>                                  const struct inode *inode)
>  {
> @@ -243,7 +318,6 @@ static void ovl_free_fs(struct ovl_fs *ofs)
>         kfree(ofs->config.lowerdir);
>         kfree(ofs->config.upperdir);
>         kfree(ofs->config.workdir);
> -       kfree(ofs->config.redirect_mode);
>         if (ofs->creator_cred)
>                 put_cred(ofs->creator_cred);
>         kfree(ofs);
> @@ -253,7 +327,8 @@ static void ovl_put_super(struct super_block *sb)
>  {
>         struct ovl_fs *ofs = sb->s_fs_info;
>
> -       ovl_free_fs(ofs);
> +       if (ofs)
> +               ovl_free_fs(ofs);
>  }
>
>  /* Sync real dirty inodes in upper filesystem (if it exists) */
> @@ -357,6 +432,7 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
>  {
>         struct super_block *sb = dentry->d_sb;
>         struct ovl_fs *ofs = sb->s_fs_info;
> +       const char *redirect_mode;
>
>         seq_show_option(m, "lowerdir", ofs->config.lowerdir);
>         if (ofs->config.upperdir) {
> @@ -365,8 +441,9 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
>         }
>         if (ofs->config.default_permissions)
>                 seq_puts(m, ",default_permissions");
> -       if (strcmp(ofs->config.redirect_mode, ovl_redirect_mode_def()) != 0)
> -               seq_printf(m, ",redirect_dir=%s", ofs->config.redirect_mode);
> +       redirect_mode = ovl_redirect_mode(&ofs->config);
> +       if (strcmp(redirect_mode, ovl_redirect_mode_def()) != 0)
> +               seq_printf(m, ",redirect_dir=%s", redirect_mode);
>         if (ofs->config.index != ovl_index_def)
>                 seq_printf(m, ",index=%s", ofs->config.index ? "on" : "off");
>         if (!ofs->config.uuid)
> @@ -386,27 +463,6 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
>         return 0;
>  }
>
> -static int ovl_remount(struct super_block *sb, int *flags, char *data)
> -{
> -       struct ovl_fs *ofs = sb->s_fs_info;
> -       struct super_block *upper_sb;
> -       int ret = 0;
> -
> -       if (!(*flags & SB_RDONLY) && ovl_force_readonly(ofs))
> -               return -EROFS;
> -
> -       if (*flags & SB_RDONLY && !sb_rdonly(sb)) {
> -               upper_sb = ovl_upper_mnt(ofs)->mnt_sb;
> -               if (ovl_should_sync(ofs)) {
> -                       down_read(&upper_sb->s_umount);
> -                       ret = sync_filesystem(upper_sb);
> -                       up_read(&upper_sb->s_umount);
> -               }
> -       }
> -
> -       return ret;
> -}

Moving code around and changing it at the same time makes
reviewing very hard. I undid the move in my patch.
If you want to rearrange the functions in the file afterwards
I don't mind.

> -
>  static const struct super_operations ovl_super_operations = {
>         .alloc_inode    = ovl_alloc_inode,
>         .free_inode     = ovl_free_inode,
> @@ -416,216 +472,42 @@ static const struct super_operations ovl_super_operations = {
>         .sync_fs        = ovl_sync_fs,
>         .statfs         = ovl_statfs,
>         .show_options   = ovl_show_options,
> -       .remount_fs     = ovl_remount,
> -};
> -
> -enum {
> -       OPT_LOWERDIR,
> -       OPT_UPPERDIR,
> -       OPT_WORKDIR,
> -       OPT_DEFAULT_PERMISSIONS,
> -       OPT_REDIRECT_DIR,
> -       OPT_INDEX_ON,
> -       OPT_INDEX_OFF,
> -       OPT_UUID_ON,
> -       OPT_UUID_OFF,
> -       OPT_NFS_EXPORT_ON,
> -       OPT_USERXATTR,
> -       OPT_NFS_EXPORT_OFF,
> -       OPT_XINO_ON,
> -       OPT_XINO_OFF,
> -       OPT_XINO_AUTO,
> -       OPT_METACOPY_ON,
> -       OPT_METACOPY_OFF,
> -       OPT_VOLATILE,
> -       OPT_ERR,
> -};
> -
> -static const match_table_t ovl_tokens = {
> -       {OPT_LOWERDIR,                  "lowerdir=%s"},
> -       {OPT_UPPERDIR,                  "upperdir=%s"},
> -       {OPT_WORKDIR,                   "workdir=%s"},
> -       {OPT_DEFAULT_PERMISSIONS,       "default_permissions"},
> -       {OPT_REDIRECT_DIR,              "redirect_dir=%s"},
> -       {OPT_INDEX_ON,                  "index=on"},
> -       {OPT_INDEX_OFF,                 "index=off"},
> -       {OPT_USERXATTR,                 "userxattr"},
> -       {OPT_UUID_ON,                   "uuid=on"},
> -       {OPT_UUID_OFF,                  "uuid=off"},
> -       {OPT_NFS_EXPORT_ON,             "nfs_export=on"},
> -       {OPT_NFS_EXPORT_OFF,            "nfs_export=off"},
> -       {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_VOLATILE,                  "volatile"},
> -       {OPT_ERR,                       NULL}
>  };
>
> -static char *ovl_next_opt(char **s)
> +static int ovl_set_redirect_mode(struct ovl_config *config)
>  {
> -       char *sbegin = *s;
> -       char *p;
> -
> -       if (sbegin == NULL)
> -               return NULL;
> -
> -       for (p = sbegin; *p; p++) {
> -               if (*p == '\\') {
> -                       p++;
> -                       if (!*p)
> -                               break;
> -               } else if (*p == ',') {
> -                       *p = '\0';
> -                       *s = p + 1;
> -                       return sbegin;
> -               }
> -       }
> -       *s = NULL;
> -       return sbegin;
> -}
> -
> -static int ovl_parse_redirect_mode(struct ovl_config *config, const char *mode)
> -{
> -       if (strcmp(mode, "on") == 0) {
> +       switch (config->redirect_mode) {
> +       case OVL_REDIRECT_DIR_ON:
>                 config->redirect_dir = true;
>                 /*
>                  * Does not make sense to have redirect creation without
>                  * redirect following.
>                  */
>                 config->redirect_follow = true;
> -       } else if (strcmp(mode, "follow") == 0) {
> +               return 0;
> +       case OVL_REDIRECT_DIR_FOLLOW:
>                 config->redirect_follow = true;
> -       } else if (strcmp(mode, "off") == 0) {
> +               return 0;
> +       case OVL_REDIRECT_DIR_OFF:
>                 if (ovl_redirect_always_follow)
>                         config->redirect_follow = true;
> -       } else if (strcmp(mode, "nofollow") != 0) {
> -               pr_err("bad mount option \"redirect_dir=%s\"\n",
> -                      mode);
> -               return -EINVAL;
> +               return 0;
> +       case OVL_REDIRECT_DIR_NOFOLLOW:
> +               return 0;
>         }
>
> -       return 0;
> +       pr_err("invalid \"redirect_dir\" mount option\n");
> +       return -EINVAL;
>  }
>
> -static int ovl_parse_opt(char *opt, struct ovl_config *config)
> +static int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
> +                               struct ovl_config *config)
>  {
> -       char *p;
>         int err;
> -       bool metacopy_opt = false, redirect_opt = false;
> -       bool nfs_export_opt = false, index_opt = false;
> -
> -       config->redirect_mode = kstrdup(ovl_redirect_mode_def(), GFP_KERNEL);
> -       if (!config->redirect_mode)
> -               return -ENOMEM;
> -
> -       while ((p = ovl_next_opt(&opt)) != NULL) {
> -               int token;
> -               substring_t args[MAX_OPT_ARGS];
> -
> -               if (!*p)
> -                       continue;
> -
> -               token = match_token(p, ovl_tokens, args);
> -               switch (token) {
> -               case OPT_UPPERDIR:
> -                       kfree(config->upperdir);
> -                       config->upperdir = match_strdup(&args[0]);
> -                       if (!config->upperdir)
> -                               return -ENOMEM;
> -                       break;
> -
> -               case OPT_LOWERDIR:
> -                       kfree(config->lowerdir);
> -                       config->lowerdir = match_strdup(&args[0]);
> -                       if (!config->lowerdir)
> -                               return -ENOMEM;
> -                       break;
> -
> -               case OPT_WORKDIR:
> -                       kfree(config->workdir);
> -                       config->workdir = match_strdup(&args[0]);
> -                       if (!config->workdir)
> -                               return -ENOMEM;
> -                       break;
> -
> -               case OPT_DEFAULT_PERMISSIONS:
> -                       config->default_permissions = true;
> -                       break;
> -
> -               case OPT_REDIRECT_DIR:
> -                       kfree(config->redirect_mode);
> -                       config->redirect_mode = match_strdup(&args[0]);
> -                       if (!config->redirect_mode)
> -                               return -ENOMEM;
> -                       redirect_opt = true;
> -                       break;
> -
> -               case OPT_INDEX_ON:
> -                       config->index = true;
> -                       index_opt = true;
> -                       break;
> -
> -               case OPT_INDEX_OFF:
> -                       config->index = false;
> -                       index_opt = true;
> -                       break;
> -
> -               case OPT_UUID_ON:
> -                       config->uuid = true;
> -                       break;
> -
> -               case OPT_UUID_OFF:
> -                       config->uuid = false;
> -                       break;
> -
> -               case OPT_NFS_EXPORT_ON:
> -                       config->nfs_export = true;
> -                       nfs_export_opt = true;
> -                       break;
> -
> -               case OPT_NFS_EXPORT_OFF:
> -                       config->nfs_export = false;
> -                       nfs_export_opt = true;
> -                       break;
> -
> -               case OPT_XINO_ON:
> -                       config->xino = OVL_XINO_ON;
> -                       break;
> -
> -               case OPT_XINO_OFF:
> -                       config->xino = OVL_XINO_OFF;
> -                       break;
> -
> -               case OPT_XINO_AUTO:
> -                       config->xino = OVL_XINO_AUTO;
> -                       break;
> -
> -               case OPT_METACOPY_ON:
> -                       config->metacopy = true;
> -                       metacopy_opt = true;
> -                       break;
> -
> -               case OPT_METACOPY_OFF:
> -                       config->metacopy = false;
> -                       metacopy_opt = true;
> -                       break;
> -
> -               case OPT_VOLATILE:
> -                       config->ovl_volatile = true;
> -                       break;
> -
> -               case OPT_USERXATTR:
> -                       config->userxattr = true;
> -                       break;
> -
> -               default:
> -                       pr_err("unrecognized mount option \"%s\" or missing value\n",
> -                                       p);
> -                       return -EINVAL;
> -               }
> -       }
> +       bool metacopy_opt = ctx->set & OVL_METACOPY_SET;
> +       bool redirect_opt = ctx->set & OVL_REDIRECT_SET;
> +       bool nfs_export_opt = ctx->set & OVL_NFS_EXPORT_SET;
> +       bool index_opt = ctx->set & OVL_INDEX_SET;
>
>         /* Workdir/index are useless in non-upper mount */
>         if (!config->upperdir) {
> @@ -647,7 +529,7 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>                 config->ovl_volatile = false;
>         }
>
> -       err = ovl_parse_redirect_mode(config, config->redirect_mode);
> +       err = ovl_set_redirect_mode(config);
>         if (err)
>                 return err;
>
> @@ -662,7 +544,7 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>         if (config->metacopy && !config->redirect_dir) {
>                 if (metacopy_opt && redirect_opt) {
>                         pr_err("conflicting options: metacopy=on,redirect_dir=%s\n",
> -                              config->redirect_mode);
> +                              ovl_redirect_mode(config));
>                         return -EINVAL;
>                 }
>                 if (redirect_opt) {
> @@ -671,7 +553,7 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>                          * in this conflict.
>                          */
>                         pr_info("disabling metacopy due to redirect_dir=%s\n",
> -                               config->redirect_mode);
> +                               ovl_redirect_mode(config));
>                         config->metacopy = false;
>                 } else {
>                         /* Automatically enable redirect otherwise. */
> @@ -728,7 +610,7 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
>         if (config->userxattr) {
>                 if (config->redirect_follow && redirect_opt) {
>                         pr_err("conflicting options: userxattr,redirect_dir=%s\n",
> -                              config->redirect_mode);
> +                              ovl_redirect_mode(config));
>                         return -EINVAL;
>                 }
>                 if (config->metacopy && metacopy_opt) {
> @@ -1926,12 +1808,128 @@ static struct dentry *ovl_get_root(struct super_block *sb,
>         return root;
>  }
>
> -static int ovl_fill_super(struct super_block *sb, void *data, int silent)
> +static int ovl_parse_param(struct fs_context *fc, struct fs_parameter *param)
> +{
> +       int err = 0;
> +       struct fs_parse_result result;
> +       struct ovl_fs *ofs = fc->s_fs_info;
> +       struct ovl_config *config = &ofs->config;
> +       struct ovl_fs_context *ctx = fc->fs_private;
> +       char *dup;
> +       int opt;
> +
> +       /*
> +        * On remount overlayfs has always ignored all mount options no
> +        * matter if malformed or not so for backwards compatibility we
> +        * do the same here.
> +        */
> +       if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE)
> +               return 0;
> +
> +       opt = fs_parse(fc, ovl_parameter_spec, param, &result);
> +       if (opt < 0)
> +               return opt;
> +
> +       switch (opt) {
> +       case Opt_lowerdir:
> +               dup = kstrdup(param->string, GFP_KERNEL);
> +               if (!dup) {
> +                       err = -ENOMEM;
> +                       break;
> +               }
> +
> +               kfree(config->lowerdir);
> +               config->lowerdir = dup;
> +               break;
> +       case Opt_upperdir:
> +               dup = kstrdup(param->string, GFP_KERNEL);
> +               if (!dup) {
> +                       err = -ENOMEM;
> +                       break;
> +               }
> +
> +               kfree(config->upperdir);
> +               config->upperdir = dup;
> +               break;
> +       case Opt_workdir:
> +               dup = kstrdup(param->string, GFP_KERNEL);
> +               if (!dup) {
> +                       err = -ENOMEM;
> +                       break;
> +               }
> +
> +               kfree(config->workdir);
> +               config->workdir = dup;
> +               break;
> +       case Opt_default_permissions:
> +               config->default_permissions = true;
> +               break;
> +       case Opt_index:
> +               config->index = result.uint_32;
> +               ctx->set |= OVL_INDEX_SET;
> +               break;
> +       case Opt_uuid:
> +               config->uuid = result.uint_32;
> +               break;
> +       case Opt_nfs_export:
> +               config->nfs_export = result.uint_32;
> +               ctx->set |= OVL_NFS_EXPORT_SET;
> +               break;
> +       case Opt_metacopy:
> +               config->metacopy = result.uint_32;
> +               ctx->set |= OVL_METACOPY_SET;
> +               break;
> +       case Opt_userxattr:
> +               config->userxattr = true;
> +               break;
> +       case Opt_volatile:
> +               config->ovl_volatile = true;
> +               break;
> +       case Opt_xino:
> +               config->xino = result.uint_32;
> +               break;
> +       case Opt_redirect_dir:
> +               config->redirect_mode = result.uint_32;
> +               ctx->set |= OVL_REDIRECT_SET;
> +               break;
> +       default:
> +               pr_err("unrecognized mount option \"%s\" or missing value\n", param->key);
> +               return -EINVAL;
> +       }
> +
> +       return err;
> +}
> +
> +
> +static int ovl_reconfigure(struct fs_context *fc)
>  {
> -       struct path upperpath = { };
> +       struct super_block *sb = fc->root->d_sb;
> +       struct ovl_fs *ofs = sb->s_fs_info;
> +       struct super_block *upper_sb;
> +       int ret = 0;
> +
> +       if (!(fc->sb_flags & SB_RDONLY) && ovl_force_readonly(ofs))
> +               return -EROFS;
> +
> +       if (fc->sb_flags & SB_RDONLY && !sb_rdonly(sb)) {
> +               upper_sb = ovl_upper_mnt(ofs)->mnt_sb;
> +               if (ovl_should_sync(ofs)) {
> +                       down_read(&upper_sb->s_umount);
> +                       ret = sync_filesystem(upper_sb);
> +                       up_read(&upper_sb->s_umount);
> +               }
> +       }
> +
> +       return ret;
> +}
> +
> +static int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
> +{
> +       struct ovl_fs *ofs = sb->s_fs_info;
> +       struct ovl_fs_context *ctx = fc->fs_private;
> +       struct path upperpath = {};
>         struct dentry *root_dentry;
>         struct ovl_entry *oe;
> -       struct ovl_fs *ofs;
>         struct ovl_layer *layers;
>         struct cred *cred;
>         char *splitlower = NULL;
> @@ -1939,36 +1937,24 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
>         int err;
>
>         err = -EIO;
> -       if (WARN_ON(sb->s_user_ns != current_user_ns()))
> -               goto out;
> +       if (WARN_ON(fc->user_ns != current_user_ns()))
> +               goto out_err;
>
> +       ofs->share_whiteout = true;
>         sb->s_d_op = &ovl_dentry_operations;
>
> -       err = -ENOMEM;
> -       ofs = kzalloc(sizeof(struct ovl_fs), GFP_KERNEL);
> -       if (!ofs)
> -               goto out;
> -
>         err = -ENOMEM;
>         ofs->creator_cred = cred = prepare_creds();
>         if (!cred)
>                 goto out_err;
>
> -       /* Is there a reason anyone would want not to share whiteouts? */
> -       ofs->share_whiteout = true;
> -
> -       ofs->config.index = ovl_index_def;
> -       ofs->config.uuid = true;
> -       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);
> +       err = ovl_fs_params_verify(ctx, &ofs->config);
>         if (err)
>                 goto out_err;
>
>         err = -EINVAL;
>         if (!ofs->config.lowerdir) {
> -               if (!silent)
> +               if (fc->sb_flags & SB_SILENT)

Test is negated here.
I fixed it in my branch.
No need to re-send.

>                         pr_err("missing 'lowerdir'\n");
>                 goto out_err;
>         }
> @@ -2113,25 +2099,90 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
>  out_free_oe:
>         ovl_free_entry(oe);
>  out_err:
> -       kfree(splitlower);
> -       path_put(&upperpath);
> -       ovl_free_fs(ofs);
> -out:

Folded your fix here:
       ovl_free_fs(ofs);
       sb->s_fs_info = NULL;

>         return err;
>  }
>

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