Commit 1b49c556 authored by Jeff Layton's avatar Jeff Layton Committed by Steve French

cifs: protect GlobalOplock_Q with its own spinlock

Right now, the GlobalOplock_Q is protected by the GlobalMid_Lock. That
lock is also used for completely unrelated purposes (mostly for managing
the global mid queue). Give the list its own dedicated spinlock
(cifs_oplock_lock) and rename the list to cifs_oplock_list to
eliminate the camel-case.
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 8e047d09
...@@ -986,19 +986,19 @@ static int cifs_oplock_thread(void *dummyarg) ...@@ -986,19 +986,19 @@ static int cifs_oplock_thread(void *dummyarg)
if (try_to_freeze()) if (try_to_freeze())
continue; continue;
spin_lock(&GlobalMid_Lock); spin_lock(&cifs_oplock_lock);
if (list_empty(&GlobalOplock_Q)) { if (list_empty(&cifs_oplock_list)) {
spin_unlock(&GlobalMid_Lock); spin_unlock(&cifs_oplock_lock);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(39*HZ); schedule_timeout(39*HZ);
} else { } else {
oplock_item = list_entry(GlobalOplock_Q.next, oplock_item = list_entry(cifs_oplock_list.next,
struct oplock_q_entry, qhead); struct oplock_q_entry, qhead);
cFYI(1, ("found oplock item to write out")); cFYI(1, ("found oplock item to write out"));
pTcon = oplock_item->tcon; pTcon = oplock_item->tcon;
inode = oplock_item->pinode; inode = oplock_item->pinode;
netfid = oplock_item->netfid; netfid = oplock_item->netfid;
spin_unlock(&GlobalMid_Lock); spin_unlock(&cifs_oplock_lock);
DeleteOplockQEntry(oplock_item); DeleteOplockQEntry(oplock_item);
/* can not grab inode sem here since it would /* can not grab inode sem here since it would
deadlock when oplock received on delete deadlock when oplock received on delete
...@@ -1055,7 +1055,7 @@ init_cifs(void) ...@@ -1055,7 +1055,7 @@ init_cifs(void)
int rc = 0; int rc = 0;
cifs_proc_init(); cifs_proc_init();
INIT_LIST_HEAD(&cifs_tcp_ses_list); INIT_LIST_HEAD(&cifs_tcp_ses_list);
INIT_LIST_HEAD(&GlobalOplock_Q); INIT_LIST_HEAD(&cifs_oplock_list);
#ifdef CONFIG_CIFS_EXPERIMENTAL #ifdef CONFIG_CIFS_EXPERIMENTAL
INIT_LIST_HEAD(&GlobalDnotifyReqList); INIT_LIST_HEAD(&GlobalDnotifyReqList);
INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); INIT_LIST_HEAD(&GlobalDnotifyRsp_Q);
...@@ -1084,6 +1084,7 @@ init_cifs(void) ...@@ -1084,6 +1084,7 @@ init_cifs(void)
rwlock_init(&GlobalSMBSeslock); rwlock_init(&GlobalSMBSeslock);
rwlock_init(&cifs_tcp_ses_lock); rwlock_init(&cifs_tcp_ses_lock);
spin_lock_init(&GlobalMid_Lock); spin_lock_init(&GlobalMid_Lock);
spin_lock_init(&cifs_oplock_lock);
if (cifs_max_pending < 2) { if (cifs_max_pending < 2) {
cifs_max_pending = 2; cifs_max_pending = 2;
......
...@@ -656,7 +656,11 @@ GLOBAL_EXTERN rwlock_t cifs_tcp_ses_lock; ...@@ -656,7 +656,11 @@ GLOBAL_EXTERN rwlock_t cifs_tcp_ses_lock;
*/ */
GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;
GLOBAL_EXTERN struct list_head GlobalOplock_Q; /* Global list of oplocks */
GLOBAL_EXTERN struct list_head cifs_oplock_list;
/* Protects the cifs_oplock_list */
GLOBAL_EXTERN spinlock_t cifs_oplock_lock;
/* Outstanding dir notify requests */ /* Outstanding dir notify requests */
GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; GLOBAL_EXTERN struct list_head GlobalDnotifyReqList;
......
...@@ -119,20 +119,19 @@ AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon) ...@@ -119,20 +119,19 @@ AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon)
temp->pinode = pinode; temp->pinode = pinode;
temp->tcon = tcon; temp->tcon = tcon;
temp->netfid = fid; temp->netfid = fid;
spin_lock(&GlobalMid_Lock); spin_lock(&cifs_oplock_lock);
list_add_tail(&temp->qhead, &GlobalOplock_Q); list_add_tail(&temp->qhead, &cifs_oplock_list);
spin_unlock(&GlobalMid_Lock); spin_unlock(&cifs_oplock_lock);
} }
return temp; return temp;
} }
void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry) void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry)
{ {
spin_lock(&GlobalMid_Lock); spin_lock(&cifs_oplock_lock);
/* should we check if list empty first? */ /* should we check if list empty first? */
list_del(&oplockEntry->qhead); list_del(&oplockEntry->qhead);
spin_unlock(&GlobalMid_Lock); spin_unlock(&cifs_oplock_lock);
kmem_cache_free(cifs_oplock_cachep, oplockEntry); kmem_cache_free(cifs_oplock_cachep, oplockEntry);
} }
...@@ -144,14 +143,14 @@ void DeleteTconOplockQEntries(struct cifsTconInfo *tcon) ...@@ -144,14 +143,14 @@ void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
if (tcon == NULL) if (tcon == NULL)
return; return;
spin_lock(&GlobalMid_Lock); spin_lock(&cifs_oplock_lock);
list_for_each_entry(temp, &GlobalOplock_Q, qhead) { list_for_each_entry(temp, &cifs_oplock_list, qhead) {
if ((temp->tcon) && (temp->tcon == tcon)) { if ((temp->tcon) && (temp->tcon == tcon)) {
list_del(&temp->qhead); list_del(&temp->qhead);
kmem_cache_free(cifs_oplock_cachep, temp); kmem_cache_free(cifs_oplock_cachep, temp);
} }
} }
spin_unlock(&GlobalMid_Lock); spin_unlock(&cifs_oplock_lock);
} }
static int static int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment