CIFS: Add SMB2 credits support
For SMB2 protocol we can add more than one credit for one received request: it depends on CreditRequest field in SMB2 response header. Also we divide all requests by type: echoes, oplocks and others. Each type uses its own slot pull. Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org> Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:
parent
2dc7e1c033
commit
28ea5290d7
|
@ -343,6 +343,11 @@ struct TCP_Server_Info {
|
||||||
char server_GUID[16];
|
char server_GUID[16];
|
||||||
__u16 sec_mode;
|
__u16 sec_mode;
|
||||||
bool session_estab; /* mark when very first sess is established */
|
bool session_estab; /* mark when very first sess is established */
|
||||||
|
#ifdef CONFIG_CIFS_SMB2
|
||||||
|
int echo_credits; /* echo reserved slots */
|
||||||
|
int oplock_credits; /* oplock break reserved slots */
|
||||||
|
bool echoes:1; /* enable echoes */
|
||||||
|
#endif
|
||||||
u16 dialect; /* dialect index that server chose */
|
u16 dialect; /* dialect index that server chose */
|
||||||
enum securityEnum secType;
|
enum securityEnum secType;
|
||||||
bool oplocks:1; /* enable oplocks */
|
bool oplocks:1; /* enable oplocks */
|
||||||
|
|
|
@ -91,6 +91,7 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
|
||||||
struct smb_hdr *in_buf ,
|
struct smb_hdr *in_buf ,
|
||||||
struct smb_hdr *out_buf,
|
struct smb_hdr *out_buf,
|
||||||
int *bytes_returned);
|
int *bytes_returned);
|
||||||
|
extern int cifs_reconnect(struct TCP_Server_Info *server);
|
||||||
extern int checkSMB(char *buf, unsigned int length);
|
extern int checkSMB(char *buf, unsigned int length);
|
||||||
extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
|
extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
|
||||||
extern bool backup_cred(struct cifs_sb_info *);
|
extern bool backup_cred(struct cifs_sb_info *);
|
||||||
|
|
|
@ -297,7 +297,7 @@ static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
|
||||||
* reconnect tcp session
|
* reconnect tcp session
|
||||||
* wake up waiters on reconnection? - (not needed currently)
|
* wake up waiters on reconnection? - (not needed currently)
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
cifs_reconnect(struct TCP_Server_Info *server)
|
cifs_reconnect(struct TCP_Server_Info *server)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
|
@ -20,6 +20,81 @@
|
||||||
#include "cifsglob.h"
|
#include "cifsglob.h"
|
||||||
#include "smb2pdu.h"
|
#include "smb2pdu.h"
|
||||||
#include "smb2proto.h"
|
#include "smb2proto.h"
|
||||||
|
#include "cifsproto.h"
|
||||||
|
#include "cifs_debug.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
change_conf(struct TCP_Server_Info *server)
|
||||||
|
{
|
||||||
|
server->credits += server->echo_credits + server->oplock_credits;
|
||||||
|
server->oplock_credits = server->echo_credits = 0;
|
||||||
|
switch (server->credits) {
|
||||||
|
case 0:
|
||||||
|
return -1;
|
||||||
|
case 1:
|
||||||
|
server->echoes = false;
|
||||||
|
server->oplocks = false;
|
||||||
|
cERROR(1, "disabling echoes and oplocks");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
server->echoes = true;
|
||||||
|
server->oplocks = false;
|
||||||
|
server->echo_credits = 1;
|
||||||
|
cFYI(1, "disabling oplocks");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
server->echoes = true;
|
||||||
|
server->oplocks = true;
|
||||||
|
server->echo_credits = 1;
|
||||||
|
server->oplock_credits = 1;
|
||||||
|
}
|
||||||
|
server->credits -= server->echo_credits + server->oplock_credits;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
|
||||||
|
const int optype)
|
||||||
|
{
|
||||||
|
int *val, rc = 0;
|
||||||
|
spin_lock(&server->req_lock);
|
||||||
|
val = server->ops->get_credits_field(server, optype);
|
||||||
|
*val += add;
|
||||||
|
server->in_flight--;
|
||||||
|
if (server->in_flight == 0)
|
||||||
|
rc = change_conf(server);
|
||||||
|
spin_unlock(&server->req_lock);
|
||||||
|
wake_up(&server->request_q);
|
||||||
|
if (rc)
|
||||||
|
cifs_reconnect(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
smb2_set_credits(struct TCP_Server_Info *server, const int val)
|
||||||
|
{
|
||||||
|
spin_lock(&server->req_lock);
|
||||||
|
server->credits = val;
|
||||||
|
spin_unlock(&server->req_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int *
|
||||||
|
smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
|
||||||
|
{
|
||||||
|
switch (optype) {
|
||||||
|
case CIFS_ECHO_OP:
|
||||||
|
return &server->echo_credits;
|
||||||
|
case CIFS_OBREAK_OP:
|
||||||
|
return &server->oplock_credits;
|
||||||
|
default:
|
||||||
|
return &server->credits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
smb2_get_credits(struct mid_q_entry *mid)
|
||||||
|
{
|
||||||
|
return le16_to_cpu(((struct smb2_hdr *)mid->resp_buf)->CreditRequest);
|
||||||
|
}
|
||||||
|
|
||||||
static __u64
|
static __u64
|
||||||
smb2_get_next_mid(struct TCP_Server_Info *server)
|
smb2_get_next_mid(struct TCP_Server_Info *server)
|
||||||
|
@ -35,6 +110,10 @@ smb2_get_next_mid(struct TCP_Server_Info *server)
|
||||||
struct smb_version_operations smb21_operations = {
|
struct smb_version_operations smb21_operations = {
|
||||||
.setup_request = smb2_setup_request,
|
.setup_request = smb2_setup_request,
|
||||||
.check_receive = smb2_check_receive,
|
.check_receive = smb2_check_receive,
|
||||||
|
.add_credits = smb2_add_credits,
|
||||||
|
.set_credits = smb2_set_credits,
|
||||||
|
.get_credits_field = smb2_get_credits_field,
|
||||||
|
.get_credits = smb2_get_credits,
|
||||||
.get_next_mid = smb2_get_next_mid,
|
.get_next_mid = smb2_get_next_mid,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Reference in New Issue