diff options
| -rw-r--r-- | fs/cifs/cifsfs.c | 19 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 19 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 102 |
3 files changed, 139 insertions, 1 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 46fdd55cf427..360fe2ec2a19 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -630,6 +630,7 @@ cifs_do_mount(struct file_system_type *fs_type, | |||
| 630 | struct super_block *sb; | 630 | struct super_block *sb; |
| 631 | struct cifs_sb_info *cifs_sb; | 631 | struct cifs_sb_info *cifs_sb; |
| 632 | struct smb_vol *volume_info; | 632 | struct smb_vol *volume_info; |
| 633 | struct cifs_mnt_data mnt_data; | ||
| 633 | struct dentry *root; | 634 | struct dentry *root; |
| 634 | 635 | ||
| 635 | cFYI(1, "Devname: %s flags: %d ", dev_name, flags); | 636 | cFYI(1, "Devname: %s flags: %d ", dev_name, flags); |
| @@ -646,12 +647,21 @@ cifs_do_mount(struct file_system_type *fs_type, | |||
| 646 | 647 | ||
| 647 | cifs_setup_cifs_sb(volume_info, cifs_sb); | 648 | cifs_setup_cifs_sb(volume_info, cifs_sb); |
| 648 | 649 | ||
| 649 | sb = sget(fs_type, NULL, set_anon_super, NULL); | 650 | mnt_data.vol = volume_info; |
| 651 | mnt_data.cifs_sb = cifs_sb; | ||
| 652 | mnt_data.flags = flags; | ||
| 653 | |||
| 654 | sb = sget(fs_type, cifs_match_super, set_anon_super, &mnt_data); | ||
| 650 | if (IS_ERR(sb)) { | 655 | if (IS_ERR(sb)) { |
| 651 | root = ERR_CAST(sb); | 656 | root = ERR_CAST(sb); |
| 652 | goto out_cifs_sb; | 657 | goto out_cifs_sb; |
| 653 | } | 658 | } |
| 654 | 659 | ||
| 660 | if (sb->s_fs_info) { | ||
| 661 | cFYI(1, "Use existing superblock"); | ||
| 662 | goto out_shared; | ||
| 663 | } | ||
| 664 | |||
| 655 | /* | 665 | /* |
| 656 | * Copy mount params for use in submounts. Better to do | 666 | * Copy mount params for use in submounts. Better to do |
| 657 | * the copy here and deal with the error before cleanup gets | 667 | * the copy here and deal with the error before cleanup gets |
| @@ -680,9 +690,16 @@ cifs_do_mount(struct file_system_type *fs_type, | |||
| 680 | root = cifs_get_root(volume_info, sb); | 690 | root = cifs_get_root(volume_info, sb); |
| 681 | if (root == NULL) | 691 | if (root == NULL) |
| 682 | goto out_super; | 692 | goto out_super; |
| 693 | |||
| 683 | cFYI(1, "dentry root is: %p", root); | 694 | cFYI(1, "dentry root is: %p", root); |
| 684 | goto out; | 695 | goto out; |
| 685 | 696 | ||
| 697 | out_shared: | ||
| 698 | root = cifs_get_root(volume_info, sb); | ||
| 699 | if (root) | ||
| 700 | cFYI(1, "dentry root is: %p", root); | ||
| 701 | goto out; | ||
| 702 | |||
| 686 | out_super: | 703 | out_super: |
| 687 | kfree(cifs_sb->mountdata); | 704 | kfree(cifs_sb->mountdata); |
| 688 | deactivate_locked_super(sb); | 705 | deactivate_locked_super(sb); |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 68ec457f8476..ca0c3789206e 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -210,6 +210,25 @@ struct smb_vol { | |||
| 210 | struct nls_table *local_nls; | 210 | struct nls_table *local_nls; |
| 211 | }; | 211 | }; |
| 212 | 212 | ||
| 213 | #define CIFS_MOUNT_MASK (CIFS_MOUNT_NO_PERM | CIFS_MOUNT_SET_UID | \ | ||
| 214 | CIFS_MOUNT_SERVER_INUM | CIFS_MOUNT_DIRECT_IO | \ | ||
| 215 | CIFS_MOUNT_NO_XATTR | CIFS_MOUNT_MAP_SPECIAL_CHR | \ | ||
| 216 | CIFS_MOUNT_UNX_EMUL | CIFS_MOUNT_NO_BRL | \ | ||
| 217 | CIFS_MOUNT_CIFS_ACL | CIFS_MOUNT_OVERR_UID | \ | ||
| 218 | CIFS_MOUNT_OVERR_GID | CIFS_MOUNT_DYNPERM | \ | ||
| 219 | CIFS_MOUNT_NOPOSIXBRL | CIFS_MOUNT_NOSSYNC | \ | ||
| 220 | CIFS_MOUNT_FSCACHE | CIFS_MOUNT_MF_SYMLINKS | \ | ||
| 221 | CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO) | ||
| 222 | |||
| 223 | #define CIFS_MS_MASK (MS_RDONLY | MS_MANDLOCK | MS_NOEXEC | MS_NOSUID | \ | ||
| 224 | MS_NODEV | MS_SYNCHRONOUS) | ||
| 225 | |||
| 226 | struct cifs_mnt_data { | ||
| 227 | struct cifs_sb_info *cifs_sb; | ||
| 228 | struct smb_vol *vol; | ||
| 229 | int flags; | ||
| 230 | }; | ||
| 231 | |||
| 213 | struct TCP_Server_Info { | 232 | struct TCP_Server_Info { |
| 214 | struct list_head tcp_ses_list; | 233 | struct list_head tcp_ses_list; |
| 215 | struct list_head smb_ses_list; | 234 | struct list_head smb_ses_list; |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 495688115988..261ca81d5e49 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -2146,6 +2146,100 @@ cifs_put_tlink(struct tcon_link *tlink) | |||
| 2146 | return; | 2146 | return; |
| 2147 | } | 2147 | } |
| 2148 | 2148 | ||
| 2149 | static inline struct tcon_link * | ||
| 2150 | cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb); | ||
| 2151 | |||
| 2152 | static int | ||
| 2153 | compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data) | ||
| 2154 | { | ||
| 2155 | struct cifs_sb_info *old = CIFS_SB(sb); | ||
| 2156 | struct cifs_sb_info *new = mnt_data->cifs_sb; | ||
| 2157 | |||
| 2158 | if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK)) | ||
| 2159 | return 0; | ||
| 2160 | |||
| 2161 | if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) != | ||
| 2162 | (new->mnt_cifs_flags & CIFS_MOUNT_MASK)) | ||
| 2163 | return 0; | ||
| 2164 | |||
| 2165 | if (old->rsize != new->rsize) | ||
| 2166 | return 0; | ||
| 2167 | |||
| 2168 | /* | ||
| 2169 | * We want to share sb only if we don't specify wsize or specified wsize | ||
| 2170 | * is greater or equal than existing one. | ||
| 2171 | */ | ||
| 2172 | if (new->wsize && new->wsize < old->wsize) | ||
| 2173 | return 0; | ||
| 2174 | |||
| 2175 | if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid) | ||
| 2176 | return 0; | ||
| 2177 | |||
| 2178 | if (old->mnt_file_mode != new->mnt_file_mode || | ||
| 2179 | old->mnt_dir_mode != new->mnt_dir_mode) | ||
| 2180 | return 0; | ||
| 2181 | |||
| 2182 | if (strcmp(old->local_nls->charset, new->local_nls->charset)) | ||
| 2183 | return 0; | ||
| 2184 | |||
| 2185 | if (old->actimeo != new->actimeo) | ||
| 2186 | return 0; | ||
| 2187 | |||
| 2188 | return 1; | ||
| 2189 | } | ||
| 2190 | |||
| 2191 | int | ||
| 2192 | cifs_match_super(struct super_block *sb, void *data) | ||
| 2193 | { | ||
| 2194 | struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data; | ||
| 2195 | struct smb_vol *volume_info; | ||
| 2196 | struct cifs_sb_info *cifs_sb; | ||
| 2197 | struct TCP_Server_Info *tcp_srv; | ||
| 2198 | struct cifsSesInfo *ses; | ||
| 2199 | struct cifsTconInfo *tcon; | ||
| 2200 | struct tcon_link *tlink; | ||
| 2201 | struct sockaddr_storage addr; | ||
| 2202 | int rc = 0; | ||
| 2203 | |||
| 2204 | memset(&addr, 0, sizeof(struct sockaddr_storage)); | ||
| 2205 | |||
| 2206 | spin_lock(&cifs_tcp_ses_lock); | ||
| 2207 | cifs_sb = CIFS_SB(sb); | ||
| 2208 | tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb)); | ||
| 2209 | if (IS_ERR(tlink)) { | ||
| 2210 | spin_unlock(&cifs_tcp_ses_lock); | ||
| 2211 | return rc; | ||
| 2212 | } | ||
| 2213 | tcon = tlink_tcon(tlink); | ||
| 2214 | ses = tcon->ses; | ||
| 2215 | tcp_srv = ses->server; | ||
| 2216 | |||
| 2217 | volume_info = mnt_data->vol; | ||
| 2218 | |||
| 2219 | if (!volume_info->UNCip || !volume_info->UNC) | ||
| 2220 | goto out; | ||
| 2221 | |||
| 2222 | rc = cifs_fill_sockaddr((struct sockaddr *)&addr, | ||
| 2223 | volume_info->UNCip, | ||
| 2224 | strlen(volume_info->UNCip), | ||
| 2225 | volume_info->port); | ||
| 2226 | if (!rc) | ||
| 2227 | goto out; | ||
| 2228 | |||
| 2229 | if (!match_server(tcp_srv, (struct sockaddr *)&addr, volume_info) || | ||
| 2230 | !match_session(ses, volume_info) || | ||
| 2231 | !match_tcon(tcon, volume_info->UNC)) { | ||
| 2232 | rc = 0; | ||
| 2233 | goto out; | ||
| 2234 | } | ||
| 2235 | |||
| 2236 | rc = compare_mount_options(sb, mnt_data); | ||
| 2237 | out: | ||
| 2238 | cifs_put_tlink(tlink); | ||
| 2239 | spin_unlock(&cifs_tcp_ses_lock); | ||
| 2240 | return rc; | ||
| 2241 | } | ||
| 2242 | |||
| 2149 | int | 2243 | int |
| 2150 | get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, | 2244 | get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, |
| 2151 | const struct nls_table *nls_codepage, unsigned int *pnum_referrals, | 2245 | const struct nls_table *nls_codepage, unsigned int *pnum_referrals, |
| @@ -2578,6 +2672,14 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | |||
| 2578 | /* Windows ME may prefer this */ | 2672 | /* Windows ME may prefer this */ |
| 2579 | cFYI(1, "readsize set to minimum: 2048"); | 2673 | cFYI(1, "readsize set to minimum: 2048"); |
| 2580 | } | 2674 | } |
| 2675 | |||
| 2676 | /* | ||
| 2677 | * Temporarily set wsize for matching superblock. If we end up using | ||
| 2678 | * new sb then cifs_negotiate_wsize will later negotiate it downward | ||
| 2679 | * if needed. | ||
| 2680 | */ | ||
| 2681 | cifs_sb->wsize = pvolume_info->wsize; | ||
| 2682 | |||
| 2581 | cifs_sb->mnt_uid = pvolume_info->linux_uid; | 2683 | cifs_sb->mnt_uid = pvolume_info->linux_uid; |
| 2582 | cifs_sb->mnt_gid = pvolume_info->linux_gid; | 2684 | cifs_sb->mnt_gid = pvolume_info->linux_gid; |
| 2583 | cifs_sb->mnt_file_mode = pvolume_info->file_mode; | 2685 | cifs_sb->mnt_file_mode = pvolume_info->file_mode; |
