diff options
author | Paulo Alcantara <pc@manguebit.com> | 2023-08-17 18:34:00 +0300 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2023-08-21 00:05:50 +0300 |
commit | ce04127c5849af610d395b5b9552ef31d83c0189 (patch) | |
tree | 2b289f02fa29ba93bd9ea9e5c882d33d06442b32 /fs/smb/client/dfs_cache.c | |
parent | 3fea12f3c67de30fd2e6a3f5da2b5354aa22348e (diff) | |
download | linux-ce04127c5849af610d395b5b9552ef31d83c0189.tar.xz |
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/dfs_cache.c')
-rw-r--r-- | fs/smb/client/dfs_cache.c | 6 |
1 files changed, 2 insertions, 4 deletions
diff --git a/fs/smb/client/dfs_cache.c b/fs/smb/client/dfs_cache.c index 89b8af831a43..508d831fabe3 100644 --- a/fs/smb/client/dfs_cache.c +++ b/fs/smb/client/dfs_cache.c @@ -29,8 +29,6 @@ #define CACHE_MIN_TTL 120 /* 2 minutes */ #define CACHE_DEFAULT_TTL 300 /* 5 minutes */ -#define IS_DFS_INTERLINK(v) (((v) & DFSREF_REFERRAL_SERVER) && !((v) & DFSREF_STORAGE_SERVER)) - struct cache_dfs_tgt { char *name; int path_consumed; @@ -174,7 +172,7 @@ static int dfscache_proc_show(struct seq_file *m, void *v) "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,hdr_flags=0x%x,ref_flags=0x%x,interlink=%s,path_consumed=%d,expired=%s\n", ce->path, ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ce->ttl, ce->etime.tv_nsec, ce->hdr_flags, ce->ref_flags, - IS_DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no", + DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no", ce->path_consumed, cache_entry_expired(ce) ? "yes" : "no"); list_for_each_entry(t, &ce->tlist, list) { @@ -243,7 +241,7 @@ static inline void dump_ce(const struct cache_entry *ce) ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", ce->ttl, ce->etime.tv_nsec, ce->hdr_flags, ce->ref_flags, - IS_DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no", + DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no", ce->path_consumed, cache_entry_expired(ce) ? "yes" : "no"); dump_tgts(ce); |