]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
cifs: convert GlobalSMBSeslock from a rwlock to regular spinlock
authorJeff Layton <jlayton@redhat.com>
Fri, 15 Oct 2010 19:34:03 +0000 (15:34 -0400)
committerSteve French <sfrench@us.ibm.com>
Mon, 18 Oct 2010 01:32:01 +0000 (01:32 +0000)
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>
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/file.c
fs/cifs/misc.c
fs/cifs/readdir.c

index cbd468c880c4e36e5377bb307e3d9f603cae8ed9..f1d9c71e807f78f2d40b12a63c1bd9825f908e4d 100644 (file)
@@ -940,8 +940,8 @@ init_cifs(void)
        GlobalTotalActiveXid = 0;
        GlobalMaxActiveXid = 0;
        memset(Local_System_Name, 0, 15);
-       rwlock_init(&GlobalSMBSeslock);
        rwlock_init(&cifs_tcp_ses_lock);
+       spin_lock_init(&cifs_file_list_lock);
        spin_lock_init(&GlobalMid_Lock);
 
        if (cifs_max_pending < 2) {
index 9f99afab9a04692f05afe843959b893639c2cd42..53899a8d7c4a7f8ba903109aaf3fedc54704788d 100644 (file)
@@ -720,7 +720,7 @@ GLOBAL_EXTERN rwlock_t              cifs_tcp_ses_lock;
  * If cifs_tcp_ses_lock and the lock below are both needed to be held, then
  * the cifs_tcp_ses_lock must be grabbed first and released last.
  */
-GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;
+GLOBAL_EXTERN spinlock_t       cifs_file_list_lock;
 
 /* Outstanding dir notify requests */
 GLOBAL_EXTERN struct list_head GlobalDnotifyReqList;
index a420c7b0852226020d4e8843775c44f95f200962..bfb59a68e4fd93b2283310fff7fba1d0459ad4ff 100644 (file)
@@ -91,13 +91,13 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
        struct list_head *tmp1;
 
 /* list all files open on tree connection and mark them invalid */
-       write_lock(&GlobalSMBSeslock);
+       spin_lock(&cifs_file_list_lock);
        list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
                open_file = list_entry(tmp, struct cifsFileInfo, tlist);
                open_file->invalidHandle = true;
                open_file->oplock_break_cancelled = true;
        }
-       write_unlock(&GlobalSMBSeslock);
+       spin_unlock(&cifs_file_list_lock);
        /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
           to this tcon */
 }
index 293e9b76762179c98656f9e3ef18385c31e5d6e3..26048dc9069aec7537e4062697e595e588e13c80 100644 (file)
@@ -246,14 +246,14 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file,
        atomic_set(&pCifsFile->count, 1);
        INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
 
-       write_lock(&GlobalSMBSeslock);
+       spin_lock(&cifs_file_list_lock);
        list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList));
        /* if readable file instance put first in list*/
        if (file->f_mode & FMODE_READ)
                list_add(&pCifsFile->flist, &pCifsInode->openFileList);
        else
                list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList);
-       write_unlock(&GlobalSMBSeslock);
+       spin_unlock(&cifs_file_list_lock);
 
        if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
                pCifsInode->clientCanCacheAll = true;
@@ -607,13 +607,13 @@ int cifs_close(struct inode *inode, struct file *file)
        pTcon = tlink_tcon(pSMBFile->tlink);
        if (pSMBFile) {
                struct cifsLockInfo *li, *tmp;
-               write_lock(&GlobalSMBSeslock);
+               spin_lock(&cifs_file_list_lock);
                pSMBFile->closePend = true;
                if (pTcon) {
                        /* no sense reconnecting to close a file that is
                           already closed */
                        if (!pTcon->need_reconnect) {
-                               write_unlock(&GlobalSMBSeslock);
+                               spin_unlock(&cifs_file_list_lock);
                                timeout = 2;
                                while ((atomic_read(&pSMBFile->count) != 1)
                                        && (timeout <= 2048)) {
@@ -633,9 +633,9 @@ int cifs_close(struct inode *inode, struct file *file)
                                        rc = CIFSSMBClose(xid, pTcon,
                                                  pSMBFile->netfid);
                        } else
-                               write_unlock(&GlobalSMBSeslock);
+                               spin_unlock(&cifs_file_list_lock);
                } else
-                       write_unlock(&GlobalSMBSeslock);
+                       spin_unlock(&cifs_file_list_lock);
 
                /* Delete any outstanding lock records.
                   We'll lose them when the file is closed anyway. */
@@ -646,16 +646,16 @@ int cifs_close(struct inode *inode, struct file *file)
                }
                mutex_unlock(&pSMBFile->lock_mutex);
 
-               write_lock(&GlobalSMBSeslock);
+               spin_lock(&cifs_file_list_lock);
                list_del(&pSMBFile->flist);
                list_del(&pSMBFile->tlist);
-               write_unlock(&GlobalSMBSeslock);
+               spin_unlock(&cifs_file_list_lock);
                cifsFileInfo_put(file->private_data);
                file->private_data = NULL;
        } else
                rc = -EBADF;
 
-       read_lock(&GlobalSMBSeslock);
+       spin_lock(&cifs_file_list_lock);
        if (list_empty(&(CIFS_I(inode)->openFileList))) {
                cFYI(1, "closing last open instance for inode %p", inode);
                /* 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)
                CIFS_I(inode)->clientCanCacheRead = false;
                CIFS_I(inode)->clientCanCacheAll  = false;
        }
-       read_unlock(&GlobalSMBSeslock);
+       spin_unlock(&cifs_file_list_lock);
        if ((rc == 0) && CIFS_I(inode)->write_behind_rc)
                rc = CIFS_I(inode)->write_behind_rc;
        FreeXid(xid);
@@ -685,18 +685,18 @@ int cifs_closedir(struct inode *inode, struct file *file)
                struct cifsTconInfo *pTcon = tlink_tcon(pCFileStruct->tlink);
 
                cFYI(1, "Freeing private data in close dir");
-               write_lock(&GlobalSMBSeslock);
+               spin_lock(&cifs_file_list_lock);
                if (!pCFileStruct->srch_inf.endOfSearch &&
                    !pCFileStruct->invalidHandle) {
                        pCFileStruct->invalidHandle = true;
-                       write_unlock(&GlobalSMBSeslock);
+                       spin_unlock(&cifs_file_list_lock);
                        rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
                        cFYI(1, "Closing uncompleted readdir with rc %d",
                                 rc);
                        /* not much we can do if it fails anyway, ignore rc */
                        rc = 0;
                } else
-                       write_unlock(&GlobalSMBSeslock);
+                       spin_unlock(&cifs_file_list_lock);
                ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
                if (ptmp) {
                        cFYI(1, "closedir free smb buf in srch struct");
@@ -1182,7 +1182,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
        if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
                fsuid_only = false;
 
-       read_lock(&GlobalSMBSeslock);
+       spin_lock(&cifs_file_list_lock);
        /* we could simply get the first_list_entry since write-only entries
           are always at the end of the list but since the first entry might
           have a close pending, we go through the whole list */
@@ -1196,7 +1196,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
                                /* found a good file */
                                /* lock it so it will not be closed on us */
                                cifsFileInfo_get(open_file);
-                               read_unlock(&GlobalSMBSeslock);
+                               spin_unlock(&cifs_file_list_lock);
                                return open_file;
                        } /* else might as well continue, and look for
                             another, or simply have the caller reopen it
@@ -1204,7 +1204,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
                } else /* write only file */
                        break; /* write only files are last so must be done */
        }
-       read_unlock(&GlobalSMBSeslock);
+       spin_unlock(&cifs_file_list_lock);
        return NULL;
 }
 #endif
@@ -1231,7 +1231,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
        if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
                fsuid_only = false;
 
-       read_lock(&GlobalSMBSeslock);
+       spin_lock(&cifs_file_list_lock);
 refind_writable:
        list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
                if (open_file->closePend)
@@ -1245,11 +1245,11 @@ refind_writable:
 
                        if (!open_file->invalidHandle) {
                                /* found a good writable file */
-                               read_unlock(&GlobalSMBSeslock);
+                               spin_unlock(&cifs_file_list_lock);
                                return open_file;
                        }
 
-                       read_unlock(&GlobalSMBSeslock);
+                       spin_unlock(&cifs_file_list_lock);
                        /* Had to unlock since following call can block */
                        rc = cifs_reopen_file(open_file, false);
                        if (!rc) {
@@ -1257,7 +1257,7 @@ refind_writable:
                                        return open_file;
                                else { /* start over in case this was deleted */
                                       /* since the list could be modified */
-                                       read_lock(&GlobalSMBSeslock);
+                                       spin_lock(&cifs_file_list_lock);
                                        cifsFileInfo_put(open_file);
                                        goto refind_writable;
                                }
@@ -1271,7 +1271,7 @@ refind_writable:
                        to hold up writepages here (rather than
                        in caller) with continuous retries */
                        cFYI(1, "wp failed on reopen file");
-                       read_lock(&GlobalSMBSeslock);
+                       spin_lock(&cifs_file_list_lock);
                        /* can not use this handle, no write
                           pending on this one after all */
                        cifsFileInfo_put(open_file);
@@ -1292,7 +1292,7 @@ refind_writable:
                any_available = true;
                goto refind_writable;
        }
-       read_unlock(&GlobalSMBSeslock);
+       spin_unlock(&cifs_file_list_lock);
        return NULL;
 }
 
@@ -2200,16 +2200,16 @@ static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
 {
        struct cifsFileInfo *open_file;
 
-       read_lock(&GlobalSMBSeslock);
+       spin_lock(&cifs_file_list_lock);
        list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
                if (open_file->closePend)
                        continue;
                if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
-                       read_unlock(&GlobalSMBSeslock);
+                       spin_unlock(&cifs_file_list_lock);
                        return 1;
                }
        }
-       read_unlock(&GlobalSMBSeslock);
+       spin_unlock(&cifs_file_list_lock);
        return 0;
 }
 
@@ -2373,8 +2373,8 @@ void cifs_oplock_break(struct work_struct *work)
         * finished grabbing reference for us.  Make sure it's done by
         * waiting for GlobalSMSSeslock.
         */
-       write_lock(&GlobalSMBSeslock);
-       write_unlock(&GlobalSMBSeslock);
+       spin_lock(&cifs_file_list_lock);
+       spin_unlock(&cifs_file_list_lock);
 
        cifs_oplock_break_put(cfile);
 }
index 9bac3e74b3149b6fd12025d362366dcf5aa21dac..de6073cccd9c995d79f2185f9e878c0d5ca484d3 100644 (file)
@@ -560,7 +560,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
                                continue;
 
                        cifs_stats_inc(&tcon->num_oplock_brks);
-                       read_lock(&GlobalSMBSeslock);
+                       spin_lock(&cifs_file_list_lock);
                        list_for_each(tmp2, &tcon->openFileList) {
                                netfile = list_entry(tmp2, struct cifsFileInfo,
                                                     tlist);
@@ -572,7 +572,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
                                 * closed anyway.
                                 */
                                if (netfile->closePend) {
-                                       read_unlock(&GlobalSMBSeslock);
+                                       spin_unlock(&cifs_file_list_lock);
                                        read_unlock(&cifs_tcp_ses_lock);
                                        return true;
                                }
@@ -594,11 +594,11 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
                                        cifs_oplock_break_get(netfile);
                                netfile->oplock_break_cancelled = false;
 
-                               read_unlock(&GlobalSMBSeslock);
+                               spin_unlock(&cifs_file_list_lock);
                                read_unlock(&cifs_tcp_ses_lock);
                                return true;
                        }
-                       read_unlock(&GlobalSMBSeslock);
+                       spin_unlock(&cifs_file_list_lock);
                        read_unlock(&cifs_tcp_ses_lock);
                        cFYI(1, "No matching file for oplock break");
                        return true;
index 6f3d13ff947086fb0ad35114c1c601cc1b0d8c8c..ef7bb7b50f58e679ffabb8b8dad65420efb81271 100644 (file)
@@ -528,14 +528,14 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
           (index_to_find < first_entry_in_buffer)) {
                /* close and restart search */
                cFYI(1, "search backing up - close and restart search");
-               write_lock(&GlobalSMBSeslock);
+               spin_lock(&cifs_file_list_lock);
                if (!cifsFile->srch_inf.endOfSearch &&
                    !cifsFile->invalidHandle) {
                        cifsFile->invalidHandle = true;
-                       write_unlock(&GlobalSMBSeslock);
+                       spin_unlock(&cifs_file_list_lock);
                        CIFSFindClose(xid, pTcon, cifsFile->netfid);
                } else
-                       write_unlock(&GlobalSMBSeslock);
+                       spin_unlock(&cifs_file_list_lock);
                if (cifsFile->srch_inf.ntwrk_buf_start) {
                        cFYI(1, "freeing SMB ff cache buf on search rewind");
                        if (cifsFile->srch_inf.smallBuf)