lkml.org 
[lkml]   [2021]   [Mar]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.11 740/775] cifs: fix DFS failover
    Date
    From: Paulo Alcantara <pc@cjr.nz>

    commit 8513222b9ef2709ba40cbda07b55d5fbcfdd4bc7 upstream.

    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@cjr.nz>
    Cc: stable@vger.kernel.org # 5.11
    Signed-off-by: Steve French <stfrench@microsoft.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    fs/cifs/connect.c | 123 +++++++++++++++++++++++++-----------------------------
    1 file changed, 59 insertions(+), 64 deletions(-)

    --- a/fs/cifs/connect.c
    +++ b/fs/cifs/connect.c
    @@ -3038,96 +3038,91 @@ static int update_vol_info(const struct
    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;
    }

    \
     
     \ /
      Last update: 2021-03-02 14:40    [W:2.694 / U:0.956 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site