diff options
author | Jeff Layton <jlayton@redhat.com> | 2010-10-15 15:34:03 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-10-17 21:32:01 -0400 |
commit | 4477288a103631980750c86547d1fd54bfd2ba7d (patch) | |
tree | e0d56476a740f043f6687e063ff88d2982b4c444 /fs/cifs/file.c | |
parent | 7a16f1961a5c61d1f60d9e0d3d171cf7793fb5cb (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/file.c')
-rw-r--r-- | fs/cifs/file.c | 54 |
1 files changed, 27 insertions, 27 deletions
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); |
1235 | refind_writable: | 1235 | refind_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 | } |