diff options
author | Pavel Shilovsky <piastry@etersoft.ru> | 2011-05-26 15:35:47 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2011-05-26 23:53:23 -0400 |
commit | 25c7f41e9234f60af30e086278f1de7974f8816f (patch) | |
tree | 41cb4da532da30418da2d33e5376ddbf9f65958a /fs/cifs/connect.c | |
parent | f87d39d951329cd8f462bf9007d334122c0599d0 (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.c | 102 |
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 | ||
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; |