summaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorPavel Shilovsky <piastry@etersoft.ru>2011-05-26 15:35:47 -0400
committerSteve French <sfrench@us.ibm.com>2011-05-26 23:53:23 -0400
commit25c7f41e9234f60af30e086278f1de7974f8816f (patch)
tree41cb4da532da30418da2d33e5376ddbf9f65958a /fs/cifs/connect.c
parentf87d39d951329cd8f462bf9007d334122c0599d0 (diff)
CIFS: Migrate to shared superblock model
Add cifs_match_super to use in sget to share superblock between mounts that have the same //server/sharename, credentials and mount options. It helps us to improve performance on work with future SMB2.1 leases. Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c102
1 files changed, 102 insertions, 0 deletions
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
2149static inline struct tcon_link *
2150cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb);
2151
2152static int
2153compare_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
2191int
2192cifs_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);
2237out:
2238 cifs_put_tlink(tlink);
2239 spin_unlock(&cifs_tcp_ses_lock);
2240 return rc;
2241}
2242
2149int 2243int
2150get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, 2244get_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;