aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/transport.c
diff options
context:
space:
mode:
authorPavel Shilovsky <piastry@etersoft.ru>2012-03-23 14:28:02 -0400
committerJeff Layton <jlayton@redhat.com>2012-03-23 14:28:02 -0400
commit792af7b05b8a78def080ec757a4d4420b9fd0cc2 (patch)
tree6f6d556f155194295375f3d4ad6cbfabbd7aeeeb /fs/cifs/transport.c
parent934e18b5cb4531cc6e81865bf54115cfd21d1ac6 (diff)
CIFS: Separate protocol-specific code from transport routines
that lets us use this functions for SMB2. Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru>
Diffstat (limited to 'fs/cifs/transport.c')
-rw-r--r--fs/cifs/transport.c171
1 files changed, 99 insertions, 72 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 310918b6fcb4..3bb447d07a1d 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -126,11 +126,11 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
126 int rc = 0; 126 int rc = 0;
127 int i = 0; 127 int i = 0;
128 struct msghdr smb_msg; 128 struct msghdr smb_msg;
129 struct smb_hdr *smb_buffer = iov[0].iov_base; 129 __be32 *buf_len = (__be32 *)(iov[0].iov_base);
130 unsigned int len = iov[0].iov_len; 130 unsigned int len = iov[0].iov_len;
131 unsigned int total_len; 131 unsigned int total_len;
132 int first_vec = 0; 132 int first_vec = 0;
133 unsigned int smb_buf_length = be32_to_cpu(smb_buffer->smb_buf_length); 133 unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
134 struct socket *ssocket = server->ssocket; 134 struct socket *ssocket = server->ssocket;
135 135
136 if (ssocket == NULL) 136 if (ssocket == NULL)
@@ -150,7 +150,7 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
150 total_len += iov[i].iov_len; 150 total_len += iov[i].iov_len;
151 151
152 cFYI(1, "Sending smb: total_len %d", total_len); 152 cFYI(1, "Sending smb: total_len %d", total_len);
153 dump_smb(smb_buffer, len); 153 dump_smb(iov[0].iov_base, len);
154 154
155 i = 0; 155 i = 0;
156 while (total_len) { 156 while (total_len) {
@@ -158,24 +158,24 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
158 n_vec - first_vec, total_len); 158 n_vec - first_vec, total_len);
159 if ((rc == -ENOSPC) || (rc == -EAGAIN)) { 159 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
160 i++; 160 i++;
161 /* if blocking send we try 3 times, since each can block 161 /*
162 for 5 seconds. For nonblocking we have to try more 162 * If blocking send we try 3 times, since each can block
163 but wait increasing amounts of time allowing time for 163 * for 5 seconds. For nonblocking we have to try more
164 socket to clear. The overall time we wait in either 164 * but wait increasing amounts of time allowing time for
165 case to send on the socket is about 15 seconds. 165 * socket to clear. The overall time we wait in either
166 Similarly we wait for 15 seconds for 166 * case to send on the socket is about 15 seconds.
167 a response from the server in SendReceive[2] 167 * Similarly we wait for 15 seconds for a response from
168 for the server to send a response back for 168 * the server in SendReceive[2] for the server to send
169 most types of requests (except SMB Write 169 * a response back for most types of requests (except
170 past end of file which can be slow, and 170 * SMB Write past end of file which can be slow, and
171 blocking lock operations). NFS waits slightly longer 171 * blocking lock operations). NFS waits slightly longer
172 than CIFS, but this can make it take longer for 172 * than CIFS, but this can make it take longer for
173 nonresponsive servers to be detected and 15 seconds 173 * nonresponsive servers to be detected and 15 seconds
174 is more than enough time for modern networks to 174 * is more than enough time for modern networks to
175 send a packet. In most cases if we fail to send 175 * send a packet. In most cases if we fail to send
176 after the retries we will kill the socket and 176 * after the retries we will kill the socket and
177 reconnect which may clear the network problem. 177 * reconnect which may clear the network problem.
178 */ 178 */
179 if ((i >= 14) || (!server->noblocksnd && (i > 2))) { 179 if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
180 cERROR(1, "sends on sock %p stuck for 15 seconds", 180 cERROR(1, "sends on sock %p stuck for 15 seconds",
181 ssocket); 181 ssocket);
@@ -235,9 +235,8 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
235 else 235 else
236 rc = 0; 236 rc = 0;
237 237
238 /* Don't want to modify the buffer as a 238 /* Don't want to modify the buffer as a side effect of this call. */
239 side effect of this call. */ 239 *buf_len = cpu_to_be32(smb_buf_length);
240 smb_buffer->smb_buf_length = cpu_to_be32(smb_buf_length);
241 240
242 return rc; 241 return rc;
243} 242}
@@ -349,6 +348,33 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
349 return 0; 348 return 0;
350} 349}
351 350
351static int
352cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
353 unsigned int nvec, struct mid_q_entry **ret_mid)
354{
355 int rc;
356 struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base;
357 struct mid_q_entry *mid;
358
359 /* enable signing if server requires it */
360 if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
361 hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
362
363 mid = AllocMidQEntry(hdr, server);
364 if (mid == NULL)
365 return -ENOMEM;
366
367 /* put it on the pending_mid_q */
368 spin_lock(&GlobalMid_Lock);
369 list_add_tail(&mid->qhead, &server->pending_mid_q);
370 spin_unlock(&GlobalMid_Lock);
371
372 rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number);
373 if (rc)
374 delete_mid(mid);
375 *ret_mid = mid;
376 return rc;
377}
352 378
353/* 379/*
354 * Send a SMB request and set the callback function in the mid to handle 380 * Send a SMB request and set the callback function in the mid to handle
@@ -361,34 +387,18 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
361{ 387{
362 int rc; 388 int rc;
363 struct mid_q_entry *mid; 389 struct mid_q_entry *mid;
364 struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base;
365 390
366 rc = wait_for_free_request(server, ignore_pend ? CIFS_ASYNC_OP : 0); 391 rc = wait_for_free_request(server, ignore_pend ? CIFS_ASYNC_OP : 0);
367 if (rc) 392 if (rc)
368 return rc; 393 return rc;
369 394
370 /* enable signing if server requires it */
371 if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
372 hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
373
374 mutex_lock(&server->srv_mutex); 395 mutex_lock(&server->srv_mutex);
375 mid = AllocMidQEntry(hdr, server); 396 rc = cifs_setup_async_request(server, iov, nvec, &mid);
376 if (mid == NULL) { 397 if (rc) {
377 mutex_unlock(&server->srv_mutex); 398 mutex_unlock(&server->srv_mutex);
378 cifs_add_credits(server, 1); 399 cifs_add_credits(server, 1);
379 wake_up(&server->request_q); 400 wake_up(&server->request_q);
380 return -ENOMEM; 401 return rc;
381 }
382
383 /* put it on the pending_mid_q */
384 spin_lock(&GlobalMid_Lock);
385 list_add_tail(&mid->qhead, &server->pending_mid_q);
386 spin_unlock(&GlobalMid_Lock);
387
388 rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number);
389 if (rc) {
390 mutex_unlock(&server->srv_mutex);
391 goto out_err;
392 } 402 }
393 403
394 mid->receive = receive; 404 mid->receive = receive;
@@ -424,14 +434,14 @@ out_err:
424 */ 434 */
425int 435int
426SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, 436SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
427 struct smb_hdr *in_buf, int flags) 437 char *in_buf, int flags)
428{ 438{
429 int rc; 439 int rc;
430 struct kvec iov[1]; 440 struct kvec iov[1];
431 int resp_buf_type; 441 int resp_buf_type;
432 442
433 iov[0].iov_base = (char *)in_buf; 443 iov[0].iov_base = in_buf;
434 iov[0].iov_len = be32_to_cpu(in_buf->smb_buf_length) + 4; 444 iov[0].iov_len = get_rfc1002_length(in_buf) + 4;
435 flags |= CIFS_NO_RESP; 445 flags |= CIFS_NO_RESP;
436 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); 446 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
437 cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc); 447 cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
@@ -514,7 +524,7 @@ int
514cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, 524cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
515 bool log_error) 525 bool log_error)
516{ 526{
517 unsigned int len = be32_to_cpu(mid->resp_buf->smb_buf_length) + 4; 527 unsigned int len = get_rfc1002_length(mid->resp_buf) + 4;
518 528
519 dump_smb(mid->resp_buf, min_t(u32, 92, len)); 529 dump_smb(mid->resp_buf, min_t(u32, 92, len));
520 530
@@ -534,6 +544,24 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
534 return map_smb_to_linux_error(mid->resp_buf, log_error); 544 return map_smb_to_linux_error(mid->resp_buf, log_error);
535} 545}
536 546
547static int
548cifs_setup_request(struct cifs_ses *ses, struct kvec *iov,
549 unsigned int nvec, struct mid_q_entry **ret_mid)
550{
551 int rc;
552 struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base;
553 struct mid_q_entry *mid;
554
555 rc = allocate_mid(ses, hdr, &mid);
556 if (rc)
557 return rc;
558 rc = cifs_sign_smb2(iov, nvec, ses->server, &mid->sequence_number);
559 if (rc)
560 delete_mid(mid);
561 *ret_mid = mid;
562 return rc;
563}
564
537int 565int
538SendReceive2(const unsigned int xid, struct cifs_ses *ses, 566SendReceive2(const unsigned int xid, struct cifs_ses *ses,
539 struct kvec *iov, int n_vec, int *pRespBufType /* ret */, 567 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
@@ -542,53 +570,51 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
542 int rc = 0; 570 int rc = 0;
543 int long_op; 571 int long_op;
544 struct mid_q_entry *midQ; 572 struct mid_q_entry *midQ;
545 struct smb_hdr *in_buf = iov[0].iov_base; 573 char *buf = iov[0].iov_base;
546 574
547 long_op = flags & CIFS_TIMEOUT_MASK; 575 long_op = flags & CIFS_TIMEOUT_MASK;
548 576
549 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ 577 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
550 578
551 if ((ses == NULL) || (ses->server == NULL)) { 579 if ((ses == NULL) || (ses->server == NULL)) {
552 cifs_small_buf_release(in_buf); 580 cifs_small_buf_release(buf);
553 cERROR(1, "Null session"); 581 cERROR(1, "Null session");
554 return -EIO; 582 return -EIO;
555 } 583 }
556 584
557 if (ses->server->tcpStatus == CifsExiting) { 585 if (ses->server->tcpStatus == CifsExiting) {
558 cifs_small_buf_release(in_buf); 586 cifs_small_buf_release(buf);
559 return -ENOENT; 587 return -ENOENT;
560 } 588 }
561 589
562 /* Ensure that we do not send more than 50 overlapping requests 590 /*
563 to the same server. We may make this configurable later or 591 * Ensure that we do not send more than 50 overlapping requests
564 use ses->maxReq */ 592 * to the same server. We may make this configurable later or
593 * use ses->maxReq.
594 */
565 595
566 rc = wait_for_free_request(ses->server, long_op); 596 rc = wait_for_free_request(ses->server, long_op);
567 if (rc) { 597 if (rc) {
568 cifs_small_buf_release(in_buf); 598 cifs_small_buf_release(buf);
569 return rc; 599 return rc;
570 } 600 }
571 601
572 /* make sure that we sign in the same order that we send on this socket 602 /*
573 and avoid races inside tcp sendmsg code that could cause corruption 603 * Make sure that we sign in the same order that we send on this socket
574 of smb data */ 604 * and avoid races inside tcp sendmsg code that could cause corruption
605 * of smb data.
606 */
575 607
576 mutex_lock(&ses->server->srv_mutex); 608 mutex_lock(&ses->server->srv_mutex);
577 609
578 rc = allocate_mid(ses, in_buf, &midQ); 610 rc = cifs_setup_request(ses, iov, n_vec, &midQ);
579 if (rc) { 611 if (rc) {
580 mutex_unlock(&ses->server->srv_mutex); 612 mutex_unlock(&ses->server->srv_mutex);
581 cifs_small_buf_release(in_buf); 613 cifs_small_buf_release(buf);
582 /* Update # of requests on wire to server */ 614 /* Update # of requests on wire to server */
583 cifs_add_credits(ses->server, 1); 615 cifs_add_credits(ses->server, 1);
584 return rc; 616 return rc;
585 } 617 }
586 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
587 if (rc) {
588 mutex_unlock(&ses->server->srv_mutex);
589 cifs_small_buf_release(in_buf);
590 goto out;
591 }
592 618
593 midQ->midState = MID_REQUEST_SUBMITTED; 619 midQ->midState = MID_REQUEST_SUBMITTED;
594 cifs_in_send_inc(ses->server); 620 cifs_in_send_inc(ses->server);
@@ -599,30 +625,30 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
599 mutex_unlock(&ses->server->srv_mutex); 625 mutex_unlock(&ses->server->srv_mutex);
600 626
601 if (rc < 0) { 627 if (rc < 0) {
602 cifs_small_buf_release(in_buf); 628 cifs_small_buf_release(buf);
603 goto out; 629 goto out;
604 } 630 }
605 631
606 if (long_op == CIFS_ASYNC_OP) { 632 if (long_op == CIFS_ASYNC_OP) {
607 cifs_small_buf_release(in_buf); 633 cifs_small_buf_release(buf);
608 goto out; 634 goto out;
609 } 635 }
610 636
611 rc = wait_for_response(ses->server, midQ); 637 rc = wait_for_response(ses->server, midQ);
612 if (rc != 0) { 638 if (rc != 0) {
613 send_nt_cancel(ses->server, in_buf, midQ); 639 send_nt_cancel(ses->server, (struct smb_hdr *)buf, midQ);
614 spin_lock(&GlobalMid_Lock); 640 spin_lock(&GlobalMid_Lock);
615 if (midQ->midState == MID_REQUEST_SUBMITTED) { 641 if (midQ->midState == MID_REQUEST_SUBMITTED) {
616 midQ->callback = DeleteMidQEntry; 642 midQ->callback = DeleteMidQEntry;
617 spin_unlock(&GlobalMid_Lock); 643 spin_unlock(&GlobalMid_Lock);
618 cifs_small_buf_release(in_buf); 644 cifs_small_buf_release(buf);
619 cifs_add_credits(ses->server, 1); 645 cifs_add_credits(ses->server, 1);
620 return rc; 646 return rc;
621 } 647 }
622 spin_unlock(&GlobalMid_Lock); 648 spin_unlock(&GlobalMid_Lock);
623 } 649 }
624 650
625 cifs_small_buf_release(in_buf); 651 cifs_small_buf_release(buf);
626 652
627 rc = cifs_sync_mid_result(midQ, ses->server); 653 rc = cifs_sync_mid_result(midQ, ses->server);
628 if (rc != 0) { 654 if (rc != 0) {
@@ -636,8 +662,9 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
636 goto out; 662 goto out;
637 } 663 }
638 664
639 iov[0].iov_base = (char *)midQ->resp_buf; 665 buf = (char *)midQ->resp_buf;
640 iov[0].iov_len = be32_to_cpu(midQ->resp_buf->smb_buf_length) + 4; 666 iov[0].iov_base = buf;
667 iov[0].iov_len = get_rfc1002_length(buf) + 4;
641 if (midQ->largeBuf) 668 if (midQ->largeBuf)
642 *pRespBufType = CIFS_LARGE_BUFFER; 669 *pRespBufType = CIFS_LARGE_BUFFER;
643 else 670 else