aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/smb2ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/smb2ops.c')
-rw-r--r--fs/cifs/smb2ops.c73
1 files changed, 68 insertions, 5 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 787844bde384..77f8aeb9c2fc 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -19,6 +19,7 @@
19 19
20#include <linux/pagemap.h> 20#include <linux/pagemap.h>
21#include <linux/vfs.h> 21#include <linux/vfs.h>
22#include <linux/falloc.h>
22#include "cifsglob.h" 23#include "cifsglob.h"
23#include "smb2pdu.h" 24#include "smb2pdu.h"
24#include "smb2proto.h" 25#include "smb2proto.h"
@@ -112,6 +113,53 @@ smb2_get_credits(struct mid_q_entry *mid)
112 return le16_to_cpu(((struct smb2_hdr *)mid->resp_buf)->CreditRequest); 113 return le16_to_cpu(((struct smb2_hdr *)mid->resp_buf)->CreditRequest);
113} 114}
114 115
116static int
117smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
118 unsigned int *num, unsigned int *credits)
119{
120 int rc = 0;
121 unsigned int scredits;
122
123 spin_lock(&server->req_lock);
124 while (1) {
125 if (server->credits <= 0) {
126 spin_unlock(&server->req_lock);
127 cifs_num_waiters_inc(server);
128 rc = wait_event_killable(server->request_q,
129 has_credits(server, &server->credits));
130 cifs_num_waiters_dec(server);
131 if (rc)
132 return rc;
133 spin_lock(&server->req_lock);
134 } else {
135 if (server->tcpStatus == CifsExiting) {
136 spin_unlock(&server->req_lock);
137 return -ENOENT;
138 }
139
140 scredits = server->credits;
141 /* can deadlock with reopen */
142 if (scredits == 1) {
143 *num = SMB2_MAX_BUFFER_SIZE;
144 *credits = 0;
145 break;
146 }
147
148 /* leave one credit for a possible reopen */
149 scredits--;
150 *num = min_t(unsigned int, size,
151 scredits * SMB2_MAX_BUFFER_SIZE);
152
153 *credits = DIV_ROUND_UP(*num, SMB2_MAX_BUFFER_SIZE);
154 server->credits -= *credits;
155 server->in_flight++;
156 break;
157 }
158 }
159 spin_unlock(&server->req_lock);
160 return rc;
161}
162
115static __u64 163static __u64
116smb2_get_next_mid(struct TCP_Server_Info *server) 164smb2_get_next_mid(struct TCP_Server_Info *server)
117{ 165{
@@ -182,8 +230,9 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
182 /* start with specified wsize, or default */ 230 /* start with specified wsize, or default */
183 wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE; 231 wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE;
184 wsize = min_t(unsigned int, wsize, server->max_write); 232 wsize = min_t(unsigned int, wsize, server->max_write);
185 /* set it to the maximum buffer size value we can send with 1 credit */ 233
186 wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE); 234 if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
235 wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE);
187 236
188 return wsize; 237 return wsize;
189} 238}
@@ -197,8 +246,9 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
197 /* start with specified rsize, or default */ 246 /* start with specified rsize, or default */
198 rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE; 247 rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE;
199 rsize = min_t(unsigned int, rsize, server->max_read); 248 rsize = min_t(unsigned int, rsize, server->max_read);
200 /* set it to the maximum buffer size value we can send with 1 credit */ 249
201 rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE); 250 if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
251 rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE);
202 252
203 return rsize; 253 return rsize;
204} 254}
@@ -687,7 +737,7 @@ smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
687{ 737{
688 __le64 eof = cpu_to_le64(size); 738 __le64 eof = cpu_to_le64(size);
689 return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, 739 return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
690 cfile->fid.volatile_fid, cfile->pid, &eof); 740 cfile->fid.volatile_fid, cfile->pid, &eof, false);
691} 741}
692 742
693static int 743static int
@@ -1104,6 +1154,13 @@ smb3_parse_lease_buf(void *buf, unsigned int *epoch)
1104 return le32_to_cpu(lc->lcontext.LeaseState); 1154 return le32_to_cpu(lc->lcontext.LeaseState);
1105} 1155}
1106 1156
1157static unsigned int
1158smb2_wp_retry_size(struct inode *inode)
1159{
1160 return min_t(unsigned int, CIFS_SB(inode->i_sb)->wsize,
1161 SMB2_MAX_BUFFER_SIZE);
1162}
1163
1107struct smb_version_operations smb20_operations = { 1164struct smb_version_operations smb20_operations = {
1108 .compare_fids = smb2_compare_fids, 1165 .compare_fids = smb2_compare_fids,
1109 .setup_request = smb2_setup_request, 1166 .setup_request = smb2_setup_request,
@@ -1113,6 +1170,7 @@ struct smb_version_operations smb20_operations = {
1113 .set_credits = smb2_set_credits, 1170 .set_credits = smb2_set_credits,
1114 .get_credits_field = smb2_get_credits_field, 1171 .get_credits_field = smb2_get_credits_field,
1115 .get_credits = smb2_get_credits, 1172 .get_credits = smb2_get_credits,
1173 .wait_mtu_credits = cifs_wait_mtu_credits,
1116 .get_next_mid = smb2_get_next_mid, 1174 .get_next_mid = smb2_get_next_mid,
1117 .read_data_offset = smb2_read_data_offset, 1175 .read_data_offset = smb2_read_data_offset,
1118 .read_data_length = smb2_read_data_length, 1176 .read_data_length = smb2_read_data_length,
@@ -1177,6 +1235,7 @@ struct smb_version_operations smb20_operations = {
1177 .create_lease_buf = smb2_create_lease_buf, 1235 .create_lease_buf = smb2_create_lease_buf,
1178 .parse_lease_buf = smb2_parse_lease_buf, 1236 .parse_lease_buf = smb2_parse_lease_buf,
1179 .clone_range = smb2_clone_range, 1237 .clone_range = smb2_clone_range,
1238 .wp_retry_size = smb2_wp_retry_size,
1180}; 1239};
1181 1240
1182struct smb_version_operations smb21_operations = { 1241struct smb_version_operations smb21_operations = {
@@ -1188,6 +1247,7 @@ struct smb_version_operations smb21_operations = {
1188 .set_credits = smb2_set_credits, 1247 .set_credits = smb2_set_credits,
1189 .get_credits_field = smb2_get_credits_field, 1248 .get_credits_field = smb2_get_credits_field,
1190 .get_credits = smb2_get_credits, 1249 .get_credits = smb2_get_credits,
1250 .wait_mtu_credits = smb2_wait_mtu_credits,
1191 .get_next_mid = smb2_get_next_mid, 1251 .get_next_mid = smb2_get_next_mid,
1192 .read_data_offset = smb2_read_data_offset, 1252 .read_data_offset = smb2_read_data_offset,
1193 .read_data_length = smb2_read_data_length, 1253 .read_data_length = smb2_read_data_length,
@@ -1252,6 +1312,7 @@ struct smb_version_operations smb21_operations = {
1252 .create_lease_buf = smb2_create_lease_buf, 1312 .create_lease_buf = smb2_create_lease_buf,
1253 .parse_lease_buf = smb2_parse_lease_buf, 1313 .parse_lease_buf = smb2_parse_lease_buf,
1254 .clone_range = smb2_clone_range, 1314 .clone_range = smb2_clone_range,
1315 .wp_retry_size = smb2_wp_retry_size,
1255}; 1316};
1256 1317
1257struct smb_version_operations smb30_operations = { 1318struct smb_version_operations smb30_operations = {
@@ -1263,6 +1324,7 @@ struct smb_version_operations smb30_operations = {
1263 .set_credits = smb2_set_credits, 1324 .set_credits = smb2_set_credits,
1264 .get_credits_field = smb2_get_credits_field, 1325 .get_credits_field = smb2_get_credits_field,
1265 .get_credits = smb2_get_credits, 1326 .get_credits = smb2_get_credits,
1327 .wait_mtu_credits = smb2_wait_mtu_credits,
1266 .get_next_mid = smb2_get_next_mid, 1328 .get_next_mid = smb2_get_next_mid,
1267 .read_data_offset = smb2_read_data_offset, 1329 .read_data_offset = smb2_read_data_offset,
1268 .read_data_length = smb2_read_data_length, 1330 .read_data_length = smb2_read_data_length,
@@ -1330,6 +1392,7 @@ struct smb_version_operations smb30_operations = {
1330 .parse_lease_buf = smb3_parse_lease_buf, 1392 .parse_lease_buf = smb3_parse_lease_buf,
1331 .clone_range = smb2_clone_range, 1393 .clone_range = smb2_clone_range,
1332 .validate_negotiate = smb3_validate_negotiate, 1394 .validate_negotiate = smb3_validate_negotiate,
1395 .wp_retry_size = smb2_wp_retry_size,
1333}; 1396};
1334 1397
1335struct smb_version_values smb20_values = { 1398struct smb_version_values smb20_values = {