diff options
author | 2025-01-10 15:58:08 -0300 | |
---|---|---|
committer | 2025-01-19 19:34:00 -0600 | |
commit | 5433c629e8d4eee77233a2bc88075886dc6e37ef (patch) | |
tree | 77903039a72dbaa46def60bb87923bb29ab0b507 /fs/smb/client/dfs.c | |
parent | smb: client: provide dns_resolve_{unc,name} helpers (diff) | |
download | linux-rng-5433c629e8d4eee77233a2bc88075886dc6e37ef.tar.xz linux-rng-5433c629e8d4eee77233a2bc88075886dc6e37ef.zip |
smb: client: optimize referral walk on failed link targets
If a link referral request sent to root server was successful but
client failed to connect to all link targets, there is no need to
retry same link referral on a different root server. Set an end
marker for the DFS root referral so the client will not attempt to
re-send link referrals to different root servers on failures.
Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/smb/client/dfs.c')
-rw-r--r-- | fs/smb/client/dfs.c | 69 |
1 files changed, 26 insertions, 43 deletions
diff --git a/fs/smb/client/dfs.c b/fs/smb/client/dfs.c index b7de814e39bd..dad521336b5e 100644 --- a/fs/smb/client/dfs.c +++ b/fs/smb/client/dfs.c @@ -98,15 +98,16 @@ static inline int parse_dfs_target(struct smb3_fs_context *ctx, return rc; } -static int setup_dfs_ref(struct cifs_mount_ctx *mnt_ctx, - struct dfs_info3_param *tgt, - struct dfs_ref_walk *rw) +static int setup_dfs_ref(struct dfs_info3_param *tgt, struct dfs_ref_walk *rw) { - struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; - struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb; + struct cifs_sb_info *cifs_sb = rw->mnt_ctx->cifs_sb; + struct smb3_fs_context *ctx = rw->mnt_ctx->fs_ctx; char *ref_path, *full_path; int rc; + set_root_smb_session(rw->mnt_ctx); + ref_walk_ses(rw) = ctx->dfs_root_ses; + full_path = smb3_fs_context_fullpath(ctx, CIFS_DIR_SEP(cifs_sb)); if (IS_ERR(full_path)) return PTR_ERR(full_path); @@ -123,35 +124,22 @@ static int setup_dfs_ref(struct cifs_mount_ctx *mnt_ctx, } ref_walk_path(rw) = ref_path; ref_walk_fpath(rw) = full_path; - ref_walk_ses(rw) = ctx->dfs_root_ses; - return 0; + + return dfs_get_referral(rw->mnt_ctx, + ref_walk_path(rw) + 1, + ref_walk_tl(rw)); } -static int __dfs_referral_walk(struct cifs_mount_ctx *mnt_ctx, - struct dfs_ref_walk *rw) +static int __dfs_referral_walk(struct dfs_ref_walk *rw) { - struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; + struct smb3_fs_context *ctx = rw->mnt_ctx->fs_ctx; + struct cifs_mount_ctx *mnt_ctx = rw->mnt_ctx; struct dfs_info3_param tgt = {}; int rc = -ENOENT; again: do { ctx->dfs_root_ses = ref_walk_ses(rw); - if (ref_walk_empty(rw)) { - rc = dfs_get_referral(mnt_ctx, ref_walk_path(rw) + 1, - NULL, ref_walk_tl(rw)); - if (rc) { - rc = cifs_mount_get_tcon(mnt_ctx); - if (!rc) - rc = cifs_is_path_remote(mnt_ctx); - continue; - } - if (!ref_walk_num_tgts(rw)) { - rc = -ENOENT; - continue; - } - } - while (ref_walk_next_tgt(rw)) { rc = parse_dfs_target(ctx, rw, &tgt); if (rc) @@ -162,32 +150,29 @@ again: if (rc) continue; - ref_walk_set_tgt_hint(rw); if (tgt.flags & DFSREF_STORAGE_SERVER) { rc = cifs_mount_get_tcon(mnt_ctx); if (!rc) rc = cifs_is_path_remote(mnt_ctx); - if (!rc) + if (!rc) { + ref_walk_set_tgt_hint(rw); break; + } if (rc != -EREMOTE) continue; } - set_root_smb_session(mnt_ctx); rc = ref_walk_advance(rw); if (!rc) { - rc = setup_dfs_ref(mnt_ctx, &tgt, rw); - if (!rc) { - rc = -EREMOTE; - goto again; - } + rc = setup_dfs_ref(&tgt, rw); + if (rc) + break; + ref_walk_mark_end(rw); + goto again; } - if (rc != -ELOOP) - goto out; } } while (rc && ref_walk_descend(rw)); -out: free_dfs_info_param(&tgt); return rc; } @@ -204,10 +189,10 @@ static int dfs_referral_walk(struct cifs_mount_ctx *mnt_ctx, return rc; } - ref_walk_init(*rw); - rc = setup_dfs_ref(mnt_ctx, NULL, *rw); + ref_walk_init(*rw, mnt_ctx); + rc = setup_dfs_ref(NULL, *rw); if (!rc) - rc = __dfs_referral_walk(mnt_ctx, *rw); + rc = __dfs_referral_walk(*rw); return rc; } @@ -297,7 +282,7 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx) * to respond with PATH_NOT_COVERED to requests that include the prefix. */ if (!nodfs) { - rc = dfs_get_referral(mnt_ctx, ctx->UNC + 1, NULL, NULL); + rc = dfs_get_referral(mnt_ctx, ctx->UNC + 1, NULL); if (rc) { cifs_dbg(FYI, "%s: no dfs referral for %s: %d\n", __func__, ctx->UNC + 1, rc); @@ -317,10 +302,8 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx) cifs_mount_put_conns(mnt_ctx); rc = get_session(mnt_ctx, NULL); } - if (!rc) { - set_root_smb_session(mnt_ctx); + if (!rc) rc = __dfs_mount_share(mnt_ctx); - } return rc; } |