diff options
author | Pavel Shilovsky <pshilovsky@samba.org> | 2012-05-23 08:18:00 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-07-24 11:25:23 -0400 |
commit | 28ea5290d78a7fc87a4b4f7cedcaa662f5b8d977 (patch) | |
tree | 25f091cdd90fa160d0a10ce2798c7960bdfd051c /fs/cifs | |
parent | 2dc7e1c03316940dec899fa3206a595de000e99b (diff) |
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>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsglob.h | 5 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 1 | ||||
-rw-r--r-- | fs/cifs/connect.c | 2 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 79 |
4 files changed, 86 insertions, 1 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 3575f0f832b1..480b6385a9b6 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -343,6 +343,11 @@ struct TCP_Server_Info { | |||
343 | char server_GUID[16]; | 343 | char server_GUID[16]; |
344 | __u16 sec_mode; | 344 | __u16 sec_mode; |
345 | bool session_estab; /* mark when very first sess is established */ | 345 | bool session_estab; /* mark when very first sess is established */ |
346 | #ifdef CONFIG_CIFS_SMB2 | ||
347 | int echo_credits; /* echo reserved slots */ | ||
348 | int oplock_credits; /* oplock break reserved slots */ | ||
349 | bool echoes:1; /* enable echoes */ | ||
350 | #endif | ||
346 | u16 dialect; /* dialect index that server chose */ | 351 | u16 dialect; /* dialect index that server chose */ |
347 | enum securityEnum secType; | 352 | enum securityEnum secType; |
348 | bool oplocks:1; /* enable oplocks */ | 353 | bool oplocks:1; /* enable oplocks */ |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 88967d0885bf..3b4d41f9ceeb 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -91,6 +91,7 @@ extern int SendReceiveBlockingLock(const unsigned int xid, | |||
91 | struct smb_hdr *in_buf , | 91 | struct smb_hdr *in_buf , |
92 | struct smb_hdr *out_buf, | 92 | struct smb_hdr *out_buf, |
93 | int *bytes_returned); | 93 | int *bytes_returned); |
94 | extern int cifs_reconnect(struct TCP_Server_Info *server); | ||
94 | extern int checkSMB(char *buf, unsigned int length); | 95 | extern int checkSMB(char *buf, unsigned int length); |
95 | extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *); | 96 | extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *); |
96 | extern bool backup_cred(struct cifs_sb_info *); | 97 | extern bool backup_cred(struct cifs_sb_info *); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index cfb7e7797642..a6197224b102 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -297,7 +297,7 @@ static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data, | |||
297 | * reconnect tcp session | 297 | * reconnect tcp session |
298 | * wake up waiters on reconnection? - (not needed currently) | 298 | * wake up waiters on reconnection? - (not needed currently) |
299 | */ | 299 | */ |
300 | static int | 300 | int |
301 | cifs_reconnect(struct TCP_Server_Info *server) | 301 | cifs_reconnect(struct TCP_Server_Info *server) |
302 | { | 302 | { |
303 | int rc = 0; | 303 | int rc = 0; |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 09530f416123..67a05984cd41 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -20,6 +20,81 @@ | |||
20 | #include "cifsglob.h" | 20 | #include "cifsglob.h" |
21 | #include "smb2pdu.h" | 21 | #include "smb2pdu.h" |
22 | #include "smb2proto.h" | 22 | #include "smb2proto.h" |
23 | #include "cifsproto.h" | ||
24 | #include "cifs_debug.h" | ||
25 | |||
26 | static int | ||
27 | change_conf(struct TCP_Server_Info *server) | ||
28 | { | ||
29 | server->credits += server->echo_credits + server->oplock_credits; | ||
30 | server->oplock_credits = server->echo_credits = 0; | ||
31 | switch (server->credits) { | ||
32 | case 0: | ||
33 | return -1; | ||
34 | case 1: | ||
35 | server->echoes = false; | ||
36 | server->oplocks = false; | ||
37 | cERROR(1, "disabling echoes and oplocks"); | ||
38 | break; | ||
39 | case 2: | ||
40 | server->echoes = true; | ||
41 | server->oplocks = false; | ||
42 | server->echo_credits = 1; | ||
43 | cFYI(1, "disabling oplocks"); | ||
44 | break; | ||
45 | default: | ||
46 | server->echoes = true; | ||
47 | server->oplocks = true; | ||
48 | server->echo_credits = 1; | ||
49 | server->oplock_credits = 1; | ||
50 | } | ||
51 | server->credits -= server->echo_credits + server->oplock_credits; | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static void | ||
56 | smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add, | ||
57 | const int optype) | ||
58 | { | ||
59 | int *val, rc = 0; | ||
60 | spin_lock(&server->req_lock); | ||
61 | val = server->ops->get_credits_field(server, optype); | ||
62 | *val += add; | ||
63 | server->in_flight--; | ||
64 | if (server->in_flight == 0) | ||
65 | rc = change_conf(server); | ||
66 | spin_unlock(&server->req_lock); | ||
67 | wake_up(&server->request_q); | ||
68 | if (rc) | ||
69 | cifs_reconnect(server); | ||
70 | } | ||
71 | |||
72 | static void | ||
73 | smb2_set_credits(struct TCP_Server_Info *server, const int val) | ||
74 | { | ||
75 | spin_lock(&server->req_lock); | ||
76 | server->credits = val; | ||
77 | spin_unlock(&server->req_lock); | ||
78 | } | ||
79 | |||
80 | static int * | ||
81 | smb2_get_credits_field(struct TCP_Server_Info *server, const int optype) | ||
82 | { | ||
83 | switch (optype) { | ||
84 | case CIFS_ECHO_OP: | ||
85 | return &server->echo_credits; | ||
86 | case CIFS_OBREAK_OP: | ||
87 | return &server->oplock_credits; | ||
88 | default: | ||
89 | return &server->credits; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | static unsigned int | ||
94 | smb2_get_credits(struct mid_q_entry *mid) | ||
95 | { | ||
96 | return le16_to_cpu(((struct smb2_hdr *)mid->resp_buf)->CreditRequest); | ||
97 | } | ||
23 | 98 | ||
24 | static __u64 | 99 | static __u64 |
25 | smb2_get_next_mid(struct TCP_Server_Info *server) | 100 | smb2_get_next_mid(struct TCP_Server_Info *server) |
@@ -35,6 +110,10 @@ smb2_get_next_mid(struct TCP_Server_Info *server) | |||
35 | struct smb_version_operations smb21_operations = { | 110 | struct smb_version_operations smb21_operations = { |
36 | .setup_request = smb2_setup_request, | 111 | .setup_request = smb2_setup_request, |
37 | .check_receive = smb2_check_receive, | 112 | .check_receive = smb2_check_receive, |
113 | .add_credits = smb2_add_credits, | ||
114 | .set_credits = smb2_set_credits, | ||
115 | .get_credits_field = smb2_get_credits_field, | ||
116 | .get_credits = smb2_get_credits, | ||
38 | .get_next_mid = smb2_get_next_mid, | 117 | .get_next_mid = smb2_get_next_mid, |
39 | }; | 118 | }; |
40 | 119 | ||