]> git.kernelconcepts.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)
committerPaul Gortmaker <paul.gortmaker@windriver.com>
Sun, 26 Jun 2011 16:46:55 +0000 (12:46 -0400)
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.

[PG: above OplockLevel bug only exists via. e66673e39a which didn't
appear until v2.6.37-rc2, so cifs/misc.c hunk dropped.]

Signed-off-by: Pavel Shilovsky <piastryyy@gmail.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/file.c

index a6db615568ba0be9a87dfed0c6afb11e6ea7950a..ef0db18d17e9f4fe111349c705af9086f733a839 100644 (file)
@@ -329,7 +329,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 5d3f29fef53228eec75dccac45b2d58697d57775..62e49ab50b5edb90631dcf4d5c28f51174d0192d 100644 (file)
@@ -1642,7 +1642,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;
@@ -1670,6 +1671,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 4cbdb204d288c9db138f139cfb1cc6c9c170330a..1ab76709b13361977f667d94d74631004e6b1064 100644 (file)
@@ -828,12 +828,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 "
@@ -850,13 +850,13 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
                                rc = CIFSSMBLock(xid, tcon, netfid, length,
                                        pfLock->fl_start, 0, 1,
                                        lockType | LOCKING_ANDX_SHARED_LOCK,
-                                       0 /* wait flag */);
+                                       0 /* wait flag */, 0);
                                if (rc == 0) {
                                        rc = CIFSSMBLock(xid, tcon, netfid,
                                                length, pfLock->fl_start, 1, 0,
                                                lockType |
                                                LOCKING_ANDX_SHARED_LOCK,
-                                               0 /* wait flag */);
+                                               0 /* wait flag */, 0);
                                        pfLock->fl_type = F_RDLCK;
                                        if (rc != 0)
                                                cERROR(1, ("Error unlocking "
@@ -900,8 +900,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. */
@@ -921,9 +921,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;
 
@@ -2340,7 +2340,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));
        }
 }