18 #include <linux/slab.h>
27 static LIST_HEAD(cifs_dfs_automount_list);
31 cifs_dfs_expire_automounts);
32 static int cifs_dfs_mountpoint_expiry_timeout = 500 *
HZ;
39 if (!list_empty(list))
41 cifs_dfs_mountpoint_expiry_timeout);
46 BUG_ON(!list_empty(&cifs_dfs_automount_list));
61 static char *cifs_get_share_name(
const char *
node_name)
74 if (node_name[1] !=
'\\') {
85 pSep =
memchr(UNC+2,
'\\', len-2);
87 cERROR(1,
"%s: no server name end in node name: %s",
95 pSep =
memchr(UNC+(pSep-UNC),
'\\', len-(pSep-UNC));
120 const char *fullpath,
125 char *mountdata =
NULL;
132 if (sb_mountdata ==
NULL)
135 *devname = cifs_get_share_name(ref->
node_name);
136 if (IS_ERR(*devname)) {
137 rc = PTR_ERR(*devname);
139 goto compose_mount_options_err;
144 cFYI(1,
"%s: Failed to resolve server part of %s to IP: %d",
145 __func__, *devname, rc);
146 goto compose_mount_options_err;
155 if (mountdata ==
NULL) {
157 goto compose_mount_options_err;
162 if (
strncmp(sb_mountdata,
"sep=", 4) == 0) {
163 sep = sb_mountdata[4];
164 strncpy(mountdata, sb_mountdata, 5);
169 tkn_e =
strchr(sb_mountdata + off, sep);
171 noff =
strlen(sb_mountdata + off);
173 noff = tkn_e - (sb_mountdata + off) + 1;
175 if (
strnicmp(sb_mountdata + off,
"unc=", 4) == 0) {
179 if (
strnicmp(sb_mountdata + off,
"ip=", 3) == 0) {
183 if (
strnicmp(sb_mountdata + off,
"prefixpath=", 11) == 0) {
187 strncat(mountdata, sb_mountdata + off, noff);
190 strcat(mountdata, sb_mountdata + off);
191 mountdata[md_len] =
'\0';
194 if (mountdata[
strlen(mountdata) - 1] != sep)
199 strcat(mountdata,
"unc=");
200 strcat(mountdata, *devname);
207 goto compose_mount_options_err;
210 tkn_e =
strchr(tkn_e + 1,
'\\');
213 strcat(mountdata,
"prefixpath=");
215 strcat(mountdata, tkn_e + 1);
222 compose_mount_options_out:
226 compose_mount_options_err:
228 mountdata = ERR_PTR(rc);
229 goto compose_mount_options_out;
243 char *devname =
NULL;
247 fullpath + 1, ref, &devname);
249 if (IS_ERR(mountdata))
250 return (
struct vfsmount *)mountdata;
264 cFYI(1,
"DFS: ref_flags: %hd, path_consumed: %hd", ref->
ref_flag,
271 static struct vfsmount *cifs_dfs_do_automount(
struct dentry *mntpt)
274 unsigned int num_referrals = 0;
284 cFYI(1,
"in %s", __func__);
295 if (full_path ==
NULL)
298 cifs_sb = CIFS_SB(mntpt->
d_inode->i_sb);
301 mnt = ERR_CAST(tlink);
304 ses = tlink_tcon(tlink)->ses;
308 &num_referrals, &referrals,
315 for (i = 0; i < num_referrals; i++) {
317 dump_referral(referrals + i);
319 len =
strlen(referrals[i].node_name);
321 cERROR(1,
"%s: Net Address path too short: %s",
322 __func__, referrals[i].node_name);
326 mnt = cifs_dfs_do_refmount(cifs_sb,
327 full_path, referrals + i);
328 cFYI(1,
"%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__,
329 referrals[i].node_name, mnt);
340 free_dfs_info_array(referrals, num_referrals);
344 cFYI(1,
"leaving %s" , __func__);
355 cFYI(1,
"in %s", __func__);
357 newmnt = cifs_dfs_do_automount(path->
dentry);
358 if (IS_ERR(newmnt)) {
359 cFYI(1,
"leaving %s [automount failed]" , __func__);
366 cifs_dfs_mountpoint_expiry_timeout);
367 cFYI(1,
"leaving %s [ok]" , __func__);