]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
CIFS: Fix oplock break handling (try #2)
authorPavel Shilovsky <piastryyy@gmail.com>
Mon, 17 Jan 2011 17:15:44 +0000 (20:15 +0300)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 21 Mar 2011 19:45:28 +0000 (12:45 -0700)
commit 12fed00de963433128b5366a21a55808fab2f756 upstream.

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>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/file.c

index 05a9b776e1a8132a3853a09f20ae13d8f79abd8e..76d9f64692e4e1f96f95e7a091cc0b1c7c27fea4 100644 (file)
@@ -323,7 +323,7 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
                        const __u16 netfid, const __u64 len,
                        const __u64 offset, const __u32 numUnlock,
                        const __u32 numLock, const __u8 lockType,
-                       const bool waitFlag);
+                       const bool waitFlag, const __u8 oplock_level);
 extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
                        const __u16 smb_file_id, const int get_flag,
                        const __u64 len, struct file_lock *,
index 4e6dbab84435b6b47bbcbd6b1e04b1a8729b1026..04b755ae1b38c2f8e43a6f8d1468522c7f56d38c 100644 (file)
@@ -1641,7 +1641,8 @@ int
 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
            const __u16 smb_file_id, const __u64 len,
            const __u64 offset, const __u32 numUnlock,
-           const __u32 numLock, const __u8 lockType, const bool waitFlag)
+           const __u32 numLock, const __u8 lockType,
+           const bool waitFlag, const __u8 oplock_level)
 {
        int rc = 0;
        LOCK_REQ *pSMB = NULL;
@@ -1669,6 +1670,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
        pSMB->NumberOfLocks = cpu_to_le16(numLock);
        pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
        pSMB->LockType = lockType;
+       pSMB->OplockLevel = oplock_level;
        pSMB->AndXCommand = 0xFF;       /* none */
        pSMB->Fid = smb_file_id; /* netfid stays le */
 
index 8639dd79bd3480b69b1fc75ab6e33927ec534ff0..99387a4e141db58c9c857f798570427c02754b8d 100644 (file)
@@ -827,12 +827,12 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
 
                /* BB we could chain these into one lock request BB */
                rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start,
-                                0, 1, lockType, 0 /* wait flag */ );
+                                0, 1, lockType, 0 /* wait flag */, 0);
                if (rc == 0) {
                        rc = CIFSSMBLock(xid, tcon, netfid, length,
                                         pfLock->fl_start, 1 /* numUnlock */ ,
                                         0 /* numLock */ , lockType,
-                                        0 /* wait flag */ );
+                                        0 /* wait flag */, 0);
                        pfLock->fl_type = F_UNLCK;
                        if (rc != 0)
                                cERROR(1, ("Error unlocking previously locked "
@@ -875,8 +875,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
 
                if (numLock) {
                        rc = CIFSSMBLock(xid, tcon, netfid, length,
-                                       pfLock->fl_start,
-                                       0, numLock, lockType, wait_flag);
+                                        pfLock->fl_start, 0, numLock, lockType,
+                                        wait_flag, 0);
 
                        if (rc == 0) {
                                /* For Windows locks we must store them. */
@@ -896,9 +896,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
                                                (pfLock->fl_start + length) >=
                                                (li->offset + li->length)) {
                                        stored_rc = CIFSSMBLock(xid, tcon,
-                                                       netfid,
-                                                       li->length, li->offset,
-                                                       1, 0, li->type, false);
+                                                       netfid, li->length,
+                                                       li->offset, 1, 0,
+                                                       li->type, false, 0);
                                        if (stored_rc)
                                                rc = stored_rc;
 
@@ -2316,7 +2316,8 @@ cifs_oplock_break(struct slow_work *work)
         */
        if (!cfile->closePend && !cfile->oplock_break_cancelled) {
                rc = CIFSSMBLock(0, cifs_sb->tcon, cfile->netfid, 0, 0, 0, 0,
-                                LOCKING_ANDX_OPLOCK_RELEASE, false);
+                                LOCKING_ANDX_OPLOCK_RELEASE, false,
+                                cinode->clientCanCacheRead ? 1 : 0);
                cFYI(1, ("Oplock release rc = %d", rc));
        }
 }