cifs: Extract DFS referral expansion logic to separate function
The logic behind the expansion of DFS referrals is now extracted from cifs_mount into a new static function, expand_dfs_referral. This will reduce duplicate code in upcoming commits. Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Sean Finney <seanius@seanius.net> Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
460458ce8e
commit
dd61394586
|
@ -2745,6 +2745,57 @@ build_unc_path_to_root(const struct smb_vol *volume_info,
|
||||||
full_path[unc_len + cifs_sb->prepathlen] = 0; /* add trailing null */
|
full_path[unc_len + cifs_sb->prepathlen] = 0; /* add trailing null */
|
||||||
return full_path;
|
return full_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform a dfs referral query for a share and (optionally) prefix
|
||||||
|
*
|
||||||
|
* If a referral is found, mount_data will be set to point at a newly
|
||||||
|
* allocated string containing updated options for the submount.
|
||||||
|
* Otherwise it will be left untouched.
|
||||||
|
*
|
||||||
|
* Returns the rc from get_dfs_path to the caller, which can be used to
|
||||||
|
* determine whether there were referrals.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
expand_dfs_referral(int xid, struct cifsSesInfo *pSesInfo,
|
||||||
|
struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
|
||||||
|
char **mount_data, int check_prefix)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
unsigned int num_referrals = 0;
|
||||||
|
struct dfs_info3_param *referrals = NULL;
|
||||||
|
char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
|
||||||
|
|
||||||
|
full_path = build_unc_path_to_root(volume_info, cifs_sb);
|
||||||
|
if (IS_ERR(full_path))
|
||||||
|
return PTR_ERR(full_path);
|
||||||
|
|
||||||
|
/* For DFS paths, skip the first '\' of the UNC */
|
||||||
|
ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
|
||||||
|
|
||||||
|
rc = get_dfs_path(xid, pSesInfo , ref_path, cifs_sb->local_nls,
|
||||||
|
&num_referrals, &referrals,
|
||||||
|
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
|
||||||
|
if (!rc && num_referrals > 0) {
|
||||||
|
char *fake_devname = NULL;
|
||||||
|
|
||||||
|
mdata = cifs_compose_mount_options(cifs_sb->mountdata,
|
||||||
|
full_path + 1, referrals,
|
||||||
|
&fake_devname);
|
||||||
|
|
||||||
|
free_dfs_info_array(referrals, num_referrals);
|
||||||
|
kfree(fake_devname);
|
||||||
|
|
||||||
|
if (IS_ERR(mdata)) {
|
||||||
|
rc = PTR_ERR(mdata);
|
||||||
|
mdata = NULL;
|
||||||
|
}
|
||||||
|
*mount_data = mdata;
|
||||||
|
}
|
||||||
|
kfree(full_path);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -2761,10 +2812,19 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
char *mount_data = mount_data_global;
|
char *mount_data = mount_data_global;
|
||||||
struct tcon_link *tlink;
|
struct tcon_link *tlink;
|
||||||
#ifdef CONFIG_CIFS_DFS_UPCALL
|
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||||
struct dfs_info3_param *referrals = NULL;
|
|
||||||
unsigned int num_referrals = 0;
|
|
||||||
int referral_walks_count = 0;
|
int referral_walks_count = 0;
|
||||||
try_mount_again:
|
try_mount_again:
|
||||||
|
|
||||||
|
/* cleanup activities if we're chasing a referral */
|
||||||
|
if (referral_walks_count) {
|
||||||
|
if (tcon)
|
||||||
|
cifs_put_tcon(tcon);
|
||||||
|
else if (pSesInfo)
|
||||||
|
cifs_put_smb_ses(pSesInfo);
|
||||||
|
|
||||||
|
cleanup_volume_info(&volume_info);
|
||||||
|
FreeXid(xid);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
rc = 0;
|
rc = 0;
|
||||||
tcon = NULL;
|
tcon = NULL;
|
||||||
|
@ -2910,46 +2970,19 @@ remote_path_check:
|
||||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
|
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
|
||||||
convert_delimiter(cifs_sb->prepath,
|
convert_delimiter(cifs_sb->prepath,
|
||||||
CIFS_DIR_SEP(cifs_sb));
|
CIFS_DIR_SEP(cifs_sb));
|
||||||
full_path = build_unc_path_to_root(volume_info, cifs_sb);
|
|
||||||
if (IS_ERR(full_path)) {
|
|
||||||
rc = PTR_ERR(full_path);
|
|
||||||
goto mount_fail_check;
|
|
||||||
}
|
|
||||||
|
|
||||||
cFYI(1, "Getting referral for: %s", full_path);
|
if (mount_data != mount_data_global)
|
||||||
rc = get_dfs_path(xid, pSesInfo , full_path + 1,
|
kfree(mount_data);
|
||||||
cifs_sb->local_nls, &num_referrals, &referrals,
|
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
if (!rc && num_referrals > 0) {
|
|
||||||
char *fake_devname = NULL;
|
|
||||||
|
|
||||||
if (mount_data != mount_data_global)
|
rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb,
|
||||||
kfree(mount_data);
|
&mount_data, true);
|
||||||
|
|
||||||
mount_data = cifs_compose_mount_options(
|
if (!rc) {
|
||||||
cifs_sb->mountdata, full_path + 1,
|
|
||||||
referrals, &fake_devname);
|
|
||||||
|
|
||||||
free_dfs_info_array(referrals, num_referrals);
|
|
||||||
kfree(fake_devname);
|
|
||||||
kfree(full_path);
|
|
||||||
|
|
||||||
if (IS_ERR(mount_data)) {
|
|
||||||
rc = PTR_ERR(mount_data);
|
|
||||||
mount_data = NULL;
|
|
||||||
goto mount_fail_check;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tcon)
|
|
||||||
cifs_put_tcon(tcon);
|
|
||||||
else if (pSesInfo)
|
|
||||||
cifs_put_smb_ses(pSesInfo);
|
|
||||||
|
|
||||||
cleanup_volume_info(&volume_info);
|
|
||||||
referral_walks_count++;
|
referral_walks_count++;
|
||||||
FreeXid(xid);
|
|
||||||
goto try_mount_again;
|
goto try_mount_again;
|
||||||
}
|
}
|
||||||
|
mount_data = NULL;
|
||||||
|
goto mount_fail_check;
|
||||||
#else /* No DFS support, return error on mount */
|
#else /* No DFS support, return error on mount */
|
||||||
rc = -EOPNOTSUPP;
|
rc = -EOPNOTSUPP;
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue