aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifs_dfs_ref.c18
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/dns_resolve.c8
-rw-r--r--fs/cifs/inode.c133
4 files changed, 86 insertions, 77 deletions
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 7f8838253410..a1a95b027136 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -74,7 +74,7 @@ static char *cifs_get_share_name(const char *node_name)
74 pSep = memchr(UNC+2, '\\', len-2); 74 pSep = memchr(UNC+2, '\\', len-2);
75 if (!pSep) { 75 if (!pSep) {
76 cERROR(1, ("%s: no server name end in node name: %s", 76 cERROR(1, ("%s: no server name end in node name: %s",
77 __FUNCTION__, node_name)); 77 __func__, node_name));
78 kfree(UNC); 78 kfree(UNC);
79 return NULL; 79 return NULL;
80 } 80 }
@@ -84,7 +84,7 @@ static char *cifs_get_share_name(const char *node_name)
84 pSep = memchr(UNC+(pSep-UNC), '\\', len-(pSep-UNC)); 84 pSep = memchr(UNC+(pSep-UNC), '\\', len-(pSep-UNC));
85 if (!pSep) { 85 if (!pSep) {
86 cERROR(1, ("%s:2 cant find share name in node name: %s", 86 cERROR(1, ("%s:2 cant find share name in node name: %s",
87 __FUNCTION__, node_name)); 87 __func__, node_name));
88 kfree(UNC); 88 kfree(UNC);
89 return NULL; 89 return NULL;
90 } 90 }
@@ -127,7 +127,7 @@ static char *compose_mount_options(const char *sb_mountdata,
127 rc = dns_resolve_server_name_to_ip(*devname, &srvIP); 127 rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
128 if (rc != 0) { 128 if (rc != 0) {
129 cERROR(1, ("%s: Failed to resolve server part of %s to IP", 129 cERROR(1, ("%s: Failed to resolve server part of %s to IP",
130 __FUNCTION__, *devname)); 130 __func__, *devname));
131 mountdata = ERR_PTR(rc); 131 mountdata = ERR_PTR(rc);
132 goto compose_mount_options_out; 132 goto compose_mount_options_out;
133 } 133 }
@@ -181,8 +181,8 @@ static char *compose_mount_options(const char *sb_mountdata,
181 } 181 }
182 } 182 }
183 183
184 /*cFYI(1,("%s: parent mountdata: %s", __FUNCTION__,sb_mountdata));*/ 184 /*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/
185 /*cFYI(1, ("%s: submount mountdata: %s", __FUNCTION__, mountdata ));*/ 185 /*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/
186 186
187compose_mount_options_out: 187compose_mount_options_out:
188 kfree(srvIP); 188 kfree(srvIP);
@@ -302,7 +302,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
302 int rc = 0; 302 int rc = 0;
303 struct vfsmount *mnt = ERR_PTR(-ENOENT); 303 struct vfsmount *mnt = ERR_PTR(-ENOENT);
304 304
305 cFYI(1, ("in %s", __FUNCTION__)); 305 cFYI(1, ("in %s", __func__));
306 BUG_ON(IS_ROOT(dentry)); 306 BUG_ON(IS_ROOT(dentry));
307 307
308 xid = GetXid(); 308 xid = GetXid();
@@ -336,7 +336,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
336 len = strlen(referrals[i].node_name); 336 len = strlen(referrals[i].node_name);
337 if (len < 2) { 337 if (len < 2) {
338 cERROR(1, ("%s: Net Address path too short: %s", 338 cERROR(1, ("%s: Net Address path too short: %s",
339 __FUNCTION__, referrals[i].node_name)); 339 __func__, referrals[i].node_name));
340 rc = -EINVAL; 340 rc = -EINVAL;
341 goto out_err; 341 goto out_err;
342 } 342 }
@@ -344,7 +344,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
344 nd->path.dentry, 344 nd->path.dentry,
345 referrals[i].node_name); 345 referrals[i].node_name);
346 cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", 346 cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p",
347 __FUNCTION__, 347 __func__,
348 referrals[i].node_name, mnt)); 348 referrals[i].node_name, mnt));
349 349
350 /* complete mount procedure if we accured submount */ 350 /* complete mount procedure if we accured submount */
@@ -365,7 +365,7 @@ out:
365 FreeXid(xid); 365 FreeXid(xid);
366 free_dfs_info_array(referrals, num_referrals); 366 free_dfs_info_array(referrals, num_referrals);
367 kfree(full_path); 367 kfree(full_path);
368 cFYI(1, ("leaving %s" , __FUNCTION__)); 368 cFYI(1, ("leaving %s" , __func__));
369 return ERR_PTR(rc); 369 return ERR_PTR(rc);
370out_err: 370out_err:
371 path_put(&nd->path); 371 path_put(&nd->path);
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 0af63e6b426b..a0414bda587c 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -39,8 +39,8 @@ extern int smb_send(struct socket *, struct smb_hdr *,
39 unsigned int /* length */ , struct sockaddr *); 39 unsigned int /* length */ , struct sockaddr *);
40extern unsigned int _GetXid(void); 40extern unsigned int _GetXid(void);
41extern void _FreeXid(unsigned int); 41extern void _FreeXid(unsigned int);
42#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid)); 42#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current->fsuid));
43#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));} 43#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
44extern char *build_path_from_dentry(struct dentry *); 44extern char *build_path_from_dentry(struct dentry *);
45extern char *build_wildcard_path_from_dentry(struct dentry *direntry); 45extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
46/* extern void renew_parental_timestamps(struct dentry *direntry);*/ 46/* extern void renew_parental_timestamps(struct dentry *direntry);*/
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c
index ef7f43824347..7cc86c418182 100644
--- a/fs/cifs/dns_resolve.c
+++ b/fs/cifs/dns_resolve.c
@@ -77,14 +77,14 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
77 /* search for server name delimiter */ 77 /* search for server name delimiter */
78 len = strlen(unc); 78 len = strlen(unc);
79 if (len < 3) { 79 if (len < 3) {
80 cFYI(1, ("%s: unc is too short: %s", __FUNCTION__, unc)); 80 cFYI(1, ("%s: unc is too short: %s", __func__, unc));
81 return -EINVAL; 81 return -EINVAL;
82 } 82 }
83 len -= 2; 83 len -= 2;
84 name = memchr(unc+2, '\\', len); 84 name = memchr(unc+2, '\\', len);
85 if (!name) { 85 if (!name) {
86 cFYI(1, ("%s: probably server name is whole unc: %s", 86 cFYI(1, ("%s: probably server name is whole unc: %s",
87 __FUNCTION__, unc)); 87 __func__, unc));
88 } else { 88 } else {
89 len = (name - unc) - 2/* leading // */; 89 len = (name - unc) - 2/* leading // */;
90 } 90 }
@@ -104,7 +104,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
104 if (*ip_addr) { 104 if (*ip_addr) {
105 memcpy(*ip_addr, rkey->payload.data, len); 105 memcpy(*ip_addr, rkey->payload.data, len);
106 (*ip_addr)[len] = '\0'; 106 (*ip_addr)[len] = '\0';
107 cFYI(1, ("%s: resolved: %s to %s", __FUNCTION__, 107 cFYI(1, ("%s: resolved: %s to %s", __func__,
108 rkey->description, 108 rkey->description,
109 *ip_addr 109 *ip_addr
110 )); 110 ));
@@ -114,7 +114,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
114 } 114 }
115 key_put(rkey); 115 key_put(rkey);
116 } else { 116 } else {
117 cERROR(1, ("%s: unable to resolve: %s", __FUNCTION__, name)); 117 cERROR(1, ("%s: unable to resolve: %s", __func__, name));
118 } 118 }
119 119
120 kfree(name); 120 kfree(name);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 24eb4d392155..4f0ee67eb954 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -30,7 +30,7 @@
30#include "cifs_fs_sb.h" 30#include "cifs_fs_sb.h"
31 31
32 32
33static void cifs_set_ops(struct inode *inode) 33static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
34{ 34{
35 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 35 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
36 36
@@ -57,8 +57,12 @@ static void cifs_set_ops(struct inode *inode)
57 inode->i_data.a_ops = &cifs_addr_ops; 57 inode->i_data.a_ops = &cifs_addr_ops;
58 break; 58 break;
59 case S_IFDIR: 59 case S_IFDIR:
60 inode->i_op = &cifs_dir_inode_ops; 60 if (is_dfs_referral) {
61 inode->i_fop = &cifs_dir_ops; 61 inode->i_op = &cifs_dfs_referral_inode_operations;
62 } else {
63 inode->i_op = &cifs_dir_inode_ops;
64 inode->i_fop = &cifs_dir_ops;
65 }
62 break; 66 break;
63 case S_IFLNK: 67 case S_IFLNK:
64 inode->i_op = &cifs_symlink_inode_ops; 68 inode->i_op = &cifs_symlink_inode_ops;
@@ -153,6 +157,30 @@ static void cifs_unix_info_to_inode(struct inode *inode,
153 spin_unlock(&inode->i_lock); 157 spin_unlock(&inode->i_lock);
154} 158}
155 159
160static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon,
161 const char *search_path)
162{
163 int tree_len;
164 int path_len;
165 char *tmp_path;
166
167 if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS))
168 return search_path;
169
170 /* use full path name for working with DFS */
171 tree_len = strnlen(pTcon->treeName, MAX_TREE_SIZE + 1);
172 path_len = strnlen(search_path, MAX_PATHCONF);
173
174 tmp_path = kmalloc(tree_len+path_len+1, GFP_KERNEL);
175 if (tmp_path == NULL)
176 return search_path;
177
178 strncpy(tmp_path, pTcon->treeName, tree_len);
179 strncpy(tmp_path+tree_len, search_path, path_len);
180 tmp_path[tree_len+path_len] = 0;
181 return tmp_path;
182}
183
156int cifs_get_inode_info_unix(struct inode **pinode, 184int cifs_get_inode_info_unix(struct inode **pinode,
157 const unsigned char *search_path, struct super_block *sb, int xid) 185 const unsigned char *search_path, struct super_block *sb, int xid)
158{ 186{
@@ -161,41 +189,28 @@ int cifs_get_inode_info_unix(struct inode **pinode,
161 struct cifsTconInfo *pTcon; 189 struct cifsTconInfo *pTcon;
162 struct inode *inode; 190 struct inode *inode;
163 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 191 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
164 char *tmp_path; 192 const unsigned char *full_path;
193 bool is_dfs_referral = false;
165 194
166 pTcon = cifs_sb->tcon; 195 pTcon = cifs_sb->tcon;
167 cFYI(1, ("Getting info on %s", search_path)); 196 cFYI(1, ("Getting info on %s", search_path));
197
198 full_path = cifs_get_search_path(pTcon, search_path);
199
200try_again_CIFSSMBUnixQPathInfo:
168 /* could have done a find first instead but this returns more info */ 201 /* could have done a find first instead but this returns more info */
169 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, 202 rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData,
170 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 203 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
171 CIFS_MOUNT_MAP_SPECIAL_CHR); 204 CIFS_MOUNT_MAP_SPECIAL_CHR);
172/* dump_mem("\nUnixQPathInfo return data", &findData, 205/* dump_mem("\nUnixQPathInfo return data", &findData,
173 sizeof(findData)); */ 206 sizeof(findData)); */
174 if (rc) { 207 if (rc) {
175 if (rc == -EREMOTE) { 208 if (rc == -EREMOTE && !is_dfs_referral) {
176 tmp_path = 209 is_dfs_referral = true;
177 kmalloc(strnlen(pTcon->treeName, 210 full_path = search_path;
178 MAX_TREE_SIZE + 1) + 211 goto try_again_CIFSSMBUnixQPathInfo;
179 strnlen(search_path, MAX_PATHCONF) + 1,
180 GFP_KERNEL);
181 if (tmp_path == NULL)
182 return -ENOMEM;
183
184 /* have to skip first of the double backslash of
185 UNC name */
186 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
187 strncat(tmp_path, search_path, MAX_PATHCONF);
188 rc = connect_to_dfs_path(xid, pTcon->ses,
189 /* treename + */ tmp_path,
190 cifs_sb->local_nls,
191 cifs_sb->mnt_cifs_flags &
192 CIFS_MOUNT_MAP_SPECIAL_CHR);
193 kfree(tmp_path);
194
195 /* BB fix up inode etc. */
196 } else if (rc) {
197 return rc;
198 } 212 }
213 goto cgiiu_exit;
199 } else { 214 } else {
200 struct cifsInodeInfo *cifsInfo; 215 struct cifsInodeInfo *cifsInfo;
201 __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); 216 __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
@@ -204,8 +219,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
204 /* get new inode */ 219 /* get new inode */
205 if (*pinode == NULL) { 220 if (*pinode == NULL) {
206 *pinode = new_inode(sb); 221 *pinode = new_inode(sb);
207 if (*pinode == NULL) 222 if (*pinode == NULL) {
208 return -ENOMEM; 223 rc = -ENOMEM;
224 goto cgiiu_exit;
225 }
209 /* Is an i_ino of zero legal? */ 226 /* Is an i_ino of zero legal? */
210 /* Are there sanity checks we can use to ensure that 227 /* Are there sanity checks we can use to ensure that
211 the server is really filling in that field? */ 228 the server is really filling in that field? */
@@ -237,8 +254,11 @@ int cifs_get_inode_info_unix(struct inode **pinode,
237 (unsigned long) inode->i_size, 254 (unsigned long) inode->i_size,
238 (unsigned long long)inode->i_blocks)); 255 (unsigned long long)inode->i_blocks));
239 256
240 cifs_set_ops(inode); 257 cifs_set_ops(inode, is_dfs_referral);
241 } 258 }
259cgiiu_exit:
260 if (full_path != search_path)
261 kfree(full_path);
242 return rc; 262 return rc;
243} 263}
244 264
@@ -353,9 +373,10 @@ int cifs_get_inode_info(struct inode **pinode,
353 struct cifsTconInfo *pTcon; 373 struct cifsTconInfo *pTcon;
354 struct inode *inode; 374 struct inode *inode;
355 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 375 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
356 char *tmp_path; 376 const unsigned char *full_path = NULL;
357 char *buf = NULL; 377 char *buf = NULL;
358 int adjustTZ = FALSE; 378 int adjustTZ = FALSE;
379 bool is_dfs_referral = false;
359 380
360 pTcon = cifs_sb->tcon; 381 pTcon = cifs_sb->tcon;
361 cFYI(1, ("Getting info on %s", search_path)); 382 cFYI(1, ("Getting info on %s", search_path));
@@ -373,8 +394,12 @@ int cifs_get_inode_info(struct inode **pinode,
373 if (buf == NULL) 394 if (buf == NULL)
374 return -ENOMEM; 395 return -ENOMEM;
375 pfindData = (FILE_ALL_INFO *)buf; 396 pfindData = (FILE_ALL_INFO *)buf;
397
398 full_path = cifs_get_search_path(pTcon, search_path);
399
400try_again_CIFSSMBQPathInfo:
376 /* could do find first instead but this returns more info */ 401 /* could do find first instead but this returns more info */
377 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, 402 rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData,
378 0 /* not legacy */, 403 0 /* not legacy */,
379 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 404 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
380 CIFS_MOUNT_MAP_SPECIAL_CHR); 405 CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -382,7 +407,7 @@ int cifs_get_inode_info(struct inode **pinode,
382 when server claims no NT SMB support and the above call 407 when server claims no NT SMB support and the above call
383 failed at least once - set flag in tcon or mount */ 408 failed at least once - set flag in tcon or mount */
384 if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { 409 if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
385 rc = SMBQueryInformation(xid, pTcon, search_path, 410 rc = SMBQueryInformation(xid, pTcon, full_path,
386 pfindData, cifs_sb->local_nls, 411 pfindData, cifs_sb->local_nls,
387 cifs_sb->mnt_cifs_flags & 412 cifs_sb->mnt_cifs_flags &
388 CIFS_MOUNT_MAP_SPECIAL_CHR); 413 CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -391,31 +416,12 @@ int cifs_get_inode_info(struct inode **pinode,
391 } 416 }
392 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ 417 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
393 if (rc) { 418 if (rc) {
394 if (rc == -EREMOTE) { 419 if (rc == -EREMOTE && !is_dfs_referral) {
395 tmp_path = 420 is_dfs_referral = true;
396 kmalloc(strnlen 421 full_path = search_path;
397 (pTcon->treeName, 422 goto try_again_CIFSSMBQPathInfo;
398 MAX_TREE_SIZE + 1) +
399 strnlen(search_path, MAX_PATHCONF) + 1,
400 GFP_KERNEL);
401 if (tmp_path == NULL) {
402 kfree(buf);
403 return -ENOMEM;
404 }
405
406 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
407 strncat(tmp_path, search_path, MAX_PATHCONF);
408 rc = connect_to_dfs_path(xid, pTcon->ses,
409 /* treename + */ tmp_path,
410 cifs_sb->local_nls,
411 cifs_sb->mnt_cifs_flags &
412 CIFS_MOUNT_MAP_SPECIAL_CHR);
413 kfree(tmp_path);
414 /* BB fix up inode etc. */
415 } else if (rc) {
416 kfree(buf);
417 return rc;
418 } 423 }
424 goto cgii_exit;
419 } else { 425 } else {
420 struct cifsInodeInfo *cifsInfo; 426 struct cifsInodeInfo *cifsInfo;
421 __u32 attr = le32_to_cpu(pfindData->Attributes); 427 __u32 attr = le32_to_cpu(pfindData->Attributes);
@@ -424,8 +430,8 @@ int cifs_get_inode_info(struct inode **pinode,
424 if (*pinode == NULL) { 430 if (*pinode == NULL) {
425 *pinode = new_inode(sb); 431 *pinode = new_inode(sb);
426 if (*pinode == NULL) { 432 if (*pinode == NULL) {
427 kfree(buf); 433 rc = -ENOMEM;
428 return -ENOMEM; 434 goto cgii_exit;
429 } 435 }
430 /* Is an i_ino of zero legal? Can we use that to check 436 /* Is an i_ino of zero legal? Can we use that to check
431 if the server supports returning inode numbers? Are 437 if the server supports returning inode numbers? Are
@@ -573,8 +579,11 @@ int cifs_get_inode_info(struct inode **pinode,
573 atomic_set(&cifsInfo->inUse, 1); 579 atomic_set(&cifsInfo->inUse, 1);
574 } 580 }
575 581
576 cifs_set_ops(inode); 582 cifs_set_ops(inode, is_dfs_referral);
577 } 583 }
584cgii_exit:
585 if (full_path != search_path)
586 kfree(full_path);
578 kfree(buf); 587 kfree(buf);
579 return rc; 588 return rc;
580} 589}
@@ -804,7 +813,7 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
804 local_size = tmp_inode->i_size; 813 local_size = tmp_inode->i_size;
805 814
806 cifs_unix_info_to_inode(tmp_inode, pData, 1); 815 cifs_unix_info_to_inode(tmp_inode, pData, 1);
807 cifs_set_ops(tmp_inode); 816 cifs_set_ops(tmp_inode, false);
808 817
809 if (!S_ISREG(tmp_inode->i_mode)) 818 if (!S_ISREG(tmp_inode->i_mode))
810 return; 819 return;