aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
authorPavel Shilovsky <pshilovsky@samba.org>2012-09-19 09:22:43 -0400
committerSteve French <smfrench@gmail.com>2012-09-24 22:46:32 -0400
commitf45d34167c67b083b54690e349e77f59062ef0ea (patch)
tree6be4f2a62e99e348e6cab03a24a1c45889a6722f /fs/cifs/file.c
parent1c0bd60b560cdf63a263f8ff3cebe9f99fe7a47c (diff)
CIFS: Remove spinlock dependence in brlock processing
Now we need to lock/unlock a spinlock while processing brlock ops on the inode. Move brlocks of a fid to a separate list and attach all such lists to the inode. This let us not hold a spinlock. Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c73
1 files changed, 43 insertions, 30 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 2421ec28df1..63963730cb2 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -245,11 +245,25 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
245 struct inode *inode = dentry->d_inode; 245 struct inode *inode = dentry->d_inode;
246 struct cifsInodeInfo *cinode = CIFS_I(inode); 246 struct cifsInodeInfo *cinode = CIFS_I(inode);
247 struct cifsFileInfo *cfile; 247 struct cifsFileInfo *cfile;
248 struct cifs_fid_locks *fdlocks;
248 249
249 cfile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 250 cfile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
250 if (cfile == NULL) 251 if (cfile == NULL)
251 return cfile; 252 return cfile;
252 253
254 fdlocks = kzalloc(sizeof(struct cifs_fid_locks), GFP_KERNEL);
255 if (!fdlocks) {
256 kfree(cfile);
257 return NULL;
258 }
259
260 INIT_LIST_HEAD(&fdlocks->locks);
261 fdlocks->cfile = cfile;
262 cfile->llist = fdlocks;
263 mutex_lock(&cinode->lock_mutex);
264 list_add(&fdlocks->llist, &cinode->llist);
265 mutex_unlock(&cinode->lock_mutex);
266
253 cfile->count = 1; 267 cfile->count = 1;
254 cfile->pid = current->tgid; 268 cfile->pid = current->tgid;
255 cfile->uid = current_fsuid(); 269 cfile->uid = current_fsuid();
@@ -257,9 +271,8 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
257 cfile->f_flags = file->f_flags; 271 cfile->f_flags = file->f_flags;
258 cfile->invalidHandle = false; 272 cfile->invalidHandle = false;
259 cfile->tlink = cifs_get_tlink(tlink); 273 cfile->tlink = cifs_get_tlink(tlink);
260 mutex_init(&cfile->fh_mutex);
261 INIT_WORK(&cfile->oplock_break, cifs_oplock_break); 274 INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
262 INIT_LIST_HEAD(&cfile->llist); 275 mutex_init(&cfile->fh_mutex);
263 tlink_tcon(tlink)->ses->server->ops->set_fid(cfile, fid, oplock); 276 tlink_tcon(tlink)->ses->server->ops->set_fid(cfile, fid, oplock);
264 277
265 spin_lock(&cifs_file_list_lock); 278 spin_lock(&cifs_file_list_lock);
@@ -336,15 +349,18 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
336 free_xid(xid); 349 free_xid(xid);
337 } 350 }
338 351
339 /* Delete any outstanding lock records. We'll lose them when the file 352 /*
353 * Delete any outstanding lock records. We'll lose them when the file
340 * is closed anyway. 354 * is closed anyway.
341 */ 355 */
342 mutex_lock(&cifsi->lock_mutex); 356 mutex_lock(&cifsi->lock_mutex);
343 list_for_each_entry_safe(li, tmp, &cifs_file->llist, llist) { 357 list_for_each_entry_safe(li, tmp, &cifs_file->llist->locks, llist) {
344 list_del(&li->llist); 358 list_del(&li->llist);
345 cifs_del_lock_waiters(li); 359 cifs_del_lock_waiters(li);
346 kfree(li); 360 kfree(li);
347 } 361 }
362 list_del(&cifs_file->llist->llist);
363 kfree(cifs_file->llist);
348 mutex_unlock(&cifsi->lock_mutex); 364 mutex_unlock(&cifsi->lock_mutex);
349 365
350 cifs_put_tlink(cifs_file->tlink); 366 cifs_put_tlink(cifs_file->tlink);
@@ -691,25 +707,24 @@ cifs_del_lock_waiters(struct cifsLockInfo *lock)
691} 707}
692 708
693static bool 709static bool
694cifs_find_fid_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, 710cifs_find_fid_lock_conflict(struct cifs_fid_locks *fdlocks, __u64 offset,
695 __u64 length, __u8 type, struct cifsFileInfo *cur, 711 __u64 length, __u8 type, struct cifsFileInfo *cfile,
696 struct cifsLockInfo **conf_lock) 712 struct cifsLockInfo **conf_lock)
697{ 713{
698 struct cifsLockInfo *li; 714 struct cifsLockInfo *li;
715 struct cifsFileInfo *cur_cfile = fdlocks->cfile;
699 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; 716 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
700 717
701 list_for_each_entry(li, &cfile->llist, llist) { 718 list_for_each_entry(li, &fdlocks->locks, llist) {
702 if (offset + length <= li->offset || 719 if (offset + length <= li->offset ||
703 offset >= li->offset + li->length) 720 offset >= li->offset + li->length)
704 continue; 721 continue;
705 else if ((type & server->vals->shared_lock_type) && 722 if ((type & server->vals->shared_lock_type) &&
706 ((server->ops->compare_fids(cur, cfile) && 723 ((server->ops->compare_fids(cfile, cur_cfile) &&
707 current->tgid == li->pid) || type == li->type)) 724 current->tgid == li->pid) || type == li->type))
708 continue; 725 continue;
709 else { 726 *conf_lock = li;
710 *conf_lock = li; 727 return true;
711 return true;
712 }
713 } 728 }
714 return false; 729 return false;
715} 730}
@@ -719,17 +734,15 @@ cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
719 __u8 type, struct cifsLockInfo **conf_lock) 734 __u8 type, struct cifsLockInfo **conf_lock)
720{ 735{
721 bool rc = false; 736 bool rc = false;
722 struct cifsFileInfo *fid, *tmp; 737 struct cifs_fid_locks *cur;
723 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); 738 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
724 739
725 spin_lock(&cifs_file_list_lock); 740 list_for_each_entry(cur, &cinode->llist, llist) {
726 list_for_each_entry_safe(fid, tmp, &cinode->openFileList, flist) { 741 rc = cifs_find_fid_lock_conflict(cur, offset, length, type,
727 rc = cifs_find_fid_lock_conflict(fid, offset, length, type,
728 cfile, conf_lock); 742 cfile, conf_lock);
729 if (rc) 743 if (rc)
730 break; 744 break;
731 } 745 }
732 spin_unlock(&cifs_file_list_lock);
733 746
734 return rc; 747 return rc;
735} 748}
@@ -777,7 +790,7 @@ cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock)
777{ 790{
778 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); 791 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
779 mutex_lock(&cinode->lock_mutex); 792 mutex_lock(&cinode->lock_mutex);
780 list_add_tail(&lock->llist, &cfile->llist); 793 list_add_tail(&lock->llist, &cfile->llist->locks);
781 mutex_unlock(&cinode->lock_mutex); 794 mutex_unlock(&cinode->lock_mutex);
782} 795}
783 796
@@ -803,7 +816,7 @@ try_again:
803 exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length, 816 exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length,
804 lock->type, &conf_lock); 817 lock->type, &conf_lock);
805 if (!exist && cinode->can_cache_brlcks) { 818 if (!exist && cinode->can_cache_brlcks) {
806 list_add_tail(&lock->llist, &cfile->llist); 819 list_add_tail(&lock->llist, &cfile->llist->locks);
807 mutex_unlock(&cinode->lock_mutex); 820 mutex_unlock(&cinode->lock_mutex);
808 return rc; 821 return rc;
809 } 822 }
@@ -937,7 +950,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
937 for (i = 0; i < 2; i++) { 950 for (i = 0; i < 2; i++) {
938 cur = buf; 951 cur = buf;
939 num = 0; 952 num = 0;
940 list_for_each_entry_safe(li, tmp, &cfile->llist, llist) { 953 list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
941 if (li->type != types[i]) 954 if (li->type != types[i])
942 continue; 955 continue;
943 cur->Pid = cpu_to_le16(li->pid); 956 cur->Pid = cpu_to_le16(li->pid);
@@ -1279,7 +1292,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
1279 for (i = 0; i < 2; i++) { 1292 for (i = 0; i < 2; i++) {
1280 cur = buf; 1293 cur = buf;
1281 num = 0; 1294 num = 0;
1282 list_for_each_entry_safe(li, tmp, &cfile->llist, llist) { 1295 list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
1283 if (flock->fl_start > li->offset || 1296 if (flock->fl_start > li->offset ||
1284 (flock->fl_start + length) < 1297 (flock->fl_start + length) <
1285 (li->offset + li->length)) 1298 (li->offset + li->length))
@@ -1320,7 +1333,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
1320 * list to the head of the file's list. 1333 * list to the head of the file's list.
1321 */ 1334 */
1322 cifs_move_llist(&tmp_llist, 1335 cifs_move_llist(&tmp_llist,
1323 &cfile->llist); 1336 &cfile->llist->locks);
1324 rc = stored_rc; 1337 rc = stored_rc;
1325 } else 1338 } else
1326 /* 1339 /*
@@ -1337,7 +1350,8 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
1337 stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid, 1350 stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid,
1338 types[i], num, 0, buf); 1351 types[i], num, 0, buf);
1339 if (stored_rc) { 1352 if (stored_rc) {
1340 cifs_move_llist(&tmp_llist, &cfile->llist); 1353 cifs_move_llist(&tmp_llist,
1354 &cfile->llist->locks);
1341 rc = stored_rc; 1355 rc = stored_rc;
1342 } else 1356 } else
1343 cifs_free_llist(&tmp_llist); 1357 cifs_free_llist(&tmp_llist);
@@ -1350,7 +1364,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
1350} 1364}
1351 1365
1352static int 1366static int
1353cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, 1367cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
1354 bool wait_flag, bool posix_lck, int lock, int unlock, 1368 bool wait_flag, bool posix_lck, int lock, int unlock,
1355 unsigned int xid) 1369 unsigned int xid)
1356{ 1370{
@@ -1359,7 +1373,6 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
1359 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; 1373 struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
1360 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 1374 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
1361 struct TCP_Server_Info *server = tcon->ses->server; 1375 struct TCP_Server_Info *server = tcon->ses->server;
1362 __u16 netfid = cfile->fid.netfid;
1363 1376
1364 if (posix_lck) { 1377 if (posix_lck) {
1365 int posix_lock_type; 1378 int posix_lock_type;
@@ -1376,9 +1389,9 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
1376 if (unlock == 1) 1389 if (unlock == 1)
1377 posix_lock_type = CIFS_UNLCK; 1390 posix_lock_type = CIFS_UNLCK;
1378 1391
1379 rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid, 1392 rc = CIFSSMBPosixLock(xid, tcon, cfile->fid.netfid,
1380 flock->fl_start, length, NULL, 1393 current->tgid, flock->fl_start, length,
1381 posix_lock_type, wait_flag); 1394 NULL, posix_lock_type, wait_flag);
1382 goto out; 1395 goto out;
1383 } 1396 }
1384 1397