Re: [PATCH 1/4] cifs: fix DFS failover

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

 



is this series of 4 identical with
   https://git.cjr.nz/linux.git/commit/?h=dfs-fixes-v2

On Wed, Feb 24, 2021 at 6:00 PM Paulo Alcantara <pc@xxxxxx> wrote:
>
> In do_dfs_failover(), the mount_get_conns() function requires the full
> fs context in order to get new connection to server, so clone the
> original context and change it accordingly when retrying the DFS
> targets in the referral.
>
> If failover was successful, then update original context with the new
> UNC, prefix path and ip address.
>
> Signed-off-by: Paulo Alcantara (SUSE) <pc@xxxxxx>
> ---
>  fs/cifs/connect.c | 123 ++++++++++++++++++++++------------------------
>  1 file changed, 59 insertions(+), 64 deletions(-)
>
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index cd6dbeaf2166..a800e055c614 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -3045,96 +3045,91 @@ static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
>         return 0;
>  }
>
> -static int setup_dfs_tgt_conn(const char *path, const char *full_path,
> -                             const struct dfs_cache_tgt_iterator *tgt_it,
> -                             struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx,
> -                             unsigned int *xid, struct TCP_Server_Info **server,
> -                             struct cifs_ses **ses, struct cifs_tcon **tcon)
> -{
> -       int rc;
> -       struct dfs_info3_param ref = {0};
> -       char *mdata = NULL;
> -       struct smb3_fs_context fake_ctx = {NULL};
> -       char *fake_devname = NULL;
> -
> -       cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
> -
> -       rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
> -       if (rc)
> -               return rc;
> -
> -       mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options,
> -                                          full_path + 1, &ref,
> -                                          &fake_devname);
> -       free_dfs_info_param(&ref);
> -
> -       if (IS_ERR(mdata)) {
> -               rc = PTR_ERR(mdata);
> -               mdata = NULL;
> -       } else
> -               rc = cifs_setup_volume_info(&fake_ctx, mdata, fake_devname);
> -
> -       kfree(mdata);
> -       kfree(fake_devname);
> -
> -       if (!rc) {
> -               /*
> -                * We use a 'fake_ctx' here because we need pass it down to the
> -                * mount_{get,put} functions to test connection against new DFS
> -                * targets.
> -                */
> -               mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
> -               rc = mount_get_conns(&fake_ctx, cifs_sb, xid, server, ses,
> -                                    tcon);
> -               if (!rc || (*server && *ses)) {
> -                       /*
> -                        * We were able to connect to new target server.
> -                        * Update current context with new target server.
> -                        */
> -                       rc = update_vol_info(tgt_it, &fake_ctx, ctx);
> -               }
> -       }
> -       smb3_cleanup_fs_context_contents(&fake_ctx);
> -       return rc;
> -}
> -
>  static int do_dfs_failover(const char *path, const char *full_path, struct cifs_sb_info *cifs_sb,
>                            struct smb3_fs_context *ctx, struct cifs_ses *root_ses,
>                            unsigned int *xid, struct TCP_Server_Info **server,
>                            struct cifs_ses **ses, struct cifs_tcon **tcon)
>  {
>         int rc;
> -       struct dfs_cache_tgt_list tgt_list;
> +       struct dfs_cache_tgt_list tgt_list = {0};
>         struct dfs_cache_tgt_iterator *tgt_it = NULL;
> +       struct smb3_fs_context tmp_ctx = {NULL};
>
>         if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
>                 return -EOPNOTSUPP;
>
> +       cifs_dbg(FYI, "%s: path=%s full_path=%s\n", __func__, path, full_path);
> +
>         rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
>         if (rc)
>                 return rc;
> +       /*
> +        * We use a 'tmp_ctx' here because we need pass it down to the mount_{get,put} functions to
> +        * test connection against new DFS targets.
> +        */
> +       rc = smb3_fs_context_dup(&tmp_ctx, ctx);
> +       if (rc)
> +               goto out;
>
>         for (;;) {
> +               struct dfs_info3_param ref = {0};
> +               char *fake_devname = NULL, *mdata = NULL;
> +
>                 /* Get next DFS target server - if any */
>                 rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
>                 if (rc)
>                         break;
> -               /* Connect to next DFS target */
> -               rc = setup_dfs_tgt_conn(path, full_path, tgt_it, cifs_sb, ctx, xid, server, ses,
> -                                       tcon);
> -               if (!rc || (*server && *ses))
> +
> +               rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
> +               if (rc)
>                         break;
> +
> +               cifs_dbg(FYI, "%s: old ctx: UNC=%s prepath=%s\n", __func__, tmp_ctx.UNC,
> +                        tmp_ctx.prepath);
> +
> +               mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options, full_path + 1, &ref,
> +                                                  &fake_devname);
> +               free_dfs_info_param(&ref);
> +
> +               if (IS_ERR(mdata)) {
> +                       rc = PTR_ERR(mdata);
> +                       mdata = NULL;
> +               } else
> +                       rc = cifs_setup_volume_info(&tmp_ctx, mdata, fake_devname);
> +
> +               kfree(mdata);
> +               kfree(fake_devname);
> +
> +               if (rc)
> +                       break;
> +
> +               cifs_dbg(FYI, "%s: new ctx: UNC=%s prepath=%s\n", __func__, tmp_ctx.UNC,
> +                        tmp_ctx.prepath);
> +
> +               mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
> +               rc = mount_get_conns(&tmp_ctx, cifs_sb, xid, server, ses, tcon);
> +               if (!rc || (*server && *ses)) {
> +                       /*
> +                        * We were able to connect to new target server. Update current context with
> +                        * new target server.
> +                        */
> +                       rc = update_vol_info(tgt_it, &tmp_ctx, ctx);
> +                       break;
> +               }
>         }
>         if (!rc) {
> +               cifs_dbg(FYI, "%s: final ctx: UNC=%s prepath=%s\n", __func__, tmp_ctx.UNC,
> +                        tmp_ctx.prepath);
>                 /*
> -                * Update DFS target hint in DFS referral cache with the target
> -                * server we successfully reconnected to.
> +                * Update DFS target hint in DFS referral cache with the target server we
> +                * successfully reconnected to.
>                  */
> -               rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
> -                                             cifs_sb->local_nls,
> -                                             cifs_remap(cifs_sb), path,
> -                                             tgt_it);
> +               rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses, cifs_sb->local_nls,
> +                                             cifs_remap(cifs_sb), path, tgt_it);
>         }
> +
> +out:
> +       smb3_cleanup_fs_context_contents(&tmp_ctx);
>         dfs_cache_free_tgts(&tgt_list);
>         return rc;
>  }
> --
> 2.30.1
>


-- 
Thanks,

Steve



[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux