Skip to content

Commit

Permalink
CIFS: Add SMB2 credits support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Pavel Shilovsky authored and Steve French committed Jul 24, 2012
1 parent 2dc7e1c commit 28ea529
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 1 deletion.
5 changes: 5 additions & 0 deletions fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,11 @@ struct TCP_Server_Info {
char server_GUID[16];
__u16 sec_mode;
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 */
enum securityEnum secType;
bool oplocks:1; /* enable oplocks */
Expand Down
1 change: 1 addition & 0 deletions fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
struct smb_hdr *in_buf ,
struct smb_hdr *out_buf,
int *bytes_returned);
extern int cifs_reconnect(struct TCP_Server_Info *server);
extern int checkSMB(char *buf, unsigned int length);
extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
extern bool backup_cred(struct cifs_sb_info *);
Expand Down
2 changes: 1 addition & 1 deletion fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
* reconnect tcp session
* wake up waiters on reconnection? - (not needed currently)
*/
static int
int
cifs_reconnect(struct TCP_Server_Info *server)
{
int rc = 0;
Expand Down
79 changes: 79 additions & 0 deletions fs/cifs/smb2ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,81 @@
#include "cifsglob.h"
#include "smb2pdu.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
smb2_get_next_mid(struct TCP_Server_Info *server)
Expand All @@ -35,6 +110,10 @@ smb2_get_next_mid(struct TCP_Server_Info *server)
struct smb_version_operations smb21_operations = {
.setup_request = smb2_setup_request,
.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,
};

Expand Down

0 comments on commit 28ea529

Please sign in to comment.