Re: [PATCH] CIFS: Fix oplock break handling (try #2)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 17 Jan 2011 20:15:44 +0300
Pavel Shilovsky <piastryyy@xxxxxxxxx> wrote:

> 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@xxxxxxxxx>
> Cc: <stable@xxxxxxxxxx>
> ---
>  fs/cifs/cifsproto.h |    2 +-
>  fs/cifs/cifssmb.c   |    4 +++-
>  fs/cifs/file.c      |   21 +++++++++++----------
>  fs/cifs/misc.c      |    2 +-
>  4 files changed, 16 insertions(+), 13 deletions(-)
> 
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index e6d1481..95d5dbb 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -347,7 +347,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 *,
> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> index 2f6795e..3652cc6 100644
> --- a/fs/cifs/cifssmb.c
> +++ b/fs/cifs/cifssmb.c
> @@ -1663,7 +1663,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;
> @@ -1691,6 +1692,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 */
>  
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index d843631..af37191 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)
>  
>  		/* 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 "
> @@ -748,13 +748,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 "
> @@ -797,8 +797,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. */
> @@ -818,9 +818,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;
>  					else {
> @@ -2192,7 +2192,8 @@ void cifs_oplock_break(struct work_struct *work)
>  	 */
>  	if (!cfile->oplock_break_cancelled) {
>  		rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0,
> -				 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false);
> +				 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false,
> +				 cinode->clientCanCacheRead ? 1 : 0);
>  		cFYI(1, "Oplock release rc = %d", rc);
>  	}
>  
> diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
> index 43f1028..09bfcf0 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)
>  				pCifsInode = CIFS_I(netfile->dentry->d_inode);
>  
>  				cifs_set_oplock_level(pCifsInode,
> -						      pSMB->OplockLevel);
> +					pSMB->OplockLevel ? OPLOCK_READ : 0);
>  				/*
>  				 * cifs_oplock_break_put() can't be called
>  				 * from here.  Get reference after queueing

Looks fine...

It might be nice to eventually package up the args to CIFSSMBLock in a
struct as the argument list is becoming quite long. That's probably best
suited to a later cleanup patch though.

Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux