summaryrefslogtreecommitdiff
path: root/fs/smb/client/cifsglob.h
diff options
context:
space:
mode:
authorPaulo Alcantara <pc@manguebit.com>2023-08-17 12:34:00 -0300
committerSteve French <stfrench@microsoft.com>2023-08-20 16:05:50 -0500
commitce04127c5849af610d395b5b9552ef31d83c0189 (patch)
tree2b289f02fa29ba93bd9ea9e5c882d33d06442b32 /fs/smb/client/cifsglob.h
parent3fea12f3c67de30fd2e6a3f5da2b5354aa22348e (diff)
downloadlwn-ce04127c5849af610d395b5b9552ef31d83c0189.tar.gz
lwn-ce04127c5849af610d395b5b9552ef31d83c0189.zip
smb: client: ensure to try all targets when finding nested links
With current implementation, when a nested DFS link is found during mount(2), the client follows the referral and then try to connect to all of its targets. If all targets failed, the client bails out rather than retrying remaining targets from previous referral. Fix this by stacking all referrals and targets so the client can retry remaining targets from previous referrals in case all targets of current referral have failed. Thanks to samba, this can be easily tested like below * Run the following under dfs folder in samba server $ ln -s "msdfs:srv\\bad-share" link1 $ ln -s "msdfs:srv\\dfs\\link1,srv\\good-share" link0 * Before patch $ mount.cifs //srv/dfs/link0 /mnt -o ... mount error(2): No such file or directory Refer to the mount.cifs(8) manual page (e.g. man mount.cifs)... * After patch $ mount.cifs //srv/dfs/link0 /mnt -o ... # ls /mnt bar fileshare1 sub Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com> Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/smb/client/cifsglob.h')
-rw-r--r--fs/smb/client/cifsglob.h16
1 files changed, 14 insertions, 2 deletions
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index 657dee4b2c8c..712557c2d526 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -1721,11 +1721,23 @@ struct cifs_mount_ctx {
struct list_head dfs_ses_list;
};
+static inline void __free_dfs_info_param(struct dfs_info3_param *param)
+{
+ kfree(param->path_name);
+ kfree(param->node_name);
+}
+
static inline void free_dfs_info_param(struct dfs_info3_param *param)
{
+ if (param)
+ __free_dfs_info_param(param);
+}
+
+static inline void zfree_dfs_info_param(struct dfs_info3_param *param)
+{
if (param) {
- kfree(param->path_name);
- kfree(param->node_name);
+ __free_dfs_info_param(param);
+ memset(param, 0, sizeof(*param));
}
}