diff options
author | Pavel Shilovsky <pshilovsky@etersoft.ru> | 2012-09-19 09:22:44 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-09-24 22:46:33 -0400 |
commit | b140799a11adb6023d5f96712874c37b71dab290 (patch) | |
tree | 7b2dc7493db1b65b0d8c03901b86fb9e967c76c5 /fs/cifs/smb2file.c | |
parent | f7ba7fe685bc3ed8fd0687870e68b2567d17357f (diff) |
CIFS: Use brlock cache for SMB2
Signed-off-by: Pavel Shilovsky <pshilovsky@etersoft.ru>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/smb2file.c')
-rw-r--r-- | fs/cifs/smb2file.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c index a25ea02149e7..181e13d9f9db 100644 --- a/fs/cifs/smb2file.c +++ b/fs/cifs/smb2file.c | |||
@@ -201,3 +201,94 @@ smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, | |||
201 | kfree(buf); | 201 | kfree(buf); |
202 | return rc; | 202 | return rc; |
203 | } | 203 | } |
204 | |||
205 | static int | ||
206 | smb2_push_mand_fdlocks(struct cifs_fid_locks *fdlocks, const unsigned int xid, | ||
207 | struct smb2_lock_element *buf, unsigned int max_num) | ||
208 | { | ||
209 | int rc = 0, stored_rc; | ||
210 | struct cifsFileInfo *cfile = fdlocks->cfile; | ||
211 | struct cifsLockInfo *li; | ||
212 | unsigned int num = 0; | ||
213 | struct smb2_lock_element *cur = buf; | ||
214 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | ||
215 | |||
216 | list_for_each_entry(li, &fdlocks->locks, llist) { | ||
217 | cur->Length = cpu_to_le64(li->length); | ||
218 | cur->Offset = cpu_to_le64(li->offset); | ||
219 | cur->Flags = cpu_to_le32(li->type | | ||
220 | SMB2_LOCKFLAG_FAIL_IMMEDIATELY); | ||
221 | if (++num == max_num) { | ||
222 | stored_rc = smb2_lockv(xid, tcon, | ||
223 | cfile->fid.persistent_fid, | ||
224 | cfile->fid.volatile_fid, | ||
225 | current->tgid, num, buf); | ||
226 | if (stored_rc) | ||
227 | rc = stored_rc; | ||
228 | cur = buf; | ||
229 | num = 0; | ||
230 | } else | ||
231 | cur++; | ||
232 | } | ||
233 | if (num) { | ||
234 | stored_rc = smb2_lockv(xid, tcon, | ||
235 | cfile->fid.persistent_fid, | ||
236 | cfile->fid.volatile_fid, | ||
237 | current->tgid, num, buf); | ||
238 | if (stored_rc) | ||
239 | rc = stored_rc; | ||
240 | } | ||
241 | |||
242 | return rc; | ||
243 | } | ||
244 | |||
245 | int | ||
246 | smb2_push_mandatory_locks(struct cifsFileInfo *cfile) | ||
247 | { | ||
248 | int rc = 0, stored_rc; | ||
249 | unsigned int xid; | ||
250 | unsigned int max_num, max_buf; | ||
251 | struct smb2_lock_element *buf; | ||
252 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); | ||
253 | struct cifs_fid_locks *fdlocks; | ||
254 | |||
255 | xid = get_xid(); | ||
256 | mutex_lock(&cinode->lock_mutex); | ||
257 | if (!cinode->can_cache_brlcks) { | ||
258 | mutex_unlock(&cinode->lock_mutex); | ||
259 | free_xid(xid); | ||
260 | return rc; | ||
261 | } | ||
262 | |||
263 | /* | ||
264 | * Accessing maxBuf is racy with cifs_reconnect - need to store value | ||
265 | * and check it for zero before using. | ||
266 | */ | ||
267 | max_buf = tlink_tcon(cfile->tlink)->ses->server->maxBuf; | ||
268 | if (!max_buf) { | ||
269 | mutex_unlock(&cinode->lock_mutex); | ||
270 | free_xid(xid); | ||
271 | return -EINVAL; | ||
272 | } | ||
273 | |||
274 | max_num = max_buf / sizeof(struct smb2_lock_element); | ||
275 | buf = kzalloc(max_num * sizeof(struct smb2_lock_element), GFP_KERNEL); | ||
276 | if (!buf) { | ||
277 | mutex_unlock(&cinode->lock_mutex); | ||
278 | free_xid(xid); | ||
279 | return -ENOMEM; | ||
280 | } | ||
281 | |||
282 | list_for_each_entry(fdlocks, &cinode->llist, llist) { | ||
283 | stored_rc = smb2_push_mand_fdlocks(fdlocks, xid, buf, max_num); | ||
284 | if (stored_rc) | ||
285 | rc = stored_rc; | ||
286 | } | ||
287 | |||
288 | cinode->can_cache_brlcks = false; | ||
289 | kfree(buf); | ||
290 | |||
291 | mutex_unlock(&cinode->lock_mutex); | ||
292 | free_xid(xid); | ||
293 | return rc; | ||
294 | } | ||