diff options
Diffstat (limited to 'fs/cifs/misc.c')
| -rw-r--r-- | fs/cifs/misc.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index e079a9190ec4..0241b25ac33f 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
| @@ -32,7 +32,6 @@ | |||
| 32 | 32 | ||
| 33 | extern mempool_t *cifs_sm_req_poolp; | 33 | extern mempool_t *cifs_sm_req_poolp; |
| 34 | extern mempool_t *cifs_req_poolp; | 34 | extern mempool_t *cifs_req_poolp; |
| 35 | extern struct task_struct *oplockThread; | ||
| 36 | 35 | ||
| 37 | /* The xid serves as a useful identifier for each incoming vfs request, | 36 | /* The xid serves as a useful identifier for each incoming vfs request, |
| 38 | in a similar way to the mid which is useful to track each sent smb, | 37 | in a similar way to the mid which is useful to track each sent smb, |
| @@ -500,6 +499,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | |||
| 500 | struct cifsTconInfo *tcon; | 499 | struct cifsTconInfo *tcon; |
| 501 | struct cifsInodeInfo *pCifsInode; | 500 | struct cifsInodeInfo *pCifsInode; |
| 502 | struct cifsFileInfo *netfile; | 501 | struct cifsFileInfo *netfile; |
| 502 | int rc; | ||
| 503 | 503 | ||
| 504 | cFYI(1, ("Checking for oplock break or dnotify response")); | 504 | cFYI(1, ("Checking for oplock break or dnotify response")); |
| 505 | if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) && | 505 | if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) && |
| @@ -562,30 +562,40 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | |||
| 562 | continue; | 562 | continue; |
| 563 | 563 | ||
| 564 | cifs_stats_inc(&tcon->num_oplock_brks); | 564 | cifs_stats_inc(&tcon->num_oplock_brks); |
| 565 | write_lock(&GlobalSMBSeslock); | 565 | read_lock(&GlobalSMBSeslock); |
| 566 | list_for_each(tmp2, &tcon->openFileList) { | 566 | list_for_each(tmp2, &tcon->openFileList) { |
| 567 | netfile = list_entry(tmp2, struct cifsFileInfo, | 567 | netfile = list_entry(tmp2, struct cifsFileInfo, |
| 568 | tlist); | 568 | tlist); |
| 569 | if (pSMB->Fid != netfile->netfid) | 569 | if (pSMB->Fid != netfile->netfid) |
| 570 | continue; | 570 | continue; |
| 571 | 571 | ||
| 572 | write_unlock(&GlobalSMBSeslock); | 572 | /* |
| 573 | read_unlock(&cifs_tcp_ses_lock); | 573 | * don't do anything if file is about to be |
| 574 | * closed anyway. | ||
| 575 | */ | ||
| 576 | if (netfile->closePend) { | ||
| 577 | read_unlock(&GlobalSMBSeslock); | ||
| 578 | read_unlock(&cifs_tcp_ses_lock); | ||
| 579 | return true; | ||
| 580 | } | ||
| 581 | |||
| 574 | cFYI(1, ("file id match, oplock break")); | 582 | cFYI(1, ("file id match, oplock break")); |
| 575 | pCifsInode = CIFS_I(netfile->pInode); | 583 | pCifsInode = CIFS_I(netfile->pInode); |
| 576 | pCifsInode->clientCanCacheAll = false; | 584 | pCifsInode->clientCanCacheAll = false; |
| 577 | if (pSMB->OplockLevel == 0) | 585 | if (pSMB->OplockLevel == 0) |
| 578 | pCifsInode->clientCanCacheRead = false; | 586 | pCifsInode->clientCanCacheRead = false; |
| 579 | pCifsInode->oplockPending = true; | 587 | rc = slow_work_enqueue(&netfile->oplock_break); |
| 580 | AllocOplockQEntry(netfile->pInode, | 588 | if (rc) { |
| 581 | netfile->netfid, tcon); | 589 | cERROR(1, ("failed to enqueue oplock " |
| 582 | cFYI(1, ("about to wake up oplock thread")); | 590 | "break: %d\n", rc)); |
| 583 | if (oplockThread) | 591 | } else { |
| 584 | wake_up_process(oplockThread); | 592 | netfile->oplock_break_cancelled = false; |
| 585 | 593 | } | |
| 594 | read_unlock(&GlobalSMBSeslock); | ||
| 595 | read_unlock(&cifs_tcp_ses_lock); | ||
| 586 | return true; | 596 | return true; |
| 587 | } | 597 | } |
| 588 | write_unlock(&GlobalSMBSeslock); | 598 | read_unlock(&GlobalSMBSeslock); |
| 589 | read_unlock(&cifs_tcp_ses_lock); | 599 | read_unlock(&cifs_tcp_ses_lock); |
| 590 | cFYI(1, ("No matching file for oplock break")); | 600 | cFYI(1, ("No matching file for oplock break")); |
| 591 | return true; | 601 | return true; |
