aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorPavel Shilovsky <piastryyy@gmail.com>2011-01-17 12:15:44 -0500
committerSteve French <sfrench@us.ibm.com>2011-01-19 12:52:29 -0500
commit12fed00de963433128b5366a21a55808fab2f756 (patch)
tree2898690f5853027b70eda1bd7f3aeb78fe9af74d /fs
parentc56eb8fb6dccb83d9fe62fd4dc00c834de9bc470 (diff)
CIFS: Fix oplock break handling (try #2)
When we get oplock break notification we should set the appropriate value of OplockLevel field in oplock break acknowledge according to the oplock level held by the client in this time. As we only can have level II oplock or no oplock in the case of oplock break, we should be aware only about clientCanCacheRead field in cifsInodeInfo structure. Also fix bug connected with wrong interpretation of OplockLevel field during oplock break notification processing. Signed-off-by: Pavel Shilovsky <piastryyy@gmail.com> Cc: <stable@kernel.org> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/cifssmb.c4
-rw-r--r--fs/cifs/file.c21
-rw-r--r--fs/cifs/misc.c2
4 files changed, 16 insertions, 13 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index e6d1481b16c1..95d5dbbb4c7a 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -347,7 +347,7 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
347 const __u16 netfid, const __u64 len, 347 const __u16 netfid, const __u64 len,
348 const __u64 offset, const __u32 numUnlock, 348 const __u64 offset, const __u32 numUnlock,
349 const __u32 numLock, const __u8 lockType, 349 const __u32 numLock, const __u8 lockType,
350 const bool waitFlag); 350 const bool waitFlag, const __u8 oplock_level);
351extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, 351extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
352 const __u16 smb_file_id, const int get_flag, 352 const __u16 smb_file_id, const int get_flag,
353 const __u64 len, struct file_lock *, 353 const __u64 len, struct file_lock *,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 2f6795e524d3..3652cc60314c 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1663,7 +1663,8 @@ int
1663CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, 1663CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1664 const __u16 smb_file_id, const __u64 len, 1664 const __u16 smb_file_id, const __u64 len,
1665 const __u64 offset, const __u32 numUnlock, 1665 const __u64 offset, const __u32 numUnlock,
1666 const __u32 numLock, const __u8 lockType, const bool waitFlag) 1666 const __u32 numLock, const __u8 lockType,
1667 const bool waitFlag, const __u8 oplock_level)
1667{ 1668{
1668 int rc = 0; 1669 int rc = 0;
1669 LOCK_REQ *pSMB = NULL; 1670 LOCK_REQ *pSMB = NULL;
@@ -1691,6 +1692,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1691 pSMB->NumberOfLocks = cpu_to_le16(numLock); 1692 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1692 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock); 1693 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1693 pSMB->LockType = lockType; 1694 pSMB->LockType = lockType;
1695 pSMB->OplockLevel = oplock_level;
1694 pSMB->AndXCommand = 0xFF; /* none */ 1696 pSMB->AndXCommand = 0xFF; /* none */
1695 pSMB->Fid = smb_file_id; /* netfid stays le */ 1697 pSMB->Fid = smb_file_id; /* netfid stays le */
1696 1698
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index d843631c028d..af371910f543 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -726,12 +726,12 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
726 726
727 /* BB we could chain these into one lock request BB */ 727 /* BB we could chain these into one lock request BB */
728 rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start, 728 rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start,
729 0, 1, lockType, 0 /* wait flag */ ); 729 0, 1, lockType, 0 /* wait flag */, 0);
730 if (rc == 0) { 730 if (rc == 0) {
731 rc = CIFSSMBLock(xid, tcon, netfid, length, 731 rc = CIFSSMBLock(xid, tcon, netfid, length,
732 pfLock->fl_start, 1 /* numUnlock */ , 732 pfLock->fl_start, 1 /* numUnlock */ ,
733 0 /* numLock */ , lockType, 733 0 /* numLock */ , lockType,
734 0 /* wait flag */ ); 734 0 /* wait flag */, 0);
735 pfLock->fl_type = F_UNLCK; 735 pfLock->fl_type = F_UNLCK;
736 if (rc != 0) 736 if (rc != 0)
737 cERROR(1, "Error unlocking previously locked " 737 cERROR(1, "Error unlocking previously locked "
@@ -748,13 +748,13 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
748 rc = CIFSSMBLock(xid, tcon, netfid, length, 748 rc = CIFSSMBLock(xid, tcon, netfid, length,
749 pfLock->fl_start, 0, 1, 749 pfLock->fl_start, 0, 1,
750 lockType | LOCKING_ANDX_SHARED_LOCK, 750 lockType | LOCKING_ANDX_SHARED_LOCK,
751 0 /* wait flag */); 751 0 /* wait flag */, 0);
752 if (rc == 0) { 752 if (rc == 0) {
753 rc = CIFSSMBLock(xid, tcon, netfid, 753 rc = CIFSSMBLock(xid, tcon, netfid,
754 length, pfLock->fl_start, 1, 0, 754 length, pfLock->fl_start, 1, 0,
755 lockType | 755 lockType |
756 LOCKING_ANDX_SHARED_LOCK, 756 LOCKING_ANDX_SHARED_LOCK,
757 0 /* wait flag */); 757 0 /* wait flag */, 0);
758 pfLock->fl_type = F_RDLCK; 758 pfLock->fl_type = F_RDLCK;
759 if (rc != 0) 759 if (rc != 0)
760 cERROR(1, "Error unlocking " 760 cERROR(1, "Error unlocking "
@@ -797,8 +797,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
797 797
798 if (numLock) { 798 if (numLock) {
799 rc = CIFSSMBLock(xid, tcon, netfid, length, 799 rc = CIFSSMBLock(xid, tcon, netfid, length,
800 pfLock->fl_start, 800 pfLock->fl_start, 0, numLock, lockType,
801 0, numLock, lockType, wait_flag); 801 wait_flag, 0);
802 802
803 if (rc == 0) { 803 if (rc == 0) {
804 /* For Windows locks we must store them. */ 804 /* For Windows locks we must store them. */
@@ -818,9 +818,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
818 (pfLock->fl_start + length) >= 818 (pfLock->fl_start + length) >=
819 (li->offset + li->length)) { 819 (li->offset + li->length)) {
820 stored_rc = CIFSSMBLock(xid, tcon, 820 stored_rc = CIFSSMBLock(xid, tcon,
821 netfid, 821 netfid, li->length,
822 li->length, li->offset, 822 li->offset, 1, 0,
823 1, 0, li->type, false); 823 li->type, false, 0);
824 if (stored_rc) 824 if (stored_rc)
825 rc = stored_rc; 825 rc = stored_rc;
826 else { 826 else {
@@ -2192,7 +2192,8 @@ void cifs_oplock_break(struct work_struct *work)
2192 */ 2192 */
2193 if (!cfile->oplock_break_cancelled) { 2193 if (!cfile->oplock_break_cancelled) {
2194 rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0, 2194 rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0,
2195 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false); 2195 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false,
2196 cinode->clientCanCacheRead ? 1 : 0);
2196 cFYI(1, "Oplock release rc = %d", rc); 2197 cFYI(1, "Oplock release rc = %d", rc);
2197 } 2198 }
2198 2199
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 43f10281bc19..09bfcf08a90f 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -571,7 +571,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
571 pCifsInode = CIFS_I(netfile->dentry->d_inode); 571 pCifsInode = CIFS_I(netfile->dentry->d_inode);
572 572
573 cifs_set_oplock_level(pCifsInode, 573 cifs_set_oplock_level(pCifsInode,
574 pSMB->OplockLevel); 574 pSMB->OplockLevel ? OPLOCK_READ : 0);
575 /* 575 /*
576 * cifs_oplock_break_put() can't be called 576 * cifs_oplock_break_put() can't be called
577 * from here. Get reference after queueing 577 * from here. Get reference after queueing