aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorPavel Shilovsky <pshilovsky@etersoft.ru>2012-09-19 09:22:44 -0400
committerSteve French <smfrench@gmail.com>2012-09-24 22:46:33 -0400
commitb140799a11adb6023d5f96712874c37b71dab290 (patch)
tree7b2dc7493db1b65b0d8c03901b86fb9e967c76c5 /fs/cifs
parentf7ba7fe685bc3ed8fd0687870e68b2567d17357f (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')
-rw-r--r--fs/cifs/smb2file.c91
-rw-r--r--fs/cifs/smb2ops.c3
-rw-r--r--fs/cifs/smb2proto.h1
3 files changed, 94 insertions, 1 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
205static int
206smb2_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
245int
246smb2_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}
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index caed2c57896d..0808b238219b 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -371,7 +371,7 @@ smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
371 cfile->fid.persistent_fid = fid->persistent_fid; 371 cfile->fid.persistent_fid = fid->persistent_fid;
372 cfile->fid.volatile_fid = fid->volatile_fid; 372 cfile->fid.volatile_fid = fid->volatile_fid;
373 smb2_set_oplock_level(cinode, oplock); 373 smb2_set_oplock_level(cinode, oplock);
374 /* cinode->can_cache_brlcks = cinode->clientCanCacheAll; */ 374 cinode->can_cache_brlcks = cinode->clientCanCacheAll;
375} 375}
376 376
377static int 377static int
@@ -615,6 +615,7 @@ struct smb_version_operations smb21_operations = {
615 .queryfs = smb2_queryfs, 615 .queryfs = smb2_queryfs,
616 .mand_lock = smb2_mand_lock, 616 .mand_lock = smb2_mand_lock,
617 .mand_unlock_range = smb2_unlock_range, 617 .mand_unlock_range = smb2_unlock_range,
618 .push_mand_locks = smb2_push_mandatory_locks,
618}; 619};
619 620
620struct smb_version_values smb21_values = { 621struct smb_version_values smb21_values = {
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index ab19152b092b..8b4d3712255b 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -86,6 +86,7 @@ extern int smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon,
86extern void smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock); 86extern void smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock);
87extern int smb2_unlock_range(struct cifsFileInfo *cfile, 87extern int smb2_unlock_range(struct cifsFileInfo *cfile,
88 struct file_lock *flock, const unsigned int xid); 88 struct file_lock *flock, const unsigned int xid);
89extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile);
89 90
90/* 91/*
91 * SMB2 Worker functions - most of protocol specific implementation details 92 * SMB2 Worker functions - most of protocol specific implementation details