diff options
author | Steve French <sfrench@us.ibm.com> | 2011-05-26 23:50:55 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2011-05-26 23:50:55 -0400 |
commit | f87d39d951329cd8f462bf9007d334122c0599d0 (patch) | |
tree | ba4c4d9dee6958c7d8ee87070a58d80389be2d2f | |
parent | 641a58d66d086327042e9d73c6606fd02c8f067c (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.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 101 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 75 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 5 | ||||
-rw-r--r-- | fs/cifs/connect.c | 128 | ||||
-rw-r--r-- | fs/cifs/dir.c | 7 | ||||
-rw-r--r-- | fs/cifs/inode.c | 19 |
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 | */ | ||
535 | static struct dentry * | ||
536 | cifs_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 | } | ||
619 | out: | ||
620 | _FreeXid(xid); | ||
621 | kfree(full_path); | ||
622 | return dparent; | ||
623 | } | ||
624 | |||
533 | static struct dentry * | 625 | static struct dentry * |
534 | cifs_do_mount(struct file_system_type *fs_type, | 626 | cifs_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 | ||
591 | out_super: | 686 | out_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 | ||
158 | struct 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 | |||
158 | struct TCP_Server_Info { | 213 | struct 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 | ||
575 | static inline void | ||
576 | convert_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); | |||
57 | extern void exit_cifs_idmap(void); | 57 | extern void exit_cifs_idmap(void); |
58 | extern void cifs_destroy_idmaptrees(void); | 58 | extern void cifs_destroy_idmaptrees(void); |
59 | extern char *build_path_from_dentry(struct dentry *); | 59 | extern char *build_path_from_dentry(struct dentry *); |
60 | extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb, | 60 | extern 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); | ||
62 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); | 63 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); |
63 | extern char *cifs_compose_mount_options(const char *sb_mountdata, | 64 | extern 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 | ||
58 | extern mempool_t *cifs_req_poolp; | 58 | extern mempool_t *cifs_req_poolp; |
59 | 59 | ||
60 | struct 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 | ||
2622 | static void | ||
2623 | convert_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 | |||
2642 | void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | 2561 | void 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; |
71 | cifs_bp_rename_retry: | 69 | cifs_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 | ||
738 | char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb, | 738 | char *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 | ||
924 | out: | 918 | out: |
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 | */ |