[linux-cifs-client] [PATCH 3/5] cifs: clean up cifs_oplock_thread loop
Jeff Layton
jlayton at redhat.com
Tue Aug 18 12:07:00 MDT 2009
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 <jlayton at redhat.com>
---
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
More information about the linux-cifs-client
mailing list