diff options
Diffstat (limited to 'fs/cifs/smb2ops.c')
-rw-r--r-- | fs/cifs/smb2ops.c | 79 |
1 files changed, 79 insertions, 0 deletions
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 | ||