diff options
Diffstat (limited to 'fs/cifs/smb2ops.c')
-rw-r--r-- | fs/cifs/smb2ops.c | 73 |
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 | ||
116 | static int | ||
117 | smb2_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 | |||
115 | static __u64 | 163 | static __u64 |
116 | smb2_get_next_mid(struct TCP_Server_Info *server) | 164 | smb2_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 | ||
693 | static int | 743 | static 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 | ||
1157 | static unsigned int | ||
1158 | smb2_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 | |||
1107 | struct smb_version_operations smb20_operations = { | 1164 | struct 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 | ||
1182 | struct smb_version_operations smb21_operations = { | 1241 | struct 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 | ||
1257 | struct smb_version_operations smb30_operations = { | 1318 | struct 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 | ||
1335 | struct smb_version_values smb20_values = { | 1398 | struct smb_version_values smb20_values = { |