[PATCH 3/5] cifs: clean up cifs_oplock_thread loop

Jeff Layton <[email protected]>
Newsgroups gmane.linux.file-systems.cifs
Message-ID <[email protected]>
Minor cleanups and optimizations mostly. Also fix it so that if a
kthread_stop races in at the right time, it won't make the thread
sleep unnecessarily for 39s.

Signed-off-by: Jeff Layton <[email protected]>
---
 fs/cifs/cifsfs.c |   66 +++++++++++++++++++++++++++++------------------------
 1 files changed, 36 insertions(+), 30 deletions(-)

diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 7ce8dcd..2fcc722 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -972,10 +972,10 @@ cifs_destroy_mids(void)
 
 static int cifs_oplock_thread(void *dummyarg)
 {
-	struct oplock_q_entry *oplock_item;
-	struct cifsTconInfo *pTcon;
+	struct oplock_q_entry *oplock;
+	struct cifsTconInfo *tcon;
 	struct inode *inode;
-	__u16  netfid;
+	struct cifsInodeInfo *cifsi;
 	int rc, waitrc = 0;
 
 	set_freezable();
@@ -984,34 +984,30 @@ static int cifs_oplock_thread(void *dummyarg)
 			continue;
 
 		spin_lock(&cifs_oplock_lock);
-		if (list_empty(&cifs_oplock_list)) {
+		while(!list_empty(&cifs_oplock_list)) {
+			oplock = list_entry(cifs_oplock_list.next,
+					    struct oplock_q_entry, qhead);
+			list_del(&oplock->qhead);
 			spin_unlock(&cifs_oplock_lock);
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(39*HZ);
-		} else {
-			oplock_item = list_entry(cifs_oplock_list.next,
-						struct oplock_q_entry, qhead);
+
 			cFYI(1, ("found oplock item to write out"));
-			pTcon = oplock_item->tcon;
-			inode = oplock_item->pinode;
-			netfid = oplock_item->netfid;
-			list_del(&oplock_item->qhead);
-			spin_unlock(&cifs_oplock_lock);
-			kmem_cache_free(cifs_oplock_cachep, oplock_item);
+			tcon = oplock->tcon;
+			inode = oplock->pinode;
 			/* can not grab inode sem here since it would
 				deadlock when oplock received on delete
 				since vfs_unlink holds the i_mutex across
 				the call */
 			/* mutex_lock(&inode->i_mutex);*/
+			cifsi = CIFS_I(inode);
 			if (S_ISREG(inode->i_mode)) {
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-				if (CIFS_I(inode)->clientCanCacheAll == 0)
+				if (cifsi->clientCanCacheAll == 0)
 					break_lease(inode, FMODE_READ);
-				else if (CIFS_I(inode)->clientCanCacheRead == 0)
+				else if (cifsi->clientCanCacheRead == 0)
 					break_lease(inode, FMODE_WRITE);
 #endif
 				rc = filemap_fdatawrite(inode->i_mapping);
-				if (CIFS_I(inode)->clientCanCacheRead == 0) {
+				if (cifsi->clientCanCacheRead == 0) {
 					waitrc = filemap_fdatawait(
 							      inode->i_mapping);
 					invalidate_remote_inode(inode);
@@ -1022,27 +1018,37 @@ static int cifs_oplock_thread(void *dummyarg)
 				rc = 0;
 			/* mutex_unlock(&inode->i_mutex);*/
 			if (rc)
-				CIFS_I(inode)->write_behind_rc = rc;
+				cifsi->write_behind_rc = rc;
 			cFYI(1, ("Oplock flush inode %p rc %d",
 				inode, rc));
 
-				/* releasing stale oplock after recent reconnect
-				of smb session using a now incorrect file
-				handle is not a data integrity issue but do
-				not bother sending an oplock release if session
-				to server still is disconnected since oplock
-				already released by the server in that case */
-			if (!pTcon->need_reconnect) {
-				rc = CIFSSMBLock(0, pTcon, netfid,
+			/*
+			 * releasing stale oplock after recent reconnect
+			 * of smb session using a now incorrect file
+			 * handle is not a data integrity issue but do
+			 * not bother sending an oplock release if session
+			 * to server still is disconnected since oplock
+			 * already released by the server in that case
+			 */
+			if (!tcon->need_reconnect) {
+				rc = CIFSSMBLock(0, tcon, oplock->netfid,
 						0 /* len */ , 0 /* offset */, 0,
 						0, LOCKING_ANDX_OPLOCK_RELEASE,
 						false /* wait flag */);
 				cFYI(1, ("Oplock release rc = %d", rc));
 			}
-			cifs_put_tcon(pTcon);
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);  /* yield in case q were corrupt */
+			cifs_put_tcon(tcon);
+			kmem_cache_free(cifs_oplock_cachep, oplock);
+			spin_lock(&cifs_oplock_lock);
+		}
+		spin_unlock(&cifs_oplock_lock);
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (kthread_should_stop()) {
+			set_current_state(TASK_RUNNING);
+			break;
 		}
+		/* FIXME: Why 39s here? This should be a named constant. */
+		schedule_timeout(39*HZ);
 	} while (!kthread_should_stop());
 
 	return 0;
-- 
1.6.0.6
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.