aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorPaulo Alcantara (SUSE) <paulo@paulo.ac>2019-03-19 16:54:29 -0300
committerSteve French <stfrench@microsoft.com>2019-05-07 23:24:54 -0500
commit5072010ccf0592950f7cfae0eb3c4008e8bf36f7 (patch)
treecde07048b7fe4faa26308571ca842ea9a36eda7c /fs/cifs/connect.c
parentcifs: don't use __constant_cpu_to_le32() (diff)
downloadlinux-dev-5072010ccf0592950f7cfae0eb3c4008e8bf36f7.tar.xz
linux-dev-5072010ccf0592950f7cfae0eb3c4008e8bf36f7.zip
cifs: Fix DFS cache refresher for DFS links
As per MS-DFSC, when a DFS cache entry is expired and it is a DFS link, then a new DFS referral must be sent to root server in order to refresh the expired entry. This patch ensures that all new DFS referrals for refreshing the cache are sent to DFS root. Signed-off-by: Paulo Alcantara (SUSE) <paulo@paulo.ac> Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to '')
-rw-r--r--fs/cifs/connect.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4c0e44489f21..9de8f61088ac 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -323,8 +323,6 @@ static int ip_connect(struct TCP_Server_Info *server);
static int generic_ip_connect(struct TCP_Server_Info *server);
static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
static void cifs_prune_tlinks(struct work_struct *work);
-static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
- const char *devname, bool is_smb3);
static char *extract_hostname(const char *unc);
/*
@@ -2904,8 +2902,7 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
return NULL;
}
-static void
-cifs_put_smb_ses(struct cifs_ses *ses)
+void cifs_put_smb_ses(struct cifs_ses *ses)
{
unsigned int rc, xid;
struct TCP_Server_Info *server = ses->server;
@@ -3082,7 +3079,7 @@ cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
* already got a server reference (server refcount +1). See
* cifs_get_tcon() for refcount explanations.
*/
-static struct cifs_ses *
+struct cifs_ses *
cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
{
int rc = -ENOMEM;
@@ -4389,7 +4386,7 @@ static int mount_do_dfs_failover(const char *path,
}
#endif
-static int
+int
cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
const char *devname, bool is_smb3)
{
@@ -4543,7 +4540,7 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
struct cifs_tcon *tcon = NULL;
struct TCP_Server_Info *server;
char *root_path = NULL, *full_path = NULL;
- char *old_mountdata;
+ char *old_mountdata, *origin_mountdata = NULL;
int count;
rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
@@ -4602,6 +4599,14 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
goto error;
}
+ /* Save DFS root volume information for DFS refresh worker */
+ origin_mountdata = kstrndup(cifs_sb->mountdata,
+ strlen(cifs_sb->mountdata), GFP_KERNEL);
+ if (!origin_mountdata) {
+ rc = -ENOMEM;
+ goto error;
+ }
+
if (cifs_sb->mountdata != old_mountdata) {
/* If we were redirected, reconnect to new target server */
mount_put_conns(cifs_sb, xid, server, ses, tcon);
@@ -4710,7 +4715,7 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
}
spin_unlock(&cifs_tcp_ses_lock);
- rc = dfs_cache_add_vol(vol, cifs_sb->origin_fullpath);
+ rc = dfs_cache_add_vol(origin_mountdata, vol, cifs_sb->origin_fullpath);
if (rc) {
kfree(cifs_sb->origin_fullpath);
goto error;
@@ -4728,6 +4733,7 @@ out:
error:
kfree(full_path);
kfree(root_path);
+ kfree(origin_mountdata);
mount_put_conns(cifs_sb, xid, server, ses, tcon);
return rc;
}