aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2011-05-26 23:50:55 -0400
committerSteve French <sfrench@us.ibm.com>2011-05-26 23:50:55 -0400
commitf87d39d951329cd8f462bf9007d334122c0599d0 (patch)
treeba4c4d9dee6958c7d8ee87070a58d80389be2d2f
parent641a58d66d086327042e9d73c6606fd02c8f067c (diff)
[CIFS] Migrate from prefixpath logic
Now we point superblock to a server share root and set a root dentry appropriately. This let us share superblock between mounts like //server/sharename/foo/bar and //server/sharename/foo further. Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r--fs/cifs/cifs_fs_sb.h2
-rw-r--r--fs/cifs/cifsfs.c101
-rw-r--r--fs/cifs/cifsglob.h75
-rw-r--r--fs/cifs/cifsproto.h5
-rw-r--r--fs/cifs/connect.c128
-rw-r--r--fs/cifs/dir.c7
-rw-r--r--fs/cifs/inode.c19
7 files changed, 189 insertions, 148 deletions
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index a9d5692e0c20..c96b44b4e262 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -56,8 +56,6 @@ struct cifs_sb_info {
56 mode_t mnt_file_mode; 56 mode_t mnt_file_mode;
57 mode_t mnt_dir_mode; 57 mode_t mnt_dir_mode;
58 unsigned int mnt_cifs_flags; 58 unsigned int mnt_cifs_flags;
59 int prepathlen;
60 char *prepath; /* relative path under the share to mount to */
61 char *mountdata; /* options received at mount time or via DFS refs */ 59 char *mountdata; /* options received at mount time or via DFS refs */
62 struct backing_dev_info bdi; 60 struct backing_dev_info bdi;
63 struct delayed_work prune_tlinks; 61 struct delayed_work prune_tlinks;
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 1d2a93c60e75..46fdd55cf427 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -415,8 +415,6 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
415 seq_printf(s, ",nocase"); 415 seq_printf(s, ",nocase");
416 if (tcon->retry) 416 if (tcon->retry)
417 seq_printf(s, ",hard"); 417 seq_printf(s, ",hard");
418 if (cifs_sb->prepath)
419 seq_printf(s, ",prepath=%s", cifs_sb->prepath);
420 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) 418 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
421 seq_printf(s, ",posixpaths"); 419 seq_printf(s, ",posixpaths");
422 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) 420 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
@@ -530,6 +528,100 @@ static const struct super_operations cifs_super_ops = {
530#endif 528#endif
531}; 529};
532 530
531/*
532 * Get root dentry from superblock according to prefix path mount option.
533 * Return dentry with refcount + 1 on success and NULL otherwise.
534 */
535static struct dentry *
536cifs_get_root(struct smb_vol *vol, struct super_block *sb)
537{
538 int xid, rc;
539 struct inode *inode;
540 struct qstr name;
541 struct dentry *dparent = NULL, *dchild = NULL, *alias;
542 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
543 unsigned int i, full_len, len;
544 char *full_path = NULL, *pstart;
545 char sep;
546
547 full_path = cifs_build_path_to_root(vol, cifs_sb,
548 cifs_sb_master_tcon(cifs_sb));
549 if (full_path == NULL)
550 return NULL;
551
552 cFYI(1, "Get root dentry for %s", full_path);
553
554 xid = GetXid();
555 sep = CIFS_DIR_SEP(cifs_sb);
556 dparent = dget(sb->s_root);
557 full_len = strlen(full_path);
558 full_path[full_len] = sep;
559 pstart = full_path + 1;
560
561 for (i = 1, len = 0; i <= full_len; i++) {
562 if (full_path[i] != sep || !len) {
563 len++;
564 continue;
565 }
566
567 full_path[i] = 0;
568 cFYI(1, "get dentry for %s", pstart);
569
570 name.name = pstart;
571 name.len = len;
572 name.hash = full_name_hash(pstart, len);
573 dchild = d_lookup(dparent, &name);
574 if (dchild == NULL) {
575 cFYI(1, "not exists");
576 dchild = d_alloc(dparent, &name);
577 if (dchild == NULL) {
578 dput(dparent);
579 dparent = NULL;
580 goto out;
581 }
582 }
583
584 cFYI(1, "get inode");
585 if (dchild->d_inode == NULL) {
586 cFYI(1, "not exists");
587 inode = NULL;
588 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
589 rc = cifs_get_inode_info_unix(&inode, full_path,
590 sb, xid);
591 else
592 rc = cifs_get_inode_info(&inode, full_path,
593 NULL, sb, xid, NULL);
594 if (rc) {
595 dput(dchild);
596 dput(dparent);
597 dparent = NULL;
598 goto out;
599 }
600 alias = d_materialise_unique(dchild, inode);
601 if (alias != NULL) {
602 dput(dchild);
603 if (IS_ERR(alias)) {
604 dput(dparent);
605 dparent = NULL;
606 goto out;
607 }
608 dchild = alias;
609 }
610 }
611 cFYI(1, "parent %p, child %p", dparent, dchild);
612
613 dput(dparent);
614 dparent = dchild;
615 len = 0;
616 pstart = full_path + i + 1;
617 full_path[i] = sep;
618 }
619out:
620 _FreeXid(xid);
621 kfree(full_path);
622 return dparent;
623}
624
533static struct dentry * 625static struct dentry *
534cifs_do_mount(struct file_system_type *fs_type, 626cifs_do_mount(struct file_system_type *fs_type,
535 int flags, const char *dev_name, void *data) 627 int flags, const char *dev_name, void *data)
@@ -585,7 +677,10 @@ cifs_do_mount(struct file_system_type *fs_type,
585 677
586 sb->s_flags |= MS_ACTIVE; 678 sb->s_flags |= MS_ACTIVE;
587 679
588 root = dget(sb->s_root); 680 root = cifs_get_root(volume_info, sb);
681 if (root == NULL)
682 goto out_super;
683 cFYI(1, "dentry root is: %p", root);
589 goto out; 684 goto out;
590 685
591out_super: 686out_super:
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 30699d9378e9..68ec457f8476 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -155,6 +155,61 @@ struct cifs_cred {
155 ***************************************************************** 155 *****************************************************************
156 */ 156 */
157 157
158struct smb_vol {
159 char *username;
160 char *password;
161 char *domainname;
162 char *UNC;
163 char *UNCip;
164 char *iocharset; /* local code page for mapping to and from Unicode */
165 char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
166 char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
167 uid_t cred_uid;
168 uid_t linux_uid;
169 gid_t linux_gid;
170 mode_t file_mode;
171 mode_t dir_mode;
172 unsigned secFlg;
173 bool retry:1;
174 bool intr:1;
175 bool setuids:1;
176 bool override_uid:1;
177 bool override_gid:1;
178 bool dynperm:1;
179 bool noperm:1;
180 bool no_psx_acl:1; /* set if posix acl support should be disabled */
181 bool cifs_acl:1;
182 bool no_xattr:1; /* set if xattr (EA) support should be disabled*/
183 bool server_ino:1; /* use inode numbers from server ie UniqueId */
184 bool direct_io:1;
185 bool strict_io:1; /* strict cache behavior */
186 bool remap:1; /* set to remap seven reserved chars in filenames */
187 bool posix_paths:1; /* unset to not ask for posix pathnames. */
188 bool no_linux_ext:1;
189 bool sfu_emul:1;
190 bool nullauth:1; /* attempt to authenticate with null user */
191 bool nocase:1; /* request case insensitive filenames */
192 bool nobrl:1; /* disable sending byte range locks to srv */
193 bool mand_lock:1; /* send mandatory not posix byte range lock reqs */
194 bool seal:1; /* request transport encryption on share */
195 bool nodfs:1; /* Do not request DFS, even if available */
196 bool local_lease:1; /* check leases only on local system, not remote */
197 bool noblocksnd:1;
198 bool noautotune:1;
199 bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
200 bool fsc:1; /* enable fscache */
201 bool mfsymlinks:1; /* use Minshall+French Symlinks */
202 bool multiuser:1;
203 unsigned int rsize;
204 unsigned int wsize;
205 bool sockopt_tcp_nodelay:1;
206 unsigned short int port;
207 unsigned long actimeo; /* attribute cache timeout (jiffies) */
208 char *prepath;
209 struct sockaddr_storage srcaddr; /* allow binding to a local IP */
210 struct nls_table *local_nls;
211};
212
158struct TCP_Server_Info { 213struct TCP_Server_Info {
159 struct list_head tcp_ses_list; 214 struct list_head tcp_ses_list;
160 struct list_head smb_ses_list; 215 struct list_head smb_ses_list;
@@ -517,6 +572,26 @@ static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
517 return '\\'; 572 return '\\';
518} 573}
519 574
575static inline void
576convert_delimiter(char *path, char delim)
577{
578 int i;
579 char old_delim;
580
581 if (path == NULL)
582 return;
583
584 if (delim == '/')
585 old_delim = '\\';
586 else
587 old_delim = '/';
588
589 for (i = 0; path[i] != '\0'; i++) {
590 if (path[i] == old_delim)
591 path[i] = delim;
592 }
593}
594
520#ifdef CONFIG_CIFS_STATS 595#ifdef CONFIG_CIFS_STATS
521#define cifs_stats_inc atomic_inc 596#define cifs_stats_inc atomic_inc
522 597
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index eb3b58d9668f..e41f6071cdd2 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -57,8 +57,9 @@ extern int init_cifs_idmap(void);
57extern void exit_cifs_idmap(void); 57extern void exit_cifs_idmap(void);
58extern void cifs_destroy_idmaptrees(void); 58extern void cifs_destroy_idmaptrees(void);
59extern char *build_path_from_dentry(struct dentry *); 59extern char *build_path_from_dentry(struct dentry *);
60extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb, 60extern char *cifs_build_path_to_root(struct smb_vol *vol,
61 struct cifsTconInfo *tcon); 61 struct cifs_sb_info *cifs_sb,
62 struct cifsTconInfo *tcon);
62extern char *build_wildcard_path_from_dentry(struct dentry *direntry); 63extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
63extern char *cifs_compose_mount_options(const char *sb_mountdata, 64extern char *cifs_compose_mount_options(const char *sb_mountdata,
64 const char *fullpath, const struct dfs_info3_param *ref, 65 const char *fullpath, const struct dfs_info3_param *ref,
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 581654fb174d..495688115988 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -57,61 +57,6 @@
57 57
58extern mempool_t *cifs_req_poolp; 58extern mempool_t *cifs_req_poolp;
59 59
60struct smb_vol {
61 char *username;
62 char *password;
63 char *domainname;
64 char *UNC;
65 char *UNCip;
66 char *iocharset; /* local code page for mapping to and from Unicode */
67 char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
68 char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
69 uid_t cred_uid;
70 uid_t linux_uid;
71 gid_t linux_gid;
72 mode_t file_mode;
73 mode_t dir_mode;
74 unsigned secFlg;
75 bool retry:1;
76 bool intr:1;
77 bool setuids:1;
78 bool override_uid:1;
79 bool override_gid:1;
80 bool dynperm:1;
81 bool noperm:1;
82 bool no_psx_acl:1; /* set if posix acl support should be disabled */
83 bool cifs_acl:1;
84 bool no_xattr:1; /* set if xattr (EA) support should be disabled*/
85 bool server_ino:1; /* use inode numbers from server ie UniqueId */
86 bool direct_io:1;
87 bool strict_io:1; /* strict cache behavior */
88 bool remap:1; /* set to remap seven reserved chars in filenames */
89 bool posix_paths:1; /* unset to not ask for posix pathnames. */
90 bool no_linux_ext:1;
91 bool sfu_emul:1;
92 bool nullauth:1; /* attempt to authenticate with null user */
93 bool nocase:1; /* request case insensitive filenames */
94 bool nobrl:1; /* disable sending byte range locks to srv */
95 bool mand_lock:1; /* send mandatory not posix byte range lock reqs */
96 bool seal:1; /* request transport encryption on share */
97 bool nodfs:1; /* Do not request DFS, even if available */
98 bool local_lease:1; /* check leases only on local system, not remote */
99 bool noblocksnd:1;
100 bool noautotune:1;
101 bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
102 bool fsc:1; /* enable fscache */
103 bool mfsymlinks:1; /* use Minshall+French Symlinks */
104 bool multiuser:1;
105 unsigned int rsize;
106 unsigned int wsize;
107 bool sockopt_tcp_nodelay:1;
108 unsigned short int port;
109 unsigned long actimeo; /* attribute cache timeout (jiffies) */
110 char *prepath;
111 struct sockaddr_storage srcaddr; /* allow binding to a local IP */
112 struct nls_table *local_nls;
113};
114
115/* FIXME: should these be tunable? */ 60/* FIXME: should these be tunable? */
116#define TLINK_ERROR_EXPIRE (1 * HZ) 61#define TLINK_ERROR_EXPIRE (1 * HZ)
117#define TLINK_IDLE_EXPIRE (600 * HZ) 62#define TLINK_IDLE_EXPIRE (600 * HZ)
@@ -2569,12 +2514,6 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
2569 CIFS_MOUNT_POSIX_PATHS; 2514 CIFS_MOUNT_POSIX_PATHS;
2570 } 2515 }
2571 2516
2572 /* We might be setting the path sep back to a different
2573 form if we are reconnecting and the server switched its
2574 posix path capability for this share */
2575 if (sb && (CIFS_SB(sb)->prepathlen > 0))
2576 CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));
2577
2578 if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) { 2517 if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) {
2579 if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) { 2518 if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
2580 CIFS_SB(sb)->rsize = 127 * 1024; 2519 CIFS_SB(sb)->rsize = 127 * 1024;
@@ -2619,26 +2558,6 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
2619 } 2558 }
2620} 2559}
2621 2560
2622static void
2623convert_delimiter(char *path, char delim)
2624{
2625 int i;
2626 char old_delim;
2627
2628 if (path == NULL)
2629 return;
2630
2631 if (delim == '/')
2632 old_delim = '\\';
2633 else
2634 old_delim = '/';
2635
2636 for (i = 0; path[i] != '\0'; i++) {
2637 if (path[i] == old_delim)
2638 path[i] = delim;
2639 }
2640}
2641
2642void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, 2561void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
2643 struct cifs_sb_info *cifs_sb) 2562 struct cifs_sb_info *cifs_sb)
2644{ 2563{
@@ -2659,18 +2578,6 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
2659 /* Windows ME may prefer this */ 2578 /* Windows ME may prefer this */
2660 cFYI(1, "readsize set to minimum: 2048"); 2579 cFYI(1, "readsize set to minimum: 2048");
2661 } 2580 }
2662 /* calculate prepath */
2663 cifs_sb->prepath = pvolume_info->prepath;
2664 if (cifs_sb->prepath) {
2665 cifs_sb->prepathlen = strlen(cifs_sb->prepath);
2666 /* we can not convert the / to \ in the path
2667 separators in the prefixpath yet because we do not
2668 know (until reset_cifs_unix_caps is called later)
2669 whether POSIX PATH CAP is available. We normalize
2670 the / to \ after reset_cifs_unix_caps is called */
2671 pvolume_info->prepath = NULL;
2672 } else
2673 cifs_sb->prepathlen = 0;
2674 cifs_sb->mnt_uid = pvolume_info->linux_uid; 2581 cifs_sb->mnt_uid = pvolume_info->linux_uid;
2675 cifs_sb->mnt_gid = pvolume_info->linux_gid; 2582 cifs_sb->mnt_gid = pvolume_info->linux_gid;
2676 cifs_sb->mnt_file_mode = pvolume_info->file_mode; 2583 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
@@ -2834,24 +2741,13 @@ build_unc_path_to_root(const struct smb_vol *volume_info,
2834 char *full_path; 2741 char *full_path;
2835 2742
2836 int unc_len = strnlen(volume_info->UNC, MAX_TREE_SIZE + 1); 2743 int unc_len = strnlen(volume_info->UNC, MAX_TREE_SIZE + 1);
2837 full_path = kmalloc(unc_len + cifs_sb->prepathlen + 1, GFP_KERNEL); 2744 full_path = kmalloc(unc_len + 1, GFP_KERNEL);
2838 if (full_path == NULL) 2745 if (full_path == NULL)
2839 return ERR_PTR(-ENOMEM); 2746 return ERR_PTR(-ENOMEM);
2840 2747
2841 strncpy(full_path, volume_info->UNC, unc_len); 2748 strncpy(full_path, volume_info->UNC, unc_len);
2842 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) { 2749 full_path[unc_len] = 0; /* add trailing null */
2843 int i; 2750 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
2844 for (i = 0; i < unc_len; i++) {
2845 if (full_path[i] == '\\')
2846 full_path[i] = '/';
2847 }
2848 }
2849
2850 if (cifs_sb->prepathlen)
2851 strncpy(full_path + unc_len, cifs_sb->prepath,
2852 cifs_sb->prepathlen);
2853
2854 full_path[unc_len + cifs_sb->prepathlen] = 0; /* add trailing null */
2855 return full_path; 2751 return full_path;
2856} 2752}
2857 2753
@@ -3049,10 +2945,6 @@ try_mount_again:
3049 CIFSSMBQFSAttributeInfo(xid, tcon); 2945 CIFSSMBQFSAttributeInfo(xid, tcon);
3050 } 2946 }
3051 2947
3052 /* convert forward to back slashes in prepath here if needed */
3053 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
3054 convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
3055
3056 if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) { 2948 if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
3057 cifs_sb->rsize = 1024 * 127; 2949 cifs_sb->rsize = 1024 * 127;
3058 cFYI(DBG2, "no very large read support, rsize now 127K"); 2950 cFYI(DBG2, "no very large read support, rsize now 127K");
@@ -3082,10 +2974,10 @@ remote_path_check:
3082 } 2974 }
3083#endif 2975#endif
3084 2976
3085 /* check if a whole path (including prepath) is not remote */ 2977 /* check if a whole path is not remote */
3086 if (!rc && tcon) { 2978 if (!rc && tcon) {
3087 /* build_path_to_root works only when we have a valid tcon */ 2979 /* build_path_to_root works only when we have a valid tcon */
3088 full_path = cifs_build_path_to_root(cifs_sb, tcon); 2980 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
3089 if (full_path == NULL) { 2981 if (full_path == NULL) {
3090 rc = -ENOMEM; 2982 rc = -ENOMEM;
3091 goto mount_fail_check; 2983 goto mount_fail_check;
@@ -3111,10 +3003,6 @@ remote_path_check:
3111 rc = -ELOOP; 3003 rc = -ELOOP;
3112 goto mount_fail_check; 3004 goto mount_fail_check;
3113 } 3005 }
3114 /* convert forward to back slashes in prepath here if needed */
3115 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
3116 convert_delimiter(cifs_sb->prepath,
3117 CIFS_DIR_SEP(cifs_sb));
3118 3006
3119 rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb, 3007 rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb,
3120 true); 3008 true);
@@ -3340,7 +3228,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3340 struct rb_root *root = &cifs_sb->tlink_tree; 3228 struct rb_root *root = &cifs_sb->tlink_tree;
3341 struct rb_node *node; 3229 struct rb_node *node;
3342 struct tcon_link *tlink; 3230 struct tcon_link *tlink;
3343 char *tmp;
3344 3231
3345 cancel_delayed_work_sync(&cifs_sb->prune_tlinks); 3232 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
3346 3233
@@ -3357,11 +3244,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3357 } 3244 }
3358 spin_unlock(&cifs_sb->tlink_tree_lock); 3245 spin_unlock(&cifs_sb->tlink_tree_lock);
3359 3246
3360 tmp = cifs_sb->prepath;
3361 cifs_sb->prepathlen = 0;
3362 cifs_sb->prepath = NULL;
3363 kfree(tmp);
3364
3365 return 0; 3247 return 0;
3366} 3248}
3367 3249
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 0521492f5b3b..aa0669a82922 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -50,7 +50,6 @@ build_path_from_dentry(struct dentry *direntry)
50{ 50{
51 struct dentry *temp; 51 struct dentry *temp;
52 int namelen; 52 int namelen;
53 int pplen;
54 int dfsplen; 53 int dfsplen;
55 char *full_path; 54 char *full_path;
56 char dirsep; 55 char dirsep;
@@ -63,13 +62,12 @@ build_path_from_dentry(struct dentry *direntry)
63 when the server crashed */ 62 when the server crashed */
64 63
65 dirsep = CIFS_DIR_SEP(cifs_sb); 64 dirsep = CIFS_DIR_SEP(cifs_sb);
66 pplen = cifs_sb->prepathlen;
67 if (tcon->Flags & SMB_SHARE_IS_IN_DFS) 65 if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
68 dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1); 66 dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
69 else 67 else
70 dfsplen = 0; 68 dfsplen = 0;
71cifs_bp_rename_retry: 69cifs_bp_rename_retry:
72 namelen = pplen + dfsplen; 70 namelen = dfsplen;
73 for (temp = direntry; !IS_ROOT(temp);) { 71 for (temp = direntry; !IS_ROOT(temp);) {
74 namelen += (1 + temp->d_name.len); 72 namelen += (1 + temp->d_name.len);
75 temp = temp->d_parent; 73 temp = temp->d_parent;
@@ -100,7 +98,7 @@ cifs_bp_rename_retry:
100 return NULL; 98 return NULL;
101 } 99 }
102 } 100 }
103 if (namelen != pplen + dfsplen) { 101 if (namelen != dfsplen) {
104 cERROR(1, "did not end path lookup where expected namelen is %d", 102 cERROR(1, "did not end path lookup where expected namelen is %d",
105 namelen); 103 namelen);
106 /* presumably this is only possible if racing with a rename 104 /* presumably this is only possible if racing with a rename
@@ -126,7 +124,6 @@ cifs_bp_rename_retry:
126 } 124 }
127 } 125 }
128 } 126 }
129 strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen);
130 return full_path; 127 return full_path;
131} 128}
132 129
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 5e278d37912b..53ea6250a51d 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -735,10 +735,10 @@ static const struct inode_operations cifs_ipc_inode_ops = {
735 .lookup = cifs_lookup, 735 .lookup = cifs_lookup,
736}; 736};
737 737
738char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb, 738char *cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
739 struct cifsTconInfo *tcon) 739 struct cifsTconInfo *tcon)
740{ 740{
741 int pplen = cifs_sb->prepathlen; 741 int pplen = vol->prepath ? strlen(vol->prepath) : 0;
742 int dfsplen; 742 int dfsplen;
743 char *full_path = NULL; 743 char *full_path = NULL;
744 744
@@ -772,7 +772,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
772 } 772 }
773 } 773 }
774 } 774 }
775 strncpy(full_path + dfsplen, cifs_sb->prepath, pplen); 775 strncpy(full_path + dfsplen, vol->prepath, pplen);
776 full_path[dfsplen + pplen] = 0; /* add trailing null */ 776 full_path[dfsplen + pplen] = 0; /* add trailing null */
777 return full_path; 777 return full_path;
778} 778}
@@ -884,19 +884,13 @@ struct inode *cifs_root_iget(struct super_block *sb)
884 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 884 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
885 struct inode *inode = NULL; 885 struct inode *inode = NULL;
886 long rc; 886 long rc;
887 char *full_path;
888 struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); 887 struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
889 888
890 full_path = cifs_build_path_to_root(cifs_sb, tcon);
891 if (full_path == NULL)
892 return ERR_PTR(-ENOMEM);
893
894 xid = GetXid(); 889 xid = GetXid();
895 if (tcon->unix_ext) 890 if (tcon->unix_ext)
896 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); 891 rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
897 else 892 else
898 rc = cifs_get_inode_info(&inode, full_path, NULL, sb, 893 rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
899 xid, NULL);
900 894
901 if (!inode) { 895 if (!inode) {
902 inode = ERR_PTR(rc); 896 inode = ERR_PTR(rc);
@@ -922,7 +916,6 @@ struct inode *cifs_root_iget(struct super_block *sb)
922 } 916 }
923 917
924out: 918out:
925 kfree(full_path);
926 /* can not call macro FreeXid here since in a void func 919 /* can not call macro FreeXid here since in a void func
927 * TODO: This is no longer true 920 * TODO: This is no longer true
928 */ 921 */