aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2010-10-15 15:34:03 -0400
committerSteve French <sfrench@us.ibm.com>2010-10-17 21:32:01 -0400
commit4477288a103631980750c86547d1fd54bfd2ba7d (patch)
treee0d56476a740f043f6687e063ff88d2982b4c444 /fs/cifs
parent7a16f1961a5c61d1f60d9e0d3d171cf7793fb5cb (diff)
cifs: convert GlobalSMBSeslock from a rwlock to regular spinlock
Convert this lock to a regular spinlock A rwlock_t offers little value here. It's more expensive than a regular spinlock unless you have a fairly large section of code that runs under the read lock and can benefit from the concurrency. Additionally, we need to ensure that the refcounting for files isn't racy and to do that we need to lock areas that can increment it for write. That means that the areas that can actually use a read_lock are very few and relatively infrequently used. While we're at it, change the name to something easier to type, and fix a bug in find_writable_file. cifsFileInfo_put can sleep and shouldn't be called while holding the lock. Signed-off-by: Jeff Layton <jlayton@redhat.com> Reviewed-by: Suresh Jayaraman <sjayaraman@suse.de> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsfs.c2
-rw-r--r--fs/cifs/cifsglob.h2
-rw-r--r--fs/cifs/cifssmb.c4
-rw-r--r--fs/cifs/file.c54
-rw-r--r--fs/cifs/misc.c8
-rw-r--r--fs/cifs/readdir.c6
6 files changed, 38 insertions, 38 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index cbd468c880c4..f1d9c71e807f 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -940,8 +940,8 @@ init_cifs(void)
940 GlobalTotalActiveXid = 0; 940 GlobalTotalActiveXid = 0;
941 GlobalMaxActiveXid = 0; 941 GlobalMaxActiveXid = 0;
942 memset(Local_System_Name, 0, 15); 942 memset(Local_System_Name, 0, 15);
943 rwlock_init(&GlobalSMBSeslock);
944 rwlock_init(&cifs_tcp_ses_lock); 943 rwlock_init(&cifs_tcp_ses_lock);
944 spin_lock_init(&cifs_file_list_lock);
945 spin_lock_init(&GlobalMid_Lock); 945 spin_lock_init(&GlobalMid_Lock);
946 946
947 if (cifs_max_pending < 2) { 947 if (cifs_max_pending < 2) {
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 9f99afab9a04..53899a8d7c4a 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -720,7 +720,7 @@ GLOBAL_EXTERN rwlock_t cifs_tcp_ses_lock;
720 * If cifs_tcp_ses_lock and the lock below are both needed to be held, then 720 * If cifs_tcp_ses_lock and the lock below are both needed to be held, then
721 * the cifs_tcp_ses_lock must be grabbed first and released last. 721 * the cifs_tcp_ses_lock must be grabbed first and released last.
722 */ 722 */
723GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; 723GLOBAL_EXTERN spinlock_t cifs_file_list_lock;
724 724
725/* Outstanding dir notify requests */ 725/* Outstanding dir notify requests */
726GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; 726GLOBAL_EXTERN struct list_head GlobalDnotifyReqList;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index a420c7b08522..bfb59a68e4fd 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -91,13 +91,13 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
91 struct list_head *tmp1; 91 struct list_head *tmp1;
92 92
93/* list all files open on tree connection and mark them invalid */ 93/* list all files open on tree connection and mark them invalid */
94 write_lock(&GlobalSMBSeslock); 94 spin_lock(&cifs_file_list_lock);
95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { 95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
96 open_file = list_entry(tmp, struct cifsFileInfo, tlist); 96 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
97 open_file->invalidHandle = true; 97 open_file->invalidHandle = true;
98 open_file->oplock_break_cancelled = true; 98 open_file->oplock_break_cancelled = true;
99 } 99 }
100 write_unlock(&GlobalSMBSeslock); 100 spin_unlock(&cifs_file_list_lock);
101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted 101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
102 to this tcon */ 102 to this tcon */
103} 103}
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 293e9b767621..26048dc9069a 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -246,14 +246,14 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file,
246 atomic_set(&pCifsFile->count, 1); 246 atomic_set(&pCifsFile->count, 1);
247 INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break); 247 INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
248 248
249 write_lock(&GlobalSMBSeslock); 249 spin_lock(&cifs_file_list_lock);
250 list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList)); 250 list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList));
251 /* if readable file instance put first in list*/ 251 /* if readable file instance put first in list*/
252 if (file->f_mode & FMODE_READ) 252 if (file->f_mode & FMODE_READ)
253 list_add(&pCifsFile->flist, &pCifsInode->openFileList); 253 list_add(&pCifsFile->flist, &pCifsInode->openFileList);
254 else 254 else
255 list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList); 255 list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList);
256 write_unlock(&GlobalSMBSeslock); 256 spin_unlock(&cifs_file_list_lock);
257 257
258 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { 258 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
259 pCifsInode->clientCanCacheAll = true; 259 pCifsInode->clientCanCacheAll = true;
@@ -607,13 +607,13 @@ int cifs_close(struct inode *inode, struct file *file)
607 pTcon = tlink_tcon(pSMBFile->tlink); 607 pTcon = tlink_tcon(pSMBFile->tlink);
608 if (pSMBFile) { 608 if (pSMBFile) {
609 struct cifsLockInfo *li, *tmp; 609 struct cifsLockInfo *li, *tmp;
610 write_lock(&GlobalSMBSeslock); 610 spin_lock(&cifs_file_list_lock);
611 pSMBFile->closePend = true; 611 pSMBFile->closePend = true;
612 if (pTcon) { 612 if (pTcon) {
613 /* no sense reconnecting to close a file that is 613 /* no sense reconnecting to close a file that is
614 already closed */ 614 already closed */
615 if (!pTcon->need_reconnect) { 615 if (!pTcon->need_reconnect) {
616 write_unlock(&GlobalSMBSeslock); 616 spin_unlock(&cifs_file_list_lock);
617 timeout = 2; 617 timeout = 2;
618 while ((atomic_read(&pSMBFile->count) != 1) 618 while ((atomic_read(&pSMBFile->count) != 1)
619 && (timeout <= 2048)) { 619 && (timeout <= 2048)) {
@@ -633,9 +633,9 @@ int cifs_close(struct inode *inode, struct file *file)
633 rc = CIFSSMBClose(xid, pTcon, 633 rc = CIFSSMBClose(xid, pTcon,
634 pSMBFile->netfid); 634 pSMBFile->netfid);
635 } else 635 } else
636 write_unlock(&GlobalSMBSeslock); 636 spin_unlock(&cifs_file_list_lock);
637 } else 637 } else
638 write_unlock(&GlobalSMBSeslock); 638 spin_unlock(&cifs_file_list_lock);
639 639
640 /* Delete any outstanding lock records. 640 /* Delete any outstanding lock records.
641 We'll lose them when the file is closed anyway. */ 641 We'll lose them when the file is closed anyway. */
@@ -646,16 +646,16 @@ int cifs_close(struct inode *inode, struct file *file)
646 } 646 }
647 mutex_unlock(&pSMBFile->lock_mutex); 647 mutex_unlock(&pSMBFile->lock_mutex);
648 648
649 write_lock(&GlobalSMBSeslock); 649 spin_lock(&cifs_file_list_lock);
650 list_del(&pSMBFile->flist); 650 list_del(&pSMBFile->flist);
651 list_del(&pSMBFile->tlist); 651 list_del(&pSMBFile->tlist);
652 write_unlock(&GlobalSMBSeslock); 652 spin_unlock(&cifs_file_list_lock);
653 cifsFileInfo_put(file->private_data); 653 cifsFileInfo_put(file->private_data);
654 file->private_data = NULL; 654 file->private_data = NULL;
655 } else 655 } else
656 rc = -EBADF; 656 rc = -EBADF;
657 657
658 read_lock(&GlobalSMBSeslock); 658 spin_lock(&cifs_file_list_lock);
659 if (list_empty(&(CIFS_I(inode)->openFileList))) { 659 if (list_empty(&(CIFS_I(inode)->openFileList))) {
660 cFYI(1, "closing last open instance for inode %p", inode); 660 cFYI(1, "closing last open instance for inode %p", inode);
661 /* if the file is not open we do not know if we can cache info 661 /* if the file is not open we do not know if we can cache info
@@ -663,7 +663,7 @@ int cifs_close(struct inode *inode, struct file *file)
663 CIFS_I(inode)->clientCanCacheRead = false; 663 CIFS_I(inode)->clientCanCacheRead = false;
664 CIFS_I(inode)->clientCanCacheAll = false; 664 CIFS_I(inode)->clientCanCacheAll = false;
665 } 665 }
666 read_unlock(&GlobalSMBSeslock); 666 spin_unlock(&cifs_file_list_lock);
667 if ((rc == 0) && CIFS_I(inode)->write_behind_rc) 667 if ((rc == 0) && CIFS_I(inode)->write_behind_rc)
668 rc = CIFS_I(inode)->write_behind_rc; 668 rc = CIFS_I(inode)->write_behind_rc;
669 FreeXid(xid); 669 FreeXid(xid);
@@ -685,18 +685,18 @@ int cifs_closedir(struct inode *inode, struct file *file)
685 struct cifsTconInfo *pTcon = tlink_tcon(pCFileStruct->tlink); 685 struct cifsTconInfo *pTcon = tlink_tcon(pCFileStruct->tlink);
686 686
687 cFYI(1, "Freeing private data in close dir"); 687 cFYI(1, "Freeing private data in close dir");
688 write_lock(&GlobalSMBSeslock); 688 spin_lock(&cifs_file_list_lock);
689 if (!pCFileStruct->srch_inf.endOfSearch && 689 if (!pCFileStruct->srch_inf.endOfSearch &&
690 !pCFileStruct->invalidHandle) { 690 !pCFileStruct->invalidHandle) {
691 pCFileStruct->invalidHandle = true; 691 pCFileStruct->invalidHandle = true;
692 write_unlock(&GlobalSMBSeslock); 692 spin_unlock(&cifs_file_list_lock);
693 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid); 693 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
694 cFYI(1, "Closing uncompleted readdir with rc %d", 694 cFYI(1, "Closing uncompleted readdir with rc %d",
695 rc); 695 rc);
696 /* not much we can do if it fails anyway, ignore rc */ 696 /* not much we can do if it fails anyway, ignore rc */
697 rc = 0; 697 rc = 0;
698 } else 698 } else
699 write_unlock(&GlobalSMBSeslock); 699 spin_unlock(&cifs_file_list_lock);
700 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start; 700 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
701 if (ptmp) { 701 if (ptmp) {
702 cFYI(1, "closedir free smb buf in srch struct"); 702 cFYI(1, "closedir free smb buf in srch struct");
@@ -1182,7 +1182,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1182 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) 1182 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1183 fsuid_only = false; 1183 fsuid_only = false;
1184 1184
1185 read_lock(&GlobalSMBSeslock); 1185 spin_lock(&cifs_file_list_lock);
1186 /* we could simply get the first_list_entry since write-only entries 1186 /* we could simply get the first_list_entry since write-only entries
1187 are always at the end of the list but since the first entry might 1187 are always at the end of the list but since the first entry might
1188 have a close pending, we go through the whole list */ 1188 have a close pending, we go through the whole list */
@@ -1196,7 +1196,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1196 /* found a good file */ 1196 /* found a good file */
1197 /* lock it so it will not be closed on us */ 1197 /* lock it so it will not be closed on us */
1198 cifsFileInfo_get(open_file); 1198 cifsFileInfo_get(open_file);
1199 read_unlock(&GlobalSMBSeslock); 1199 spin_unlock(&cifs_file_list_lock);
1200 return open_file; 1200 return open_file;
1201 } /* else might as well continue, and look for 1201 } /* else might as well continue, and look for
1202 another, or simply have the caller reopen it 1202 another, or simply have the caller reopen it
@@ -1204,7 +1204,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
1204 } else /* write only file */ 1204 } else /* write only file */
1205 break; /* write only files are last so must be done */ 1205 break; /* write only files are last so must be done */
1206 } 1206 }
1207 read_unlock(&GlobalSMBSeslock); 1207 spin_unlock(&cifs_file_list_lock);
1208 return NULL; 1208 return NULL;
1209} 1209}
1210#endif 1210#endif
@@ -1231,7 +1231,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
1231 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) 1231 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
1232 fsuid_only = false; 1232 fsuid_only = false;
1233 1233
1234 read_lock(&GlobalSMBSeslock); 1234 spin_lock(&cifs_file_list_lock);
1235refind_writable: 1235refind_writable:
1236 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { 1236 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
1237 if (open_file->closePend) 1237 if (open_file->closePend)
@@ -1245,11 +1245,11 @@ refind_writable:
1245 1245
1246 if (!open_file->invalidHandle) { 1246 if (!open_file->invalidHandle) {
1247 /* found a good writable file */ 1247 /* found a good writable file */
1248 read_unlock(&GlobalSMBSeslock); 1248 spin_unlock(&cifs_file_list_lock);
1249 return open_file; 1249 return open_file;
1250 } 1250 }
1251 1251
1252 read_unlock(&GlobalSMBSeslock); 1252 spin_unlock(&cifs_file_list_lock);
1253 /* Had to unlock since following call can block */ 1253 /* Had to unlock since following call can block */
1254 rc = cifs_reopen_file(open_file, false); 1254 rc = cifs_reopen_file(open_file, false);
1255 if (!rc) { 1255 if (!rc) {
@@ -1257,7 +1257,7 @@ refind_writable:
1257 return open_file; 1257 return open_file;
1258 else { /* start over in case this was deleted */ 1258 else { /* start over in case this was deleted */
1259 /* since the list could be modified */ 1259 /* since the list could be modified */
1260 read_lock(&GlobalSMBSeslock); 1260 spin_lock(&cifs_file_list_lock);
1261 cifsFileInfo_put(open_file); 1261 cifsFileInfo_put(open_file);
1262 goto refind_writable; 1262 goto refind_writable;
1263 } 1263 }
@@ -1271,7 +1271,7 @@ refind_writable:
1271 to hold up writepages here (rather than 1271 to hold up writepages here (rather than
1272 in caller) with continuous retries */ 1272 in caller) with continuous retries */
1273 cFYI(1, "wp failed on reopen file"); 1273 cFYI(1, "wp failed on reopen file");
1274 read_lock(&GlobalSMBSeslock); 1274 spin_lock(&cifs_file_list_lock);
1275 /* can not use this handle, no write 1275 /* can not use this handle, no write
1276 pending on this one after all */ 1276 pending on this one after all */
1277 cifsFileInfo_put(open_file); 1277 cifsFileInfo_put(open_file);
@@ -1292,7 +1292,7 @@ refind_writable:
1292 any_available = true; 1292 any_available = true;
1293 goto refind_writable; 1293 goto refind_writable;
1294 } 1294 }
1295 read_unlock(&GlobalSMBSeslock); 1295 spin_unlock(&cifs_file_list_lock);
1296 return NULL; 1296 return NULL;
1297} 1297}
1298 1298
@@ -2200,16 +2200,16 @@ static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
2200{ 2200{
2201 struct cifsFileInfo *open_file; 2201 struct cifsFileInfo *open_file;
2202 2202
2203 read_lock(&GlobalSMBSeslock); 2203 spin_lock(&cifs_file_list_lock);
2204 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { 2204 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
2205 if (open_file->closePend) 2205 if (open_file->closePend)
2206 continue; 2206 continue;
2207 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { 2207 if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
2208 read_unlock(&GlobalSMBSeslock); 2208 spin_unlock(&cifs_file_list_lock);
2209 return 1; 2209 return 1;
2210 } 2210 }
2211 } 2211 }
2212 read_unlock(&GlobalSMBSeslock); 2212 spin_unlock(&cifs_file_list_lock);
2213 return 0; 2213 return 0;
2214} 2214}
2215 2215
@@ -2373,8 +2373,8 @@ void cifs_oplock_break(struct work_struct *work)
2373 * finished grabbing reference for us. Make sure it's done by 2373 * finished grabbing reference for us. Make sure it's done by
2374 * waiting for GlobalSMSSeslock. 2374 * waiting for GlobalSMSSeslock.
2375 */ 2375 */
2376 write_lock(&GlobalSMBSeslock); 2376 spin_lock(&cifs_file_list_lock);
2377 write_unlock(&GlobalSMBSeslock); 2377 spin_unlock(&cifs_file_list_lock);
2378 2378
2379 cifs_oplock_break_put(cfile); 2379 cifs_oplock_break_put(cfile);
2380} 2380}
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 9bac3e74b314..de6073cccd9c 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -560,7 +560,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
560 continue; 560 continue;
561 561
562 cifs_stats_inc(&tcon->num_oplock_brks); 562 cifs_stats_inc(&tcon->num_oplock_brks);
563 read_lock(&GlobalSMBSeslock); 563 spin_lock(&cifs_file_list_lock);
564 list_for_each(tmp2, &tcon->openFileList) { 564 list_for_each(tmp2, &tcon->openFileList) {
565 netfile = list_entry(tmp2, struct cifsFileInfo, 565 netfile = list_entry(tmp2, struct cifsFileInfo,
566 tlist); 566 tlist);
@@ -572,7 +572,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
572 * closed anyway. 572 * closed anyway.
573 */ 573 */
574 if (netfile->closePend) { 574 if (netfile->closePend) {
575 read_unlock(&GlobalSMBSeslock); 575 spin_unlock(&cifs_file_list_lock);
576 read_unlock(&cifs_tcp_ses_lock); 576 read_unlock(&cifs_tcp_ses_lock);
577 return true; 577 return true;
578 } 578 }
@@ -594,11 +594,11 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
594 cifs_oplock_break_get(netfile); 594 cifs_oplock_break_get(netfile);
595 netfile->oplock_break_cancelled = false; 595 netfile->oplock_break_cancelled = false;
596 596
597 read_unlock(&GlobalSMBSeslock); 597 spin_unlock(&cifs_file_list_lock);
598 read_unlock(&cifs_tcp_ses_lock); 598 read_unlock(&cifs_tcp_ses_lock);
599 return true; 599 return true;
600 } 600 }
601 read_unlock(&GlobalSMBSeslock); 601 spin_unlock(&cifs_file_list_lock);
602 read_unlock(&cifs_tcp_ses_lock); 602 read_unlock(&cifs_tcp_ses_lock);
603 cFYI(1, "No matching file for oplock break"); 603 cFYI(1, "No matching file for oplock break");
604 return true; 604 return true;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 6f3d13ff9470..ef7bb7b50f58 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -528,14 +528,14 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
528 (index_to_find < first_entry_in_buffer)) { 528 (index_to_find < first_entry_in_buffer)) {
529 /* close and restart search */ 529 /* close and restart search */
530 cFYI(1, "search backing up - close and restart search"); 530 cFYI(1, "search backing up - close and restart search");
531 write_lock(&GlobalSMBSeslock); 531 spin_lock(&cifs_file_list_lock);
532 if (!cifsFile->srch_inf.endOfSearch && 532 if (!cifsFile->srch_inf.endOfSearch &&
533 !cifsFile->invalidHandle) { 533 !cifsFile->invalidHandle) {
534 cifsFile->invalidHandle = true; 534 cifsFile->invalidHandle = true;
535 write_unlock(&GlobalSMBSeslock); 535 spin_unlock(&cifs_file_list_lock);
536 CIFSFindClose(xid, pTcon, cifsFile->netfid); 536 CIFSFindClose(xid, pTcon, cifsFile->netfid);
537 } else 537 } else
538 write_unlock(&GlobalSMBSeslock); 538 spin_unlock(&cifs_file_list_lock);
539 if (cifsFile->srch_inf.ntwrk_buf_start) { 539 if (cifsFile->srch_inf.ntwrk_buf_start) {
540 cFYI(1, "freeing SMB ff cache buf on search rewind"); 540 cFYI(1, "freeing SMB ff cache buf on search rewind");
541 if (cifsFile->srch_inf.smallBuf) 541 if (cifsFile->srch_inf.smallBuf)