Skip to content

Commit

Permalink
cifs: Extract DFS referral expansion logic to separate function
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Sean Finney authored and Steve French committed May 19, 2011
1 parent 460458c commit dd61394
Showing 1 changed file with 69 additions and 36 deletions.
105 changes: 69 additions & 36 deletions fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
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

int
Expand All @@ -2761,10 +2812,19 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
char *mount_data = mount_data_global;
struct tcon_link *tlink;
#ifdef CONFIG_CIFS_DFS_UPCALL
struct dfs_info3_param *referrals = NULL;
unsigned int num_referrals = 0;
int referral_walks_count = 0;
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
rc = 0;
tcon = NULL;
Expand Down Expand Up @@ -2910,46 +2970,19 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
convert_delimiter(cifs_sb->prepath,
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);
rc = get_dfs_path(xid, pSesInfo , full_path + 1,
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)
kfree(mount_data);

mount_data = cifs_compose_mount_options(
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 (mount_data != mount_data_global)
kfree(mount_data);

if (tcon)
cifs_put_tcon(tcon);
else if (pSesInfo)
cifs_put_smb_ses(pSesInfo);
rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb,
&mount_data, true);

cleanup_volume_info(&volume_info);
if (!rc) {
referral_walks_count++;
FreeXid(xid);
goto try_mount_again;
}
mount_data = NULL;
goto mount_fail_check;
#else /* No DFS support, return error on mount */
rc = -EOPNOTSUPP;
#endif
Expand Down

0 comments on commit dd61394

Please sign in to comment.