Re: [PATCH 06/50] CIFS: Add SMB2 credits support

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

 



On Fri, 20 Jan 2012 12:34:27 +0400
Pavel Shilovsky <piastry@xxxxxxxxxxx> wrote:

> From: Steve French <sfrench@xxxxxxxxxx>
> 
> Convert wait_for_free_request to wait on available credits
> for SMB2 servers and decrement a credit number for every call.
> Increment the credit number in smb2_sendrcv2 with every response
> got from the server.
> 
> Signed-off-by: Pavel Shilovsky <piastry@xxxxxxxxxxx>
> ---
>  fs/cifs/cifsglob.h      |    1 +
>  fs/cifs/cifsproto.h     |    2 +-
>  fs/cifs/smb2transport.c |    6 ++++++
>  fs/cifs/transport.c     |   20 ++++++++++++++++++--
>  4 files changed, 26 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index bb2af48..e5f0b86 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -318,6 +318,7 @@ struct TCP_Server_Info {
>  	atomic_t num_waiters;   /* blocked waiting to get in sendrecv */
>  #endif
>  #ifdef CONFIG_CIFS_SMB2
> +	atomic_t credits; /* send no more simultaneous requests than this */
>  	__u64 current_smb2_mid;         /* multiplex id - rotating counter */
>  #endif
>  };
> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> index d1e30d9..b6c784b 100644
> --- a/fs/cifs/cifsproto.h
> +++ b/fs/cifs/cifsproto.h
> @@ -1,7 +1,7 @@
>  /*
>   *   fs/cifs/cifsproto.h
>   *
> - *   Copyright (c) International Business Machines  Corp., 2002,2008
> + *   Copyright (c) International Business Machines  Corp., 2002,2011
>   *   Author(s): Steve French (sfrench@xxxxxxxxxx)
>   *
>   *   This library is free software; you can redistribute it and/or modify
> diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
> index d7f1c05..b5702f3 100644
> --- a/fs/cifs/smb2transport.c
> +++ b/fs/cifs/smb2transport.c
> @@ -148,6 +148,7 @@ smb2_sendrcv2(const unsigned int xid, struct cifs_ses *ses,
>  	unsigned int receive_len;
>  	struct mid_q_entry *midQ;
>  	struct smb2_hdr *buf = iov[0].iov_base;
> +	unsigned int credits = 1;
>  
>  	if (status)
>  		*status = STATUS_SUCCESS;
> @@ -186,6 +187,7 @@ smb2_sendrcv2(const unsigned int xid, struct cifs_ses *ses,
>  	if (rc) {
>  		mutex_unlock(&ses->server->srv_mutex);
>  		cifs_small_buf_release(buf);
> +		atomic_inc(&ses->server->credits);
>  		wake_up(&ses->server->request_q);
>  		return rc;
>  	}
> @@ -222,6 +224,7 @@ smb2_sendrcv2(const unsigned int xid, struct cifs_ses *ses,
>  			midQ->callback = cifs_delete_mid;
>  			spin_unlock(&GlobalMid_Lock);
>  			cifs_small_buf_release(buf);
> +			atomic_inc(&ses->server->credits);
>  			wake_up(&ses->server->request_q);
>  			return rc;
>  		}
> @@ -232,6 +235,7 @@ smb2_sendrcv2(const unsigned int xid, struct cifs_ses *ses,
>  
>  	rc = cifs_sync_mid_result(midQ, ses->server);
>  	if (rc) {
> +		atomic_inc(&ses->server->credits);
>  		wake_up(&ses->server->request_q);
>  		return rc;
>  	}
> @@ -271,7 +275,9 @@ smb2_sendrcv2(const unsigned int xid, struct cifs_ses *ses,
>  		/* mark it so buf will not be freed by free_smb2mid */
>  		midQ->resp_buf = NULL;
>  
> +	credits = le16_to_cpu(buf->CreditRequest);
>  out:
> +	atomic_add(credits, &ses->server->credits);
>  	cifs_delete_mid(midQ);
>  	wake_up(&ses->server->request_q);
>  	return rc;
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index f7ac3f0..4414df8 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -287,7 +287,8 @@ cifs_wait_for_free_request(struct TCP_Server_Info *server, const int long_op)
>  
>  	spin_lock(&GlobalMid_Lock);
>  	while (1) {
> -		if (atomic_read(&server->inFlight) >= cifs_max_pending) {
> +		if ((server->is_smb2 == false) &&
> +		    atomic_read(&server->inFlight) >= cifs_max_pending) {
>  			spin_unlock(&GlobalMid_Lock);
>  			cifs_num_waiters_inc(server);
>  			wait_event(server->request_q,
> @@ -295,6 +296,16 @@ cifs_wait_for_free_request(struct TCP_Server_Info *server, const int long_op)
>  				     < cifs_max_pending);
>  			cifs_num_waiters_dec(server);
>  			spin_lock(&GlobalMid_Lock);
> +#ifdef CONFIG_CIFS_SMB2
> +		} else if (server->is_smb2 &&
> +			  (atomic_read(&server->credits) < 1)) {
> +			spin_unlock(&GlobalMid_Lock);
> +			cifs_num_waiters_inc(server);
> +			wait_event(server->request_q,
> +				   atomic_read(&server->credits) > 0);
> +			cifs_num_waiters_dec(server);
> +			spin_lock(&GlobalMid_Lock);
> +#endif /* CONFIG_CIFS_SMB2 */
>  		} else {
>  			if (server->tcpStatus == CifsExiting) {
>  				spin_unlock(&GlobalMid_Lock);
> @@ -305,8 +316,13 @@ cifs_wait_for_free_request(struct TCP_Server_Info *server, const int long_op)
>  			   as they are allowed to block on server */
>  
>  			/* update # of requests on the wire to server */
> -			if (long_op != CIFS_BLOCKING_OP)
> +			if (server->is_smb2 == false &&
> +			    long_op != CIFS_BLOCKING_OP)
>  				atomic_inc(&server->inFlight);
> +#ifdef CONFIG_CIFS_SMB2
> +			else if (server->is_smb2)
> +				atomic_dec(&server->credits);
> +#endif
>  			spin_unlock(&GlobalMid_Lock);
>  			break;
>  		}

I'd like to suggest an alternate approach here...

Instead of considering this as a SMB1 vs. SMB2 either/or thing we
should consider the SMB1 case to be a special case of SMB2 credits. In
the SMB1 NEGOTIATE response, the server sends us a MaxMpx value. We
could consider that to be an initial set of credits. Every time we get
a SMB1 response from the server, we'll increment the credit value.

If we do that, then there's a lot less protocol dependent code that's
needed, and if done correctly should also fix the current bug in
the SMB1 code where it ignores the MaxMpx value.

Thoughts?
-- 
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