.. | .. |
---|
50 | 50 | #include "cifs_spnego.h" |
---|
51 | 51 | #include "smbdirect.h" |
---|
52 | 52 | #include "trace.h" |
---|
| 53 | +#ifdef CONFIG_CIFS_DFS_UPCALL |
---|
| 54 | +#include "dfs_cache.h" |
---|
| 55 | +#endif |
---|
53 | 56 | |
---|
54 | 57 | /* |
---|
55 | 58 | * The following table defines the expected "StructureSize" of SMB2 requests |
---|
.. | .. |
---|
82 | 85 | |
---|
83 | 86 | int smb3_encryption_required(const struct cifs_tcon *tcon) |
---|
84 | 87 | { |
---|
85 | | - if (!tcon) |
---|
| 88 | + if (!tcon || !tcon->ses) |
---|
86 | 89 | return 0; |
---|
87 | 90 | if ((tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) || |
---|
88 | 91 | (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA)) |
---|
.. | .. |
---|
95 | 98 | |
---|
96 | 99 | static void |
---|
97 | 100 | smb2_hdr_assemble(struct smb2_sync_hdr *shdr, __le16 smb2_cmd, |
---|
98 | | - const struct cifs_tcon *tcon) |
---|
| 101 | + const struct cifs_tcon *tcon, |
---|
| 102 | + struct TCP_Server_Info *server) |
---|
99 | 103 | { |
---|
100 | 104 | shdr->ProtocolId = SMB2_PROTO_NUMBER; |
---|
101 | 105 | shdr->StructureSize = cpu_to_le16(64); |
---|
102 | 106 | shdr->Command = smb2_cmd; |
---|
103 | | - if (tcon && tcon->ses && tcon->ses->server) { |
---|
104 | | - struct TCP_Server_Info *server = tcon->ses->server; |
---|
105 | | - |
---|
| 107 | + if (server) { |
---|
106 | 108 | spin_lock(&server->req_lock); |
---|
107 | | - /* Request up to 2 credits but don't go over the limit. */ |
---|
| 109 | + /* Request up to 10 credits but don't go over the limit. */ |
---|
108 | 110 | if (server->credits >= server->max_credits) |
---|
109 | 111 | shdr->CreditRequest = cpu_to_le16(0); |
---|
110 | 112 | else |
---|
111 | 113 | shdr->CreditRequest = cpu_to_le16( |
---|
112 | 114 | min_t(int, server->max_credits - |
---|
113 | | - server->credits, 2)); |
---|
| 115 | + server->credits, 10)); |
---|
114 | 116 | spin_unlock(&server->req_lock); |
---|
115 | 117 | } else { |
---|
116 | 118 | shdr->CreditRequest = cpu_to_le16(2); |
---|
.. | .. |
---|
122 | 124 | |
---|
123 | 125 | /* GLOBAL_CAP_LARGE_MTU will only be set if dialect > SMB2.02 */ |
---|
124 | 126 | /* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */ |
---|
125 | | - if ((tcon->ses) && (tcon->ses->server) && |
---|
126 | | - (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) |
---|
| 127 | + if (server && (server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) |
---|
127 | 128 | shdr->CreditCharge = cpu_to_le16(1); |
---|
128 | 129 | /* else CreditCharge MBZ */ |
---|
129 | 130 | |
---|
.. | .. |
---|
145 | 146 | /* if (tcon->share_flags & SHI1005_FLAGS_DFS) |
---|
146 | 147 | shdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */ |
---|
147 | 148 | |
---|
148 | | - if (tcon->ses && tcon->ses->server && tcon->ses->server->sign && |
---|
149 | | - !smb3_encryption_required(tcon)) |
---|
| 149 | + if (server && server->sign && !smb3_encryption_required(tcon)) |
---|
150 | 150 | shdr->Flags |= SMB2_FLAGS_SIGNED; |
---|
151 | 151 | out: |
---|
152 | 152 | return; |
---|
153 | 153 | } |
---|
154 | 154 | |
---|
155 | 155 | static int |
---|
156 | | -smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) |
---|
| 156 | +smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, |
---|
| 157 | + struct TCP_Server_Info *server) |
---|
157 | 158 | { |
---|
158 | 159 | int rc; |
---|
159 | 160 | struct nls_table *nls_codepage; |
---|
160 | 161 | struct cifs_ses *ses; |
---|
161 | | - struct TCP_Server_Info *server; |
---|
| 162 | + int retries; |
---|
162 | 163 | |
---|
163 | 164 | /* |
---|
164 | 165 | * SMB2s NegProt, SessSetup, Logoff do not have tcon yet so |
---|
.. | .. |
---|
186 | 187 | } |
---|
187 | 188 | } |
---|
188 | 189 | if ((!tcon->ses) || (tcon->ses->status == CifsExiting) || |
---|
189 | | - (!tcon->ses->server)) |
---|
| 190 | + (!tcon->ses->server) || !server) |
---|
190 | 191 | return -EIO; |
---|
191 | 192 | |
---|
192 | 193 | ses = tcon->ses; |
---|
193 | | - server = ses->server; |
---|
| 194 | + retries = server->nr_targets; |
---|
194 | 195 | |
---|
195 | 196 | /* |
---|
196 | | - * Give demultiplex thread up to 10 seconds to reconnect, should be |
---|
197 | | - * greater than cifs socket timeout which is 7 seconds |
---|
| 197 | + * Give demultiplex thread up to 10 seconds to each target available for |
---|
| 198 | + * reconnect -- should be greater than cifs socket timeout which is 7 |
---|
| 199 | + * seconds. |
---|
198 | 200 | */ |
---|
199 | 201 | while (server->tcpStatus == CifsNeedReconnect) { |
---|
200 | 202 | /* |
---|
.. | .. |
---|
216 | 218 | (server->tcpStatus != CifsNeedReconnect), |
---|
217 | 219 | 10 * HZ); |
---|
218 | 220 | if (rc < 0) { |
---|
219 | | - cifs_dbg(FYI, "%s: aborting reconnect due to a received" |
---|
220 | | - " signal by the process\n", __func__); |
---|
| 221 | + cifs_dbg(FYI, "%s: aborting reconnect due to a received signal by the process\n", |
---|
| 222 | + __func__); |
---|
221 | 223 | return -ERESTARTSYS; |
---|
222 | 224 | } |
---|
223 | 225 | |
---|
224 | 226 | /* are we still trying to reconnect? */ |
---|
225 | 227 | if (server->tcpStatus != CifsNeedReconnect) |
---|
226 | 228 | break; |
---|
| 229 | + |
---|
| 230 | + if (retries && --retries) |
---|
| 231 | + continue; |
---|
227 | 232 | |
---|
228 | 233 | /* |
---|
229 | 234 | * on "soft" mounts we wait once. Hard mounts keep |
---|
.. | .. |
---|
234 | 239 | cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n"); |
---|
235 | 240 | return -EHOSTDOWN; |
---|
236 | 241 | } |
---|
| 242 | + retries = server->nr_targets; |
---|
237 | 243 | } |
---|
238 | 244 | |
---|
239 | 245 | if (!tcon->ses->need_reconnect && !tcon->need_reconnect) |
---|
.. | .. |
---|
258 | 264 | goto out; |
---|
259 | 265 | } |
---|
260 | 266 | |
---|
| 267 | + /* |
---|
| 268 | + * If we are reconnecting an extra channel, bind |
---|
| 269 | + */ |
---|
| 270 | + if (server->is_channel) { |
---|
| 271 | + ses->binding = true; |
---|
| 272 | + ses->binding_chan = cifs_ses_find_chan(ses, server); |
---|
| 273 | + } |
---|
| 274 | + |
---|
261 | 275 | rc = cifs_negotiate_protocol(0, tcon->ses); |
---|
262 | 276 | if (!rc && tcon->ses->need_reconnect) { |
---|
263 | 277 | rc = cifs_setup_session(0, tcon->ses, nls_codepage); |
---|
264 | 278 | if ((rc == -EACCES) && !tcon->retry) { |
---|
265 | 279 | rc = -EHOSTDOWN; |
---|
| 280 | + ses->binding = false; |
---|
| 281 | + ses->binding_chan = NULL; |
---|
266 | 282 | mutex_unlock(&tcon->ses->session_mutex); |
---|
267 | 283 | goto failed; |
---|
| 284 | + } else if (rc) { |
---|
| 285 | + mutex_unlock(&ses->session_mutex); |
---|
| 286 | + goto out; |
---|
268 | 287 | } |
---|
269 | 288 | } |
---|
| 289 | + /* |
---|
| 290 | + * End of channel binding |
---|
| 291 | + */ |
---|
| 292 | + ses->binding = false; |
---|
| 293 | + ses->binding_chan = NULL; |
---|
| 294 | + |
---|
270 | 295 | if (rc || !tcon->need_reconnect) { |
---|
271 | 296 | mutex_unlock(&tcon->ses->session_mutex); |
---|
272 | 297 | goto out; |
---|
.. | .. |
---|
276 | 301 | if (tcon->use_persistent) |
---|
277 | 302 | tcon->need_reopen_files = true; |
---|
278 | 303 | |
---|
279 | | - rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nls_codepage); |
---|
| 304 | + rc = cifs_tree_connect(0, tcon, nls_codepage); |
---|
280 | 305 | mutex_unlock(&tcon->ses->session_mutex); |
---|
281 | 306 | |
---|
282 | 307 | cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); |
---|
283 | 308 | if (rc) { |
---|
284 | 309 | /* If sess reconnected but tcon didn't, something strange ... */ |
---|
285 | | - printk_once(KERN_WARNING "reconnect tcon failed rc = %d\n", rc); |
---|
| 310 | + pr_warn_once("reconnect tcon failed rc = %d\n", rc); |
---|
286 | 311 | goto out; |
---|
287 | 312 | } |
---|
288 | 313 | |
---|
289 | 314 | if (smb2_command != SMB2_INTERNAL_CMD) |
---|
290 | | - queue_delayed_work(cifsiod_wq, &server->reconnect, 0); |
---|
| 315 | + mod_delayed_work(cifsiod_wq, &server->reconnect, 0); |
---|
291 | 316 | |
---|
292 | 317 | atomic_inc(&tconInfoReconnectCount); |
---|
293 | 318 | out: |
---|
.. | .. |
---|
317 | 342 | } |
---|
318 | 343 | |
---|
319 | 344 | static void |
---|
320 | | -fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, void *buf, |
---|
| 345 | +fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, |
---|
| 346 | + struct TCP_Server_Info *server, |
---|
| 347 | + void *buf, |
---|
321 | 348 | unsigned int *total_len) |
---|
322 | 349 | { |
---|
323 | 350 | struct smb2_sync_pdu *spdu = (struct smb2_sync_pdu *)buf; |
---|
.. | .. |
---|
330 | 357 | */ |
---|
331 | 358 | memset(buf, 0, 256); |
---|
332 | 359 | |
---|
333 | | - smb2_hdr_assemble(&spdu->sync_hdr, smb2_command, tcon); |
---|
| 360 | + smb2_hdr_assemble(&spdu->sync_hdr, smb2_command, tcon, server); |
---|
334 | 361 | spdu->StructureSize2 = cpu_to_le16(parmsize); |
---|
335 | 362 | |
---|
336 | 363 | *total_len = parmsize + sizeof(struct smb2_sync_hdr); |
---|
.. | .. |
---|
342 | 369 | * function must have filled in request_buf pointer. |
---|
343 | 370 | */ |
---|
344 | 371 | static int __smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, |
---|
345 | | - void **request_buf, unsigned int *total_len) |
---|
| 372 | + struct TCP_Server_Info *server, |
---|
| 373 | + void **request_buf, unsigned int *total_len) |
---|
346 | 374 | { |
---|
347 | 375 | /* BB eventually switch this to SMB2 specific small buf size */ |
---|
348 | 376 | if (smb2_command == SMB2_SET_INFO) |
---|
.. | .. |
---|
354 | 382 | return -ENOMEM; |
---|
355 | 383 | } |
---|
356 | 384 | |
---|
357 | | - fill_small_buf(smb2_command, tcon, |
---|
| 385 | + fill_small_buf(smb2_command, tcon, server, |
---|
358 | 386 | (struct smb2_sync_hdr *)(*request_buf), |
---|
359 | 387 | total_len); |
---|
360 | 388 | |
---|
.. | .. |
---|
368 | 396 | } |
---|
369 | 397 | |
---|
370 | 398 | static int smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, |
---|
| 399 | + struct TCP_Server_Info *server, |
---|
371 | 400 | void **request_buf, unsigned int *total_len) |
---|
372 | 401 | { |
---|
373 | 402 | int rc; |
---|
374 | 403 | |
---|
375 | | - rc = smb2_reconnect(smb2_command, tcon); |
---|
| 404 | + rc = smb2_reconnect(smb2_command, tcon, server); |
---|
376 | 405 | if (rc) |
---|
377 | 406 | return rc; |
---|
378 | 407 | |
---|
379 | | - return __smb2_plain_req_init(smb2_command, tcon, request_buf, |
---|
| 408 | + return __smb2_plain_req_init(smb2_command, tcon, server, request_buf, |
---|
380 | 409 | total_len); |
---|
381 | 410 | } |
---|
382 | 411 | |
---|
383 | 412 | static int smb2_ioctl_req_init(u32 opcode, struct cifs_tcon *tcon, |
---|
| 413 | + struct TCP_Server_Info *server, |
---|
384 | 414 | void **request_buf, unsigned int *total_len) |
---|
385 | 415 | { |
---|
386 | 416 | /* Skip reconnect only for FSCTL_VALIDATE_NEGOTIATE_INFO IOCTLs */ |
---|
387 | 417 | if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) { |
---|
388 | | - return __smb2_plain_req_init(SMB2_IOCTL, tcon, request_buf, |
---|
389 | | - total_len); |
---|
| 418 | + return __smb2_plain_req_init(SMB2_IOCTL, tcon, server, |
---|
| 419 | + request_buf, total_len); |
---|
390 | 420 | } |
---|
391 | | - return smb2_plain_req_init(SMB2_IOCTL, tcon, request_buf, total_len); |
---|
| 421 | + return smb2_plain_req_init(SMB2_IOCTL, tcon, server, |
---|
| 422 | + request_buf, total_len); |
---|
392 | 423 | } |
---|
393 | 424 | |
---|
394 | | - |
---|
395 | | -/* offset is sizeof smb2_negotiate_req but rounded up to 8 bytes */ |
---|
396 | | -#define OFFSET_OF_NEG_CONTEXT 0x68 /* sizeof(struct smb2_negotiate_req) */ |
---|
397 | | - |
---|
398 | | - |
---|
399 | | -#define SMB2_PREAUTH_INTEGRITY_CAPABILITIES cpu_to_le16(1) |
---|
400 | | -#define SMB2_ENCRYPTION_CAPABILITIES cpu_to_le16(2) |
---|
401 | | -#define SMB2_POSIX_EXTENSIONS_AVAILABLE cpu_to_le16(0x100) |
---|
| 425 | +/* For explanation of negotiate contexts see MS-SMB2 section 2.2.3.1 */ |
---|
402 | 426 | |
---|
403 | 427 | static void |
---|
404 | 428 | build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt) |
---|
.. | .. |
---|
412 | 436 | } |
---|
413 | 437 | |
---|
414 | 438 | static void |
---|
| 439 | +build_compression_ctxt(struct smb2_compression_capabilities_context *pneg_ctxt) |
---|
| 440 | +{ |
---|
| 441 | + pneg_ctxt->ContextType = SMB2_COMPRESSION_CAPABILITIES; |
---|
| 442 | + pneg_ctxt->DataLength = |
---|
| 443 | + cpu_to_le16(sizeof(struct smb2_compression_capabilities_context) |
---|
| 444 | + - sizeof(struct smb2_neg_context)); |
---|
| 445 | + pneg_ctxt->CompressionAlgorithmCount = cpu_to_le16(3); |
---|
| 446 | + pneg_ctxt->CompressionAlgorithms[0] = SMB3_COMPRESS_LZ77; |
---|
| 447 | + pneg_ctxt->CompressionAlgorithms[1] = SMB3_COMPRESS_LZ77_HUFF; |
---|
| 448 | + pneg_ctxt->CompressionAlgorithms[2] = SMB3_COMPRESS_LZNT1; |
---|
| 449 | +} |
---|
| 450 | + |
---|
| 451 | +static void |
---|
415 | 452 | build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt) |
---|
416 | 453 | { |
---|
417 | 454 | pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES; |
---|
418 | | - pneg_ctxt->DataLength = cpu_to_le16(4); /* Cipher Count + le16 cipher */ |
---|
419 | | - pneg_ctxt->CipherCount = cpu_to_le16(1); |
---|
420 | | -/* pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM;*/ /* not supported yet */ |
---|
421 | | - pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_CCM; |
---|
| 455 | + if (require_gcm_256) { |
---|
| 456 | + pneg_ctxt->DataLength = cpu_to_le16(4); /* Cipher Count + 1 cipher */ |
---|
| 457 | + pneg_ctxt->CipherCount = cpu_to_le16(1); |
---|
| 458 | + pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES256_GCM; |
---|
| 459 | + } else if (enable_gcm_256) { |
---|
| 460 | + pneg_ctxt->DataLength = cpu_to_le16(8); /* Cipher Count + 3 ciphers */ |
---|
| 461 | + pneg_ctxt->CipherCount = cpu_to_le16(3); |
---|
| 462 | + pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM; |
---|
| 463 | + pneg_ctxt->Ciphers[1] = SMB2_ENCRYPTION_AES256_GCM; |
---|
| 464 | + pneg_ctxt->Ciphers[2] = SMB2_ENCRYPTION_AES128_CCM; |
---|
| 465 | + } else { |
---|
| 466 | + pneg_ctxt->DataLength = cpu_to_le16(6); /* Cipher Count + 2 ciphers */ |
---|
| 467 | + pneg_ctxt->CipherCount = cpu_to_le16(2); |
---|
| 468 | + pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM; |
---|
| 469 | + pneg_ctxt->Ciphers[1] = SMB2_ENCRYPTION_AES128_CCM; |
---|
| 470 | + } |
---|
| 471 | +} |
---|
| 472 | + |
---|
| 473 | +static unsigned int |
---|
| 474 | +build_netname_ctxt(struct smb2_netname_neg_context *pneg_ctxt, char *hostname) |
---|
| 475 | +{ |
---|
| 476 | + struct nls_table *cp = load_nls_default(); |
---|
| 477 | + |
---|
| 478 | + pneg_ctxt->ContextType = SMB2_NETNAME_NEGOTIATE_CONTEXT_ID; |
---|
| 479 | + |
---|
| 480 | + /* copy up to max of first 100 bytes of server name to NetName field */ |
---|
| 481 | + pneg_ctxt->DataLength = cpu_to_le16(2 * cifs_strtoUTF16(pneg_ctxt->NetName, hostname, 100, cp)); |
---|
| 482 | + /* context size is DataLength + minimal smb2_neg_context */ |
---|
| 483 | + return DIV_ROUND_UP(le16_to_cpu(pneg_ctxt->DataLength) + |
---|
| 484 | + sizeof(struct smb2_neg_context), 8) * 8; |
---|
422 | 485 | } |
---|
423 | 486 | |
---|
424 | 487 | static void |
---|
.. | .. |
---|
426 | 489 | { |
---|
427 | 490 | pneg_ctxt->ContextType = SMB2_POSIX_EXTENSIONS_AVAILABLE; |
---|
428 | 491 | pneg_ctxt->DataLength = cpu_to_le16(POSIX_CTXT_DATA_LEN); |
---|
| 492 | + /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */ |
---|
| 493 | + pneg_ctxt->Name[0] = 0x93; |
---|
| 494 | + pneg_ctxt->Name[1] = 0xAD; |
---|
| 495 | + pneg_ctxt->Name[2] = 0x25; |
---|
| 496 | + pneg_ctxt->Name[3] = 0x50; |
---|
| 497 | + pneg_ctxt->Name[4] = 0x9C; |
---|
| 498 | + pneg_ctxt->Name[5] = 0xB4; |
---|
| 499 | + pneg_ctxt->Name[6] = 0x11; |
---|
| 500 | + pneg_ctxt->Name[7] = 0xE7; |
---|
| 501 | + pneg_ctxt->Name[8] = 0xB4; |
---|
| 502 | + pneg_ctxt->Name[9] = 0x23; |
---|
| 503 | + pneg_ctxt->Name[10] = 0x83; |
---|
| 504 | + pneg_ctxt->Name[11] = 0xDE; |
---|
| 505 | + pneg_ctxt->Name[12] = 0x96; |
---|
| 506 | + pneg_ctxt->Name[13] = 0x8B; |
---|
| 507 | + pneg_ctxt->Name[14] = 0xCD; |
---|
| 508 | + pneg_ctxt->Name[15] = 0x7C; |
---|
429 | 509 | } |
---|
430 | 510 | |
---|
431 | 511 | static void |
---|
432 | 512 | assemble_neg_contexts(struct smb2_negotiate_req *req, |
---|
433 | | - unsigned int *total_len) |
---|
| 513 | + struct TCP_Server_Info *server, unsigned int *total_len) |
---|
434 | 514 | { |
---|
435 | | - char *pneg_ctxt = (char *)req + OFFSET_OF_NEG_CONTEXT; |
---|
| 515 | + char *pneg_ctxt; |
---|
436 | 516 | unsigned int ctxt_len; |
---|
437 | 517 | |
---|
438 | | - *total_len += 2; /* Add 2 due to round to 8 byte boundary for 1st ctxt */ |
---|
| 518 | + if (*total_len > 200) { |
---|
| 519 | + /* In case length corrupted don't want to overrun smb buffer */ |
---|
| 520 | + cifs_server_dbg(VFS, "Bad frame length assembling neg contexts\n"); |
---|
| 521 | + return; |
---|
| 522 | + } |
---|
| 523 | + |
---|
| 524 | + /* |
---|
| 525 | + * round up total_len of fixed part of SMB3 negotiate request to 8 |
---|
| 526 | + * byte boundary before adding negotiate contexts |
---|
| 527 | + */ |
---|
| 528 | + *total_len = roundup(*total_len, 8); |
---|
| 529 | + |
---|
| 530 | + pneg_ctxt = (*total_len) + (char *)req; |
---|
| 531 | + req->NegotiateContextOffset = cpu_to_le32(*total_len); |
---|
| 532 | + |
---|
439 | 533 | build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt); |
---|
440 | 534 | ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_preauth_neg_context), 8) * 8; |
---|
441 | 535 | *total_len += ctxt_len; |
---|
.. | .. |
---|
446 | 540 | *total_len += ctxt_len; |
---|
447 | 541 | pneg_ctxt += ctxt_len; |
---|
448 | 542 | |
---|
| 543 | + if (server->compress_algorithm) { |
---|
| 544 | + build_compression_ctxt((struct smb2_compression_capabilities_context *) |
---|
| 545 | + pneg_ctxt); |
---|
| 546 | + ctxt_len = DIV_ROUND_UP( |
---|
| 547 | + sizeof(struct smb2_compression_capabilities_context), |
---|
| 548 | + 8) * 8; |
---|
| 549 | + *total_len += ctxt_len; |
---|
| 550 | + pneg_ctxt += ctxt_len; |
---|
| 551 | + req->NegotiateContextCount = cpu_to_le16(5); |
---|
| 552 | + } else |
---|
| 553 | + req->NegotiateContextCount = cpu_to_le16(4); |
---|
| 554 | + |
---|
| 555 | + ctxt_len = build_netname_ctxt((struct smb2_netname_neg_context *)pneg_ctxt, |
---|
| 556 | + server->hostname); |
---|
| 557 | + *total_len += ctxt_len; |
---|
| 558 | + pneg_ctxt += ctxt_len; |
---|
| 559 | + |
---|
449 | 560 | build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt); |
---|
450 | 561 | *total_len += sizeof(struct smb2_posix_neg_context); |
---|
451 | | - |
---|
452 | | - req->NegotiateContextOffset = cpu_to_le32(OFFSET_OF_NEG_CONTEXT); |
---|
453 | | - req->NegotiateContextCount = cpu_to_le16(3); |
---|
454 | 562 | } |
---|
455 | 563 | |
---|
456 | 564 | static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt) |
---|
.. | .. |
---|
459 | 567 | |
---|
460 | 568 | /* If invalid preauth context warn but use what we requested, SHA-512 */ |
---|
461 | 569 | if (len < MIN_PREAUTH_CTXT_DATA_LEN) { |
---|
462 | | - printk_once(KERN_WARNING "server sent bad preauth context\n"); |
---|
| 570 | + pr_warn_once("server sent bad preauth context\n"); |
---|
463 | 571 | return; |
---|
464 | 572 | } else if (len < MIN_PREAUTH_CTXT_DATA_LEN + le16_to_cpu(ctxt->SaltLength)) { |
---|
465 | 573 | pr_warn_once("server sent invalid SaltLength\n"); |
---|
466 | 574 | return; |
---|
467 | 575 | } |
---|
468 | 576 | if (le16_to_cpu(ctxt->HashAlgorithmCount) != 1) |
---|
469 | | - printk_once(KERN_WARNING "illegal SMB3 hash algorithm count\n"); |
---|
| 577 | + pr_warn_once("Invalid SMB3 hash algorithm count\n"); |
---|
470 | 578 | if (ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512) |
---|
471 | | - printk_once(KERN_WARNING "unknown SMB3 hash algorithm\n"); |
---|
| 579 | + pr_warn_once("unknown SMB3 hash algorithm\n"); |
---|
| 580 | +} |
---|
| 581 | + |
---|
| 582 | +static void decode_compress_ctx(struct TCP_Server_Info *server, |
---|
| 583 | + struct smb2_compression_capabilities_context *ctxt) |
---|
| 584 | +{ |
---|
| 585 | + unsigned int len = le16_to_cpu(ctxt->DataLength); |
---|
| 586 | + |
---|
| 587 | + /* sizeof compress context is a one element compression capbility struct */ |
---|
| 588 | + if (len < 10) { |
---|
| 589 | + pr_warn_once("server sent bad compression cntxt\n"); |
---|
| 590 | + return; |
---|
| 591 | + } |
---|
| 592 | + if (le16_to_cpu(ctxt->CompressionAlgorithmCount) != 1) { |
---|
| 593 | + pr_warn_once("Invalid SMB3 compress algorithm count\n"); |
---|
| 594 | + return; |
---|
| 595 | + } |
---|
| 596 | + if (le16_to_cpu(ctxt->CompressionAlgorithms[0]) > 3) { |
---|
| 597 | + pr_warn_once("unknown compression algorithm\n"); |
---|
| 598 | + return; |
---|
| 599 | + } |
---|
| 600 | + server->compress_algorithm = ctxt->CompressionAlgorithms[0]; |
---|
472 | 601 | } |
---|
473 | 602 | |
---|
474 | 603 | static int decode_encrypt_ctx(struct TCP_Server_Info *server, |
---|
.. | .. |
---|
478 | 607 | |
---|
479 | 608 | cifs_dbg(FYI, "decode SMB3.11 encryption neg context of len %d\n", len); |
---|
480 | 609 | if (len < MIN_ENCRYPT_CTXT_DATA_LEN) { |
---|
481 | | - printk_once(KERN_WARNING "server sent bad crypto ctxt len\n"); |
---|
| 610 | + pr_warn_once("server sent bad crypto ctxt len\n"); |
---|
482 | 611 | return -EINVAL; |
---|
483 | 612 | } |
---|
484 | 613 | |
---|
485 | 614 | if (le16_to_cpu(ctxt->CipherCount) != 1) { |
---|
486 | | - printk_once(KERN_WARNING "illegal SMB3.11 cipher count\n"); |
---|
| 615 | + pr_warn_once("Invalid SMB3.11 cipher count\n"); |
---|
487 | 616 | return -EINVAL; |
---|
488 | 617 | } |
---|
489 | 618 | cifs_dbg(FYI, "SMB311 cipher type:%d\n", le16_to_cpu(ctxt->Ciphers[0])); |
---|
490 | | - if ((ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_CCM) && |
---|
491 | | - (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_GCM)) { |
---|
492 | | - printk_once(KERN_WARNING "invalid SMB3.11 cipher returned\n"); |
---|
| 619 | + if (require_gcm_256) { |
---|
| 620 | + if (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES256_GCM) { |
---|
| 621 | + cifs_dbg(VFS, "Server does not support requested encryption type (AES256 GCM)\n"); |
---|
| 622 | + return -EOPNOTSUPP; |
---|
| 623 | + } |
---|
| 624 | + } else if (ctxt->Ciphers[0] == 0) { |
---|
| 625 | + /* |
---|
| 626 | + * e.g. if server only supported AES256_CCM (very unlikely) |
---|
| 627 | + * or server supported no encryption types or had all disabled. |
---|
| 628 | + * Since GLOBAL_CAP_ENCRYPTION will be not set, in the case |
---|
| 629 | + * in which mount requested encryption ("seal") checks later |
---|
| 630 | + * on during tree connection will return proper rc, but if |
---|
| 631 | + * seal not requested by client, since server is allowed to |
---|
| 632 | + * return 0 to indicate no supported cipher, we can't fail here |
---|
| 633 | + */ |
---|
| 634 | + server->cipher_type = 0; |
---|
| 635 | + server->capabilities &= ~SMB2_GLOBAL_CAP_ENCRYPTION; |
---|
| 636 | + pr_warn_once("Server does not support requested encryption types\n"); |
---|
| 637 | + return 0; |
---|
| 638 | + } else if ((ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_CCM) && |
---|
| 639 | + (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_GCM) && |
---|
| 640 | + (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES256_GCM)) { |
---|
| 641 | + /* server returned a cipher we didn't ask for */ |
---|
| 642 | + pr_warn_once("Invalid SMB3.11 cipher returned\n"); |
---|
493 | 643 | return -EINVAL; |
---|
494 | 644 | } |
---|
495 | 645 | server->cipher_type = ctxt->Ciphers[0]; |
---|
.. | .. |
---|
509 | 659 | |
---|
510 | 660 | cifs_dbg(FYI, "decoding %d negotiate contexts\n", ctxt_cnt); |
---|
511 | 661 | if (len_of_smb <= offset) { |
---|
512 | | - cifs_dbg(VFS, "Invalid response: negotiate context offset\n"); |
---|
| 662 | + cifs_server_dbg(VFS, "Invalid response: negotiate context offset\n"); |
---|
513 | 663 | return -EINVAL; |
---|
514 | 664 | } |
---|
515 | 665 | |
---|
.. | .. |
---|
535 | 685 | else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) |
---|
536 | 686 | rc = decode_encrypt_ctx(server, |
---|
537 | 687 | (struct smb2_encryption_neg_context *)pctx); |
---|
| 688 | + else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES) |
---|
| 689 | + decode_compress_ctx(server, |
---|
| 690 | + (struct smb2_compression_capabilities_context *)pctx); |
---|
538 | 691 | else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) |
---|
539 | 692 | server->posix_ext_supported = true; |
---|
540 | 693 | else |
---|
541 | | - cifs_dbg(VFS, "unknown negcontext of type %d ignored\n", |
---|
| 694 | + cifs_server_dbg(VFS, "unknown negcontext of type %d ignored\n", |
---|
542 | 695 | le16_to_cpu(pctx->ContextType)); |
---|
543 | 696 | |
---|
544 | 697 | if (rc) |
---|
.. | .. |
---|
586 | 739 | buf->Name[14] = 0xCD; |
---|
587 | 740 | buf->Name[15] = 0x7C; |
---|
588 | 741 | buf->Mode = cpu_to_le32(mode); |
---|
589 | | - cifs_dbg(FYI, "mode on posix create 0%o", mode); |
---|
| 742 | + cifs_dbg(FYI, "mode on posix create 0%o\n", mode); |
---|
590 | 743 | return buf; |
---|
591 | 744 | } |
---|
592 | 745 | |
---|
.. | .. |
---|
597 | 750 | unsigned int num = *num_iovec; |
---|
598 | 751 | |
---|
599 | 752 | iov[num].iov_base = create_posix_buf(mode); |
---|
| 753 | + if (mode == ACL_NO_MODE) |
---|
| 754 | + cifs_dbg(FYI, "Invalid mode\n"); |
---|
600 | 755 | if (iov[num].iov_base == NULL) |
---|
601 | 756 | return -ENOMEM; |
---|
602 | 757 | iov[num].iov_len = sizeof(struct create_posix); |
---|
.. | .. |
---|
635 | 790 | struct kvec rsp_iov; |
---|
636 | 791 | int rc = 0; |
---|
637 | 792 | int resp_buftype; |
---|
638 | | - struct TCP_Server_Info *server = ses->server; |
---|
| 793 | + struct TCP_Server_Info *server = cifs_ses_server(ses); |
---|
639 | 794 | int blob_offset, blob_length; |
---|
640 | 795 | char *security_blob; |
---|
641 | 796 | int flags = CIFS_NEG_OP; |
---|
.. | .. |
---|
648 | 803 | return -EIO; |
---|
649 | 804 | } |
---|
650 | 805 | |
---|
651 | | - rc = smb2_plain_req_init(SMB2_NEGOTIATE, NULL, (void **) &req, &total_len); |
---|
| 806 | + rc = smb2_plain_req_init(SMB2_NEGOTIATE, NULL, server, |
---|
| 807 | + (void **) &req, &total_len); |
---|
652 | 808 | if (rc) |
---|
653 | 809 | return rc; |
---|
654 | 810 | |
---|
.. | .. |
---|
657 | 813 | memset(server->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE); |
---|
658 | 814 | memset(ses->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE); |
---|
659 | 815 | |
---|
660 | | - if (strcmp(ses->server->vals->version_string, |
---|
| 816 | + if (strcmp(server->vals->version_string, |
---|
661 | 817 | SMB3ANY_VERSION_STRING) == 0) { |
---|
662 | 818 | req->Dialects[0] = cpu_to_le16(SMB30_PROT_ID); |
---|
663 | 819 | req->Dialects[1] = cpu_to_le16(SMB302_PROT_ID); |
---|
664 | 820 | req->DialectCount = cpu_to_le16(2); |
---|
665 | 821 | total_len += 4; |
---|
666 | | - } else if (strcmp(ses->server->vals->version_string, |
---|
| 822 | + } else if (strcmp(server->vals->version_string, |
---|
667 | 823 | SMBDEFAULT_VERSION_STRING) == 0) { |
---|
668 | 824 | req->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); |
---|
669 | 825 | req->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); |
---|
670 | 826 | req->Dialects[2] = cpu_to_le16(SMB302_PROT_ID); |
---|
671 | | - req->DialectCount = cpu_to_le16(3); |
---|
672 | | - total_len += 6; |
---|
| 827 | + req->Dialects[3] = cpu_to_le16(SMB311_PROT_ID); |
---|
| 828 | + req->DialectCount = cpu_to_le16(4); |
---|
| 829 | + total_len += 8; |
---|
673 | 830 | } else { |
---|
674 | 831 | /* otherwise send specific dialect */ |
---|
675 | | - req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id); |
---|
| 832 | + req->Dialects[0] = cpu_to_le16(server->vals->protocol_id); |
---|
676 | 833 | req->DialectCount = cpu_to_le16(1); |
---|
677 | 834 | total_len += 2; |
---|
678 | 835 | } |
---|
.. | .. |
---|
685 | 842 | else |
---|
686 | 843 | req->SecurityMode = 0; |
---|
687 | 844 | |
---|
688 | | - req->Capabilities = cpu_to_le32(ses->server->vals->req_capabilities); |
---|
| 845 | + req->Capabilities = cpu_to_le32(server->vals->req_capabilities); |
---|
| 846 | + if (ses->chan_max > 1) |
---|
| 847 | + req->Capabilities |= cpu_to_le32(SMB2_GLOBAL_CAP_MULTI_CHANNEL); |
---|
689 | 848 | |
---|
690 | 849 | /* ClientGUID must be zero for SMB2.02 dialect */ |
---|
691 | | - if (ses->server->vals->protocol_id == SMB20_PROT_ID) |
---|
| 850 | + if (server->vals->protocol_id == SMB20_PROT_ID) |
---|
692 | 851 | memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE); |
---|
693 | 852 | else { |
---|
694 | 853 | memcpy(req->ClientGUID, server->client_guid, |
---|
695 | 854 | SMB2_CLIENT_GUID_SIZE); |
---|
696 | | - if (ses->server->vals->protocol_id == SMB311_PROT_ID) |
---|
697 | | - assemble_neg_contexts(req, &total_len); |
---|
| 855 | + if ((server->vals->protocol_id == SMB311_PROT_ID) || |
---|
| 856 | + (strcmp(server->vals->version_string, |
---|
| 857 | + SMBDEFAULT_VERSION_STRING) == 0)) |
---|
| 858 | + assemble_neg_contexts(req, server, &total_len); |
---|
698 | 859 | } |
---|
699 | 860 | iov[0].iov_base = (char *)req; |
---|
700 | 861 | iov[0].iov_len = total_len; |
---|
.. | .. |
---|
703 | 864 | rqst.rq_iov = iov; |
---|
704 | 865 | rqst.rq_nvec = 1; |
---|
705 | 866 | |
---|
706 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
---|
| 867 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 868 | + &rqst, &resp_buftype, flags, &rsp_iov); |
---|
707 | 869 | cifs_small_buf_release(req); |
---|
708 | 870 | rsp = (struct smb2_negotiate_rsp *)rsp_iov.iov_base; |
---|
709 | 871 | /* |
---|
.. | .. |
---|
711 | 873 | * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); |
---|
712 | 874 | */ |
---|
713 | 875 | if (rc == -EOPNOTSUPP) { |
---|
714 | | - cifs_dbg(VFS, "Dialect not supported by server. Consider " |
---|
715 | | - "specifying vers=1.0 or vers=2.0 on mount for accessing" |
---|
716 | | - " older servers\n"); |
---|
| 876 | + cifs_server_dbg(VFS, "Dialect not supported by server. Consider specifying vers=1.0 or vers=2.0 on mount for accessing older servers\n"); |
---|
717 | 877 | goto neg_exit; |
---|
718 | 878 | } else if (rc != 0) |
---|
719 | 879 | goto neg_exit; |
---|
720 | 880 | |
---|
721 | | - if (strcmp(ses->server->vals->version_string, |
---|
| 881 | + if (strcmp(server->vals->version_string, |
---|
722 | 882 | SMB3ANY_VERSION_STRING) == 0) { |
---|
723 | 883 | if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) { |
---|
724 | | - cifs_dbg(VFS, |
---|
| 884 | + cifs_server_dbg(VFS, |
---|
725 | 885 | "SMB2 dialect returned but not requested\n"); |
---|
726 | 886 | return -EIO; |
---|
727 | 887 | } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) { |
---|
728 | | - cifs_dbg(VFS, |
---|
| 888 | + cifs_server_dbg(VFS, |
---|
729 | 889 | "SMB2.1 dialect returned but not requested\n"); |
---|
730 | 890 | return -EIO; |
---|
731 | 891 | } |
---|
732 | | - } else if (strcmp(ses->server->vals->version_string, |
---|
| 892 | + } else if (strcmp(server->vals->version_string, |
---|
733 | 893 | SMBDEFAULT_VERSION_STRING) == 0) { |
---|
734 | 894 | if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) { |
---|
735 | | - cifs_dbg(VFS, |
---|
| 895 | + cifs_server_dbg(VFS, |
---|
736 | 896 | "SMB2 dialect returned but not requested\n"); |
---|
737 | 897 | return -EIO; |
---|
738 | 898 | } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) { |
---|
739 | 899 | /* ops set to 3.0 by default for default so update */ |
---|
740 | | - ses->server->ops = &smb21_operations; |
---|
741 | | - ses->server->vals = &smb21_values; |
---|
| 900 | + server->ops = &smb21_operations; |
---|
| 901 | + server->vals = &smb21_values; |
---|
| 902 | + } else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) { |
---|
| 903 | + server->ops = &smb311_operations; |
---|
| 904 | + server->vals = &smb311_values; |
---|
742 | 905 | } |
---|
743 | 906 | } else if (le16_to_cpu(rsp->DialectRevision) != |
---|
744 | | - ses->server->vals->protocol_id) { |
---|
| 907 | + server->vals->protocol_id) { |
---|
745 | 908 | /* if requested single dialect ensure returned dialect matched */ |
---|
746 | | - cifs_dbg(VFS, "Illegal 0x%x dialect returned: not requested\n", |
---|
747 | | - le16_to_cpu(rsp->DialectRevision)); |
---|
| 909 | + cifs_server_dbg(VFS, "Invalid 0x%x dialect returned: not requested\n", |
---|
| 910 | + le16_to_cpu(rsp->DialectRevision)); |
---|
748 | 911 | return -EIO; |
---|
749 | 912 | } |
---|
750 | 913 | |
---|
.. | .. |
---|
761 | 924 | else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) |
---|
762 | 925 | cifs_dbg(FYI, "negotiated smb3.1.1 dialect\n"); |
---|
763 | 926 | else { |
---|
764 | | - cifs_dbg(VFS, "Illegal dialect returned by server 0x%x\n", |
---|
765 | | - le16_to_cpu(rsp->DialectRevision)); |
---|
| 927 | + cifs_server_dbg(VFS, "Invalid dialect returned by server 0x%x\n", |
---|
| 928 | + le16_to_cpu(rsp->DialectRevision)); |
---|
766 | 929 | rc = -EIO; |
---|
767 | 930 | goto neg_exit; |
---|
768 | 931 | } |
---|
.. | .. |
---|
828 | 991 | rc = smb311_decode_neg_context(rsp, server, |
---|
829 | 992 | rsp_iov.iov_len); |
---|
830 | 993 | else |
---|
831 | | - cifs_dbg(VFS, "Missing expected negotiate contexts\n"); |
---|
| 994 | + cifs_server_dbg(VFS, "Missing expected negotiate contexts\n"); |
---|
832 | 995 | } |
---|
833 | 996 | neg_exit: |
---|
834 | 997 | free_rsp_buf(resp_buftype, rsp); |
---|
.. | .. |
---|
842 | 1005 | struct validate_negotiate_info_rsp *pneg_rsp = NULL; |
---|
843 | 1006 | u32 rsplen; |
---|
844 | 1007 | u32 inbuflen; /* max of 4 dialects */ |
---|
| 1008 | + struct TCP_Server_Info *server = tcon->ses->server; |
---|
845 | 1009 | |
---|
846 | 1010 | cifs_dbg(FYI, "validate negotiate\n"); |
---|
847 | 1011 | |
---|
848 | 1012 | /* In SMB3.11 preauth integrity supersedes validate negotiate */ |
---|
849 | | - if (tcon->ses->server->dialect == SMB311_PROT_ID) |
---|
| 1013 | + if (server->dialect == SMB311_PROT_ID) |
---|
850 | 1014 | return 0; |
---|
851 | 1015 | |
---|
852 | 1016 | /* |
---|
.. | .. |
---|
865 | 1029 | } |
---|
866 | 1030 | |
---|
867 | 1031 | if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL) |
---|
868 | | - cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n"); |
---|
| 1032 | + cifs_tcon_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n"); |
---|
869 | 1033 | |
---|
870 | 1034 | pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_NOFS); |
---|
871 | 1035 | if (!pneg_inbuf) |
---|
872 | 1036 | return -ENOMEM; |
---|
873 | 1037 | |
---|
874 | 1038 | pneg_inbuf->Capabilities = |
---|
875 | | - cpu_to_le32(tcon->ses->server->vals->req_capabilities); |
---|
876 | | - memcpy(pneg_inbuf->Guid, tcon->ses->server->client_guid, |
---|
| 1039 | + cpu_to_le32(server->vals->req_capabilities); |
---|
| 1040 | + if (tcon->ses->chan_max > 1) |
---|
| 1041 | + pneg_inbuf->Capabilities |= cpu_to_le32(SMB2_GLOBAL_CAP_MULTI_CHANNEL); |
---|
| 1042 | + |
---|
| 1043 | + memcpy(pneg_inbuf->Guid, server->client_guid, |
---|
877 | 1044 | SMB2_CLIENT_GUID_SIZE); |
---|
878 | 1045 | |
---|
879 | 1046 | if (tcon->ses->sign) |
---|
.. | .. |
---|
886 | 1053 | pneg_inbuf->SecurityMode = 0; |
---|
887 | 1054 | |
---|
888 | 1055 | |
---|
889 | | - if (strcmp(tcon->ses->server->vals->version_string, |
---|
| 1056 | + if (strcmp(server->vals->version_string, |
---|
890 | 1057 | SMB3ANY_VERSION_STRING) == 0) { |
---|
891 | 1058 | pneg_inbuf->Dialects[0] = cpu_to_le16(SMB30_PROT_ID); |
---|
892 | 1059 | pneg_inbuf->Dialects[1] = cpu_to_le16(SMB302_PROT_ID); |
---|
893 | 1060 | pneg_inbuf->DialectCount = cpu_to_le16(2); |
---|
894 | 1061 | /* structure is big enough for 3 dialects, sending only 2 */ |
---|
895 | 1062 | inbuflen = sizeof(*pneg_inbuf) - |
---|
896 | | - sizeof(pneg_inbuf->Dialects[0]); |
---|
897 | | - } else if (strcmp(tcon->ses->server->vals->version_string, |
---|
| 1063 | + (2 * sizeof(pneg_inbuf->Dialects[0])); |
---|
| 1064 | + } else if (strcmp(server->vals->version_string, |
---|
898 | 1065 | SMBDEFAULT_VERSION_STRING) == 0) { |
---|
899 | 1066 | pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); |
---|
900 | 1067 | pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); |
---|
901 | 1068 | pneg_inbuf->Dialects[2] = cpu_to_le16(SMB302_PROT_ID); |
---|
902 | | - pneg_inbuf->DialectCount = cpu_to_le16(3); |
---|
| 1069 | + pneg_inbuf->Dialects[3] = cpu_to_le16(SMB311_PROT_ID); |
---|
| 1070 | + pneg_inbuf->DialectCount = cpu_to_le16(4); |
---|
903 | 1071 | /* structure is big enough for 3 dialects */ |
---|
904 | 1072 | inbuflen = sizeof(*pneg_inbuf); |
---|
905 | 1073 | } else { |
---|
906 | 1074 | /* otherwise specific dialect was requested */ |
---|
907 | 1075 | pneg_inbuf->Dialects[0] = |
---|
908 | | - cpu_to_le16(tcon->ses->server->vals->protocol_id); |
---|
| 1076 | + cpu_to_le16(server->vals->protocol_id); |
---|
909 | 1077 | pneg_inbuf->DialectCount = cpu_to_le16(1); |
---|
910 | | - /* structure is big enough for 3 dialects, sending only 1 */ |
---|
| 1078 | + /* structure is big enough for 4 dialects, sending only 1 */ |
---|
911 | 1079 | inbuflen = sizeof(*pneg_inbuf) - |
---|
912 | | - sizeof(pneg_inbuf->Dialects[0]) * 2; |
---|
| 1080 | + sizeof(pneg_inbuf->Dialects[0]) * 3; |
---|
913 | 1081 | } |
---|
914 | 1082 | |
---|
915 | 1083 | rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, |
---|
916 | | - FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */, |
---|
917 | | - (char *)pneg_inbuf, inbuflen, (char **)&pneg_rsp, &rsplen); |
---|
| 1084 | + FSCTL_VALIDATE_NEGOTIATE_INFO, |
---|
| 1085 | + (char *)pneg_inbuf, inbuflen, CIFSMaxBufSize, |
---|
| 1086 | + (char **)&pneg_rsp, &rsplen); |
---|
918 | 1087 | if (rc == -EOPNOTSUPP) { |
---|
919 | 1088 | /* |
---|
920 | 1089 | * Old Windows versions or Netapp SMB server can return |
---|
921 | 1090 | * not supported error. Client should accept it. |
---|
922 | 1091 | */ |
---|
923 | | - cifs_dbg(VFS, "Server does not support validate negotiate\n"); |
---|
| 1092 | + cifs_tcon_dbg(VFS, "Server does not support validate negotiate\n"); |
---|
924 | 1093 | rc = 0; |
---|
925 | 1094 | goto out_free_inbuf; |
---|
926 | 1095 | } else if (rc != 0) { |
---|
927 | | - cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", rc); |
---|
| 1096 | + cifs_tcon_dbg(VFS, "validate protocol negotiate failed: %d\n", |
---|
| 1097 | + rc); |
---|
928 | 1098 | rc = -EIO; |
---|
929 | 1099 | goto out_free_inbuf; |
---|
930 | 1100 | } |
---|
931 | 1101 | |
---|
932 | 1102 | rc = -EIO; |
---|
933 | 1103 | if (rsplen != sizeof(*pneg_rsp)) { |
---|
934 | | - cifs_dbg(VFS, "invalid protocol negotiate response size: %d\n", |
---|
935 | | - rsplen); |
---|
| 1104 | + cifs_tcon_dbg(VFS, "Invalid protocol negotiate response size: %d\n", |
---|
| 1105 | + rsplen); |
---|
936 | 1106 | |
---|
937 | 1107 | /* relax check since Mac returns max bufsize allowed on ioctl */ |
---|
938 | 1108 | if (rsplen > CIFSMaxBufSize || rsplen < sizeof(*pneg_rsp)) |
---|
.. | .. |
---|
940 | 1110 | } |
---|
941 | 1111 | |
---|
942 | 1112 | /* check validate negotiate info response matches what we got earlier */ |
---|
943 | | - if (pneg_rsp->Dialect != cpu_to_le16(tcon->ses->server->dialect)) |
---|
| 1113 | + if (pneg_rsp->Dialect != cpu_to_le16(server->dialect)) |
---|
944 | 1114 | goto vneg_out; |
---|
945 | 1115 | |
---|
946 | | - if (pneg_rsp->SecurityMode != cpu_to_le16(tcon->ses->server->sec_mode)) |
---|
| 1116 | + if (pneg_rsp->SecurityMode != cpu_to_le16(server->sec_mode)) |
---|
947 | 1117 | goto vneg_out; |
---|
948 | 1118 | |
---|
949 | 1119 | /* do not validate server guid because not saved at negprot time yet */ |
---|
950 | 1120 | |
---|
951 | 1121 | if ((le32_to_cpu(pneg_rsp->Capabilities) | SMB2_NT_FIND | |
---|
952 | | - SMB2_LARGE_FILES) != tcon->ses->server->capabilities) |
---|
| 1122 | + SMB2_LARGE_FILES) != server->capabilities) |
---|
953 | 1123 | goto vneg_out; |
---|
954 | 1124 | |
---|
955 | 1125 | /* validate negotiate successful */ |
---|
.. | .. |
---|
958 | 1128 | goto out_free_rsp; |
---|
959 | 1129 | |
---|
960 | 1130 | vneg_out: |
---|
961 | | - cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n"); |
---|
| 1131 | + cifs_tcon_dbg(VFS, "protocol revalidation - security settings mismatch\n"); |
---|
962 | 1132 | out_free_rsp: |
---|
963 | 1133 | kfree(pneg_rsp); |
---|
964 | 1134 | out_free_inbuf: |
---|
.. | .. |
---|
982 | 1152 | if ((server->sec_kerberos || server->sec_mskerberos) && |
---|
983 | 1153 | (global_secflags & CIFSSEC_MAY_KRB5)) |
---|
984 | 1154 | return Kerberos; |
---|
985 | | - /* Fallthrough */ |
---|
| 1155 | + fallthrough; |
---|
986 | 1156 | default: |
---|
987 | 1157 | return Unspecified; |
---|
988 | 1158 | } |
---|
.. | .. |
---|
1013 | 1183 | int rc; |
---|
1014 | 1184 | struct cifs_ses *ses = sess_data->ses; |
---|
1015 | 1185 | struct smb2_sess_setup_req *req; |
---|
1016 | | - struct TCP_Server_Info *server = ses->server; |
---|
| 1186 | + struct TCP_Server_Info *server = cifs_ses_server(ses); |
---|
1017 | 1187 | unsigned int total_len; |
---|
1018 | 1188 | |
---|
1019 | | - rc = smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, (void **) &req, |
---|
1020 | | - &total_len); |
---|
| 1189 | + rc = smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, server, |
---|
| 1190 | + (void **) &req, |
---|
| 1191 | + &total_len); |
---|
1021 | 1192 | if (rc) |
---|
1022 | 1193 | return rc; |
---|
1023 | 1194 | |
---|
1024 | | - /* First session, not a reauthenticate */ |
---|
1025 | | - req->sync_hdr.SessionId = 0; |
---|
1026 | | - |
---|
1027 | | - /* if reconnect, we need to send previous sess id, otherwise it is 0 */ |
---|
1028 | | - req->PreviousSessionId = sess_data->previous_session; |
---|
1029 | | - |
---|
1030 | | - req->Flags = 0; /* MBZ */ |
---|
| 1195 | + if (sess_data->ses->binding) { |
---|
| 1196 | + req->sync_hdr.SessionId = sess_data->ses->Suid; |
---|
| 1197 | + req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; |
---|
| 1198 | + req->PreviousSessionId = 0; |
---|
| 1199 | + req->Flags = SMB2_SESSION_REQ_FLAG_BINDING; |
---|
| 1200 | + } else { |
---|
| 1201 | + /* First session, not a reauthenticate */ |
---|
| 1202 | + req->sync_hdr.SessionId = 0; |
---|
| 1203 | + /* |
---|
| 1204 | + * if reconnect, we need to send previous sess id |
---|
| 1205 | + * otherwise it is 0 |
---|
| 1206 | + */ |
---|
| 1207 | + req->PreviousSessionId = sess_data->previous_session; |
---|
| 1208 | + req->Flags = 0; /* MBZ */ |
---|
| 1209 | + } |
---|
1031 | 1210 | |
---|
1032 | 1211 | /* enough to enable echos and oplocks and one max size write */ |
---|
1033 | 1212 | req->sync_hdr.CreditRequest = cpu_to_le16(130); |
---|
.. | .. |
---|
1086 | 1265 | |
---|
1087 | 1266 | /* BB add code to build os and lm fields */ |
---|
1088 | 1267 | rc = cifs_send_recv(sess_data->xid, sess_data->ses, |
---|
| 1268 | + cifs_ses_server(sess_data->ses), |
---|
1089 | 1269 | &rqst, |
---|
1090 | 1270 | &sess_data->buf0_type, |
---|
1091 | 1271 | CIFS_LOG_ERROR | CIFS_NEG_OP, &rsp_iov); |
---|
.. | .. |
---|
1100 | 1280 | { |
---|
1101 | 1281 | int rc = 0; |
---|
1102 | 1282 | struct cifs_ses *ses = sess_data->ses; |
---|
| 1283 | + struct TCP_Server_Info *server = cifs_ses_server(ses); |
---|
1103 | 1284 | |
---|
1104 | | - mutex_lock(&ses->server->srv_mutex); |
---|
1105 | | - if (ses->server->ops->generate_signingkey) { |
---|
1106 | | - rc = ses->server->ops->generate_signingkey(ses); |
---|
| 1285 | + mutex_lock(&server->srv_mutex); |
---|
| 1286 | + if (server->ops->generate_signingkey) { |
---|
| 1287 | + rc = server->ops->generate_signingkey(ses); |
---|
1107 | 1288 | if (rc) { |
---|
1108 | 1289 | cifs_dbg(FYI, |
---|
1109 | 1290 | "SMB3 session key generation failed\n"); |
---|
1110 | | - mutex_unlock(&ses->server->srv_mutex); |
---|
| 1291 | + mutex_unlock(&server->srv_mutex); |
---|
1111 | 1292 | return rc; |
---|
1112 | 1293 | } |
---|
1113 | 1294 | } |
---|
1114 | | - if (!ses->server->session_estab) { |
---|
1115 | | - ses->server->sequence_number = 0x2; |
---|
1116 | | - ses->server->session_estab = true; |
---|
| 1295 | + if (!server->session_estab) { |
---|
| 1296 | + server->sequence_number = 0x2; |
---|
| 1297 | + server->session_estab = true; |
---|
1117 | 1298 | } |
---|
1118 | | - mutex_unlock(&ses->server->srv_mutex); |
---|
| 1299 | + mutex_unlock(&server->srv_mutex); |
---|
1119 | 1300 | |
---|
1120 | 1301 | cifs_dbg(FYI, "SMB2/3 session established successfully\n"); |
---|
1121 | | - spin_lock(&GlobalMid_Lock); |
---|
1122 | | - ses->status = CifsGood; |
---|
1123 | | - ses->need_reconnect = false; |
---|
1124 | | - spin_unlock(&GlobalMid_Lock); |
---|
| 1302 | + /* keep existing ses state if binding */ |
---|
| 1303 | + if (!ses->binding) { |
---|
| 1304 | + spin_lock(&GlobalMid_Lock); |
---|
| 1305 | + ses->status = CifsGood; |
---|
| 1306 | + ses->need_reconnect = false; |
---|
| 1307 | + spin_unlock(&GlobalMid_Lock); |
---|
| 1308 | + } |
---|
| 1309 | + |
---|
1125 | 1310 | return rc; |
---|
1126 | 1311 | } |
---|
1127 | 1312 | |
---|
.. | .. |
---|
1154 | 1339 | * sending us a response in an expected form |
---|
1155 | 1340 | */ |
---|
1156 | 1341 | if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) { |
---|
1157 | | - cifs_dbg(VFS, |
---|
1158 | | - "bad cifs.upcall version. Expected %d got %d", |
---|
1159 | | - CIFS_SPNEGO_UPCALL_VERSION, msg->version); |
---|
| 1342 | + cifs_dbg(VFS, "bad cifs.upcall version. Expected %d got %d\n", |
---|
| 1343 | + CIFS_SPNEGO_UPCALL_VERSION, msg->version); |
---|
1160 | 1344 | rc = -EKEYREJECTED; |
---|
1161 | 1345 | goto out_put_spnego_key; |
---|
1162 | 1346 | } |
---|
1163 | 1347 | |
---|
1164 | | - ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len, |
---|
1165 | | - GFP_KERNEL); |
---|
1166 | | - if (!ses->auth_key.response) { |
---|
1167 | | - cifs_dbg(VFS, |
---|
1168 | | - "Kerberos can't allocate (%u bytes) memory", |
---|
1169 | | - msg->sesskey_len); |
---|
1170 | | - rc = -ENOMEM; |
---|
1171 | | - goto out_put_spnego_key; |
---|
| 1348 | + /* keep session key if binding */ |
---|
| 1349 | + if (!ses->binding) { |
---|
| 1350 | + ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len, |
---|
| 1351 | + GFP_KERNEL); |
---|
| 1352 | + if (!ses->auth_key.response) { |
---|
| 1353 | + cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory\n", |
---|
| 1354 | + msg->sesskey_len); |
---|
| 1355 | + rc = -ENOMEM; |
---|
| 1356 | + goto out_put_spnego_key; |
---|
| 1357 | + } |
---|
| 1358 | + ses->auth_key.len = msg->sesskey_len; |
---|
1172 | 1359 | } |
---|
1173 | | - ses->auth_key.len = msg->sesskey_len; |
---|
1174 | 1360 | |
---|
1175 | 1361 | sess_data->iov[1].iov_base = msg->data + msg->sesskey_len; |
---|
1176 | 1362 | sess_data->iov[1].iov_len = msg->secblob_len; |
---|
.. | .. |
---|
1180 | 1366 | goto out_put_spnego_key; |
---|
1181 | 1367 | |
---|
1182 | 1368 | rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; |
---|
1183 | | - ses->Suid = rsp->sync_hdr.SessionId; |
---|
1184 | | - |
---|
1185 | | - ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
---|
| 1369 | + /* keep session id and flags if binding */ |
---|
| 1370 | + if (!ses->binding) { |
---|
| 1371 | + ses->Suid = rsp->sync_hdr.SessionId; |
---|
| 1372 | + ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
---|
| 1373 | + } |
---|
1186 | 1374 | |
---|
1187 | 1375 | rc = SMB2_sess_establish_session(sess_data); |
---|
1188 | 1376 | out_put_spnego_key: |
---|
.. | .. |
---|
1276 | 1464 | |
---|
1277 | 1465 | cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n"); |
---|
1278 | 1466 | |
---|
1279 | | - |
---|
1280 | | - ses->Suid = rsp->sync_hdr.SessionId; |
---|
1281 | | - ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
---|
| 1467 | + /* keep existing ses id and flags if binding */ |
---|
| 1468 | + if (!ses->binding) { |
---|
| 1469 | + ses->Suid = rsp->sync_hdr.SessionId; |
---|
| 1470 | + ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
---|
| 1471 | + } |
---|
1282 | 1472 | |
---|
1283 | 1473 | out: |
---|
1284 | 1474 | kfree(ntlmssp_blob); |
---|
.. | .. |
---|
1335 | 1525 | |
---|
1336 | 1526 | rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; |
---|
1337 | 1527 | |
---|
1338 | | - ses->Suid = rsp->sync_hdr.SessionId; |
---|
1339 | | - ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
---|
| 1528 | + /* keep existing ses id and flags if binding */ |
---|
| 1529 | + if (!ses->binding) { |
---|
| 1530 | + ses->Suid = rsp->sync_hdr.SessionId; |
---|
| 1531 | + ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
---|
| 1532 | + } |
---|
1340 | 1533 | |
---|
1341 | 1534 | rc = SMB2_sess_establish_session(sess_data); |
---|
| 1535 | +#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS |
---|
| 1536 | + if (ses->server->dialect < SMB30_PROT_ID) { |
---|
| 1537 | + cifs_dbg(VFS, "%s: dumping generated SMB2 session keys\n", __func__); |
---|
| 1538 | + /* |
---|
| 1539 | + * The session id is opaque in terms of endianness, so we can't |
---|
| 1540 | + * print it as a long long. we dump it as we got it on the wire |
---|
| 1541 | + */ |
---|
| 1542 | + cifs_dbg(VFS, "Session Id %*ph\n", (int)sizeof(ses->Suid), |
---|
| 1543 | + &ses->Suid); |
---|
| 1544 | + cifs_dbg(VFS, "Session Key %*ph\n", |
---|
| 1545 | + SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response); |
---|
| 1546 | + cifs_dbg(VFS, "Signing Key %*ph\n", |
---|
| 1547 | + SMB3_SIGN_KEY_SIZE, ses->auth_key.response); |
---|
| 1548 | + } |
---|
| 1549 | +#endif |
---|
1342 | 1550 | out: |
---|
1343 | 1551 | kfree(ntlmssp_blob); |
---|
1344 | 1552 | SMB2_sess_free_buffer(sess_data); |
---|
.. | .. |
---|
1353 | 1561 | { |
---|
1354 | 1562 | int type; |
---|
1355 | 1563 | |
---|
1356 | | - type = smb2_select_sectype(ses->server, ses->sectype); |
---|
| 1564 | + type = smb2_select_sectype(cifs_ses_server(ses), ses->sectype); |
---|
1357 | 1565 | cifs_dbg(FYI, "sess setup type %d\n", type); |
---|
1358 | 1566 | if (type == Unspecified) { |
---|
1359 | | - cifs_dbg(VFS, |
---|
1360 | | - "Unable to select appropriate authentication method!"); |
---|
| 1567 | + cifs_dbg(VFS, "Unable to select appropriate authentication method!\n"); |
---|
1361 | 1568 | return -EINVAL; |
---|
1362 | 1569 | } |
---|
1363 | 1570 | |
---|
.. | .. |
---|
1381 | 1588 | const struct nls_table *nls_cp) |
---|
1382 | 1589 | { |
---|
1383 | 1590 | int rc = 0; |
---|
1384 | | - struct TCP_Server_Info *server = ses->server; |
---|
| 1591 | + struct TCP_Server_Info *server = cifs_ses_server(ses); |
---|
1385 | 1592 | struct SMB2_sess_data *sess_data; |
---|
1386 | 1593 | |
---|
1387 | 1594 | cifs_dbg(FYI, "Session Setup\n"); |
---|
.. | .. |
---|
1407 | 1614 | /* |
---|
1408 | 1615 | * Initialize the session hash with the server one. |
---|
1409 | 1616 | */ |
---|
1410 | | - memcpy(ses->preauth_sha_hash, ses->server->preauth_sha_hash, |
---|
| 1617 | + memcpy(ses->preauth_sha_hash, server->preauth_sha_hash, |
---|
1411 | 1618 | SMB2_PREAUTH_HASH_SIZE); |
---|
1412 | 1619 | |
---|
1413 | 1620 | while (sess_data->func) |
---|
1414 | 1621 | sess_data->func(sess_data); |
---|
1415 | 1622 | |
---|
1416 | 1623 | if ((ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) && (ses->sign)) |
---|
1417 | | - cifs_dbg(VFS, "signing requested but authenticated as guest\n"); |
---|
| 1624 | + cifs_server_dbg(VFS, "signing requested but authenticated as guest\n"); |
---|
1418 | 1625 | rc = sess_data->result; |
---|
1419 | 1626 | out: |
---|
1420 | 1627 | kfree(sess_data); |
---|
.. | .. |
---|
1445 | 1652 | if (ses->need_reconnect) |
---|
1446 | 1653 | goto smb2_session_already_dead; |
---|
1447 | 1654 | |
---|
1448 | | - rc = smb2_plain_req_init(SMB2_LOGOFF, NULL, (void **) &req, &total_len); |
---|
| 1655 | + rc = smb2_plain_req_init(SMB2_LOGOFF, NULL, ses->server, |
---|
| 1656 | + (void **) &req, &total_len); |
---|
1449 | 1657 | if (rc) |
---|
1450 | 1658 | return rc; |
---|
1451 | 1659 | |
---|
.. | .. |
---|
1457 | 1665 | else if (server->sign) |
---|
1458 | 1666 | req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; |
---|
1459 | 1667 | |
---|
1460 | | - flags |= CIFS_NO_RESP; |
---|
| 1668 | + flags |= CIFS_NO_RSP_BUF; |
---|
1461 | 1669 | |
---|
1462 | 1670 | iov[0].iov_base = (char *)req; |
---|
1463 | 1671 | iov[0].iov_len = total_len; |
---|
.. | .. |
---|
1466 | 1674 | rqst.rq_iov = iov; |
---|
1467 | 1675 | rqst.rq_nvec = 1; |
---|
1468 | 1676 | |
---|
1469 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov); |
---|
| 1677 | + rc = cifs_send_recv(xid, ses, ses->server, |
---|
| 1678 | + &rqst, &resp_buf_type, flags, &rsp_iov); |
---|
1470 | 1679 | cifs_small_buf_release(req); |
---|
1471 | 1680 | /* |
---|
1472 | 1681 | * No tcon so can't do |
---|
.. | .. |
---|
1507 | 1716 | __le16 *unc_path = NULL; |
---|
1508 | 1717 | int flags = 0; |
---|
1509 | 1718 | unsigned int total_len; |
---|
| 1719 | + struct TCP_Server_Info *server; |
---|
| 1720 | + |
---|
| 1721 | + /* always use master channel */ |
---|
| 1722 | + server = ses->server; |
---|
1510 | 1723 | |
---|
1511 | 1724 | cifs_dbg(FYI, "TCON\n"); |
---|
1512 | 1725 | |
---|
1513 | | - if (!(ses->server) || !tree) |
---|
| 1726 | + if (!server || !tree) |
---|
1514 | 1727 | return -EIO; |
---|
1515 | 1728 | |
---|
1516 | 1729 | unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL); |
---|
.. | .. |
---|
1526 | 1739 | |
---|
1527 | 1740 | /* SMB2 TREE_CONNECT request must be called with TreeId == 0 */ |
---|
1528 | 1741 | tcon->tid = 0; |
---|
1529 | | - |
---|
1530 | | - rc = smb2_plain_req_init(SMB2_TREE_CONNECT, tcon, (void **) &req, |
---|
1531 | | - &total_len); |
---|
| 1742 | + atomic_set(&tcon->num_remote_opens, 0); |
---|
| 1743 | + rc = smb2_plain_req_init(SMB2_TREE_CONNECT, tcon, server, |
---|
| 1744 | + (void **) &req, &total_len); |
---|
1532 | 1745 | if (rc) { |
---|
1533 | 1746 | kfree(unc_path); |
---|
1534 | 1747 | return rc; |
---|
.. | .. |
---|
1553 | 1766 | * unless it is guest or anonymous user. See MS-SMB2 3.2.5.3.1 |
---|
1554 | 1767 | * (Samba servers don't always set the flag so also check if null user) |
---|
1555 | 1768 | */ |
---|
1556 | | - if ((ses->server->dialect == SMB311_PROT_ID) && |
---|
| 1769 | + if ((server->dialect == SMB311_PROT_ID) && |
---|
1557 | 1770 | !smb3_encryption_required(tcon) && |
---|
1558 | 1771 | !(ses->session_flags & |
---|
1559 | 1772 | (SMB2_SESSION_FLAG_IS_GUEST|SMB2_SESSION_FLAG_IS_NULL)) && |
---|
.. | .. |
---|
1564 | 1777 | rqst.rq_iov = iov; |
---|
1565 | 1778 | rqst.rq_nvec = 2; |
---|
1566 | 1779 | |
---|
1567 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
---|
| 1780 | + /* Need 64 for max size write so ask for more in case not there yet */ |
---|
| 1781 | + req->sync_hdr.CreditRequest = cpu_to_le16(64); |
---|
| 1782 | + |
---|
| 1783 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 1784 | + &rqst, &resp_buftype, flags, &rsp_iov); |
---|
1568 | 1785 | cifs_small_buf_release(req); |
---|
1569 | 1786 | rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base; |
---|
1570 | | - |
---|
| 1787 | + trace_smb3_tcon(xid, tcon->tid, ses->Suid, tree, rc); |
---|
1571 | 1788 | if (rc != 0) { |
---|
1572 | 1789 | if (tcon) { |
---|
1573 | 1790 | cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT_HE); |
---|
.. | .. |
---|
1589 | 1806 | cifs_dbg(FYI, "connection to printer\n"); |
---|
1590 | 1807 | break; |
---|
1591 | 1808 | default: |
---|
1592 | | - cifs_dbg(VFS, "unknown share type %d\n", rsp->ShareType); |
---|
| 1809 | + cifs_server_dbg(VFS, "unknown share type %d\n", rsp->ShareType); |
---|
1593 | 1810 | rc = -EOPNOTSUPP; |
---|
1594 | 1811 | goto tcon_error_exit; |
---|
1595 | 1812 | } |
---|
.. | .. |
---|
1604 | 1821 | |
---|
1605 | 1822 | if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && |
---|
1606 | 1823 | ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) |
---|
1607 | | - cifs_dbg(VFS, "DFS capability contradicts DFS flag\n"); |
---|
| 1824 | + cifs_tcon_dbg(VFS, "DFS capability contradicts DFS flag\n"); |
---|
1608 | 1825 | |
---|
1609 | 1826 | if (tcon->seal && |
---|
1610 | | - !(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) |
---|
1611 | | - cifs_dbg(VFS, "Encryption is requested but not supported\n"); |
---|
| 1827 | + !(server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) |
---|
| 1828 | + cifs_tcon_dbg(VFS, "Encryption is requested but not supported\n"); |
---|
1612 | 1829 | |
---|
1613 | 1830 | init_copy_chunk_defaults(tcon); |
---|
1614 | | - if (tcon->ses->server->ops->validate_negotiate) |
---|
1615 | | - rc = tcon->ses->server->ops->validate_negotiate(xid, tcon); |
---|
| 1831 | + if (server->ops->validate_negotiate) |
---|
| 1832 | + rc = server->ops->validate_negotiate(xid, tcon); |
---|
1616 | 1833 | tcon_exit: |
---|
| 1834 | + |
---|
1617 | 1835 | free_rsp_buf(resp_buftype, rsp); |
---|
1618 | 1836 | kfree(unc_path); |
---|
1619 | 1837 | return rc; |
---|
1620 | 1838 | |
---|
1621 | 1839 | tcon_error_exit: |
---|
1622 | 1840 | if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { |
---|
1623 | | - cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); |
---|
| 1841 | + cifs_tcon_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); |
---|
1624 | 1842 | } |
---|
1625 | 1843 | goto tcon_exit; |
---|
1626 | 1844 | } |
---|
.. | .. |
---|
1646 | 1864 | if ((tcon->need_reconnect) || (tcon->ses->need_reconnect)) |
---|
1647 | 1865 | return 0; |
---|
1648 | 1866 | |
---|
1649 | | - rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, (void **) &req, |
---|
1650 | | - &total_len); |
---|
| 1867 | + close_shroot_lease(&tcon->crfid); |
---|
| 1868 | + |
---|
| 1869 | + rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, ses->server, |
---|
| 1870 | + (void **) &req, |
---|
| 1871 | + &total_len); |
---|
1651 | 1872 | if (rc) |
---|
1652 | 1873 | return rc; |
---|
1653 | 1874 | |
---|
1654 | 1875 | if (smb3_encryption_required(tcon)) |
---|
1655 | 1876 | flags |= CIFS_TRANSFORM_REQ; |
---|
1656 | 1877 | |
---|
1657 | | - flags |= CIFS_NO_RESP; |
---|
| 1878 | + flags |= CIFS_NO_RSP_BUF; |
---|
1658 | 1879 | |
---|
1659 | 1880 | iov[0].iov_base = (char *)req; |
---|
1660 | 1881 | iov[0].iov_len = total_len; |
---|
.. | .. |
---|
1663 | 1884 | rqst.rq_iov = iov; |
---|
1664 | 1885 | rqst.rq_nvec = 1; |
---|
1665 | 1886 | |
---|
1666 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov); |
---|
| 1887 | + rc = cifs_send_recv(xid, ses, ses->server, |
---|
| 1888 | + &rqst, &resp_buf_type, flags, &rsp_iov); |
---|
1667 | 1889 | cifs_small_buf_release(req); |
---|
1668 | 1890 | if (rc) |
---|
1669 | 1891 | cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT_HE); |
---|
.. | .. |
---|
1720 | 1942 | return buf; |
---|
1721 | 1943 | } |
---|
1722 | 1944 | |
---|
1723 | | -static __u8 |
---|
1724 | | -parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp, |
---|
1725 | | - unsigned int *epoch, char *lease_key) |
---|
| 1945 | +static void |
---|
| 1946 | +parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *buf) |
---|
| 1947 | +{ |
---|
| 1948 | + struct create_on_disk_id *pdisk_id = (struct create_on_disk_id *)cc; |
---|
| 1949 | + |
---|
| 1950 | + cifs_dbg(FYI, "parse query id context 0x%llx 0x%llx\n", |
---|
| 1951 | + pdisk_id->DiskFileId, pdisk_id->VolumeId); |
---|
| 1952 | + buf->IndexNumber = pdisk_id->DiskFileId; |
---|
| 1953 | +} |
---|
| 1954 | + |
---|
| 1955 | +static void |
---|
| 1956 | +parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *info, |
---|
| 1957 | + struct create_posix_rsp *posix) |
---|
| 1958 | +{ |
---|
| 1959 | + int sid_len; |
---|
| 1960 | + u8 *beg = (u8 *)cc + le16_to_cpu(cc->DataOffset); |
---|
| 1961 | + u8 *end = beg + le32_to_cpu(cc->DataLength); |
---|
| 1962 | + u8 *sid; |
---|
| 1963 | + |
---|
| 1964 | + memset(posix, 0, sizeof(*posix)); |
---|
| 1965 | + |
---|
| 1966 | + posix->nlink = le32_to_cpu(*(__le32 *)(beg + 0)); |
---|
| 1967 | + posix->reparse_tag = le32_to_cpu(*(__le32 *)(beg + 4)); |
---|
| 1968 | + posix->mode = le32_to_cpu(*(__le32 *)(beg + 8)); |
---|
| 1969 | + |
---|
| 1970 | + sid = beg + 12; |
---|
| 1971 | + sid_len = posix_info_sid_size(sid, end); |
---|
| 1972 | + if (sid_len < 0) { |
---|
| 1973 | + cifs_dbg(VFS, "bad owner sid in posix create response\n"); |
---|
| 1974 | + return; |
---|
| 1975 | + } |
---|
| 1976 | + memcpy(&posix->owner, sid, sid_len); |
---|
| 1977 | + |
---|
| 1978 | + sid = sid + sid_len; |
---|
| 1979 | + sid_len = posix_info_sid_size(sid, end); |
---|
| 1980 | + if (sid_len < 0) { |
---|
| 1981 | + cifs_dbg(VFS, "bad group sid in posix create response\n"); |
---|
| 1982 | + return; |
---|
| 1983 | + } |
---|
| 1984 | + memcpy(&posix->group, sid, sid_len); |
---|
| 1985 | + |
---|
| 1986 | + cifs_dbg(FYI, "nlink=%d mode=%o reparse_tag=%x\n", |
---|
| 1987 | + posix->nlink, posix->mode, posix->reparse_tag); |
---|
| 1988 | +} |
---|
| 1989 | + |
---|
| 1990 | +void |
---|
| 1991 | +smb2_parse_contexts(struct TCP_Server_Info *server, |
---|
| 1992 | + struct smb2_create_rsp *rsp, |
---|
| 1993 | + unsigned int *epoch, char *lease_key, __u8 *oplock, |
---|
| 1994 | + struct smb2_file_all_info *buf, |
---|
| 1995 | + struct create_posix_rsp *posix) |
---|
1726 | 1996 | { |
---|
1727 | 1997 | char *data_offset; |
---|
1728 | 1998 | struct create_context *cc; |
---|
1729 | 1999 | unsigned int next; |
---|
1730 | 2000 | unsigned int remaining; |
---|
1731 | 2001 | char *name; |
---|
| 2002 | + static const char smb3_create_tag_posix[] = { |
---|
| 2003 | + 0x93, 0xAD, 0x25, 0x50, 0x9C, |
---|
| 2004 | + 0xB4, 0x11, 0xE7, 0xB4, 0x23, 0x83, |
---|
| 2005 | + 0xDE, 0x96, 0x8B, 0xCD, 0x7C |
---|
| 2006 | + }; |
---|
1732 | 2007 | |
---|
| 2008 | + *oplock = 0; |
---|
1733 | 2009 | data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset); |
---|
1734 | 2010 | remaining = le32_to_cpu(rsp->CreateContextsLength); |
---|
1735 | 2011 | cc = (struct create_context *)data_offset; |
---|
| 2012 | + |
---|
| 2013 | + /* Initialize inode number to 0 in case no valid data in qfid context */ |
---|
| 2014 | + if (buf) |
---|
| 2015 | + buf->IndexNumber = 0; |
---|
| 2016 | + |
---|
1736 | 2017 | while (remaining >= sizeof(struct create_context)) { |
---|
1737 | 2018 | name = le16_to_cpu(cc->NameOffset) + (char *)cc; |
---|
1738 | 2019 | if (le16_to_cpu(cc->NameLength) == 4 && |
---|
1739 | | - strncmp(name, "RqLs", 4) == 0) |
---|
1740 | | - return server->ops->parse_lease_buf(cc, epoch, |
---|
1741 | | - lease_key); |
---|
| 2020 | + strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4) == 0) |
---|
| 2021 | + *oplock = server->ops->parse_lease_buf(cc, epoch, |
---|
| 2022 | + lease_key); |
---|
| 2023 | + else if (buf && (le16_to_cpu(cc->NameLength) == 4) && |
---|
| 2024 | + strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0) |
---|
| 2025 | + parse_query_id_ctxt(cc, buf); |
---|
| 2026 | + else if ((le16_to_cpu(cc->NameLength) == 16)) { |
---|
| 2027 | + if (posix && |
---|
| 2028 | + memcmp(name, smb3_create_tag_posix, 16) == 0) |
---|
| 2029 | + parse_posix_ctxt(cc, buf, posix); |
---|
| 2030 | + } |
---|
| 2031 | + /* else { |
---|
| 2032 | + cifs_dbg(FYI, "Context not matched with len %d\n", |
---|
| 2033 | + le16_to_cpu(cc->NameLength)); |
---|
| 2034 | + cifs_dump_mem("Cctxt name: ", name, 4); |
---|
| 2035 | + } */ |
---|
1742 | 2036 | |
---|
1743 | 2037 | next = le32_to_cpu(cc->Next); |
---|
1744 | 2038 | if (!next) |
---|
.. | .. |
---|
1747 | 2041 | cc = (struct create_context *)((char *)cc + next); |
---|
1748 | 2042 | } |
---|
1749 | 2043 | |
---|
1750 | | - return 0; |
---|
| 2044 | + if (rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE) |
---|
| 2045 | + *oplock = rsp->OplockLevel; |
---|
| 2046 | + |
---|
| 2047 | + return; |
---|
1751 | 2048 | } |
---|
1752 | 2049 | |
---|
1753 | 2050 | static int |
---|
.. | .. |
---|
1773 | 2070 | } |
---|
1774 | 2071 | |
---|
1775 | 2072 | static struct create_durable_v2 * |
---|
1776 | | -create_durable_v2_buf(struct cifs_fid *pfid) |
---|
| 2073 | +create_durable_v2_buf(struct cifs_open_parms *oparms) |
---|
1777 | 2074 | { |
---|
| 2075 | + struct cifs_fid *pfid = oparms->fid; |
---|
1778 | 2076 | struct create_durable_v2 *buf; |
---|
1779 | 2077 | |
---|
1780 | 2078 | buf = kzalloc(sizeof(struct create_durable_v2), GFP_KERNEL); |
---|
.. | .. |
---|
1788 | 2086 | (struct create_durable_v2, Name)); |
---|
1789 | 2087 | buf->ccontext.NameLength = cpu_to_le16(4); |
---|
1790 | 2088 | |
---|
1791 | | - buf->dcontext.Timeout = 0; /* Should this be configurable by workload */ |
---|
| 2089 | + /* |
---|
| 2090 | + * NB: Handle timeout defaults to 0, which allows server to choose |
---|
| 2091 | + * (most servers default to 120 seconds) and most clients default to 0. |
---|
| 2092 | + * This can be overridden at mount ("handletimeout=") if the user wants |
---|
| 2093 | + * a different persistent (or resilient) handle timeout for all opens |
---|
| 2094 | + * opens on a particular SMB3 mount. |
---|
| 2095 | + */ |
---|
| 2096 | + buf->dcontext.Timeout = cpu_to_le32(oparms->tcon->handle_timeout); |
---|
1792 | 2097 | buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT); |
---|
1793 | 2098 | generate_random_uuid(buf->dcontext.CreateGuid); |
---|
1794 | 2099 | memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16); |
---|
.. | .. |
---|
1841 | 2146 | struct smb2_create_req *req = iov[0].iov_base; |
---|
1842 | 2147 | unsigned int num = *num_iovec; |
---|
1843 | 2148 | |
---|
1844 | | - iov[num].iov_base = create_durable_v2_buf(oparms->fid); |
---|
| 2149 | + iov[num].iov_base = create_durable_v2_buf(oparms); |
---|
1845 | 2150 | if (iov[num].iov_base == NULL) |
---|
1846 | 2151 | return -ENOMEM; |
---|
1847 | 2152 | iov[num].iov_len = sizeof(struct create_durable_v2); |
---|
.. | .. |
---|
1956 | 2261 | return 0; |
---|
1957 | 2262 | } |
---|
1958 | 2263 | |
---|
| 2264 | +/* See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx */ |
---|
| 2265 | +static void setup_owner_group_sids(char *buf) |
---|
| 2266 | +{ |
---|
| 2267 | + struct owner_group_sids *sids = (struct owner_group_sids *)buf; |
---|
| 2268 | + |
---|
| 2269 | + /* Populate the user ownership fields S-1-5-88-1 */ |
---|
| 2270 | + sids->owner.Revision = 1; |
---|
| 2271 | + sids->owner.NumAuth = 3; |
---|
| 2272 | + sids->owner.Authority[5] = 5; |
---|
| 2273 | + sids->owner.SubAuthorities[0] = cpu_to_le32(88); |
---|
| 2274 | + sids->owner.SubAuthorities[1] = cpu_to_le32(1); |
---|
| 2275 | + sids->owner.SubAuthorities[2] = cpu_to_le32(current_fsuid().val); |
---|
| 2276 | + |
---|
| 2277 | + /* Populate the group ownership fields S-1-5-88-2 */ |
---|
| 2278 | + sids->group.Revision = 1; |
---|
| 2279 | + sids->group.NumAuth = 3; |
---|
| 2280 | + sids->group.Authority[5] = 5; |
---|
| 2281 | + sids->group.SubAuthorities[0] = cpu_to_le32(88); |
---|
| 2282 | + sids->group.SubAuthorities[1] = cpu_to_le32(2); |
---|
| 2283 | + sids->group.SubAuthorities[2] = cpu_to_le32(current_fsgid().val); |
---|
| 2284 | + |
---|
| 2285 | + cifs_dbg(FYI, "owner S-1-5-88-1-%d, group S-1-5-88-2-%d\n", current_fsuid().val, current_fsgid().val); |
---|
| 2286 | +} |
---|
| 2287 | + |
---|
| 2288 | +/* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */ |
---|
| 2289 | +static struct crt_sd_ctxt * |
---|
| 2290 | +create_sd_buf(umode_t mode, bool set_owner, unsigned int *len) |
---|
| 2291 | +{ |
---|
| 2292 | + struct crt_sd_ctxt *buf; |
---|
| 2293 | + __u8 *ptr, *aclptr; |
---|
| 2294 | + unsigned int acelen, acl_size, ace_count; |
---|
| 2295 | + unsigned int owner_offset = 0; |
---|
| 2296 | + unsigned int group_offset = 0; |
---|
| 2297 | + struct smb3_acl acl = {}; |
---|
| 2298 | + |
---|
| 2299 | + *len = roundup(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 4), 8); |
---|
| 2300 | + |
---|
| 2301 | + if (set_owner) { |
---|
| 2302 | + /* sizeof(struct owner_group_sids) is already multiple of 8 so no need to round */ |
---|
| 2303 | + *len += sizeof(struct owner_group_sids); |
---|
| 2304 | + } |
---|
| 2305 | + |
---|
| 2306 | + buf = kzalloc(*len, GFP_KERNEL); |
---|
| 2307 | + if (buf == NULL) |
---|
| 2308 | + return buf; |
---|
| 2309 | + |
---|
| 2310 | + ptr = (__u8 *)&buf[1]; |
---|
| 2311 | + if (set_owner) { |
---|
| 2312 | + /* offset fields are from beginning of security descriptor not of create context */ |
---|
| 2313 | + owner_offset = ptr - (__u8 *)&buf->sd; |
---|
| 2314 | + buf->sd.OffsetOwner = cpu_to_le32(owner_offset); |
---|
| 2315 | + group_offset = owner_offset + offsetof(struct owner_group_sids, group); |
---|
| 2316 | + buf->sd.OffsetGroup = cpu_to_le32(group_offset); |
---|
| 2317 | + |
---|
| 2318 | + setup_owner_group_sids(ptr); |
---|
| 2319 | + ptr += sizeof(struct owner_group_sids); |
---|
| 2320 | + } else { |
---|
| 2321 | + buf->sd.OffsetOwner = 0; |
---|
| 2322 | + buf->sd.OffsetGroup = 0; |
---|
| 2323 | + } |
---|
| 2324 | + |
---|
| 2325 | + buf->ccontext.DataOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, sd)); |
---|
| 2326 | + buf->ccontext.NameOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, Name)); |
---|
| 2327 | + buf->ccontext.NameLength = cpu_to_le16(4); |
---|
| 2328 | + /* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */ |
---|
| 2329 | + buf->Name[0] = 'S'; |
---|
| 2330 | + buf->Name[1] = 'e'; |
---|
| 2331 | + buf->Name[2] = 'c'; |
---|
| 2332 | + buf->Name[3] = 'D'; |
---|
| 2333 | + buf->sd.Revision = 1; /* Must be one see MS-DTYP 2.4.6 */ |
---|
| 2334 | + |
---|
| 2335 | + /* |
---|
| 2336 | + * ACL is "self relative" ie ACL is stored in contiguous block of memory |
---|
| 2337 | + * and "DP" ie the DACL is present |
---|
| 2338 | + */ |
---|
| 2339 | + buf->sd.Control = cpu_to_le16(ACL_CONTROL_SR | ACL_CONTROL_DP); |
---|
| 2340 | + |
---|
| 2341 | + /* offset owner, group and Sbz1 and SACL are all zero */ |
---|
| 2342 | + buf->sd.OffsetDacl = cpu_to_le32(ptr - (__u8 *)&buf->sd); |
---|
| 2343 | + /* Ship the ACL for now. we will copy it into buf later. */ |
---|
| 2344 | + aclptr = ptr; |
---|
| 2345 | + ptr += sizeof(struct smb3_acl); |
---|
| 2346 | + |
---|
| 2347 | + /* create one ACE to hold the mode embedded in reserved special SID */ |
---|
| 2348 | + acelen = setup_special_mode_ACE((struct cifs_ace *)ptr, (__u64)mode); |
---|
| 2349 | + ptr += acelen; |
---|
| 2350 | + acl_size = acelen + sizeof(struct smb3_acl); |
---|
| 2351 | + ace_count = 1; |
---|
| 2352 | + |
---|
| 2353 | + if (set_owner) { |
---|
| 2354 | + /* we do not need to reallocate buffer to add the two more ACEs. plenty of space */ |
---|
| 2355 | + acelen = setup_special_user_owner_ACE((struct cifs_ace *)ptr); |
---|
| 2356 | + ptr += acelen; |
---|
| 2357 | + acl_size += acelen; |
---|
| 2358 | + ace_count += 1; |
---|
| 2359 | + } |
---|
| 2360 | + |
---|
| 2361 | + /* and one more ACE to allow access for authenticated users */ |
---|
| 2362 | + acelen = setup_authusers_ACE((struct cifs_ace *)ptr); |
---|
| 2363 | + ptr += acelen; |
---|
| 2364 | + acl_size += acelen; |
---|
| 2365 | + ace_count += 1; |
---|
| 2366 | + |
---|
| 2367 | + acl.AclRevision = ACL_REVISION; /* See 2.4.4.1 of MS-DTYP */ |
---|
| 2368 | + acl.AclSize = cpu_to_le16(acl_size); |
---|
| 2369 | + acl.AceCount = cpu_to_le16(ace_count); |
---|
| 2370 | + /* acl.Sbz1 and Sbz2 MBZ so are not set here, but initialized above */ |
---|
| 2371 | + memcpy(aclptr, &acl, sizeof(struct smb3_acl)); |
---|
| 2372 | + |
---|
| 2373 | + buf->ccontext.DataLength = cpu_to_le32(ptr - (__u8 *)&buf->sd); |
---|
| 2374 | + *len = roundup(ptr - (__u8 *)buf, 8); |
---|
| 2375 | + |
---|
| 2376 | + return buf; |
---|
| 2377 | +} |
---|
| 2378 | + |
---|
| 2379 | +static int |
---|
| 2380 | +add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode, bool set_owner) |
---|
| 2381 | +{ |
---|
| 2382 | + struct smb2_create_req *req = iov[0].iov_base; |
---|
| 2383 | + unsigned int num = *num_iovec; |
---|
| 2384 | + unsigned int len = 0; |
---|
| 2385 | + |
---|
| 2386 | + iov[num].iov_base = create_sd_buf(mode, set_owner, &len); |
---|
| 2387 | + if (iov[num].iov_base == NULL) |
---|
| 2388 | + return -ENOMEM; |
---|
| 2389 | + iov[num].iov_len = len; |
---|
| 2390 | + if (!req->CreateContextsOffset) |
---|
| 2391 | + req->CreateContextsOffset = cpu_to_le32( |
---|
| 2392 | + sizeof(struct smb2_create_req) + |
---|
| 2393 | + iov[num - 1].iov_len); |
---|
| 2394 | + le32_add_cpu(&req->CreateContextsLength, len); |
---|
| 2395 | + *num_iovec = num + 1; |
---|
| 2396 | + return 0; |
---|
| 2397 | +} |
---|
| 2398 | + |
---|
| 2399 | +static struct crt_query_id_ctxt * |
---|
| 2400 | +create_query_id_buf(void) |
---|
| 2401 | +{ |
---|
| 2402 | + struct crt_query_id_ctxt *buf; |
---|
| 2403 | + |
---|
| 2404 | + buf = kzalloc(sizeof(struct crt_query_id_ctxt), GFP_KERNEL); |
---|
| 2405 | + if (!buf) |
---|
| 2406 | + return NULL; |
---|
| 2407 | + |
---|
| 2408 | + buf->ccontext.DataOffset = cpu_to_le16(0); |
---|
| 2409 | + buf->ccontext.DataLength = cpu_to_le32(0); |
---|
| 2410 | + buf->ccontext.NameOffset = cpu_to_le16(offsetof |
---|
| 2411 | + (struct crt_query_id_ctxt, Name)); |
---|
| 2412 | + buf->ccontext.NameLength = cpu_to_le16(4); |
---|
| 2413 | + /* SMB2_CREATE_QUERY_ON_DISK_ID is "QFid" */ |
---|
| 2414 | + buf->Name[0] = 'Q'; |
---|
| 2415 | + buf->Name[1] = 'F'; |
---|
| 2416 | + buf->Name[2] = 'i'; |
---|
| 2417 | + buf->Name[3] = 'd'; |
---|
| 2418 | + return buf; |
---|
| 2419 | +} |
---|
| 2420 | + |
---|
| 2421 | +/* See MS-SMB2 2.2.13.2.9 */ |
---|
| 2422 | +static int |
---|
| 2423 | +add_query_id_context(struct kvec *iov, unsigned int *num_iovec) |
---|
| 2424 | +{ |
---|
| 2425 | + struct smb2_create_req *req = iov[0].iov_base; |
---|
| 2426 | + unsigned int num = *num_iovec; |
---|
| 2427 | + |
---|
| 2428 | + iov[num].iov_base = create_query_id_buf(); |
---|
| 2429 | + if (iov[num].iov_base == NULL) |
---|
| 2430 | + return -ENOMEM; |
---|
| 2431 | + iov[num].iov_len = sizeof(struct crt_query_id_ctxt); |
---|
| 2432 | + if (!req->CreateContextsOffset) |
---|
| 2433 | + req->CreateContextsOffset = cpu_to_le32( |
---|
| 2434 | + sizeof(struct smb2_create_req) + |
---|
| 2435 | + iov[num - 1].iov_len); |
---|
| 2436 | + le32_add_cpu(&req->CreateContextsLength, sizeof(struct crt_query_id_ctxt)); |
---|
| 2437 | + *num_iovec = num + 1; |
---|
| 2438 | + return 0; |
---|
| 2439 | +} |
---|
| 2440 | + |
---|
1959 | 2441 | static int |
---|
1960 | 2442 | alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len, |
---|
1961 | 2443 | const char *treename, const __le16 *path) |
---|
.. | .. |
---|
2009 | 2491 | struct smb_rqst rqst; |
---|
2010 | 2492 | struct smb2_create_req *req; |
---|
2011 | 2493 | struct smb2_create_rsp *rsp = NULL; |
---|
2012 | | - struct TCP_Server_Info *server; |
---|
2013 | 2494 | struct cifs_ses *ses = tcon->ses; |
---|
2014 | 2495 | struct kvec iov[3]; /* make sure at least one for each open context */ |
---|
2015 | 2496 | struct kvec rsp_iov = {NULL, 0}; |
---|
.. | .. |
---|
2024 | 2505 | int flags = 0; |
---|
2025 | 2506 | unsigned int total_len; |
---|
2026 | 2507 | __le16 *utf16_path = NULL; |
---|
| 2508 | + struct TCP_Server_Info *server = cifs_pick_channel(ses); |
---|
2027 | 2509 | |
---|
2028 | 2510 | cifs_dbg(FYI, "mkdir\n"); |
---|
2029 | 2511 | |
---|
.. | .. |
---|
2032 | 2514 | if (!utf16_path) |
---|
2033 | 2515 | return -ENOMEM; |
---|
2034 | 2516 | |
---|
2035 | | - if (ses && (ses->server)) |
---|
2036 | | - server = ses->server; |
---|
2037 | | - else { |
---|
| 2517 | + if (!ses || !server) { |
---|
2038 | 2518 | rc = -EIO; |
---|
2039 | 2519 | goto err_free_path; |
---|
2040 | 2520 | } |
---|
2041 | 2521 | |
---|
2042 | 2522 | /* resource #2: request */ |
---|
2043 | | - rc = smb2_plain_req_init(SMB2_CREATE, tcon, (void **) &req, &total_len); |
---|
| 2523 | + rc = smb2_plain_req_init(SMB2_CREATE, tcon, server, |
---|
| 2524 | + (void **) &req, &total_len); |
---|
2044 | 2525 | if (rc) |
---|
2045 | 2526 | goto err_free_path; |
---|
2046 | 2527 | |
---|
.. | .. |
---|
2122 | 2603 | rqst.rq_iov = iov; |
---|
2123 | 2604 | rqst.rq_nvec = n_iov; |
---|
2124 | 2605 | |
---|
| 2606 | + /* no need to inc num_remote_opens because we close it just below */ |
---|
| 2607 | + trace_smb3_posix_mkdir_enter(xid, tcon->tid, ses->Suid, CREATE_NOT_FILE, |
---|
| 2608 | + FILE_WRITE_ATTRIBUTES); |
---|
2125 | 2609 | /* resource #4: response buffer */ |
---|
2126 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
---|
| 2610 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 2611 | + &rqst, &resp_buftype, flags, &rsp_iov); |
---|
2127 | 2612 | if (rc) { |
---|
2128 | 2613 | cifs_stats_fail_inc(tcon, SMB2_CREATE_HE); |
---|
2129 | 2614 | trace_smb3_posix_mkdir_err(xid, tcon->tid, ses->Suid, |
---|
.. | .. |
---|
2152 | 2637 | } |
---|
2153 | 2638 | |
---|
2154 | 2639 | int |
---|
2155 | | -SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock, |
---|
| 2640 | +SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, |
---|
| 2641 | + struct smb_rqst *rqst, __u8 *oplock, |
---|
2156 | 2642 | struct cifs_open_parms *oparms, __le16 *path) |
---|
2157 | 2643 | { |
---|
2158 | | - struct TCP_Server_Info *server = tcon->ses->server; |
---|
2159 | 2644 | struct smb2_create_req *req; |
---|
2160 | 2645 | unsigned int n_iov = 2; |
---|
2161 | 2646 | __u32 file_attributes = 0; |
---|
.. | .. |
---|
2166 | 2651 | __le16 *copy_path; |
---|
2167 | 2652 | int rc; |
---|
2168 | 2653 | |
---|
2169 | | - rc = smb2_plain_req_init(SMB2_CREATE, tcon, (void **) &req, &total_len); |
---|
| 2654 | + rc = smb2_plain_req_init(SMB2_CREATE, tcon, server, |
---|
| 2655 | + (void **) &req, &total_len); |
---|
2170 | 2656 | if (rc) |
---|
2171 | 2657 | return rc; |
---|
2172 | 2658 | |
---|
.. | .. |
---|
2184 | 2670 | /* File attributes ignored on open (used in create though) */ |
---|
2185 | 2671 | req->FileAttributes = cpu_to_le32(file_attributes); |
---|
2186 | 2672 | req->ShareAccess = FILE_SHARE_ALL_LE; |
---|
| 2673 | + |
---|
2187 | 2674 | req->CreateDisposition = cpu_to_le32(oparms->disposition); |
---|
2188 | 2675 | req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK); |
---|
2189 | 2676 | req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req)); |
---|
.. | .. |
---|
2285 | 2772 | return rc; |
---|
2286 | 2773 | } |
---|
2287 | 2774 | |
---|
| 2775 | + if ((oparms->disposition != FILE_OPEN) && (oparms->cifs_sb)) { |
---|
| 2776 | + bool set_mode; |
---|
| 2777 | + bool set_owner; |
---|
| 2778 | + |
---|
| 2779 | + if ((oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) && |
---|
| 2780 | + (oparms->mode != ACL_NO_MODE)) |
---|
| 2781 | + set_mode = true; |
---|
| 2782 | + else { |
---|
| 2783 | + set_mode = false; |
---|
| 2784 | + oparms->mode = ACL_NO_MODE; |
---|
| 2785 | + } |
---|
| 2786 | + |
---|
| 2787 | + if (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) |
---|
| 2788 | + set_owner = true; |
---|
| 2789 | + else |
---|
| 2790 | + set_owner = false; |
---|
| 2791 | + |
---|
| 2792 | + if (set_owner | set_mode) { |
---|
| 2793 | + if (n_iov > 2) { |
---|
| 2794 | + struct create_context *ccontext = |
---|
| 2795 | + (struct create_context *)iov[n_iov-1].iov_base; |
---|
| 2796 | + ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len); |
---|
| 2797 | + } |
---|
| 2798 | + |
---|
| 2799 | + cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode); |
---|
| 2800 | + rc = add_sd_context(iov, &n_iov, oparms->mode, set_owner); |
---|
| 2801 | + if (rc) |
---|
| 2802 | + return rc; |
---|
| 2803 | + } |
---|
| 2804 | + } |
---|
| 2805 | + |
---|
| 2806 | + if (n_iov > 2) { |
---|
| 2807 | + struct create_context *ccontext = |
---|
| 2808 | + (struct create_context *)iov[n_iov-1].iov_base; |
---|
| 2809 | + ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len); |
---|
| 2810 | + } |
---|
| 2811 | + add_query_id_context(iov, &n_iov); |
---|
2288 | 2812 | |
---|
2289 | 2813 | rqst->rq_nvec = n_iov; |
---|
2290 | 2814 | return 0; |
---|
.. | .. |
---|
2309 | 2833 | int |
---|
2310 | 2834 | SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, |
---|
2311 | 2835 | __u8 *oplock, struct smb2_file_all_info *buf, |
---|
| 2836 | + struct create_posix_rsp *posix, |
---|
2312 | 2837 | struct kvec *err_iov, int *buftype) |
---|
2313 | 2838 | { |
---|
2314 | 2839 | struct smb_rqst rqst; |
---|
2315 | 2840 | struct smb2_create_rsp *rsp = NULL; |
---|
2316 | | - struct TCP_Server_Info *server; |
---|
2317 | 2841 | struct cifs_tcon *tcon = oparms->tcon; |
---|
2318 | 2842 | struct cifs_ses *ses = tcon->ses; |
---|
| 2843 | + struct TCP_Server_Info *server = cifs_pick_channel(ses); |
---|
2319 | 2844 | struct kvec iov[SMB2_CREATE_IOV_SIZE]; |
---|
2320 | 2845 | struct kvec rsp_iov = {NULL, 0}; |
---|
2321 | 2846 | int resp_buftype = CIFS_NO_BUFFER; |
---|
.. | .. |
---|
2323 | 2848 | int flags = 0; |
---|
2324 | 2849 | |
---|
2325 | 2850 | cifs_dbg(FYI, "create/open\n"); |
---|
2326 | | - if (ses && (ses->server)) |
---|
2327 | | - server = ses->server; |
---|
2328 | | - else |
---|
| 2851 | + if (!ses || !server) |
---|
2329 | 2852 | return -EIO; |
---|
2330 | 2853 | |
---|
2331 | 2854 | if (smb3_encryption_required(tcon)) |
---|
.. | .. |
---|
2336 | 2859 | rqst.rq_iov = iov; |
---|
2337 | 2860 | rqst.rq_nvec = SMB2_CREATE_IOV_SIZE; |
---|
2338 | 2861 | |
---|
2339 | | - rc = SMB2_open_init(tcon, &rqst, oplock, oparms, path); |
---|
| 2862 | + rc = SMB2_open_init(tcon, server, |
---|
| 2863 | + &rqst, oplock, oparms, path); |
---|
2340 | 2864 | if (rc) |
---|
2341 | 2865 | goto creat_exit; |
---|
2342 | 2866 | |
---|
2343 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, |
---|
| 2867 | + trace_smb3_open_enter(xid, tcon->tid, tcon->ses->Suid, |
---|
| 2868 | + oparms->create_options, oparms->desired_access); |
---|
| 2869 | + |
---|
| 2870 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 2871 | + &rqst, &resp_buftype, flags, |
---|
2344 | 2872 | &rsp_iov); |
---|
2345 | 2873 | rsp = (struct smb2_create_rsp *)rsp_iov.iov_base; |
---|
2346 | 2874 | |
---|
.. | .. |
---|
2354 | 2882 | } |
---|
2355 | 2883 | trace_smb3_open_err(xid, tcon->tid, ses->Suid, |
---|
2356 | 2884 | oparms->create_options, oparms->desired_access, rc); |
---|
| 2885 | + if (rc == -EREMCHG) { |
---|
| 2886 | + pr_warn_once("server share %s deleted\n", |
---|
| 2887 | + tcon->treeName); |
---|
| 2888 | + tcon->need_reconnect = true; |
---|
| 2889 | + } |
---|
2357 | 2890 | goto creat_exit; |
---|
2358 | 2891 | } else |
---|
2359 | 2892 | trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid, |
---|
2360 | 2893 | ses->Suid, oparms->create_options, |
---|
2361 | 2894 | oparms->desired_access); |
---|
2362 | 2895 | |
---|
| 2896 | + atomic_inc(&tcon->num_remote_opens); |
---|
2363 | 2897 | oparms->fid->persistent_fid = rsp->PersistentFileId; |
---|
2364 | 2898 | oparms->fid->volatile_fid = rsp->VolatileFileId; |
---|
| 2899 | + oparms->fid->access = oparms->desired_access; |
---|
| 2900 | +#ifdef CONFIG_CIFS_DEBUG2 |
---|
| 2901 | + oparms->fid->mid = le64_to_cpu(rsp->sync_hdr.MessageId); |
---|
| 2902 | +#endif /* CIFS_DEBUG2 */ |
---|
2365 | 2903 | |
---|
2366 | 2904 | if (buf) { |
---|
2367 | 2905 | memcpy(buf, &rsp->CreationTime, 32); |
---|
.. | .. |
---|
2372 | 2910 | buf->DeletePending = 0; |
---|
2373 | 2911 | } |
---|
2374 | 2912 | |
---|
2375 | | - if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) |
---|
2376 | | - *oplock = parse_lease_state(server, rsp, &oparms->fid->epoch, |
---|
2377 | | - oparms->fid->lease_key); |
---|
2378 | | - else |
---|
2379 | | - *oplock = rsp->OplockLevel; |
---|
| 2913 | + |
---|
| 2914 | + smb2_parse_contexts(server, rsp, &oparms->fid->epoch, |
---|
| 2915 | + oparms->fid->lease_key, oplock, buf, posix); |
---|
2380 | 2916 | creat_exit: |
---|
2381 | 2917 | SMB2_open_free(&rqst); |
---|
2382 | 2918 | free_rsp_buf(resp_buftype, rsp); |
---|
2383 | 2919 | return rc; |
---|
2384 | 2920 | } |
---|
2385 | 2921 | |
---|
| 2922 | +int |
---|
| 2923 | +SMB2_ioctl_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, |
---|
| 2924 | + struct smb_rqst *rqst, |
---|
| 2925 | + u64 persistent_fid, u64 volatile_fid, u32 opcode, |
---|
| 2926 | + char *in_data, u32 indatalen, |
---|
| 2927 | + __u32 max_response_size) |
---|
| 2928 | +{ |
---|
| 2929 | + struct smb2_ioctl_req *req; |
---|
| 2930 | + struct kvec *iov = rqst->rq_iov; |
---|
| 2931 | + unsigned int total_len; |
---|
| 2932 | + int rc; |
---|
| 2933 | + char *in_data_buf; |
---|
| 2934 | + |
---|
| 2935 | + rc = smb2_ioctl_req_init(opcode, tcon, server, |
---|
| 2936 | + (void **) &req, &total_len); |
---|
| 2937 | + if (rc) |
---|
| 2938 | + return rc; |
---|
| 2939 | + |
---|
| 2940 | + if (indatalen) { |
---|
| 2941 | + /* |
---|
| 2942 | + * indatalen is usually small at a couple of bytes max, so |
---|
| 2943 | + * just allocate through generic pool |
---|
| 2944 | + */ |
---|
| 2945 | + in_data_buf = kmemdup(in_data, indatalen, GFP_NOFS); |
---|
| 2946 | + if (!in_data_buf) { |
---|
| 2947 | + cifs_small_buf_release(req); |
---|
| 2948 | + return -ENOMEM; |
---|
| 2949 | + } |
---|
| 2950 | + } |
---|
| 2951 | + |
---|
| 2952 | + req->CtlCode = cpu_to_le32(opcode); |
---|
| 2953 | + req->PersistentFileId = persistent_fid; |
---|
| 2954 | + req->VolatileFileId = volatile_fid; |
---|
| 2955 | + |
---|
| 2956 | + iov[0].iov_base = (char *)req; |
---|
| 2957 | + /* |
---|
| 2958 | + * If no input data, the size of ioctl struct in |
---|
| 2959 | + * protocol spec still includes a 1 byte data buffer, |
---|
| 2960 | + * but if input data passed to ioctl, we do not |
---|
| 2961 | + * want to double count this, so we do not send |
---|
| 2962 | + * the dummy one byte of data in iovec[0] if sending |
---|
| 2963 | + * input data (in iovec[1]). |
---|
| 2964 | + */ |
---|
| 2965 | + if (indatalen) { |
---|
| 2966 | + req->InputCount = cpu_to_le32(indatalen); |
---|
| 2967 | + /* do not set InputOffset if no input data */ |
---|
| 2968 | + req->InputOffset = |
---|
| 2969 | + cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer)); |
---|
| 2970 | + rqst->rq_nvec = 2; |
---|
| 2971 | + iov[0].iov_len = total_len - 1; |
---|
| 2972 | + iov[1].iov_base = in_data_buf; |
---|
| 2973 | + iov[1].iov_len = indatalen; |
---|
| 2974 | + } else { |
---|
| 2975 | + rqst->rq_nvec = 1; |
---|
| 2976 | + iov[0].iov_len = total_len; |
---|
| 2977 | + } |
---|
| 2978 | + |
---|
| 2979 | + req->OutputOffset = 0; |
---|
| 2980 | + req->OutputCount = 0; /* MBZ */ |
---|
| 2981 | + |
---|
| 2982 | + /* |
---|
| 2983 | + * In most cases max_response_size is set to 16K (CIFSMaxBufSize) |
---|
| 2984 | + * We Could increase default MaxOutputResponse, but that could require |
---|
| 2985 | + * more credits. Windows typically sets this smaller, but for some |
---|
| 2986 | + * ioctls it may be useful to allow server to send more. No point |
---|
| 2987 | + * limiting what the server can send as long as fits in one credit |
---|
| 2988 | + * We can not handle more than CIFS_MAX_BUF_SIZE yet but may want |
---|
| 2989 | + * to increase this limit up in the future. |
---|
| 2990 | + * Note that for snapshot queries that servers like Azure expect that |
---|
| 2991 | + * the first query be minimal size (and just used to get the number/size |
---|
| 2992 | + * of previous versions) so response size must be specified as EXACTLY |
---|
| 2993 | + * sizeof(struct snapshot_array) which is 16 when rounded up to multiple |
---|
| 2994 | + * of eight bytes. Currently that is the only case where we set max |
---|
| 2995 | + * response size smaller. |
---|
| 2996 | + */ |
---|
| 2997 | + req->MaxOutputResponse = cpu_to_le32(max_response_size); |
---|
| 2998 | + req->sync_hdr.CreditCharge = |
---|
| 2999 | + cpu_to_le16(DIV_ROUND_UP(max(indatalen, max_response_size), |
---|
| 3000 | + SMB2_MAX_BUFFER_SIZE)); |
---|
| 3001 | + /* always an FSCTL (for now) */ |
---|
| 3002 | + req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL); |
---|
| 3003 | + |
---|
| 3004 | + /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */ |
---|
| 3005 | + if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) |
---|
| 3006 | + req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; |
---|
| 3007 | + |
---|
| 3008 | + return 0; |
---|
| 3009 | +} |
---|
| 3010 | + |
---|
| 3011 | +void |
---|
| 3012 | +SMB2_ioctl_free(struct smb_rqst *rqst) |
---|
| 3013 | +{ |
---|
| 3014 | + int i; |
---|
| 3015 | + if (rqst && rqst->rq_iov) { |
---|
| 3016 | + cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ |
---|
| 3017 | + for (i = 1; i < rqst->rq_nvec; i++) |
---|
| 3018 | + if (rqst->rq_iov[i].iov_base != smb2_padding) |
---|
| 3019 | + kfree(rqst->rq_iov[i].iov_base); |
---|
| 3020 | + } |
---|
| 3021 | +} |
---|
| 3022 | + |
---|
| 3023 | + |
---|
2386 | 3024 | /* |
---|
2387 | 3025 | * SMB2 IOCTL is used for both IOCTLs and FSCTLs |
---|
2388 | 3026 | */ |
---|
2389 | 3027 | int |
---|
2390 | 3028 | SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, |
---|
2391 | | - u64 volatile_fid, u32 opcode, bool is_fsctl, |
---|
2392 | | - char *in_data, u32 indatalen, |
---|
2393 | | - char **out_data, u32 *plen /* returned data len */) |
---|
| 3029 | + u64 volatile_fid, u32 opcode, char *in_data, u32 indatalen, |
---|
| 3030 | + u32 max_out_data_len, char **out_data, |
---|
| 3031 | + u32 *plen /* returned data len */) |
---|
2394 | 3032 | { |
---|
2395 | 3033 | struct smb_rqst rqst; |
---|
2396 | | - struct smb2_ioctl_req *req; |
---|
2397 | | - struct smb2_ioctl_rsp *rsp; |
---|
| 3034 | + struct smb2_ioctl_rsp *rsp = NULL; |
---|
2398 | 3035 | struct cifs_ses *ses; |
---|
2399 | | - struct kvec iov[2]; |
---|
2400 | | - struct kvec rsp_iov; |
---|
2401 | | - int resp_buftype; |
---|
2402 | | - int n_iov; |
---|
| 3036 | + struct TCP_Server_Info *server; |
---|
| 3037 | + struct kvec iov[SMB2_IOCTL_IOV_SIZE]; |
---|
| 3038 | + struct kvec rsp_iov = {NULL, 0}; |
---|
| 3039 | + int resp_buftype = CIFS_NO_BUFFER; |
---|
2403 | 3040 | int rc = 0; |
---|
2404 | 3041 | int flags = 0; |
---|
2405 | | - unsigned int total_len; |
---|
2406 | 3042 | |
---|
2407 | 3043 | cifs_dbg(FYI, "SMB2 IOCTL\n"); |
---|
2408 | 3044 | |
---|
.. | .. |
---|
2413 | 3049 | if (plen) |
---|
2414 | 3050 | *plen = 0; |
---|
2415 | 3051 | |
---|
2416 | | - if (tcon) |
---|
2417 | | - ses = tcon->ses; |
---|
2418 | | - else |
---|
| 3052 | + if (!tcon) |
---|
2419 | 3053 | return -EIO; |
---|
2420 | 3054 | |
---|
2421 | | - if (!ses || !(ses->server)) |
---|
| 3055 | + ses = tcon->ses; |
---|
| 3056 | + if (!ses) |
---|
2422 | 3057 | return -EIO; |
---|
2423 | 3058 | |
---|
2424 | | - rc = smb2_ioctl_req_init(opcode, tcon, (void **) &req, &total_len); |
---|
2425 | | - if (rc) |
---|
2426 | | - return rc; |
---|
| 3059 | + server = cifs_pick_channel(ses); |
---|
| 3060 | + if (!server) |
---|
| 3061 | + return -EIO; |
---|
2427 | 3062 | |
---|
2428 | 3063 | if (smb3_encryption_required(tcon)) |
---|
2429 | 3064 | flags |= CIFS_TRANSFORM_REQ; |
---|
2430 | 3065 | |
---|
2431 | | - req->CtlCode = cpu_to_le32(opcode); |
---|
2432 | | - req->PersistentFileId = persistent_fid; |
---|
2433 | | - req->VolatileFileId = volatile_fid; |
---|
2434 | | - |
---|
2435 | | - if (indatalen) { |
---|
2436 | | - req->InputCount = cpu_to_le32(indatalen); |
---|
2437 | | - /* do not set InputOffset if no input data */ |
---|
2438 | | - req->InputOffset = |
---|
2439 | | - cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer)); |
---|
2440 | | - iov[1].iov_base = in_data; |
---|
2441 | | - iov[1].iov_len = indatalen; |
---|
2442 | | - n_iov = 2; |
---|
2443 | | - } else |
---|
2444 | | - n_iov = 1; |
---|
2445 | | - |
---|
2446 | | - req->OutputOffset = 0; |
---|
2447 | | - req->OutputCount = 0; /* MBZ */ |
---|
2448 | | - |
---|
2449 | | - /* |
---|
2450 | | - * Could increase MaxOutputResponse, but that would require more |
---|
2451 | | - * than one credit. Windows typically sets this smaller, but for some |
---|
2452 | | - * ioctls it may be useful to allow server to send more. No point |
---|
2453 | | - * limiting what the server can send as long as fits in one credit |
---|
2454 | | - * Unfortunately - we can not handle more than CIFS_MAX_MSG_SIZE |
---|
2455 | | - * (by default, note that it can be overridden to make max larger) |
---|
2456 | | - * in responses (except for read responses which can be bigger. |
---|
2457 | | - * We may want to bump this limit up |
---|
2458 | | - */ |
---|
2459 | | - req->MaxOutputResponse = cpu_to_le32(CIFSMaxBufSize); |
---|
2460 | | - |
---|
2461 | | - if (is_fsctl) |
---|
2462 | | - req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL); |
---|
2463 | | - else |
---|
2464 | | - req->Flags = 0; |
---|
2465 | | - |
---|
2466 | | - iov[0].iov_base = (char *)req; |
---|
2467 | | - |
---|
2468 | | - /* |
---|
2469 | | - * If no input data, the size of ioctl struct in |
---|
2470 | | - * protocol spec still includes a 1 byte data buffer, |
---|
2471 | | - * but if input data passed to ioctl, we do not |
---|
2472 | | - * want to double count this, so we do not send |
---|
2473 | | - * the dummy one byte of data in iovec[0] if sending |
---|
2474 | | - * input data (in iovec[1]). |
---|
2475 | | - */ |
---|
2476 | | - |
---|
2477 | | - if (indatalen) { |
---|
2478 | | - iov[0].iov_len = total_len - 1; |
---|
2479 | | - } else |
---|
2480 | | - iov[0].iov_len = total_len; |
---|
2481 | | - |
---|
2482 | | - /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */ |
---|
2483 | | - if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) |
---|
2484 | | - req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; |
---|
2485 | | - |
---|
2486 | 3066 | memset(&rqst, 0, sizeof(struct smb_rqst)); |
---|
| 3067 | + memset(&iov, 0, sizeof(iov)); |
---|
2487 | 3068 | rqst.rq_iov = iov; |
---|
2488 | | - rqst.rq_nvec = n_iov; |
---|
| 3069 | + rqst.rq_nvec = SMB2_IOCTL_IOV_SIZE; |
---|
2489 | 3070 | |
---|
2490 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, |
---|
| 3071 | + rc = SMB2_ioctl_init(tcon, server, |
---|
| 3072 | + &rqst, persistent_fid, volatile_fid, opcode, |
---|
| 3073 | + in_data, indatalen, max_out_data_len); |
---|
| 3074 | + if (rc) |
---|
| 3075 | + goto ioctl_exit; |
---|
| 3076 | + |
---|
| 3077 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 3078 | + &rqst, &resp_buftype, flags, |
---|
2491 | 3079 | &rsp_iov); |
---|
2492 | | - cifs_small_buf_release(req); |
---|
2493 | 3080 | rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base; |
---|
2494 | 3081 | |
---|
2495 | 3082 | if (rc != 0) |
---|
2496 | 3083 | trace_smb3_fsctl_err(xid, persistent_fid, tcon->tid, |
---|
2497 | 3084 | ses->Suid, 0, opcode, rc); |
---|
2498 | 3085 | |
---|
2499 | | - if ((rc != 0) && (rc != -EINVAL)) { |
---|
| 3086 | + if ((rc != 0) && (rc != -EINVAL) && (rc != -E2BIG)) { |
---|
2500 | 3087 | cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); |
---|
2501 | 3088 | goto ioctl_exit; |
---|
2502 | 3089 | } else if (rc == -EINVAL) { |
---|
2503 | 3090 | if ((opcode != FSCTL_SRV_COPYCHUNK_WRITE) && |
---|
2504 | 3091 | (opcode != FSCTL_SRV_COPYCHUNK)) { |
---|
| 3092 | + cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); |
---|
| 3093 | + goto ioctl_exit; |
---|
| 3094 | + } |
---|
| 3095 | + } else if (rc == -E2BIG) { |
---|
| 3096 | + if (opcode != FSCTL_QUERY_ALLOCATED_RANGES) { |
---|
2505 | 3097 | cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); |
---|
2506 | 3098 | goto ioctl_exit; |
---|
2507 | 3099 | } |
---|
.. | .. |
---|
2517 | 3109 | if (*plen == 0) |
---|
2518 | 3110 | goto ioctl_exit; /* server returned no data */ |
---|
2519 | 3111 | else if (*plen > rsp_iov.iov_len || *plen > 0xFF00) { |
---|
2520 | | - cifs_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen); |
---|
| 3112 | + cifs_tcon_dbg(VFS, "srv returned invalid ioctl length: %d\n", *plen); |
---|
2521 | 3113 | *plen = 0; |
---|
2522 | 3114 | rc = -EIO; |
---|
2523 | 3115 | goto ioctl_exit; |
---|
2524 | 3116 | } |
---|
2525 | 3117 | |
---|
2526 | 3118 | if (rsp_iov.iov_len - *plen < le32_to_cpu(rsp->OutputOffset)) { |
---|
2527 | | - cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen, |
---|
| 3119 | + cifs_tcon_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen, |
---|
2528 | 3120 | le32_to_cpu(rsp->OutputOffset)); |
---|
2529 | 3121 | *plen = 0; |
---|
2530 | 3122 | rc = -EIO; |
---|
2531 | 3123 | goto ioctl_exit; |
---|
2532 | 3124 | } |
---|
2533 | 3125 | |
---|
2534 | | - *out_data = kmalloc(*plen, GFP_KERNEL); |
---|
| 3126 | + *out_data = kmemdup((char *)rsp + le32_to_cpu(rsp->OutputOffset), |
---|
| 3127 | + *plen, GFP_KERNEL); |
---|
2535 | 3128 | if (*out_data == NULL) { |
---|
2536 | 3129 | rc = -ENOMEM; |
---|
2537 | 3130 | goto ioctl_exit; |
---|
2538 | 3131 | } |
---|
2539 | 3132 | |
---|
2540 | | - memcpy(*out_data, (char *)rsp + le32_to_cpu(rsp->OutputOffset), *plen); |
---|
2541 | 3133 | ioctl_exit: |
---|
| 3134 | + SMB2_ioctl_free(&rqst); |
---|
2542 | 3135 | free_rsp_buf(resp_buftype, rsp); |
---|
2543 | 3136 | return rc; |
---|
2544 | 3137 | } |
---|
.. | .. |
---|
2559 | 3152 | cpu_to_le16(COMPRESSION_FORMAT_DEFAULT); |
---|
2560 | 3153 | |
---|
2561 | 3154 | rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid, |
---|
2562 | | - FSCTL_SET_COMPRESSION, true /* is_fsctl */, |
---|
| 3155 | + FSCTL_SET_COMPRESSION, |
---|
2563 | 3156 | (char *)&fsctl_input /* data input */, |
---|
2564 | | - 2 /* in data len */, &ret_data /* out data */, NULL); |
---|
| 3157 | + 2 /* in data len */, CIFSMaxBufSize /* max out data */, |
---|
| 3158 | + &ret_data /* out data */, NULL); |
---|
2565 | 3159 | |
---|
2566 | 3160 | cifs_dbg(FYI, "set compression rc %d\n", rc); |
---|
2567 | 3161 | |
---|
.. | .. |
---|
2569 | 3163 | } |
---|
2570 | 3164 | |
---|
2571 | 3165 | int |
---|
2572 | | -SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, |
---|
2573 | | - u64 persistent_fid, u64 volatile_fid) |
---|
| 3166 | +SMB2_close_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, |
---|
| 3167 | + struct smb_rqst *rqst, |
---|
| 3168 | + u64 persistent_fid, u64 volatile_fid, bool query_attrs) |
---|
2574 | 3169 | { |
---|
2575 | 3170 | struct smb2_close_req *req; |
---|
2576 | 3171 | struct kvec *iov = rqst->rq_iov; |
---|
2577 | 3172 | unsigned int total_len; |
---|
2578 | 3173 | int rc; |
---|
2579 | 3174 | |
---|
2580 | | - rc = smb2_plain_req_init(SMB2_CLOSE, tcon, (void **) &req, &total_len); |
---|
| 3175 | + rc = smb2_plain_req_init(SMB2_CLOSE, tcon, server, |
---|
| 3176 | + (void **) &req, &total_len); |
---|
2581 | 3177 | if (rc) |
---|
2582 | 3178 | return rc; |
---|
2583 | 3179 | |
---|
2584 | 3180 | req->PersistentFileId = persistent_fid; |
---|
2585 | 3181 | req->VolatileFileId = volatile_fid; |
---|
| 3182 | + if (query_attrs) |
---|
| 3183 | + req->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB; |
---|
| 3184 | + else |
---|
| 3185 | + req->Flags = 0; |
---|
2586 | 3186 | iov[0].iov_base = (char *)req; |
---|
2587 | 3187 | iov[0].iov_len = total_len; |
---|
2588 | 3188 | |
---|
.. | .. |
---|
2597 | 3197 | } |
---|
2598 | 3198 | |
---|
2599 | 3199 | int |
---|
2600 | | -SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, |
---|
2601 | | - u64 persistent_fid, u64 volatile_fid, int flags) |
---|
| 3200 | +__SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, |
---|
| 3201 | + u64 persistent_fid, u64 volatile_fid, |
---|
| 3202 | + struct smb2_file_network_open_info *pbuf) |
---|
2602 | 3203 | { |
---|
2603 | 3204 | struct smb_rqst rqst; |
---|
2604 | 3205 | struct smb2_close_rsp *rsp = NULL; |
---|
2605 | 3206 | struct cifs_ses *ses = tcon->ses; |
---|
| 3207 | + struct TCP_Server_Info *server = cifs_pick_channel(ses); |
---|
2606 | 3208 | struct kvec iov[1]; |
---|
2607 | 3209 | struct kvec rsp_iov; |
---|
2608 | 3210 | int resp_buftype = CIFS_NO_BUFFER; |
---|
2609 | 3211 | int rc = 0; |
---|
| 3212 | + int flags = 0; |
---|
| 3213 | + bool query_attrs = false; |
---|
2610 | 3214 | |
---|
2611 | 3215 | cifs_dbg(FYI, "Close\n"); |
---|
2612 | 3216 | |
---|
2613 | | - if (!ses || !(ses->server)) |
---|
| 3217 | + if (!ses || !server) |
---|
2614 | 3218 | return -EIO; |
---|
2615 | 3219 | |
---|
2616 | 3220 | if (smb3_encryption_required(tcon)) |
---|
.. | .. |
---|
2621 | 3225 | rqst.rq_iov = iov; |
---|
2622 | 3226 | rqst.rq_nvec = 1; |
---|
2623 | 3227 | |
---|
2624 | | - rc = SMB2_close_init(tcon, &rqst, persistent_fid, volatile_fid); |
---|
| 3228 | + /* check if need to ask server to return timestamps in close response */ |
---|
| 3229 | + if (pbuf) |
---|
| 3230 | + query_attrs = true; |
---|
| 3231 | + |
---|
| 3232 | + trace_smb3_close_enter(xid, persistent_fid, tcon->tid, ses->Suid); |
---|
| 3233 | + rc = SMB2_close_init(tcon, server, |
---|
| 3234 | + &rqst, persistent_fid, volatile_fid, |
---|
| 3235 | + query_attrs); |
---|
2625 | 3236 | if (rc) |
---|
2626 | 3237 | goto close_exit; |
---|
2627 | 3238 | |
---|
2628 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
---|
| 3239 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 3240 | + &rqst, &resp_buftype, flags, &rsp_iov); |
---|
2629 | 3241 | rsp = (struct smb2_close_rsp *)rsp_iov.iov_base; |
---|
2630 | 3242 | |
---|
2631 | 3243 | if (rc != 0) { |
---|
.. | .. |
---|
2633 | 3245 | trace_smb3_close_err(xid, persistent_fid, tcon->tid, ses->Suid, |
---|
2634 | 3246 | rc); |
---|
2635 | 3247 | goto close_exit; |
---|
| 3248 | + } else { |
---|
| 3249 | + trace_smb3_close_done(xid, persistent_fid, tcon->tid, |
---|
| 3250 | + ses->Suid); |
---|
| 3251 | + /* |
---|
| 3252 | + * Note that have to subtract 4 since struct network_open_info |
---|
| 3253 | + * has a final 4 byte pad that close response does not have |
---|
| 3254 | + */ |
---|
| 3255 | + if (pbuf) |
---|
| 3256 | + memcpy(pbuf, (char *)&rsp->CreationTime, sizeof(*pbuf) - 4); |
---|
2636 | 3257 | } |
---|
2637 | 3258 | |
---|
2638 | | - /* BB FIXME - decode close response, update inode for caching */ |
---|
2639 | | - |
---|
| 3259 | + atomic_dec(&tcon->num_remote_opens); |
---|
2640 | 3260 | close_exit: |
---|
2641 | 3261 | SMB2_close_free(&rqst); |
---|
2642 | 3262 | free_rsp_buf(resp_buftype, rsp); |
---|
2643 | | - return rc; |
---|
2644 | | -} |
---|
2645 | | - |
---|
2646 | | -int |
---|
2647 | | -SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, |
---|
2648 | | - u64 persistent_fid, u64 volatile_fid) |
---|
2649 | | -{ |
---|
2650 | | - int rc; |
---|
2651 | | - int tmp_rc; |
---|
2652 | | - |
---|
2653 | | - rc = SMB2_close_flags(xid, tcon, persistent_fid, volatile_fid, 0); |
---|
2654 | 3263 | |
---|
2655 | 3264 | /* retry close in a worker thread if this one is interrupted */ |
---|
2656 | | - if (rc == -EINTR) { |
---|
| 3265 | + if (is_interrupt_error(rc)) { |
---|
| 3266 | + int tmp_rc; |
---|
| 3267 | + |
---|
2657 | 3268 | tmp_rc = smb2_handle_cancelled_close(tcon, persistent_fid, |
---|
2658 | 3269 | volatile_fid); |
---|
2659 | 3270 | if (tmp_rc) |
---|
2660 | 3271 | cifs_dbg(VFS, "handle cancelled close fid 0x%llx returned error %d\n", |
---|
2661 | 3272 | persistent_fid, tmp_rc); |
---|
2662 | 3273 | } |
---|
2663 | | - |
---|
2664 | 3274 | return rc; |
---|
| 3275 | +} |
---|
| 3276 | + |
---|
| 3277 | +int |
---|
| 3278 | +SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, |
---|
| 3279 | + u64 persistent_fid, u64 volatile_fid) |
---|
| 3280 | +{ |
---|
| 3281 | + return __SMB2_close(xid, tcon, persistent_fid, volatile_fid, NULL); |
---|
2665 | 3282 | } |
---|
2666 | 3283 | |
---|
2667 | 3284 | int |
---|
.. | .. |
---|
2688 | 3305 | } |
---|
2689 | 3306 | |
---|
2690 | 3307 | if ((begin_of_buf > end_of_smb) || (end_of_buf > end_of_smb)) { |
---|
2691 | | - cifs_dbg(VFS, "illegal server response, bad offset to data\n"); |
---|
| 3308 | + cifs_dbg(VFS, "Invalid server response, bad offset to data\n"); |
---|
2692 | 3309 | return -EINVAL; |
---|
2693 | 3310 | } |
---|
2694 | 3311 | |
---|
.. | .. |
---|
2699 | 3316 | * If SMB buffer fields are valid, copy into temporary buffer to hold result. |
---|
2700 | 3317 | * Caller must free buffer. |
---|
2701 | 3318 | */ |
---|
2702 | | -static int |
---|
2703 | | -validate_and_copy_iov(unsigned int offset, unsigned int buffer_length, |
---|
2704 | | - struct kvec *iov, unsigned int minbufsize, |
---|
2705 | | - char *data) |
---|
| 3319 | +int |
---|
| 3320 | +smb2_validate_and_copy_iov(unsigned int offset, unsigned int buffer_length, |
---|
| 3321 | + struct kvec *iov, unsigned int minbufsize, |
---|
| 3322 | + char *data) |
---|
2706 | 3323 | { |
---|
2707 | 3324 | char *begin_of_buf = offset + (char *)iov->iov_base; |
---|
2708 | 3325 | int rc; |
---|
.. | .. |
---|
2720 | 3337 | } |
---|
2721 | 3338 | |
---|
2722 | 3339 | int |
---|
2723 | | -SMB2_query_info_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, |
---|
| 3340 | +SMB2_query_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, |
---|
| 3341 | + struct smb_rqst *rqst, |
---|
2724 | 3342 | u64 persistent_fid, u64 volatile_fid, |
---|
2725 | 3343 | u8 info_class, u8 info_type, u32 additional_info, |
---|
2726 | | - size_t output_len) |
---|
| 3344 | + size_t output_len, size_t input_len, void *input) |
---|
2727 | 3345 | { |
---|
2728 | 3346 | struct smb2_query_info_req *req; |
---|
2729 | 3347 | struct kvec *iov = rqst->rq_iov; |
---|
2730 | 3348 | unsigned int total_len; |
---|
2731 | 3349 | int rc; |
---|
2732 | 3350 | |
---|
2733 | | - rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, (void **) &req, |
---|
2734 | | - &total_len); |
---|
| 3351 | + rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server, |
---|
| 3352 | + (void **) &req, &total_len); |
---|
2735 | 3353 | if (rc) |
---|
2736 | 3354 | return rc; |
---|
2737 | 3355 | |
---|
.. | .. |
---|
2741 | 3359 | req->VolatileFileId = volatile_fid; |
---|
2742 | 3360 | req->AdditionalInformation = cpu_to_le32(additional_info); |
---|
2743 | 3361 | |
---|
2744 | | - /* |
---|
2745 | | - * We do not use the input buffer (do not send extra byte) |
---|
2746 | | - */ |
---|
2747 | | - req->InputBufferOffset = 0; |
---|
2748 | | - |
---|
2749 | 3362 | req->OutputBufferLength = cpu_to_le32(output_len); |
---|
| 3363 | + if (input_len) { |
---|
| 3364 | + req->InputBufferLength = cpu_to_le32(input_len); |
---|
| 3365 | + /* total_len for smb query request never close to le16 max */ |
---|
| 3366 | + req->InputBufferOffset = cpu_to_le16(total_len - 1); |
---|
| 3367 | + memcpy(req->Buffer, input, input_len); |
---|
| 3368 | + } |
---|
2750 | 3369 | |
---|
2751 | 3370 | iov[0].iov_base = (char *)req; |
---|
2752 | 3371 | /* 1 for Buffer */ |
---|
2753 | | - iov[0].iov_len = total_len - 1; |
---|
| 3372 | + iov[0].iov_len = total_len - 1 + input_len; |
---|
2754 | 3373 | return 0; |
---|
2755 | 3374 | } |
---|
2756 | 3375 | |
---|
.. | .. |
---|
2774 | 3393 | int rc = 0; |
---|
2775 | 3394 | int resp_buftype = CIFS_NO_BUFFER; |
---|
2776 | 3395 | struct cifs_ses *ses = tcon->ses; |
---|
| 3396 | + struct TCP_Server_Info *server; |
---|
2777 | 3397 | int flags = 0; |
---|
| 3398 | + bool allocated = false; |
---|
2778 | 3399 | |
---|
2779 | 3400 | cifs_dbg(FYI, "Query Info\n"); |
---|
2780 | 3401 | |
---|
2781 | | - if (!ses || !(ses->server)) |
---|
| 3402 | + if (!ses) |
---|
| 3403 | + return -EIO; |
---|
| 3404 | + server = cifs_pick_channel(ses); |
---|
| 3405 | + if (!server) |
---|
2782 | 3406 | return -EIO; |
---|
2783 | 3407 | |
---|
2784 | 3408 | if (smb3_encryption_required(tcon)) |
---|
.. | .. |
---|
2789 | 3413 | rqst.rq_iov = iov; |
---|
2790 | 3414 | rqst.rq_nvec = 1; |
---|
2791 | 3415 | |
---|
2792 | | - rc = SMB2_query_info_init(tcon, &rqst, persistent_fid, volatile_fid, |
---|
| 3416 | + rc = SMB2_query_info_init(tcon, server, |
---|
| 3417 | + &rqst, persistent_fid, volatile_fid, |
---|
2793 | 3418 | info_class, info_type, additional_info, |
---|
2794 | | - output_len); |
---|
| 3419 | + output_len, 0, NULL); |
---|
2795 | 3420 | if (rc) |
---|
2796 | 3421 | goto qinf_exit; |
---|
2797 | 3422 | |
---|
2798 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
---|
| 3423 | + trace_smb3_query_info_enter(xid, persistent_fid, tcon->tid, |
---|
| 3424 | + ses->Suid, info_class, (__u32)info_type); |
---|
| 3425 | + |
---|
| 3426 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 3427 | + &rqst, &resp_buftype, flags, &rsp_iov); |
---|
2799 | 3428 | rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base; |
---|
2800 | 3429 | |
---|
2801 | 3430 | if (rc) { |
---|
.. | .. |
---|
2805 | 3434 | goto qinf_exit; |
---|
2806 | 3435 | } |
---|
2807 | 3436 | |
---|
| 3437 | + trace_smb3_query_info_done(xid, persistent_fid, tcon->tid, |
---|
| 3438 | + ses->Suid, info_class, (__u32)info_type); |
---|
| 3439 | + |
---|
2808 | 3440 | if (dlen) { |
---|
2809 | 3441 | *dlen = le32_to_cpu(rsp->OutputBufferLength); |
---|
2810 | 3442 | if (!*data) { |
---|
2811 | 3443 | *data = kmalloc(*dlen, GFP_KERNEL); |
---|
2812 | 3444 | if (!*data) { |
---|
2813 | | - cifs_dbg(VFS, |
---|
| 3445 | + cifs_tcon_dbg(VFS, |
---|
2814 | 3446 | "Error %d allocating memory for acl\n", |
---|
2815 | 3447 | rc); |
---|
2816 | 3448 | *dlen = 0; |
---|
| 3449 | + rc = -ENOMEM; |
---|
2817 | 3450 | goto qinf_exit; |
---|
2818 | 3451 | } |
---|
| 3452 | + allocated = true; |
---|
2819 | 3453 | } |
---|
2820 | 3454 | } |
---|
2821 | 3455 | |
---|
2822 | | - rc = validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset), |
---|
2823 | | - le32_to_cpu(rsp->OutputBufferLength), |
---|
2824 | | - &rsp_iov, min_len, *data); |
---|
| 3456 | + rc = smb2_validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset), |
---|
| 3457 | + le32_to_cpu(rsp->OutputBufferLength), |
---|
| 3458 | + &rsp_iov, min_len, *data); |
---|
| 3459 | + if (rc && allocated) { |
---|
| 3460 | + kfree(*data); |
---|
| 3461 | + *data = NULL; |
---|
| 3462 | + *dlen = 0; |
---|
| 3463 | + } |
---|
2825 | 3464 | |
---|
2826 | 3465 | qinf_exit: |
---|
2827 | 3466 | SMB2_query_info_free(&rqst); |
---|
2828 | 3467 | free_rsp_buf(resp_buftype, rsp); |
---|
2829 | 3468 | return rc; |
---|
2830 | | -} |
---|
2831 | | - |
---|
2832 | | -int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, |
---|
2833 | | - u64 persistent_fid, u64 volatile_fid, |
---|
2834 | | - int ea_buf_size, struct smb2_file_full_ea_info *data) |
---|
2835 | | -{ |
---|
2836 | | - return query_info(xid, tcon, persistent_fid, volatile_fid, |
---|
2837 | | - FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0, |
---|
2838 | | - ea_buf_size, |
---|
2839 | | - sizeof(struct smb2_file_full_ea_info), |
---|
2840 | | - (void **)&data, |
---|
2841 | | - NULL); |
---|
2842 | 3469 | } |
---|
2843 | 3470 | |
---|
2844 | 3471 | int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, |
---|
.. | .. |
---|
2849 | 3476 | sizeof(struct smb2_file_all_info) + PATH_MAX * 2, |
---|
2850 | 3477 | sizeof(struct smb2_file_all_info), (void **)&data, |
---|
2851 | 3478 | NULL); |
---|
| 3479 | +} |
---|
| 3480 | + |
---|
| 3481 | +int |
---|
| 3482 | +SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon, |
---|
| 3483 | + u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen) |
---|
| 3484 | +{ |
---|
| 3485 | + size_t output_len = sizeof(struct smb311_posix_qinfo *) + |
---|
| 3486 | + (sizeof(struct cifs_sid) * 2) + (PATH_MAX * 2); |
---|
| 3487 | + *plen = 0; |
---|
| 3488 | + |
---|
| 3489 | + return query_info(xid, tcon, persistent_fid, volatile_fid, |
---|
| 3490 | + SMB_FIND_FILE_POSIX_INFO, SMB2_O_INFO_FILE, 0, |
---|
| 3491 | + output_len, sizeof(struct smb311_posix_qinfo), (void **)&data, plen); |
---|
2852 | 3492 | } |
---|
2853 | 3493 | |
---|
2854 | 3494 | int |
---|
.. | .. |
---|
2876 | 3516 | } |
---|
2877 | 3517 | |
---|
2878 | 3518 | /* |
---|
| 3519 | + * CHANGE_NOTIFY Request is sent to get notifications on changes to a directory |
---|
| 3520 | + * See MS-SMB2 2.2.35 and 2.2.36 |
---|
| 3521 | + */ |
---|
| 3522 | + |
---|
| 3523 | +static int |
---|
| 3524 | +SMB2_notify_init(const unsigned int xid, struct smb_rqst *rqst, |
---|
| 3525 | + struct cifs_tcon *tcon, struct TCP_Server_Info *server, |
---|
| 3526 | + u64 persistent_fid, u64 volatile_fid, |
---|
| 3527 | + u32 completion_filter, bool watch_tree) |
---|
| 3528 | +{ |
---|
| 3529 | + struct smb2_change_notify_req *req; |
---|
| 3530 | + struct kvec *iov = rqst->rq_iov; |
---|
| 3531 | + unsigned int total_len; |
---|
| 3532 | + int rc; |
---|
| 3533 | + |
---|
| 3534 | + rc = smb2_plain_req_init(SMB2_CHANGE_NOTIFY, tcon, server, |
---|
| 3535 | + (void **) &req, &total_len); |
---|
| 3536 | + if (rc) |
---|
| 3537 | + return rc; |
---|
| 3538 | + |
---|
| 3539 | + req->PersistentFileId = persistent_fid; |
---|
| 3540 | + req->VolatileFileId = volatile_fid; |
---|
| 3541 | + /* See note 354 of MS-SMB2, 64K max */ |
---|
| 3542 | + req->OutputBufferLength = |
---|
| 3543 | + cpu_to_le32(SMB2_MAX_BUFFER_SIZE - MAX_SMB2_HDR_SIZE); |
---|
| 3544 | + req->CompletionFilter = cpu_to_le32(completion_filter); |
---|
| 3545 | + if (watch_tree) |
---|
| 3546 | + req->Flags = cpu_to_le16(SMB2_WATCH_TREE); |
---|
| 3547 | + else |
---|
| 3548 | + req->Flags = 0; |
---|
| 3549 | + |
---|
| 3550 | + iov[0].iov_base = (char *)req; |
---|
| 3551 | + iov[0].iov_len = total_len; |
---|
| 3552 | + |
---|
| 3553 | + return 0; |
---|
| 3554 | +} |
---|
| 3555 | + |
---|
| 3556 | +int |
---|
| 3557 | +SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, |
---|
| 3558 | + u64 persistent_fid, u64 volatile_fid, bool watch_tree, |
---|
| 3559 | + u32 completion_filter) |
---|
| 3560 | +{ |
---|
| 3561 | + struct cifs_ses *ses = tcon->ses; |
---|
| 3562 | + struct TCP_Server_Info *server = cifs_pick_channel(ses); |
---|
| 3563 | + struct smb_rqst rqst; |
---|
| 3564 | + struct kvec iov[1]; |
---|
| 3565 | + struct kvec rsp_iov = {NULL, 0}; |
---|
| 3566 | + int resp_buftype = CIFS_NO_BUFFER; |
---|
| 3567 | + int flags = 0; |
---|
| 3568 | + int rc = 0; |
---|
| 3569 | + |
---|
| 3570 | + cifs_dbg(FYI, "change notify\n"); |
---|
| 3571 | + if (!ses || !server) |
---|
| 3572 | + return -EIO; |
---|
| 3573 | + |
---|
| 3574 | + if (smb3_encryption_required(tcon)) |
---|
| 3575 | + flags |= CIFS_TRANSFORM_REQ; |
---|
| 3576 | + |
---|
| 3577 | + memset(&rqst, 0, sizeof(struct smb_rqst)); |
---|
| 3578 | + memset(&iov, 0, sizeof(iov)); |
---|
| 3579 | + rqst.rq_iov = iov; |
---|
| 3580 | + rqst.rq_nvec = 1; |
---|
| 3581 | + |
---|
| 3582 | + rc = SMB2_notify_init(xid, &rqst, tcon, server, |
---|
| 3583 | + persistent_fid, volatile_fid, |
---|
| 3584 | + completion_filter, watch_tree); |
---|
| 3585 | + if (rc) |
---|
| 3586 | + goto cnotify_exit; |
---|
| 3587 | + |
---|
| 3588 | + trace_smb3_notify_enter(xid, persistent_fid, tcon->tid, ses->Suid, |
---|
| 3589 | + (u8)watch_tree, completion_filter); |
---|
| 3590 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 3591 | + &rqst, &resp_buftype, flags, &rsp_iov); |
---|
| 3592 | + |
---|
| 3593 | + if (rc != 0) { |
---|
| 3594 | + cifs_stats_fail_inc(tcon, SMB2_CHANGE_NOTIFY_HE); |
---|
| 3595 | + trace_smb3_notify_err(xid, persistent_fid, tcon->tid, ses->Suid, |
---|
| 3596 | + (u8)watch_tree, completion_filter, rc); |
---|
| 3597 | + } else |
---|
| 3598 | + trace_smb3_notify_done(xid, persistent_fid, tcon->tid, |
---|
| 3599 | + ses->Suid, (u8)watch_tree, completion_filter); |
---|
| 3600 | + |
---|
| 3601 | + cnotify_exit: |
---|
| 3602 | + if (rqst.rq_iov) |
---|
| 3603 | + cifs_small_buf_release(rqst.rq_iov[0].iov_base); /* request */ |
---|
| 3604 | + free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
---|
| 3605 | + return rc; |
---|
| 3606 | +} |
---|
| 3607 | + |
---|
| 3608 | + |
---|
| 3609 | + |
---|
| 3610 | +/* |
---|
2879 | 3611 | * This is a no-op for now. We're not really interested in the reply, but |
---|
2880 | 3612 | * rather in the fact that the server sent one and that server->lstrp |
---|
2881 | 3613 | * gets updated. |
---|
.. | .. |
---|
2887 | 3619 | { |
---|
2888 | 3620 | struct TCP_Server_Info *server = mid->callback_data; |
---|
2889 | 3621 | struct smb2_echo_rsp *rsp = (struct smb2_echo_rsp *)mid->resp_buf; |
---|
2890 | | - unsigned int credits_received = 0; |
---|
| 3622 | + struct cifs_credits credits = { .value = 0, .instance = 0 }; |
---|
2891 | 3623 | |
---|
2892 | 3624 | if (mid->mid_state == MID_RESPONSE_RECEIVED |
---|
2893 | | - || mid->mid_state == MID_RESPONSE_MALFORMED) |
---|
2894 | | - credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest); |
---|
| 3625 | + || mid->mid_state == MID_RESPONSE_MALFORMED) { |
---|
| 3626 | + credits.value = le16_to_cpu(rsp->sync_hdr.CreditRequest); |
---|
| 3627 | + credits.instance = server->reconnect_instance; |
---|
| 3628 | + } |
---|
2895 | 3629 | |
---|
2896 | 3630 | DeleteMidQEntry(mid); |
---|
2897 | | - add_credits(server, credits_received, CIFS_ECHO_OP); |
---|
| 3631 | + add_credits(server, &credits, CIFS_ECHO_OP); |
---|
2898 | 3632 | } |
---|
2899 | 3633 | |
---|
2900 | 3634 | void smb2_reconnect_server(struct work_struct *work) |
---|
.. | .. |
---|
2924 | 3658 | tcon_exist = true; |
---|
2925 | 3659 | } |
---|
2926 | 3660 | } |
---|
| 3661 | + /* |
---|
| 3662 | + * IPC has the same lifetime as its session and uses its |
---|
| 3663 | + * refcount. |
---|
| 3664 | + */ |
---|
2927 | 3665 | if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) { |
---|
2928 | 3666 | list_add_tail(&ses->tcon_ipc->rlist, &tmp_list); |
---|
2929 | 3667 | tcon_exist = true; |
---|
| 3668 | + ses->ses_count++; |
---|
2930 | 3669 | } |
---|
2931 | 3670 | } |
---|
2932 | 3671 | /* |
---|
.. | .. |
---|
2939 | 3678 | spin_unlock(&cifs_tcp_ses_lock); |
---|
2940 | 3679 | |
---|
2941 | 3680 | list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) { |
---|
2942 | | - rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon); |
---|
| 3681 | + rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server); |
---|
2943 | 3682 | if (!rc) |
---|
2944 | 3683 | cifs_reopen_persistent_handles(tcon); |
---|
2945 | 3684 | else |
---|
2946 | 3685 | resched = true; |
---|
2947 | 3686 | list_del_init(&tcon->rlist); |
---|
2948 | | - cifs_put_tcon(tcon); |
---|
| 3687 | + if (tcon->ipc) |
---|
| 3688 | + cifs_put_smb_ses(tcon->ses); |
---|
| 3689 | + else |
---|
| 3690 | + cifs_put_tcon(tcon); |
---|
2949 | 3691 | } |
---|
2950 | 3692 | |
---|
2951 | 3693 | cifs_dbg(FYI, "Reconnecting tcons finished\n"); |
---|
.. | .. |
---|
2972 | 3714 | |
---|
2973 | 3715 | if (server->tcpStatus == CifsNeedNegotiate) { |
---|
2974 | 3716 | /* No need to send echo on newly established connections */ |
---|
2975 | | - queue_delayed_work(cifsiod_wq, &server->reconnect, 0); |
---|
| 3717 | + mod_delayed_work(cifsiod_wq, &server->reconnect, 0); |
---|
2976 | 3718 | return rc; |
---|
2977 | 3719 | } |
---|
2978 | 3720 | |
---|
2979 | | - rc = smb2_plain_req_init(SMB2_ECHO, NULL, (void **)&req, &total_len); |
---|
| 3721 | + rc = smb2_plain_req_init(SMB2_ECHO, NULL, server, |
---|
| 3722 | + (void **)&req, &total_len); |
---|
2980 | 3723 | if (rc) |
---|
2981 | 3724 | return rc; |
---|
2982 | 3725 | |
---|
.. | .. |
---|
2986 | 3729 | iov[0].iov_base = (char *)req; |
---|
2987 | 3730 | |
---|
2988 | 3731 | rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, NULL, |
---|
2989 | | - server, CIFS_ECHO_OP); |
---|
| 3732 | + server, CIFS_ECHO_OP, NULL); |
---|
2990 | 3733 | if (rc) |
---|
2991 | 3734 | cifs_dbg(FYI, "Echo request failed: %d\n", rc); |
---|
2992 | 3735 | |
---|
.. | .. |
---|
2994 | 3737 | return rc; |
---|
2995 | 3738 | } |
---|
2996 | 3739 | |
---|
2997 | | -int |
---|
2998 | | -SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, |
---|
2999 | | - u64 volatile_fid) |
---|
| 3740 | +void |
---|
| 3741 | +SMB2_flush_free(struct smb_rqst *rqst) |
---|
3000 | 3742 | { |
---|
3001 | | - struct smb_rqst rqst; |
---|
| 3743 | + if (rqst && rqst->rq_iov) |
---|
| 3744 | + cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ |
---|
| 3745 | +} |
---|
| 3746 | + |
---|
| 3747 | +int |
---|
| 3748 | +SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst, |
---|
| 3749 | + struct cifs_tcon *tcon, struct TCP_Server_Info *server, |
---|
| 3750 | + u64 persistent_fid, u64 volatile_fid) |
---|
| 3751 | +{ |
---|
3002 | 3752 | struct smb2_flush_req *req; |
---|
3003 | | - struct cifs_ses *ses = tcon->ses; |
---|
3004 | | - struct kvec iov[1]; |
---|
3005 | | - struct kvec rsp_iov; |
---|
3006 | | - int resp_buftype; |
---|
3007 | | - int rc = 0; |
---|
3008 | | - int flags = 0; |
---|
| 3753 | + struct kvec *iov = rqst->rq_iov; |
---|
3009 | 3754 | unsigned int total_len; |
---|
| 3755 | + int rc; |
---|
3010 | 3756 | |
---|
3011 | | - cifs_dbg(FYI, "Flush\n"); |
---|
3012 | | - |
---|
3013 | | - if (!ses || !(ses->server)) |
---|
3014 | | - return -EIO; |
---|
3015 | | - |
---|
3016 | | - rc = smb2_plain_req_init(SMB2_FLUSH, tcon, (void **) &req, &total_len); |
---|
| 3757 | + rc = smb2_plain_req_init(SMB2_FLUSH, tcon, server, |
---|
| 3758 | + (void **) &req, &total_len); |
---|
3017 | 3759 | if (rc) |
---|
3018 | 3760 | return rc; |
---|
3019 | | - |
---|
3020 | | - if (smb3_encryption_required(tcon)) |
---|
3021 | | - flags |= CIFS_TRANSFORM_REQ; |
---|
3022 | 3761 | |
---|
3023 | 3762 | req->PersistentFileId = persistent_fid; |
---|
3024 | 3763 | req->VolatileFileId = volatile_fid; |
---|
.. | .. |
---|
3026 | 3765 | iov[0].iov_base = (char *)req; |
---|
3027 | 3766 | iov[0].iov_len = total_len; |
---|
3028 | 3767 | |
---|
| 3768 | + return 0; |
---|
| 3769 | +} |
---|
| 3770 | + |
---|
| 3771 | +int |
---|
| 3772 | +SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, |
---|
| 3773 | + u64 volatile_fid) |
---|
| 3774 | +{ |
---|
| 3775 | + struct cifs_ses *ses = tcon->ses; |
---|
| 3776 | + struct smb_rqst rqst; |
---|
| 3777 | + struct kvec iov[1]; |
---|
| 3778 | + struct kvec rsp_iov = {NULL, 0}; |
---|
| 3779 | + struct TCP_Server_Info *server = cifs_pick_channel(ses); |
---|
| 3780 | + int resp_buftype = CIFS_NO_BUFFER; |
---|
| 3781 | + int flags = 0; |
---|
| 3782 | + int rc = 0; |
---|
| 3783 | + |
---|
| 3784 | + cifs_dbg(FYI, "flush\n"); |
---|
| 3785 | + if (!ses || !(ses->server)) |
---|
| 3786 | + return -EIO; |
---|
| 3787 | + |
---|
| 3788 | + if (smb3_encryption_required(tcon)) |
---|
| 3789 | + flags |= CIFS_TRANSFORM_REQ; |
---|
| 3790 | + |
---|
3029 | 3791 | memset(&rqst, 0, sizeof(struct smb_rqst)); |
---|
| 3792 | + memset(&iov, 0, sizeof(iov)); |
---|
3030 | 3793 | rqst.rq_iov = iov; |
---|
3031 | 3794 | rqst.rq_nvec = 1; |
---|
3032 | 3795 | |
---|
3033 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
---|
3034 | | - cifs_small_buf_release(req); |
---|
| 3796 | + rc = SMB2_flush_init(xid, &rqst, tcon, server, |
---|
| 3797 | + persistent_fid, volatile_fid); |
---|
| 3798 | + if (rc) |
---|
| 3799 | + goto flush_exit; |
---|
| 3800 | + |
---|
| 3801 | + trace_smb3_flush_enter(xid, persistent_fid, tcon->tid, ses->Suid); |
---|
| 3802 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 3803 | + &rqst, &resp_buftype, flags, &rsp_iov); |
---|
3035 | 3804 | |
---|
3036 | 3805 | if (rc != 0) { |
---|
3037 | 3806 | cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE); |
---|
3038 | 3807 | trace_smb3_flush_err(xid, persistent_fid, tcon->tid, ses->Suid, |
---|
3039 | 3808 | rc); |
---|
3040 | | - } |
---|
| 3809 | + } else |
---|
| 3810 | + trace_smb3_flush_done(xid, persistent_fid, tcon->tid, |
---|
| 3811 | + ses->Suid); |
---|
3041 | 3812 | |
---|
| 3813 | + flush_exit: |
---|
| 3814 | + SMB2_flush_free(&rqst); |
---|
3042 | 3815 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
---|
3043 | 3816 | return rc; |
---|
3044 | 3817 | } |
---|
.. | .. |
---|
3055 | 3828 | int rc = -EACCES; |
---|
3056 | 3829 | struct smb2_read_plain_req *req = NULL; |
---|
3057 | 3830 | struct smb2_sync_hdr *shdr; |
---|
3058 | | - struct TCP_Server_Info *server; |
---|
| 3831 | + struct TCP_Server_Info *server = io_parms->server; |
---|
3059 | 3832 | |
---|
3060 | | - rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, (void **) &req, |
---|
3061 | | - total_len); |
---|
| 3833 | + rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, server, |
---|
| 3834 | + (void **) &req, total_len); |
---|
3062 | 3835 | if (rc) |
---|
3063 | 3836 | return rc; |
---|
3064 | 3837 | |
---|
3065 | | - server = io_parms->tcon->ses->server; |
---|
3066 | 3838 | if (server == NULL) |
---|
3067 | 3839 | return -ECONNABORTED; |
---|
3068 | 3840 | |
---|
.. | .. |
---|
3077 | 3849 | req->MinimumCount = 0; |
---|
3078 | 3850 | req->Length = cpu_to_le32(io_parms->length); |
---|
3079 | 3851 | req->Offset = cpu_to_le64(io_parms->offset); |
---|
| 3852 | + |
---|
| 3853 | + trace_smb3_read_enter(0 /* xid */, |
---|
| 3854 | + io_parms->persistent_fid, |
---|
| 3855 | + io_parms->tcon->tid, io_parms->tcon->ses->Suid, |
---|
| 3856 | + io_parms->offset, io_parms->length); |
---|
3080 | 3857 | #ifdef CONFIG_CIFS_SMB_DIRECT |
---|
3081 | 3858 | /* |
---|
3082 | 3859 | * If we want to do a RDMA write, fill in and append |
---|
.. | .. |
---|
3086 | 3863 | rdata->bytes >= server->smbd_conn->rdma_readwrite_threshold) { |
---|
3087 | 3864 | |
---|
3088 | 3865 | struct smbd_buffer_descriptor_v1 *v1; |
---|
3089 | | - bool need_invalidate = |
---|
3090 | | - io_parms->tcon->ses->server->dialect == SMB30_PROT_ID; |
---|
| 3866 | + bool need_invalidate = server->dialect == SMB30_PROT_ID; |
---|
3091 | 3867 | |
---|
3092 | 3868 | rdata->mr = smbd_register_mr( |
---|
3093 | 3869 | server->smbd_conn, rdata->pages, |
---|
3094 | 3870 | rdata->nr_pages, rdata->page_offset, |
---|
3095 | 3871 | rdata->tailsz, true, need_invalidate); |
---|
3096 | 3872 | if (!rdata->mr) |
---|
3097 | | - return -ENOBUFS; |
---|
| 3873 | + return -EAGAIN; |
---|
3098 | 3874 | |
---|
3099 | 3875 | req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE; |
---|
3100 | 3876 | if (need_invalidate) |
---|
.. | .. |
---|
3144 | 3920 | { |
---|
3145 | 3921 | struct cifs_readdata *rdata = mid->callback_data; |
---|
3146 | 3922 | struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); |
---|
3147 | | - struct TCP_Server_Info *server = tcon->ses->server; |
---|
| 3923 | + struct TCP_Server_Info *server = rdata->server; |
---|
3148 | 3924 | struct smb2_sync_hdr *shdr = |
---|
3149 | 3925 | (struct smb2_sync_hdr *)rdata->iov[0].iov_base; |
---|
3150 | | - unsigned int credits_received = 0; |
---|
| 3926 | + struct cifs_credits credits = { .value = 0, .instance = 0 }; |
---|
3151 | 3927 | struct smb_rqst rqst = { .rq_iov = &rdata->iov[1], |
---|
3152 | | - .rq_nvec = 1, |
---|
3153 | | - .rq_pages = rdata->pages, |
---|
3154 | | - .rq_offset = rdata->page_offset, |
---|
3155 | | - .rq_npages = rdata->nr_pages, |
---|
3156 | | - .rq_pagesz = rdata->pagesz, |
---|
3157 | | - .rq_tailsz = rdata->tailsz }; |
---|
| 3928 | + .rq_nvec = 1, }; |
---|
| 3929 | + |
---|
| 3930 | + if (rdata->got_bytes) { |
---|
| 3931 | + rqst.rq_pages = rdata->pages; |
---|
| 3932 | + rqst.rq_offset = rdata->page_offset; |
---|
| 3933 | + rqst.rq_npages = rdata->nr_pages; |
---|
| 3934 | + rqst.rq_pagesz = rdata->pagesz; |
---|
| 3935 | + rqst.rq_tailsz = rdata->tailsz; |
---|
| 3936 | + } |
---|
| 3937 | + |
---|
| 3938 | + WARN_ONCE(rdata->server != mid->server, |
---|
| 3939 | + "rdata server %p != mid server %p", |
---|
| 3940 | + rdata->server, mid->server); |
---|
3158 | 3941 | |
---|
3159 | 3942 | cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n", |
---|
3160 | 3943 | __func__, mid->mid, mid->mid_state, rdata->result, |
---|
.. | .. |
---|
3162 | 3945 | |
---|
3163 | 3946 | switch (mid->mid_state) { |
---|
3164 | 3947 | case MID_RESPONSE_RECEIVED: |
---|
3165 | | - credits_received = le16_to_cpu(shdr->CreditRequest); |
---|
| 3948 | + credits.value = le16_to_cpu(shdr->CreditRequest); |
---|
| 3949 | + credits.instance = server->reconnect_instance; |
---|
3166 | 3950 | /* result already set, check signature */ |
---|
3167 | 3951 | if (server->sign && !mid->decrypted) { |
---|
3168 | 3952 | int rc; |
---|
3169 | 3953 | |
---|
3170 | 3954 | rc = smb2_verify_signature(&rqst, server); |
---|
3171 | 3955 | if (rc) |
---|
3172 | | - cifs_dbg(VFS, "SMB signature verification returned error = %d\n", |
---|
| 3956 | + cifs_tcon_dbg(VFS, "SMB signature verification returned error = %d\n", |
---|
3173 | 3957 | rc); |
---|
3174 | 3958 | } |
---|
3175 | 3959 | /* FIXME: should this be counted toward the initiating task? */ |
---|
.. | .. |
---|
3187 | 3971 | cifs_stats_bytes_read(tcon, rdata->got_bytes); |
---|
3188 | 3972 | break; |
---|
3189 | 3973 | case MID_RESPONSE_MALFORMED: |
---|
3190 | | - credits_received = le16_to_cpu(shdr->CreditRequest); |
---|
3191 | | - /* fall through */ |
---|
| 3974 | + credits.value = le16_to_cpu(shdr->CreditRequest); |
---|
| 3975 | + credits.instance = server->reconnect_instance; |
---|
| 3976 | + fallthrough; |
---|
3192 | 3977 | default: |
---|
3193 | | - if (rdata->result != -ENODATA) |
---|
3194 | | - rdata->result = -EIO; |
---|
| 3978 | + rdata->result = -EIO; |
---|
3195 | 3979 | } |
---|
3196 | 3980 | #ifdef CONFIG_CIFS_SMB_DIRECT |
---|
3197 | 3981 | /* |
---|
.. | .. |
---|
3218 | 4002 | |
---|
3219 | 4003 | queue_work(cifsiod_wq, &rdata->work); |
---|
3220 | 4004 | DeleteMidQEntry(mid); |
---|
3221 | | - add_credits(server, credits_received, 0); |
---|
| 4005 | + add_credits(server, &credits, 0); |
---|
3222 | 4006 | } |
---|
3223 | 4007 | |
---|
3224 | 4008 | /* smb2_async_readv - send an async read, and set up mid to handle result */ |
---|
.. | .. |
---|
3232 | 4016 | struct smb_rqst rqst = { .rq_iov = rdata->iov, |
---|
3233 | 4017 | .rq_nvec = 1 }; |
---|
3234 | 4018 | struct TCP_Server_Info *server; |
---|
| 4019 | + struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); |
---|
3235 | 4020 | unsigned int total_len; |
---|
3236 | 4021 | |
---|
3237 | 4022 | cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n", |
---|
3238 | 4023 | __func__, rdata->offset, rdata->bytes); |
---|
3239 | 4024 | |
---|
| 4025 | + if (!rdata->server) |
---|
| 4026 | + rdata->server = cifs_pick_channel(tcon->ses); |
---|
| 4027 | + |
---|
3240 | 4028 | io_parms.tcon = tlink_tcon(rdata->cfile->tlink); |
---|
| 4029 | + io_parms.server = server = rdata->server; |
---|
3241 | 4030 | io_parms.offset = rdata->offset; |
---|
3242 | 4031 | io_parms.length = rdata->bytes; |
---|
3243 | 4032 | io_parms.persistent_fid = rdata->cfile->fid.persistent_fid; |
---|
3244 | 4033 | io_parms.volatile_fid = rdata->cfile->fid.volatile_fid; |
---|
3245 | 4034 | io_parms.pid = rdata->pid; |
---|
3246 | 4035 | |
---|
3247 | | - server = io_parms.tcon->ses->server; |
---|
3248 | | - |
---|
3249 | 4036 | rc = smb2_new_read_req( |
---|
3250 | 4037 | (void **) &buf, &total_len, &io_parms, rdata, 0, 0); |
---|
3251 | | - if (rc) { |
---|
3252 | | - if (rc == -EAGAIN && rdata->credits) { |
---|
3253 | | - /* credits was reset by reconnect */ |
---|
3254 | | - rdata->credits = 0; |
---|
3255 | | - /* reduce in_flight value since we won't send the req */ |
---|
3256 | | - spin_lock(&server->req_lock); |
---|
3257 | | - server->in_flight--; |
---|
3258 | | - spin_unlock(&server->req_lock); |
---|
3259 | | - } |
---|
| 4038 | + if (rc) |
---|
3260 | 4039 | return rc; |
---|
3261 | | - } |
---|
3262 | 4040 | |
---|
3263 | 4041 | if (smb3_encryption_required(io_parms.tcon)) |
---|
3264 | 4042 | flags |= CIFS_TRANSFORM_REQ; |
---|
.. | .. |
---|
3268 | 4046 | |
---|
3269 | 4047 | shdr = (struct smb2_sync_hdr *)buf; |
---|
3270 | 4048 | |
---|
3271 | | - if (rdata->credits) { |
---|
| 4049 | + if (rdata->credits.value > 0) { |
---|
3272 | 4050 | shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes, |
---|
3273 | 4051 | SMB2_MAX_BUFFER_SIZE)); |
---|
3274 | | - shdr->CreditRequest = |
---|
3275 | | - cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 1); |
---|
3276 | | - spin_lock(&server->req_lock); |
---|
3277 | | - server->credits += rdata->credits - |
---|
3278 | | - le16_to_cpu(shdr->CreditCharge); |
---|
3279 | | - spin_unlock(&server->req_lock); |
---|
3280 | | - wake_up(&server->request_q); |
---|
3281 | | - rdata->credits = le16_to_cpu(shdr->CreditCharge); |
---|
| 4052 | + shdr->CreditRequest = cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 8); |
---|
| 4053 | + |
---|
| 4054 | + rc = adjust_credits(server, &rdata->credits, rdata->bytes); |
---|
| 4055 | + if (rc) |
---|
| 4056 | + goto async_readv_out; |
---|
| 4057 | + |
---|
3282 | 4058 | flags |= CIFS_HAS_CREDITS; |
---|
3283 | 4059 | } |
---|
3284 | 4060 | |
---|
3285 | 4061 | kref_get(&rdata->refcount); |
---|
3286 | | - rc = cifs_call_async(io_parms.tcon->ses->server, &rqst, |
---|
| 4062 | + rc = cifs_call_async(server, &rqst, |
---|
3287 | 4063 | cifs_readv_receive, smb2_readv_callback, |
---|
3288 | | - smb3_handle_read_data, rdata, flags); |
---|
| 4064 | + smb3_handle_read_data, rdata, flags, |
---|
| 4065 | + &rdata->credits); |
---|
3289 | 4066 | if (rc) { |
---|
3290 | 4067 | kref_put(&rdata->refcount, cifs_readdata_release); |
---|
3291 | 4068 | cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE); |
---|
.. | .. |
---|
3295 | 4072 | io_parms.offset, io_parms.length, rc); |
---|
3296 | 4073 | } |
---|
3297 | 4074 | |
---|
| 4075 | +async_readv_out: |
---|
3298 | 4076 | cifs_small_buf_release(buf); |
---|
3299 | 4077 | return rc; |
---|
3300 | 4078 | } |
---|
.. | .. |
---|
3304 | 4082 | unsigned int *nbytes, char **buf, int *buf_type) |
---|
3305 | 4083 | { |
---|
3306 | 4084 | struct smb_rqst rqst; |
---|
3307 | | - int resp_buftype, rc = -EACCES; |
---|
| 4085 | + int resp_buftype, rc; |
---|
3308 | 4086 | struct smb2_read_plain_req *req = NULL; |
---|
3309 | 4087 | struct smb2_read_rsp *rsp = NULL; |
---|
3310 | 4088 | struct kvec iov[1]; |
---|
.. | .. |
---|
3312 | 4090 | unsigned int total_len; |
---|
3313 | 4091 | int flags = CIFS_LOG_ERROR; |
---|
3314 | 4092 | struct cifs_ses *ses = io_parms->tcon->ses; |
---|
| 4093 | + |
---|
| 4094 | + if (!io_parms->server) |
---|
| 4095 | + io_parms->server = cifs_pick_channel(io_parms->tcon->ses); |
---|
3315 | 4096 | |
---|
3316 | 4097 | *nbytes = 0; |
---|
3317 | 4098 | rc = smb2_new_read_req((void **)&req, &total_len, io_parms, NULL, 0, 0); |
---|
.. | .. |
---|
3328 | 4109 | rqst.rq_iov = iov; |
---|
3329 | 4110 | rqst.rq_nvec = 1; |
---|
3330 | 4111 | |
---|
3331 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
---|
| 4112 | + rc = cifs_send_recv(xid, ses, io_parms->server, |
---|
| 4113 | + &rqst, &resp_buftype, flags, &rsp_iov); |
---|
3332 | 4114 | rsp = (struct smb2_read_rsp *)rsp_iov.iov_base; |
---|
3333 | 4115 | |
---|
3334 | 4116 | if (rc) { |
---|
.. | .. |
---|
3339 | 4121 | io_parms->tcon->tid, ses->Suid, |
---|
3340 | 4122 | io_parms->offset, io_parms->length, |
---|
3341 | 4123 | rc); |
---|
3342 | | - } |
---|
| 4124 | + } else |
---|
| 4125 | + trace_smb3_read_done(xid, req->PersistentFileId, |
---|
| 4126 | + io_parms->tcon->tid, ses->Suid, |
---|
| 4127 | + io_parms->offset, 0); |
---|
3343 | 4128 | free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
---|
3344 | 4129 | cifs_small_buf_release(req); |
---|
3345 | 4130 | return rc == -ENODATA ? 0 : rc; |
---|
.. | .. |
---|
3381 | 4166 | { |
---|
3382 | 4167 | struct cifs_writedata *wdata = mid->callback_data; |
---|
3383 | 4168 | struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); |
---|
| 4169 | + struct TCP_Server_Info *server = wdata->server; |
---|
3384 | 4170 | unsigned int written; |
---|
3385 | 4171 | struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf; |
---|
3386 | | - unsigned int credits_received = 0; |
---|
| 4172 | + struct cifs_credits credits = { .value = 0, .instance = 0 }; |
---|
| 4173 | + |
---|
| 4174 | + WARN_ONCE(wdata->server != mid->server, |
---|
| 4175 | + "wdata server %p != mid server %p", |
---|
| 4176 | + wdata->server, mid->server); |
---|
3387 | 4177 | |
---|
3388 | 4178 | switch (mid->mid_state) { |
---|
3389 | 4179 | case MID_RESPONSE_RECEIVED: |
---|
3390 | | - credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest); |
---|
3391 | | - wdata->result = smb2_check_receive(mid, tcon->ses->server, 0); |
---|
| 4180 | + credits.value = le16_to_cpu(rsp->sync_hdr.CreditRequest); |
---|
| 4181 | + credits.instance = server->reconnect_instance; |
---|
| 4182 | + wdata->result = smb2_check_receive(mid, server, 0); |
---|
3392 | 4183 | if (wdata->result != 0) |
---|
3393 | 4184 | break; |
---|
3394 | 4185 | |
---|
.. | .. |
---|
3412 | 4203 | wdata->result = -EAGAIN; |
---|
3413 | 4204 | break; |
---|
3414 | 4205 | case MID_RESPONSE_MALFORMED: |
---|
3415 | | - credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest); |
---|
3416 | | - /* fall through */ |
---|
| 4206 | + credits.value = le16_to_cpu(rsp->sync_hdr.CreditRequest); |
---|
| 4207 | + credits.instance = server->reconnect_instance; |
---|
| 4208 | + fallthrough; |
---|
3417 | 4209 | default: |
---|
3418 | 4210 | wdata->result = -EIO; |
---|
3419 | 4211 | break; |
---|
.. | .. |
---|
3438 | 4230 | tcon->tid, tcon->ses->Suid, wdata->offset, |
---|
3439 | 4231 | wdata->bytes, wdata->result); |
---|
3440 | 4232 | if (wdata->result == -ENOSPC) |
---|
3441 | | - printk_once(KERN_WARNING "Out of space writing to %s\n", |
---|
3442 | | - tcon->treeName); |
---|
| 4233 | + pr_warn_once("Out of space writing to %s\n", |
---|
| 4234 | + tcon->treeName); |
---|
3443 | 4235 | } else |
---|
3444 | 4236 | trace_smb3_write_done(0 /* no xid */, |
---|
3445 | 4237 | wdata->cfile->fid.persistent_fid, |
---|
.. | .. |
---|
3448 | 4240 | |
---|
3449 | 4241 | queue_work(cifsiod_wq, &wdata->work); |
---|
3450 | 4242 | DeleteMidQEntry(mid); |
---|
3451 | | - add_credits(tcon->ses->server, credits_received, 0); |
---|
| 4243 | + add_credits(server, &credits, 0); |
---|
3452 | 4244 | } |
---|
3453 | 4245 | |
---|
3454 | 4246 | /* smb2_async_writev - send an async write, and set up mid to handle result */ |
---|
.. | .. |
---|
3460 | 4252 | struct smb2_write_req *req = NULL; |
---|
3461 | 4253 | struct smb2_sync_hdr *shdr; |
---|
3462 | 4254 | struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); |
---|
3463 | | - struct TCP_Server_Info *server = tcon->ses->server; |
---|
| 4255 | + struct TCP_Server_Info *server = wdata->server; |
---|
3464 | 4256 | struct kvec iov[1]; |
---|
3465 | 4257 | struct smb_rqst rqst = { }; |
---|
3466 | 4258 | unsigned int total_len; |
---|
3467 | 4259 | |
---|
3468 | | - rc = smb2_plain_req_init(SMB2_WRITE, tcon, (void **) &req, &total_len); |
---|
3469 | | - if (rc) { |
---|
3470 | | - if (rc == -EAGAIN && wdata->credits) { |
---|
3471 | | - /* credits was reset by reconnect */ |
---|
3472 | | - wdata->credits = 0; |
---|
3473 | | - /* reduce in_flight value since we won't send the req */ |
---|
3474 | | - spin_lock(&server->req_lock); |
---|
3475 | | - server->in_flight--; |
---|
3476 | | - spin_unlock(&server->req_lock); |
---|
3477 | | - } |
---|
3478 | | - goto async_writev_out; |
---|
3479 | | - } |
---|
| 4260 | + if (!wdata->server) |
---|
| 4261 | + server = wdata->server = cifs_pick_channel(tcon->ses); |
---|
| 4262 | + |
---|
| 4263 | + rc = smb2_plain_req_init(SMB2_WRITE, tcon, server, |
---|
| 4264 | + (void **) &req, &total_len); |
---|
| 4265 | + if (rc) |
---|
| 4266 | + return rc; |
---|
3480 | 4267 | |
---|
3481 | 4268 | if (smb3_encryption_required(tcon)) |
---|
3482 | 4269 | flags |= CIFS_TRANSFORM_REQ; |
---|
.. | .. |
---|
3493 | 4280 | req->DataOffset = cpu_to_le16( |
---|
3494 | 4281 | offsetof(struct smb2_write_req, Buffer)); |
---|
3495 | 4282 | req->RemainingBytes = 0; |
---|
| 4283 | + |
---|
| 4284 | + trace_smb3_write_enter(0 /* xid */, wdata->cfile->fid.persistent_fid, |
---|
| 4285 | + tcon->tid, tcon->ses->Suid, wdata->offset, wdata->bytes); |
---|
3496 | 4286 | #ifdef CONFIG_CIFS_SMB_DIRECT |
---|
3497 | 4287 | /* |
---|
3498 | 4288 | * If we want to do a server RDMA read, fill in and append |
---|
.. | .. |
---|
3509 | 4299 | wdata->nr_pages, wdata->page_offset, |
---|
3510 | 4300 | wdata->tailsz, false, need_invalidate); |
---|
3511 | 4301 | if (!wdata->mr) { |
---|
3512 | | - rc = -ENOBUFS; |
---|
| 4302 | + rc = -EAGAIN; |
---|
3513 | 4303 | goto async_writev_out; |
---|
3514 | 4304 | } |
---|
3515 | 4305 | req->Length = 0; |
---|
.. | .. |
---|
3562 | 4352 | req->Length = cpu_to_le32(wdata->bytes); |
---|
3563 | 4353 | #endif |
---|
3564 | 4354 | |
---|
3565 | | - if (wdata->credits) { |
---|
| 4355 | + if (wdata->credits.value > 0) { |
---|
3566 | 4356 | shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes, |
---|
3567 | 4357 | SMB2_MAX_BUFFER_SIZE)); |
---|
3568 | | - shdr->CreditRequest = |
---|
3569 | | - cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 1); |
---|
3570 | | - spin_lock(&server->req_lock); |
---|
3571 | | - server->credits += wdata->credits - |
---|
3572 | | - le16_to_cpu(shdr->CreditCharge); |
---|
3573 | | - spin_unlock(&server->req_lock); |
---|
3574 | | - wake_up(&server->request_q); |
---|
3575 | | - wdata->credits = le16_to_cpu(shdr->CreditCharge); |
---|
| 4358 | + shdr->CreditRequest = cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 8); |
---|
| 4359 | + |
---|
| 4360 | + rc = adjust_credits(server, &wdata->credits, wdata->bytes); |
---|
| 4361 | + if (rc) |
---|
| 4362 | + goto async_writev_out; |
---|
| 4363 | + |
---|
3576 | 4364 | flags |= CIFS_HAS_CREDITS; |
---|
3577 | 4365 | } |
---|
3578 | 4366 | |
---|
3579 | 4367 | kref_get(&wdata->refcount); |
---|
3580 | 4368 | rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL, |
---|
3581 | | - wdata, flags); |
---|
| 4369 | + wdata, flags, &wdata->credits); |
---|
3582 | 4370 | |
---|
3583 | 4371 | if (rc) { |
---|
3584 | 4372 | trace_smb3_write_err(0 /* no xid */, req->PersistentFileId, |
---|
.. | .. |
---|
3611 | 4399 | struct kvec rsp_iov; |
---|
3612 | 4400 | int flags = 0; |
---|
3613 | 4401 | unsigned int total_len; |
---|
| 4402 | + struct TCP_Server_Info *server; |
---|
3614 | 4403 | |
---|
3615 | 4404 | *nbytes = 0; |
---|
3616 | 4405 | |
---|
3617 | 4406 | if (n_vec < 1) |
---|
3618 | 4407 | return rc; |
---|
3619 | 4408 | |
---|
3620 | | - rc = smb2_plain_req_init(SMB2_WRITE, io_parms->tcon, (void **) &req, |
---|
3621 | | - &total_len); |
---|
| 4409 | + if (!io_parms->server) |
---|
| 4410 | + io_parms->server = cifs_pick_channel(io_parms->tcon->ses); |
---|
| 4411 | + server = io_parms->server; |
---|
| 4412 | + if (server == NULL) |
---|
| 4413 | + return -ECONNABORTED; |
---|
| 4414 | + |
---|
| 4415 | + rc = smb2_plain_req_init(SMB2_WRITE, io_parms->tcon, server, |
---|
| 4416 | + (void **) &req, &total_len); |
---|
3622 | 4417 | if (rc) |
---|
3623 | 4418 | return rc; |
---|
3624 | | - |
---|
3625 | | - if (io_parms->tcon->ses->server == NULL) |
---|
3626 | | - return -ECONNABORTED; |
---|
3627 | 4419 | |
---|
3628 | 4420 | if (smb3_encryption_required(io_parms->tcon)) |
---|
3629 | 4421 | flags |= CIFS_TRANSFORM_REQ; |
---|
.. | .. |
---|
3641 | 4433 | offsetof(struct smb2_write_req, Buffer)); |
---|
3642 | 4434 | req->RemainingBytes = 0; |
---|
3643 | 4435 | |
---|
| 4436 | + trace_smb3_write_enter(xid, io_parms->persistent_fid, |
---|
| 4437 | + io_parms->tcon->tid, io_parms->tcon->ses->Suid, |
---|
| 4438 | + io_parms->offset, io_parms->length); |
---|
| 4439 | + |
---|
3644 | 4440 | iov[0].iov_base = (char *)req; |
---|
3645 | 4441 | /* 1 for Buffer */ |
---|
3646 | 4442 | iov[0].iov_len = total_len - 1; |
---|
.. | .. |
---|
3649 | 4445 | rqst.rq_iov = iov; |
---|
3650 | 4446 | rqst.rq_nvec = n_vec + 1; |
---|
3651 | 4447 | |
---|
3652 | | - rc = cifs_send_recv(xid, io_parms->tcon->ses, &rqst, |
---|
| 4448 | + rc = cifs_send_recv(xid, io_parms->tcon->ses, server, |
---|
| 4449 | + &rqst, |
---|
3653 | 4450 | &resp_buftype, flags, &rsp_iov); |
---|
3654 | 4451 | rsp = (struct smb2_write_rsp *)rsp_iov.iov_base; |
---|
3655 | 4452 | |
---|
.. | .. |
---|
3673 | 4470 | return rc; |
---|
3674 | 4471 | } |
---|
3675 | 4472 | |
---|
| 4473 | +int posix_info_sid_size(const void *beg, const void *end) |
---|
| 4474 | +{ |
---|
| 4475 | + size_t subauth; |
---|
| 4476 | + int total; |
---|
| 4477 | + |
---|
| 4478 | + if (beg + 1 > end) |
---|
| 4479 | + return -1; |
---|
| 4480 | + |
---|
| 4481 | + subauth = *(u8 *)(beg+1); |
---|
| 4482 | + if (subauth < 1 || subauth > 15) |
---|
| 4483 | + return -1; |
---|
| 4484 | + |
---|
| 4485 | + total = 1 + 1 + 6 + 4*subauth; |
---|
| 4486 | + if (beg + total > end) |
---|
| 4487 | + return -1; |
---|
| 4488 | + |
---|
| 4489 | + return total; |
---|
| 4490 | +} |
---|
| 4491 | + |
---|
| 4492 | +int posix_info_parse(const void *beg, const void *end, |
---|
| 4493 | + struct smb2_posix_info_parsed *out) |
---|
| 4494 | + |
---|
| 4495 | +{ |
---|
| 4496 | + int total_len = 0; |
---|
| 4497 | + int sid_len; |
---|
| 4498 | + int name_len; |
---|
| 4499 | + const void *owner_sid; |
---|
| 4500 | + const void *group_sid; |
---|
| 4501 | + const void *name; |
---|
| 4502 | + |
---|
| 4503 | + /* if no end bound given, assume payload to be correct */ |
---|
| 4504 | + if (!end) { |
---|
| 4505 | + const struct smb2_posix_info *p = beg; |
---|
| 4506 | + |
---|
| 4507 | + end = beg + le32_to_cpu(p->NextEntryOffset); |
---|
| 4508 | + /* last element will have a 0 offset, pick a sensible bound */ |
---|
| 4509 | + if (end == beg) |
---|
| 4510 | + end += 0xFFFF; |
---|
| 4511 | + } |
---|
| 4512 | + |
---|
| 4513 | + /* check base buf */ |
---|
| 4514 | + if (beg + sizeof(struct smb2_posix_info) > end) |
---|
| 4515 | + return -1; |
---|
| 4516 | + total_len = sizeof(struct smb2_posix_info); |
---|
| 4517 | + |
---|
| 4518 | + /* check owner sid */ |
---|
| 4519 | + owner_sid = beg + total_len; |
---|
| 4520 | + sid_len = posix_info_sid_size(owner_sid, end); |
---|
| 4521 | + if (sid_len < 0) |
---|
| 4522 | + return -1; |
---|
| 4523 | + total_len += sid_len; |
---|
| 4524 | + |
---|
| 4525 | + /* check group sid */ |
---|
| 4526 | + group_sid = beg + total_len; |
---|
| 4527 | + sid_len = posix_info_sid_size(group_sid, end); |
---|
| 4528 | + if (sid_len < 0) |
---|
| 4529 | + return -1; |
---|
| 4530 | + total_len += sid_len; |
---|
| 4531 | + |
---|
| 4532 | + /* check name len */ |
---|
| 4533 | + if (beg + total_len + 4 > end) |
---|
| 4534 | + return -1; |
---|
| 4535 | + name_len = le32_to_cpu(*(__le32 *)(beg + total_len)); |
---|
| 4536 | + if (name_len < 1 || name_len > 0xFFFF) |
---|
| 4537 | + return -1; |
---|
| 4538 | + total_len += 4; |
---|
| 4539 | + |
---|
| 4540 | + /* check name */ |
---|
| 4541 | + name = beg + total_len; |
---|
| 4542 | + if (name + name_len > end) |
---|
| 4543 | + return -1; |
---|
| 4544 | + total_len += name_len; |
---|
| 4545 | + |
---|
| 4546 | + if (out) { |
---|
| 4547 | + out->base = beg; |
---|
| 4548 | + out->size = total_len; |
---|
| 4549 | + out->name_len = name_len; |
---|
| 4550 | + out->name = name; |
---|
| 4551 | + memcpy(&out->owner, owner_sid, |
---|
| 4552 | + posix_info_sid_size(owner_sid, end)); |
---|
| 4553 | + memcpy(&out->group, group_sid, |
---|
| 4554 | + posix_info_sid_size(group_sid, end)); |
---|
| 4555 | + } |
---|
| 4556 | + return total_len; |
---|
| 4557 | +} |
---|
| 4558 | + |
---|
| 4559 | +static int posix_info_extra_size(const void *beg, const void *end) |
---|
| 4560 | +{ |
---|
| 4561 | + int len = posix_info_parse(beg, end, NULL); |
---|
| 4562 | + |
---|
| 4563 | + if (len < 0) |
---|
| 4564 | + return -1; |
---|
| 4565 | + return len - sizeof(struct smb2_posix_info); |
---|
| 4566 | +} |
---|
| 4567 | + |
---|
3676 | 4568 | static unsigned int |
---|
3677 | | -num_entries(char *bufstart, char *end_of_buf, char **lastentry, size_t size) |
---|
| 4569 | +num_entries(int infotype, char *bufstart, char *end_of_buf, char **lastentry, |
---|
| 4570 | + size_t size) |
---|
3678 | 4571 | { |
---|
3679 | 4572 | int len; |
---|
3680 | 4573 | unsigned int entrycount = 0; |
---|
.. | .. |
---|
3698 | 4591 | entryptr = entryptr + next_offset; |
---|
3699 | 4592 | dir_info = (FILE_DIRECTORY_INFO *)entryptr; |
---|
3700 | 4593 | |
---|
3701 | | - len = le32_to_cpu(dir_info->FileNameLength); |
---|
3702 | | - if (entryptr + len < entryptr || |
---|
| 4594 | + if (infotype == SMB_FIND_FILE_POSIX_INFO) |
---|
| 4595 | + len = posix_info_extra_size(entryptr, end_of_buf); |
---|
| 4596 | + else |
---|
| 4597 | + len = le32_to_cpu(dir_info->FileNameLength); |
---|
| 4598 | + |
---|
| 4599 | + if (len < 0 || |
---|
| 4600 | + entryptr + len < entryptr || |
---|
3703 | 4601 | entryptr + len > end_of_buf || |
---|
3704 | 4602 | entryptr + len + size > end_of_buf) { |
---|
3705 | 4603 | cifs_dbg(VFS, "directory entry name would overflow frame end of buf %p\n", |
---|
.. | .. |
---|
3721 | 4619 | /* |
---|
3722 | 4620 | * Readdir/FindFirst |
---|
3723 | 4621 | */ |
---|
3724 | | -int |
---|
3725 | | -SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, |
---|
3726 | | - u64 persistent_fid, u64 volatile_fid, int index, |
---|
3727 | | - struct cifs_search_info *srch_inf) |
---|
| 4622 | +int SMB2_query_directory_init(const unsigned int xid, |
---|
| 4623 | + struct cifs_tcon *tcon, |
---|
| 4624 | + struct TCP_Server_Info *server, |
---|
| 4625 | + struct smb_rqst *rqst, |
---|
| 4626 | + u64 persistent_fid, u64 volatile_fid, |
---|
| 4627 | + int index, int info_level) |
---|
3728 | 4628 | { |
---|
3729 | | - struct smb_rqst rqst; |
---|
3730 | 4629 | struct smb2_query_directory_req *req; |
---|
3731 | | - struct smb2_query_directory_rsp *rsp = NULL; |
---|
3732 | | - struct kvec iov[2]; |
---|
3733 | | - struct kvec rsp_iov; |
---|
3734 | | - int rc = 0; |
---|
3735 | | - int len; |
---|
3736 | | - int resp_buftype = CIFS_NO_BUFFER; |
---|
3737 | 4630 | unsigned char *bufptr; |
---|
3738 | | - struct TCP_Server_Info *server; |
---|
3739 | | - struct cifs_ses *ses = tcon->ses; |
---|
3740 | 4631 | __le16 asteriks = cpu_to_le16('*'); |
---|
3741 | | - char *end_of_smb; |
---|
3742 | | - unsigned int output_size = CIFSMaxBufSize; |
---|
3743 | | - size_t info_buf_size; |
---|
3744 | | - int flags = 0; |
---|
| 4632 | + unsigned int output_size = CIFSMaxBufSize - |
---|
| 4633 | + MAX_SMB2_CREATE_RESPONSE_SIZE - |
---|
| 4634 | + MAX_SMB2_CLOSE_RESPONSE_SIZE; |
---|
3745 | 4635 | unsigned int total_len; |
---|
| 4636 | + struct kvec *iov = rqst->rq_iov; |
---|
| 4637 | + int len, rc; |
---|
3746 | 4638 | |
---|
3747 | | - if (ses && (ses->server)) |
---|
3748 | | - server = ses->server; |
---|
3749 | | - else |
---|
3750 | | - return -EIO; |
---|
3751 | | - |
---|
3752 | | - rc = smb2_plain_req_init(SMB2_QUERY_DIRECTORY, tcon, (void **) &req, |
---|
3753 | | - &total_len); |
---|
| 4639 | + rc = smb2_plain_req_init(SMB2_QUERY_DIRECTORY, tcon, server, |
---|
| 4640 | + (void **) &req, &total_len); |
---|
3754 | 4641 | if (rc) |
---|
3755 | 4642 | return rc; |
---|
3756 | 4643 | |
---|
3757 | | - if (smb3_encryption_required(tcon)) |
---|
3758 | | - flags |= CIFS_TRANSFORM_REQ; |
---|
3759 | | - |
---|
3760 | | - switch (srch_inf->info_level) { |
---|
| 4644 | + switch (info_level) { |
---|
3761 | 4645 | case SMB_FIND_FILE_DIRECTORY_INFO: |
---|
3762 | 4646 | req->FileInformationClass = FILE_DIRECTORY_INFORMATION; |
---|
3763 | | - info_buf_size = sizeof(FILE_DIRECTORY_INFO) - 1; |
---|
3764 | 4647 | break; |
---|
3765 | 4648 | case SMB_FIND_FILE_ID_FULL_DIR_INFO: |
---|
3766 | 4649 | req->FileInformationClass = FILEID_FULL_DIRECTORY_INFORMATION; |
---|
3767 | | - info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1; |
---|
| 4650 | + break; |
---|
| 4651 | + case SMB_FIND_FILE_POSIX_INFO: |
---|
| 4652 | + req->FileInformationClass = SMB_FIND_FILE_POSIX_INFO; |
---|
3768 | 4653 | break; |
---|
3769 | 4654 | default: |
---|
3770 | | - cifs_dbg(VFS, "info level %u isn't supported\n", |
---|
3771 | | - srch_inf->info_level); |
---|
3772 | | - rc = -EINVAL; |
---|
3773 | | - goto qdir_exit; |
---|
| 4655 | + cifs_tcon_dbg(VFS, "info level %u isn't supported\n", |
---|
| 4656 | + info_level); |
---|
| 4657 | + return -EINVAL; |
---|
3774 | 4658 | } |
---|
3775 | 4659 | |
---|
3776 | 4660 | req->FileIndex = cpu_to_le32(index); |
---|
.. | .. |
---|
3799 | 4683 | iov[1].iov_base = (char *)(req->Buffer); |
---|
3800 | 4684 | iov[1].iov_len = len; |
---|
3801 | 4685 | |
---|
3802 | | - memset(&rqst, 0, sizeof(struct smb_rqst)); |
---|
3803 | | - rqst.rq_iov = iov; |
---|
3804 | | - rqst.rq_nvec = 2; |
---|
| 4686 | + trace_smb3_query_dir_enter(xid, persistent_fid, tcon->tid, |
---|
| 4687 | + tcon->ses->Suid, index, output_size); |
---|
3805 | 4688 | |
---|
3806 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
---|
3807 | | - cifs_small_buf_release(req); |
---|
3808 | | - rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base; |
---|
| 4689 | + return 0; |
---|
| 4690 | +} |
---|
3809 | 4691 | |
---|
3810 | | - if (rc) { |
---|
3811 | | - if (rc == -ENODATA && |
---|
3812 | | - rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) { |
---|
3813 | | - srch_inf->endOfSearch = true; |
---|
3814 | | - rc = 0; |
---|
3815 | | - } else |
---|
3816 | | - cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE); |
---|
3817 | | - goto qdir_exit; |
---|
| 4692 | +void SMB2_query_directory_free(struct smb_rqst *rqst) |
---|
| 4693 | +{ |
---|
| 4694 | + if (rqst && rqst->rq_iov) { |
---|
| 4695 | + cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ |
---|
| 4696 | + } |
---|
| 4697 | +} |
---|
| 4698 | + |
---|
| 4699 | +int |
---|
| 4700 | +smb2_parse_query_directory(struct cifs_tcon *tcon, |
---|
| 4701 | + struct kvec *rsp_iov, |
---|
| 4702 | + int resp_buftype, |
---|
| 4703 | + struct cifs_search_info *srch_inf) |
---|
| 4704 | +{ |
---|
| 4705 | + struct smb2_query_directory_rsp *rsp; |
---|
| 4706 | + size_t info_buf_size; |
---|
| 4707 | + char *end_of_smb; |
---|
| 4708 | + int rc; |
---|
| 4709 | + |
---|
| 4710 | + rsp = (struct smb2_query_directory_rsp *)rsp_iov->iov_base; |
---|
| 4711 | + |
---|
| 4712 | + switch (srch_inf->info_level) { |
---|
| 4713 | + case SMB_FIND_FILE_DIRECTORY_INFO: |
---|
| 4714 | + info_buf_size = sizeof(FILE_DIRECTORY_INFO) - 1; |
---|
| 4715 | + break; |
---|
| 4716 | + case SMB_FIND_FILE_ID_FULL_DIR_INFO: |
---|
| 4717 | + info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1; |
---|
| 4718 | + break; |
---|
| 4719 | + case SMB_FIND_FILE_POSIX_INFO: |
---|
| 4720 | + /* note that posix payload are variable size */ |
---|
| 4721 | + info_buf_size = sizeof(struct smb2_posix_info); |
---|
| 4722 | + break; |
---|
| 4723 | + default: |
---|
| 4724 | + cifs_tcon_dbg(VFS, "info level %u isn't supported\n", |
---|
| 4725 | + srch_inf->info_level); |
---|
| 4726 | + return -EINVAL; |
---|
3818 | 4727 | } |
---|
3819 | 4728 | |
---|
3820 | 4729 | rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset), |
---|
3821 | | - le32_to_cpu(rsp->OutputBufferLength), &rsp_iov, |
---|
| 4730 | + le32_to_cpu(rsp->OutputBufferLength), rsp_iov, |
---|
3822 | 4731 | info_buf_size); |
---|
3823 | | - if (rc) |
---|
3824 | | - goto qdir_exit; |
---|
| 4732 | + if (rc) { |
---|
| 4733 | + cifs_tcon_dbg(VFS, "bad info payload"); |
---|
| 4734 | + return rc; |
---|
| 4735 | + } |
---|
3825 | 4736 | |
---|
3826 | 4737 | srch_inf->unicode = true; |
---|
3827 | 4738 | |
---|
.. | .. |
---|
3834 | 4745 | srch_inf->ntwrk_buf_start = (char *)rsp; |
---|
3835 | 4746 | srch_inf->srch_entries_start = srch_inf->last_entry = |
---|
3836 | 4747 | (char *)rsp + le16_to_cpu(rsp->OutputBufferOffset); |
---|
3837 | | - end_of_smb = rsp_iov.iov_len + (char *)rsp; |
---|
3838 | | - srch_inf->entries_in_buffer = |
---|
3839 | | - num_entries(srch_inf->srch_entries_start, end_of_smb, |
---|
3840 | | - &srch_inf->last_entry, info_buf_size); |
---|
| 4748 | + end_of_smb = rsp_iov->iov_len + (char *)rsp; |
---|
| 4749 | + |
---|
| 4750 | + srch_inf->entries_in_buffer = num_entries( |
---|
| 4751 | + srch_inf->info_level, |
---|
| 4752 | + srch_inf->srch_entries_start, |
---|
| 4753 | + end_of_smb, |
---|
| 4754 | + &srch_inf->last_entry, |
---|
| 4755 | + info_buf_size); |
---|
| 4756 | + |
---|
3841 | 4757 | srch_inf->index_of_last_entry += srch_inf->entries_in_buffer; |
---|
3842 | 4758 | cifs_dbg(FYI, "num entries %d last_index %lld srch start %p srch end %p\n", |
---|
3843 | 4759 | srch_inf->entries_in_buffer, srch_inf->index_of_last_entry, |
---|
.. | .. |
---|
3847 | 4763 | else if (resp_buftype == CIFS_SMALL_BUFFER) |
---|
3848 | 4764 | srch_inf->smallBuf = true; |
---|
3849 | 4765 | else |
---|
3850 | | - cifs_dbg(VFS, "illegal search buffer type\n"); |
---|
| 4766 | + cifs_tcon_dbg(VFS, "Invalid search buffer type\n"); |
---|
3851 | 4767 | |
---|
3852 | | - return rc; |
---|
3853 | | - |
---|
3854 | | -qdir_exit: |
---|
3855 | | - free_rsp_buf(resp_buftype, rsp); |
---|
3856 | | - return rc; |
---|
| 4768 | + return 0; |
---|
3857 | 4769 | } |
---|
3858 | 4770 | |
---|
3859 | | -static int |
---|
3860 | | -send_set_info(const unsigned int xid, struct cifs_tcon *tcon, |
---|
3861 | | - u64 persistent_fid, u64 volatile_fid, u32 pid, u8 info_class, |
---|
3862 | | - u8 info_type, u32 additional_info, unsigned int num, |
---|
3863 | | - void **data, unsigned int *size) |
---|
| 4771 | +int |
---|
| 4772 | +SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, |
---|
| 4773 | + u64 persistent_fid, u64 volatile_fid, int index, |
---|
| 4774 | + struct cifs_search_info *srch_inf) |
---|
3864 | 4775 | { |
---|
3865 | 4776 | struct smb_rqst rqst; |
---|
3866 | | - struct smb2_set_info_req *req; |
---|
3867 | | - struct smb2_set_info_rsp *rsp = NULL; |
---|
3868 | | - struct kvec *iov; |
---|
| 4777 | + struct kvec iov[SMB2_QUERY_DIRECTORY_IOV_SIZE]; |
---|
| 4778 | + struct smb2_query_directory_rsp *rsp = NULL; |
---|
| 4779 | + int resp_buftype = CIFS_NO_BUFFER; |
---|
3869 | 4780 | struct kvec rsp_iov; |
---|
3870 | 4781 | int rc = 0; |
---|
3871 | | - int resp_buftype; |
---|
3872 | | - unsigned int i; |
---|
3873 | 4782 | struct cifs_ses *ses = tcon->ses; |
---|
| 4783 | + struct TCP_Server_Info *server = cifs_pick_channel(ses); |
---|
3874 | 4784 | int flags = 0; |
---|
3875 | | - unsigned int total_len; |
---|
3876 | 4785 | |
---|
3877 | 4786 | if (!ses || !(ses->server)) |
---|
3878 | 4787 | return -EIO; |
---|
3879 | 4788 | |
---|
3880 | | - if (!num) |
---|
3881 | | - return -EINVAL; |
---|
3882 | | - |
---|
3883 | | - iov = kmalloc_array(num, sizeof(struct kvec), GFP_KERNEL); |
---|
3884 | | - if (!iov) |
---|
3885 | | - return -ENOMEM; |
---|
3886 | | - |
---|
3887 | | - rc = smb2_plain_req_init(SMB2_SET_INFO, tcon, (void **) &req, &total_len); |
---|
3888 | | - if (rc) { |
---|
3889 | | - kfree(iov); |
---|
3890 | | - return rc; |
---|
3891 | | - } |
---|
3892 | | - |
---|
3893 | 4789 | if (smb3_encryption_required(tcon)) |
---|
3894 | 4790 | flags |= CIFS_TRANSFORM_REQ; |
---|
3895 | 4791 | |
---|
3896 | | - req->sync_hdr.ProcessId = cpu_to_le32(pid); |
---|
| 4792 | + memset(&rqst, 0, sizeof(struct smb_rqst)); |
---|
| 4793 | + memset(&iov, 0, sizeof(iov)); |
---|
| 4794 | + rqst.rq_iov = iov; |
---|
| 4795 | + rqst.rq_nvec = SMB2_QUERY_DIRECTORY_IOV_SIZE; |
---|
3897 | 4796 | |
---|
| 4797 | + rc = SMB2_query_directory_init(xid, tcon, server, |
---|
| 4798 | + &rqst, persistent_fid, |
---|
| 4799 | + volatile_fid, index, |
---|
| 4800 | + srch_inf->info_level); |
---|
| 4801 | + if (rc) |
---|
| 4802 | + goto qdir_exit; |
---|
| 4803 | + |
---|
| 4804 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 4805 | + &rqst, &resp_buftype, flags, &rsp_iov); |
---|
| 4806 | + rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base; |
---|
| 4807 | + |
---|
| 4808 | + if (rc) { |
---|
| 4809 | + if (rc == -ENODATA && |
---|
| 4810 | + rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) { |
---|
| 4811 | + trace_smb3_query_dir_done(xid, persistent_fid, |
---|
| 4812 | + tcon->tid, tcon->ses->Suid, index, 0); |
---|
| 4813 | + srch_inf->endOfSearch = true; |
---|
| 4814 | + rc = 0; |
---|
| 4815 | + } else { |
---|
| 4816 | + trace_smb3_query_dir_err(xid, persistent_fid, tcon->tid, |
---|
| 4817 | + tcon->ses->Suid, index, 0, rc); |
---|
| 4818 | + cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE); |
---|
| 4819 | + } |
---|
| 4820 | + goto qdir_exit; |
---|
| 4821 | + } |
---|
| 4822 | + |
---|
| 4823 | + rc = smb2_parse_query_directory(tcon, &rsp_iov, resp_buftype, |
---|
| 4824 | + srch_inf); |
---|
| 4825 | + if (rc) { |
---|
| 4826 | + trace_smb3_query_dir_err(xid, persistent_fid, tcon->tid, |
---|
| 4827 | + tcon->ses->Suid, index, 0, rc); |
---|
| 4828 | + goto qdir_exit; |
---|
| 4829 | + } |
---|
| 4830 | + resp_buftype = CIFS_NO_BUFFER; |
---|
| 4831 | + |
---|
| 4832 | + trace_smb3_query_dir_done(xid, persistent_fid, tcon->tid, |
---|
| 4833 | + tcon->ses->Suid, index, srch_inf->entries_in_buffer); |
---|
| 4834 | + |
---|
| 4835 | +qdir_exit: |
---|
| 4836 | + SMB2_query_directory_free(&rqst); |
---|
| 4837 | + free_rsp_buf(resp_buftype, rsp); |
---|
| 4838 | + return rc; |
---|
| 4839 | +} |
---|
| 4840 | + |
---|
| 4841 | +int |
---|
| 4842 | +SMB2_set_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, |
---|
| 4843 | + struct smb_rqst *rqst, |
---|
| 4844 | + u64 persistent_fid, u64 volatile_fid, u32 pid, |
---|
| 4845 | + u8 info_class, u8 info_type, u32 additional_info, |
---|
| 4846 | + void **data, unsigned int *size) |
---|
| 4847 | +{ |
---|
| 4848 | + struct smb2_set_info_req *req; |
---|
| 4849 | + struct kvec *iov = rqst->rq_iov; |
---|
| 4850 | + unsigned int i, total_len; |
---|
| 4851 | + int rc; |
---|
| 4852 | + |
---|
| 4853 | + rc = smb2_plain_req_init(SMB2_SET_INFO, tcon, server, |
---|
| 4854 | + (void **) &req, &total_len); |
---|
| 4855 | + if (rc) |
---|
| 4856 | + return rc; |
---|
| 4857 | + |
---|
| 4858 | + req->sync_hdr.ProcessId = cpu_to_le32(pid); |
---|
3898 | 4859 | req->InfoType = info_type; |
---|
3899 | 4860 | req->FileInfoClass = info_class; |
---|
3900 | 4861 | req->PersistentFileId = persistent_fid; |
---|
.. | .. |
---|
3912 | 4873 | /* 1 for Buffer */ |
---|
3913 | 4874 | iov[0].iov_len = total_len - 1; |
---|
3914 | 4875 | |
---|
3915 | | - for (i = 1; i < num; i++) { |
---|
| 4876 | + for (i = 1; i < rqst->rq_nvec; i++) { |
---|
3916 | 4877 | le32_add_cpu(&req->BufferLength, size[i]); |
---|
3917 | 4878 | iov[i].iov_base = (char *)data[i]; |
---|
3918 | 4879 | iov[i].iov_len = size[i]; |
---|
3919 | 4880 | } |
---|
3920 | 4881 | |
---|
| 4882 | + return 0; |
---|
| 4883 | +} |
---|
| 4884 | + |
---|
| 4885 | +void |
---|
| 4886 | +SMB2_set_info_free(struct smb_rqst *rqst) |
---|
| 4887 | +{ |
---|
| 4888 | + if (rqst && rqst->rq_iov) |
---|
| 4889 | + cifs_buf_release(rqst->rq_iov[0].iov_base); /* request */ |
---|
| 4890 | +} |
---|
| 4891 | + |
---|
| 4892 | +static int |
---|
| 4893 | +send_set_info(const unsigned int xid, struct cifs_tcon *tcon, |
---|
| 4894 | + u64 persistent_fid, u64 volatile_fid, u32 pid, u8 info_class, |
---|
| 4895 | + u8 info_type, u32 additional_info, unsigned int num, |
---|
| 4896 | + void **data, unsigned int *size) |
---|
| 4897 | +{ |
---|
| 4898 | + struct smb_rqst rqst; |
---|
| 4899 | + struct smb2_set_info_rsp *rsp = NULL; |
---|
| 4900 | + struct kvec *iov; |
---|
| 4901 | + struct kvec rsp_iov; |
---|
| 4902 | + int rc = 0; |
---|
| 4903 | + int resp_buftype; |
---|
| 4904 | + struct cifs_ses *ses = tcon->ses; |
---|
| 4905 | + struct TCP_Server_Info *server = cifs_pick_channel(ses); |
---|
| 4906 | + int flags = 0; |
---|
| 4907 | + |
---|
| 4908 | + if (!ses || !server) |
---|
| 4909 | + return -EIO; |
---|
| 4910 | + |
---|
| 4911 | + if (!num) |
---|
| 4912 | + return -EINVAL; |
---|
| 4913 | + |
---|
| 4914 | + if (smb3_encryption_required(tcon)) |
---|
| 4915 | + flags |= CIFS_TRANSFORM_REQ; |
---|
| 4916 | + |
---|
| 4917 | + iov = kmalloc_array(num, sizeof(struct kvec), GFP_KERNEL); |
---|
| 4918 | + if (!iov) |
---|
| 4919 | + return -ENOMEM; |
---|
| 4920 | + |
---|
3921 | 4921 | memset(&rqst, 0, sizeof(struct smb_rqst)); |
---|
3922 | 4922 | rqst.rq_iov = iov; |
---|
3923 | 4923 | rqst.rq_nvec = num; |
---|
3924 | 4924 | |
---|
3925 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, |
---|
| 4925 | + rc = SMB2_set_info_init(tcon, server, |
---|
| 4926 | + &rqst, persistent_fid, volatile_fid, pid, |
---|
| 4927 | + info_class, info_type, additional_info, |
---|
| 4928 | + data, size); |
---|
| 4929 | + if (rc) { |
---|
| 4930 | + kfree(iov); |
---|
| 4931 | + return rc; |
---|
| 4932 | + } |
---|
| 4933 | + |
---|
| 4934 | + |
---|
| 4935 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 4936 | + &rqst, &resp_buftype, flags, |
---|
3926 | 4937 | &rsp_iov); |
---|
3927 | | - cifs_buf_release(req); |
---|
| 4938 | + SMB2_set_info_free(&rqst); |
---|
3928 | 4939 | rsp = (struct smb2_set_info_rsp *)rsp_iov.iov_base; |
---|
3929 | 4940 | |
---|
3930 | 4941 | if (rc != 0) { |
---|
.. | .. |
---|
3939 | 4950 | } |
---|
3940 | 4951 | |
---|
3941 | 4952 | int |
---|
3942 | | -SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon, |
---|
3943 | | - u64 persistent_fid, u64 volatile_fid, __le16 *target_file) |
---|
3944 | | -{ |
---|
3945 | | - struct smb2_file_rename_info info; |
---|
3946 | | - void **data; |
---|
3947 | | - unsigned int size[2]; |
---|
3948 | | - int rc; |
---|
3949 | | - int len = (2 * UniStrnlen((wchar_t *)target_file, PATH_MAX)); |
---|
3950 | | - |
---|
3951 | | - data = kmalloc_array(2, sizeof(void *), GFP_KERNEL); |
---|
3952 | | - if (!data) |
---|
3953 | | - return -ENOMEM; |
---|
3954 | | - |
---|
3955 | | - info.ReplaceIfExists = 1; /* 1 = replace existing target with new */ |
---|
3956 | | - /* 0 = fail if target already exists */ |
---|
3957 | | - info.RootDirectory = 0; /* MBZ for network ops (why does spec say?) */ |
---|
3958 | | - info.FileNameLength = cpu_to_le32(len); |
---|
3959 | | - |
---|
3960 | | - data[0] = &info; |
---|
3961 | | - size[0] = sizeof(struct smb2_file_rename_info); |
---|
3962 | | - |
---|
3963 | | - data[1] = target_file; |
---|
3964 | | - size[1] = len + 2 /* null */; |
---|
3965 | | - |
---|
3966 | | - rc = send_set_info(xid, tcon, persistent_fid, volatile_fid, |
---|
3967 | | - current->tgid, FILE_RENAME_INFORMATION, SMB2_O_INFO_FILE, |
---|
3968 | | - 0, 2, data, size); |
---|
3969 | | - kfree(data); |
---|
3970 | | - return rc; |
---|
3971 | | -} |
---|
3972 | | - |
---|
3973 | | -int |
---|
3974 | | -SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, |
---|
3975 | | - u64 persistent_fid, u64 volatile_fid) |
---|
3976 | | -{ |
---|
3977 | | - __u8 delete_pending = 1; |
---|
3978 | | - void *data; |
---|
3979 | | - unsigned int size; |
---|
3980 | | - |
---|
3981 | | - data = &delete_pending; |
---|
3982 | | - size = 1; /* sizeof __u8 */ |
---|
3983 | | - |
---|
3984 | | - return send_set_info(xid, tcon, persistent_fid, volatile_fid, |
---|
3985 | | - current->tgid, FILE_DISPOSITION_INFORMATION, SMB2_O_INFO_FILE, |
---|
3986 | | - 0, 1, &data, &size); |
---|
3987 | | -} |
---|
3988 | | - |
---|
3989 | | -int |
---|
3990 | | -SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon, |
---|
3991 | | - u64 persistent_fid, u64 volatile_fid, __le16 *target_file) |
---|
3992 | | -{ |
---|
3993 | | - struct smb2_file_link_info info; |
---|
3994 | | - void **data; |
---|
3995 | | - unsigned int size[2]; |
---|
3996 | | - int rc; |
---|
3997 | | - int len = (2 * UniStrnlen((wchar_t *)target_file, PATH_MAX)); |
---|
3998 | | - |
---|
3999 | | - data = kmalloc_array(2, sizeof(void *), GFP_KERNEL); |
---|
4000 | | - if (!data) |
---|
4001 | | - return -ENOMEM; |
---|
4002 | | - |
---|
4003 | | - info.ReplaceIfExists = 0; /* 1 = replace existing link with new */ |
---|
4004 | | - /* 0 = fail if link already exists */ |
---|
4005 | | - info.RootDirectory = 0; /* MBZ for network ops (why does spec say?) */ |
---|
4006 | | - info.FileNameLength = cpu_to_le32(len); |
---|
4007 | | - |
---|
4008 | | - data[0] = &info; |
---|
4009 | | - size[0] = sizeof(struct smb2_file_link_info); |
---|
4010 | | - |
---|
4011 | | - data[1] = target_file; |
---|
4012 | | - size[1] = len + 2 /* null */; |
---|
4013 | | - |
---|
4014 | | - rc = send_set_info(xid, tcon, persistent_fid, volatile_fid, |
---|
4015 | | - current->tgid, FILE_LINK_INFORMATION, SMB2_O_INFO_FILE, |
---|
4016 | | - 0, 2, data, size); |
---|
4017 | | - kfree(data); |
---|
4018 | | - return rc; |
---|
4019 | | -} |
---|
4020 | | - |
---|
4021 | | -int |
---|
4022 | 4953 | SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, |
---|
4023 | | - u64 volatile_fid, u32 pid, __le64 *eof, bool is_falloc) |
---|
| 4954 | + u64 volatile_fid, u32 pid, __le64 *eof) |
---|
4024 | 4955 | { |
---|
4025 | 4956 | struct smb2_file_eof_info info; |
---|
4026 | 4957 | void *data; |
---|
.. | .. |
---|
4031 | 4962 | data = &info; |
---|
4032 | 4963 | size = sizeof(struct smb2_file_eof_info); |
---|
4033 | 4964 | |
---|
4034 | | - if (is_falloc) |
---|
4035 | | - return send_set_info(xid, tcon, persistent_fid, volatile_fid, |
---|
4036 | | - pid, FILE_ALLOCATION_INFORMATION, SMB2_O_INFO_FILE, |
---|
4037 | | - 0, 1, &data, &size); |
---|
4038 | | - else |
---|
4039 | | - return send_set_info(xid, tcon, persistent_fid, volatile_fid, |
---|
| 4965 | + return send_set_info(xid, tcon, persistent_fid, volatile_fid, |
---|
4040 | 4966 | pid, FILE_END_OF_FILE_INFORMATION, SMB2_O_INFO_FILE, |
---|
4041 | 4967 | 0, 1, &data, &size); |
---|
4042 | | -} |
---|
4043 | | - |
---|
4044 | | -int |
---|
4045 | | -SMB2_set_info(const unsigned int xid, struct cifs_tcon *tcon, |
---|
4046 | | - u64 persistent_fid, u64 volatile_fid, FILE_BASIC_INFO *buf) |
---|
4047 | | -{ |
---|
4048 | | - unsigned int size; |
---|
4049 | | - size = sizeof(FILE_BASIC_INFO); |
---|
4050 | | - return send_set_info(xid, tcon, persistent_fid, volatile_fid, |
---|
4051 | | - current->tgid, FILE_BASIC_INFORMATION, SMB2_O_INFO_FILE, |
---|
4052 | | - 0, 1, (void **)&buf, &size); |
---|
4053 | 4968 | } |
---|
4054 | 4969 | |
---|
4055 | 4970 | int |
---|
.. | .. |
---|
4081 | 4996 | int rc; |
---|
4082 | 4997 | struct smb2_oplock_break *req = NULL; |
---|
4083 | 4998 | struct cifs_ses *ses = tcon->ses; |
---|
| 4999 | + struct TCP_Server_Info *server = cifs_pick_channel(ses); |
---|
4084 | 5000 | int flags = CIFS_OBREAK_OP; |
---|
4085 | 5001 | unsigned int total_len; |
---|
4086 | 5002 | struct kvec iov[1]; |
---|
.. | .. |
---|
4088 | 5004 | int resp_buf_type; |
---|
4089 | 5005 | |
---|
4090 | 5006 | cifs_dbg(FYI, "SMB2_oplock_break\n"); |
---|
4091 | | - rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req, |
---|
4092 | | - &total_len); |
---|
| 5007 | + rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server, |
---|
| 5008 | + (void **) &req, &total_len); |
---|
4093 | 5009 | if (rc) |
---|
4094 | 5010 | return rc; |
---|
4095 | 5011 | |
---|
.. | .. |
---|
4101 | 5017 | req->OplockLevel = oplock_level; |
---|
4102 | 5018 | req->sync_hdr.CreditRequest = cpu_to_le16(1); |
---|
4103 | 5019 | |
---|
4104 | | - flags |= CIFS_NO_RESP; |
---|
| 5020 | + flags |= CIFS_NO_RSP_BUF; |
---|
4105 | 5021 | |
---|
4106 | 5022 | iov[0].iov_base = (char *)req; |
---|
4107 | 5023 | iov[0].iov_len = total_len; |
---|
.. | .. |
---|
4110 | 5026 | rqst.rq_iov = iov; |
---|
4111 | 5027 | rqst.rq_nvec = 1; |
---|
4112 | 5028 | |
---|
4113 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov); |
---|
| 5029 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 5030 | + &rqst, &resp_buf_type, flags, &rsp_iov); |
---|
4114 | 5031 | cifs_small_buf_release(req); |
---|
4115 | 5032 | |
---|
4116 | 5033 | if (rc) { |
---|
.. | .. |
---|
4153 | 5070 | } |
---|
4154 | 5071 | |
---|
4155 | 5072 | static int |
---|
4156 | | -build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level, |
---|
4157 | | - int outbuf_len, u64 persistent_fid, u64 volatile_fid) |
---|
| 5073 | +build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, |
---|
| 5074 | + struct TCP_Server_Info *server, |
---|
| 5075 | + int level, int outbuf_len, u64 persistent_fid, |
---|
| 5076 | + u64 volatile_fid) |
---|
4158 | 5077 | { |
---|
4159 | | - struct TCP_Server_Info *server; |
---|
4160 | 5078 | int rc; |
---|
4161 | 5079 | struct smb2_query_info_req *req; |
---|
4162 | 5080 | unsigned int total_len; |
---|
4163 | 5081 | |
---|
4164 | 5082 | cifs_dbg(FYI, "Query FSInfo level %d\n", level); |
---|
4165 | 5083 | |
---|
4166 | | - if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) |
---|
| 5084 | + if ((tcon->ses == NULL) || server == NULL) |
---|
4167 | 5085 | return -EIO; |
---|
4168 | 5086 | |
---|
4169 | | - server = tcon->ses->server; |
---|
4170 | | - |
---|
4171 | | - rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, (void **) &req, |
---|
4172 | | - &total_len); |
---|
| 5087 | + rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server, |
---|
| 5088 | + (void **) &req, &total_len); |
---|
4173 | 5089 | if (rc) |
---|
4174 | 5090 | return rc; |
---|
4175 | 5091 | |
---|
.. | .. |
---|
4199 | 5115 | int rc = 0; |
---|
4200 | 5116 | int resp_buftype; |
---|
4201 | 5117 | struct cifs_ses *ses = tcon->ses; |
---|
| 5118 | + struct TCP_Server_Info *server = cifs_pick_channel(ses); |
---|
4202 | 5119 | FILE_SYSTEM_POSIX_INFO *info = NULL; |
---|
4203 | 5120 | int flags = 0; |
---|
4204 | 5121 | |
---|
4205 | | - rc = build_qfs_info_req(&iov, tcon, FS_POSIX_INFORMATION, |
---|
| 5122 | + rc = build_qfs_info_req(&iov, tcon, server, |
---|
| 5123 | + FS_POSIX_INFORMATION, |
---|
4206 | 5124 | sizeof(FILE_SYSTEM_POSIX_INFO), |
---|
4207 | 5125 | persistent_fid, volatile_fid); |
---|
4208 | 5126 | if (rc) |
---|
.. | .. |
---|
4215 | 5133 | rqst.rq_iov = &iov; |
---|
4216 | 5134 | rqst.rq_nvec = 1; |
---|
4217 | 5135 | |
---|
4218 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
---|
| 5136 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 5137 | + &rqst, &resp_buftype, flags, &rsp_iov); |
---|
4219 | 5138 | cifs_small_buf_release(iov.iov_base); |
---|
4220 | 5139 | if (rc) { |
---|
4221 | 5140 | cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); |
---|
.. | .. |
---|
4247 | 5166 | int rc = 0; |
---|
4248 | 5167 | int resp_buftype; |
---|
4249 | 5168 | struct cifs_ses *ses = tcon->ses; |
---|
| 5169 | + struct TCP_Server_Info *server = cifs_pick_channel(ses); |
---|
4250 | 5170 | struct smb2_fs_full_size_info *info = NULL; |
---|
4251 | 5171 | int flags = 0; |
---|
4252 | 5172 | |
---|
4253 | | - rc = build_qfs_info_req(&iov, tcon, FS_FULL_SIZE_INFORMATION, |
---|
| 5173 | + rc = build_qfs_info_req(&iov, tcon, server, |
---|
| 5174 | + FS_FULL_SIZE_INFORMATION, |
---|
4254 | 5175 | sizeof(struct smb2_fs_full_size_info), |
---|
4255 | 5176 | persistent_fid, volatile_fid); |
---|
4256 | 5177 | if (rc) |
---|
.. | .. |
---|
4263 | 5184 | rqst.rq_iov = &iov; |
---|
4264 | 5185 | rqst.rq_nvec = 1; |
---|
4265 | 5186 | |
---|
4266 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
---|
| 5187 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 5188 | + &rqst, &resp_buftype, flags, &rsp_iov); |
---|
4267 | 5189 | cifs_small_buf_release(iov.iov_base); |
---|
4268 | 5190 | if (rc) { |
---|
4269 | 5191 | cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); |
---|
.. | .. |
---|
4295 | 5217 | int rc = 0; |
---|
4296 | 5218 | int resp_buftype, max_len, min_len; |
---|
4297 | 5219 | struct cifs_ses *ses = tcon->ses; |
---|
| 5220 | + struct TCP_Server_Info *server = cifs_pick_channel(ses); |
---|
4298 | 5221 | unsigned int rsp_len, offset; |
---|
4299 | 5222 | int flags = 0; |
---|
4300 | 5223 | |
---|
.. | .. |
---|
4315 | 5238 | return -EINVAL; |
---|
4316 | 5239 | } |
---|
4317 | 5240 | |
---|
4318 | | - rc = build_qfs_info_req(&iov, tcon, level, max_len, |
---|
| 5241 | + rc = build_qfs_info_req(&iov, tcon, server, |
---|
| 5242 | + level, max_len, |
---|
4319 | 5243 | persistent_fid, volatile_fid); |
---|
4320 | 5244 | if (rc) |
---|
4321 | 5245 | return rc; |
---|
.. | .. |
---|
4327 | 5251 | rqst.rq_iov = &iov; |
---|
4328 | 5252 | rqst.rq_nvec = 1; |
---|
4329 | 5253 | |
---|
4330 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
---|
| 5254 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 5255 | + &rqst, &resp_buftype, flags, &rsp_iov); |
---|
4331 | 5256 | cifs_small_buf_release(iov.iov_base); |
---|
4332 | 5257 | if (rc) { |
---|
4333 | 5258 | cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); |
---|
.. | .. |
---|
4378 | 5303 | struct kvec rsp_iov; |
---|
4379 | 5304 | int resp_buf_type; |
---|
4380 | 5305 | unsigned int count; |
---|
4381 | | - int flags = CIFS_NO_RESP; |
---|
| 5306 | + int flags = CIFS_NO_RSP_BUF; |
---|
4382 | 5307 | unsigned int total_len; |
---|
| 5308 | + struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses); |
---|
4383 | 5309 | |
---|
4384 | 5310 | cifs_dbg(FYI, "smb2_lockv num lock %d\n", num_lock); |
---|
4385 | 5311 | |
---|
4386 | | - rc = smb2_plain_req_init(SMB2_LOCK, tcon, (void **) &req, &total_len); |
---|
| 5312 | + rc = smb2_plain_req_init(SMB2_LOCK, tcon, server, |
---|
| 5313 | + (void **) &req, &total_len); |
---|
4387 | 5314 | if (rc) |
---|
4388 | 5315 | return rc; |
---|
4389 | 5316 | |
---|
.. | .. |
---|
4409 | 5336 | rqst.rq_iov = iov; |
---|
4410 | 5337 | rqst.rq_nvec = 2; |
---|
4411 | 5338 | |
---|
4412 | | - rc = cifs_send_recv(xid, tcon->ses, &rqst, &resp_buf_type, flags, |
---|
| 5339 | + rc = cifs_send_recv(xid, tcon->ses, server, |
---|
| 5340 | + &rqst, &resp_buf_type, flags, |
---|
4413 | 5341 | &rsp_iov); |
---|
4414 | 5342 | cifs_small_buf_release(req); |
---|
4415 | 5343 | if (rc) { |
---|
.. | .. |
---|
4452 | 5380 | struct kvec iov[1]; |
---|
4453 | 5381 | struct kvec rsp_iov; |
---|
4454 | 5382 | int resp_buf_type; |
---|
| 5383 | + __u64 *please_key_high; |
---|
| 5384 | + __u64 *please_key_low; |
---|
| 5385 | + struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses); |
---|
4455 | 5386 | |
---|
4456 | 5387 | cifs_dbg(FYI, "SMB2_lease_break\n"); |
---|
4457 | | - rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req, |
---|
4458 | | - &total_len); |
---|
| 5388 | + rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server, |
---|
| 5389 | + (void **) &req, &total_len); |
---|
4459 | 5390 | if (rc) |
---|
4460 | 5391 | return rc; |
---|
4461 | 5392 | |
---|
.. | .. |
---|
4469 | 5400 | memcpy(req->LeaseKey, lease_key, 16); |
---|
4470 | 5401 | req->LeaseState = lease_state; |
---|
4471 | 5402 | |
---|
4472 | | - flags |= CIFS_NO_RESP; |
---|
| 5403 | + flags |= CIFS_NO_RSP_BUF; |
---|
4473 | 5404 | |
---|
4474 | 5405 | iov[0].iov_base = (char *)req; |
---|
4475 | 5406 | iov[0].iov_len = total_len; |
---|
.. | .. |
---|
4478 | 5409 | rqst.rq_iov = iov; |
---|
4479 | 5410 | rqst.rq_nvec = 1; |
---|
4480 | 5411 | |
---|
4481 | | - rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov); |
---|
| 5412 | + rc = cifs_send_recv(xid, ses, server, |
---|
| 5413 | + &rqst, &resp_buf_type, flags, &rsp_iov); |
---|
4482 | 5414 | cifs_small_buf_release(req); |
---|
4483 | 5415 | |
---|
| 5416 | + please_key_low = (__u64 *)lease_key; |
---|
| 5417 | + please_key_high = (__u64 *)(lease_key+8); |
---|
4484 | 5418 | if (rc) { |
---|
4485 | 5419 | cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE); |
---|
| 5420 | + trace_smb3_lease_err(le32_to_cpu(lease_state), tcon->tid, |
---|
| 5421 | + ses->Suid, *please_key_low, *please_key_high, rc); |
---|
4486 | 5422 | cifs_dbg(FYI, "Send error in Lease Break = %d\n", rc); |
---|
4487 | | - } |
---|
| 5423 | + } else |
---|
| 5424 | + trace_smb3_lease_done(le32_to_cpu(lease_state), tcon->tid, |
---|
| 5425 | + ses->Suid, *please_key_low, *please_key_high); |
---|
4488 | 5426 | |
---|
4489 | 5427 | return rc; |
---|
4490 | 5428 | } |
---|