~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to fs/cifs/transport.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
129
129
        unsigned int len = iov[0].iov_len;
130
130
        unsigned int total_len;
131
131
        int first_vec = 0;
132
 
        unsigned int smb_buf_length = smb_buffer->smb_buf_length;
 
132
        unsigned int smb_buf_length = be32_to_cpu(smb_buffer->smb_buf_length);
133
133
        struct socket *ssocket = server->ssocket;
134
134
 
135
135
        if (ssocket == NULL)
144
144
        else
145
145
                smb_msg.msg_flags = MSG_NOSIGNAL;
146
146
 
147
 
        /* smb header is converted in header_assemble. bcc and rest of SMB word
148
 
           area, and byte area if necessary, is converted to littleendian in
149
 
           cifssmb.c and RFC1001 len is converted to bigendian in smb_send
150
 
           Flags2 is converted in SendReceive */
151
 
 
152
 
 
153
147
        total_len = 0;
154
148
        for (i = 0; i < n_vec; i++)
155
149
                total_len += iov[i].iov_len;
156
150
 
157
 
        smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
158
151
        cFYI(1, "Sending smb:  total_len %d", total_len);
159
152
        dump_smb(smb_buffer, len);
160
153
 
243
236
 
244
237
        /* Don't want to modify the buffer as a
245
238
           side effect of this call. */
246
 
        smb_buffer->smb_buf_length = smb_buf_length;
 
239
        smb_buffer->smb_buf_length = cpu_to_be32(smb_buf_length);
247
240
 
248
241
        return rc;
249
242
}
302
295
        return 0;
303
296
}
304
297
 
305
 
static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
 
298
static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
306
299
                        struct mid_q_entry **ppmidQ)
307
300
{
308
301
        if (ses->server->tcpStatus == CifsExiting) {
349
342
 * the result. Caller is responsible for dealing with timeouts.
350
343
 */
351
344
int
352
 
cifs_call_async(struct TCP_Server_Info *server, struct smb_hdr *in_buf,
353
 
                mid_callback_t *callback, void *cbdata)
 
345
cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
 
346
                unsigned int nvec, mid_callback_t *callback, void *cbdata,
 
347
                bool ignore_pend)
354
348
{
355
349
        int rc;
356
350
        struct mid_q_entry *mid;
 
351
        struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base;
357
352
 
358
 
        rc = wait_for_free_request(server, CIFS_ASYNC_OP);
 
353
        rc = wait_for_free_request(server, ignore_pend ? CIFS_ASYNC_OP : 0);
359
354
        if (rc)
360
355
                return rc;
361
356
 
362
357
        /* enable signing if server requires it */
363
 
        if (server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
364
 
                in_buf->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
358
        if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 
359
                hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
365
360
 
366
361
        mutex_lock(&server->srv_mutex);
367
 
        mid = AllocMidQEntry(in_buf, server);
 
362
        mid = AllocMidQEntry(hdr, server);
368
363
        if (mid == NULL) {
369
364
                mutex_unlock(&server->srv_mutex);
370
365
                return -ENOMEM;
375
370
        list_add_tail(&mid->qhead, &server->pending_mid_q);
376
371
        spin_unlock(&GlobalMid_Lock);
377
372
 
378
 
        rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
 
373
        rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number);
379
374
        if (rc) {
380
375
                mutex_unlock(&server->srv_mutex);
381
376
                goto out_err;
387
382
#ifdef CONFIG_CIFS_STATS2
388
383
        atomic_inc(&server->inSend);
389
384
#endif
390
 
        rc = smb_send(server, in_buf, in_buf->smb_buf_length);
 
385
        rc = smb_sendv(server, iov, nvec);
391
386
#ifdef CONFIG_CIFS_STATS2
392
387
        atomic_dec(&server->inSend);
393
388
        mid->when_sent = jiffies;
414
409
 *
415
410
 */
416
411
int
417
 
SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
 
412
SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
418
413
                struct smb_hdr *in_buf, int flags)
419
414
{
420
415
        int rc;
422
417
        int resp_buf_type;
423
418
 
424
419
        iov[0].iov_base = (char *)in_buf;
425
 
        iov[0].iov_len = in_buf->smb_buf_length + 4;
 
420
        iov[0].iov_len = be32_to_cpu(in_buf->smb_buf_length) + 4;
426
421
        flags |= CIFS_NO_RESP;
427
422
        rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
428
423
        cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
431
426
}
432
427
 
433
428
static int
434
 
sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
 
429
cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
435
430
{
436
431
        int rc = 0;
437
432
 
439
434
                mid->mid, mid->midState);
440
435
 
441
436
        spin_lock(&GlobalMid_Lock);
442
 
        /* ensure that it's no longer on the pending_mid_q */
443
 
        list_del_init(&mid->qhead);
444
 
 
445
437
        switch (mid->midState) {
446
438
        case MID_RESPONSE_RECEIVED:
447
439
                spin_unlock(&GlobalMid_Lock);
448
440
                return rc;
449
 
        case MID_REQUEST_SUBMITTED:
450
 
                /* socket is going down, reject all calls */
451
 
                if (server->tcpStatus == CifsExiting) {
452
 
                        cERROR(1, "%s: canceling mid=%d cmd=0x%x state=%d",
453
 
                               __func__, mid->mid, mid->command, mid->midState);
454
 
                        rc = -EHOSTDOWN;
455
 
                        break;
456
 
                }
457
441
        case MID_RETRY_NEEDED:
458
442
                rc = -EAGAIN;
459
443
                break;
460
444
        case MID_RESPONSE_MALFORMED:
461
445
                rc = -EIO;
462
446
                break;
 
447
        case MID_SHUTDOWN:
 
448
                rc = -EHOSTDOWN;
 
449
                break;
463
450
        default:
 
451
                list_del_init(&mid->qhead);
464
452
                cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
465
453
                        mid->mid, mid->midState);
466
454
                rc = -EIO;
488
476
        int rc = 0;
489
477
 
490
478
        /* -4 for RFC1001 length and +2 for BCC field */
491
 
        in_buf->smb_buf_length = sizeof(struct smb_hdr) - 4  + 2;
 
479
        in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4  + 2);
492
480
        in_buf->Command = SMB_COM_NT_CANCEL;
493
481
        in_buf->WordCount = 0;
494
 
        put_bcc_le(0, in_buf);
 
482
        put_bcc(0, in_buf);
495
483
 
496
484
        mutex_lock(&server->srv_mutex);
497
485
        rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
499
487
                mutex_unlock(&server->srv_mutex);
500
488
                return rc;
501
489
        }
502
 
        rc = smb_send(server, in_buf, in_buf->smb_buf_length);
 
490
        rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
503
491
        mutex_unlock(&server->srv_mutex);
504
492
 
505
493
        cFYI(1, "issued NT_CANCEL for mid %u, rc = %d",
509
497
}
510
498
 
511
499
int
512
 
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
 
500
cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
 
501
                   bool log_error)
 
502
{
 
503
        dump_smb(mid->resp_buf,
 
504
                 min_t(u32, 92, be32_to_cpu(mid->resp_buf->smb_buf_length)));
 
505
 
 
506
        /* convert the length into a more usable form */
 
507
        if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
 
508
                /* FIXME: add code to kill session */
 
509
                if (cifs_verify_signature(mid->resp_buf, server,
 
510
                                          mid->sequence_number + 1) != 0)
 
511
                        cERROR(1, "Unexpected SMB signature");
 
512
        }
 
513
 
 
514
        /* BB special case reconnect tid and uid here? */
 
515
        return map_smb_to_linux_error(mid->resp_buf, log_error);
 
516
}
 
517
 
 
518
int
 
519
SendReceive2(const unsigned int xid, struct cifs_ses *ses,
513
520
             struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
514
521
             const int flags)
515
522
{
516
523
        int rc = 0;
517
524
        int long_op;
518
 
        unsigned int receive_len;
519
525
        struct mid_q_entry *midQ;
520
526
        struct smb_hdr *in_buf = iov[0].iov_base;
521
527
 
605
611
 
606
612
        cifs_small_buf_release(in_buf);
607
613
 
608
 
        rc = sync_mid_result(midQ, ses->server);
 
614
        rc = cifs_sync_mid_result(midQ, ses->server);
609
615
        if (rc != 0) {
610
616
                atomic_dec(&ses->server->inFlight);
611
617
                wake_up(&ses->server->request_q);
612
618
                return rc;
613
619
        }
614
620
 
615
 
        receive_len = midQ->resp_buf->smb_buf_length;
616
 
 
617
 
        if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
618
 
                cERROR(1, "Frame too large received.  Length: %d  Xid: %d",
619
 
                        receive_len, xid);
620
 
                rc = -EIO;
621
 
                goto out;
622
 
        }
623
 
 
624
 
        /* rcvd frame is ok */
625
 
 
626
 
        if (midQ->resp_buf &&
627
 
            (midQ->midState == MID_RESPONSE_RECEIVED)) {
628
 
 
629
 
                iov[0].iov_base = (char *)midQ->resp_buf;
630
 
                if (midQ->largeBuf)
631
 
                        *pRespBufType = CIFS_LARGE_BUFFER;
632
 
                else
633
 
                        *pRespBufType = CIFS_SMALL_BUFFER;
634
 
                iov[0].iov_len = receive_len + 4;
635
 
 
636
 
                dump_smb(midQ->resp_buf, 80);
637
 
                /* convert the length into a more usable form */
638
 
                if ((receive_len > 24) &&
639
 
                    (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
640
 
                                             SECMODE_SIGN_ENABLED))) {
641
 
                        rc = cifs_verify_signature(midQ->resp_buf,
642
 
                                                ses->server,
643
 
                                                midQ->sequence_number+1);
644
 
                        if (rc) {
645
 
                                cERROR(1, "Unexpected SMB signature");
646
 
                                /* BB FIXME add code to kill session */
647
 
                        }
648
 
                }
649
 
 
650
 
                /* BB special case reconnect tid and uid here? */
651
 
                rc = map_smb_to_linux_error(midQ->resp_buf,
652
 
                                            flags & CIFS_LOG_ERROR);
653
 
 
654
 
                /* convert ByteCount if necessary */
655
 
                if (receive_len >= sizeof(struct smb_hdr) - 4
656
 
                    /* do not count RFC1001 header */  +
657
 
                    (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
658
 
                        put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf);
659
 
                if ((flags & CIFS_NO_RESP) == 0)
660
 
                        midQ->resp_buf = NULL;  /* mark it so buf will
661
 
                                                   not be freed by
662
 
                                                   delete_mid */
663
 
        } else {
 
621
        if (!midQ->resp_buf || midQ->midState != MID_RESPONSE_RECEIVED) {
664
622
                rc = -EIO;
665
623
                cFYI(1, "Bad MID state?");
 
624
                goto out;
666
625
        }
667
626
 
 
627
        iov[0].iov_base = (char *)midQ->resp_buf;
 
628
        iov[0].iov_len = be32_to_cpu(midQ->resp_buf->smb_buf_length) + 4;
 
629
        if (midQ->largeBuf)
 
630
                *pRespBufType = CIFS_LARGE_BUFFER;
 
631
        else
 
632
                *pRespBufType = CIFS_SMALL_BUFFER;
 
633
 
 
634
        rc = cifs_check_receive(midQ, ses->server, flags & CIFS_LOG_ERROR);
 
635
 
 
636
        /* mark it so buf will not be freed by delete_mid */
 
637
        if ((flags & CIFS_NO_RESP) == 0)
 
638
                midQ->resp_buf = NULL;
668
639
out:
669
640
        delete_mid(midQ);
670
641
        atomic_dec(&ses->server->inFlight);
674
645
}
675
646
 
676
647
int
677
 
SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
 
648
SendReceive(const unsigned int xid, struct cifs_ses *ses,
678
649
            struct smb_hdr *in_buf, struct smb_hdr *out_buf,
679
650
            int *pbytes_returned, const int long_op)
680
651
{
681
652
        int rc = 0;
682
 
        unsigned int receive_len;
683
653
        struct mid_q_entry *midQ;
684
654
 
685
655
        if (ses == NULL) {
698
668
           to the same server. We may make this configurable later or
699
669
           use ses->maxReq */
700
670
 
701
 
        if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
 
671
        if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
 
672
                        MAX_CIFS_HDR_SIZE - 4) {
702
673
                cERROR(1, "Illegal length, greater than maximum frame, %d",
703
 
                           in_buf->smb_buf_length);
 
674
                           be32_to_cpu(in_buf->smb_buf_length));
704
675
                return -EIO;
705
676
        }
706
677
 
733
704
#ifdef CONFIG_CIFS_STATS2
734
705
        atomic_inc(&ses->server->inSend);
735
706
#endif
736
 
        rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
 
707
        rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
737
708
#ifdef CONFIG_CIFS_STATS2
738
709
        atomic_dec(&ses->server->inSend);
739
710
        midQ->when_sent = jiffies;
761
732
                spin_unlock(&GlobalMid_Lock);
762
733
        }
763
734
 
764
 
        rc = sync_mid_result(midQ, ses->server);
 
735
        rc = cifs_sync_mid_result(midQ, ses->server);
765
736
        if (rc != 0) {
766
737
                atomic_dec(&ses->server->inFlight);
767
738
                wake_up(&ses->server->request_q);
768
739
                return rc;
769
740
        }
770
741
 
771
 
        receive_len = midQ->resp_buf->smb_buf_length;
772
 
 
773
 
        if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
774
 
                cERROR(1, "Frame too large received.  Length: %d  Xid: %d",
775
 
                        receive_len, xid);
 
742
        if (!midQ->resp_buf || !out_buf ||
 
743
            midQ->midState != MID_RESPONSE_RECEIVED) {
776
744
                rc = -EIO;
 
745
                cERROR(1, "Bad MID state?");
777
746
                goto out;
778
747
        }
779
748
 
780
 
        /* rcvd frame is ok */
781
 
 
782
 
        if (midQ->resp_buf && out_buf
783
 
            && (midQ->midState == MID_RESPONSE_RECEIVED)) {
784
 
                out_buf->smb_buf_length = receive_len;
785
 
                memcpy((char *)out_buf + 4,
786
 
                       (char *)midQ->resp_buf + 4,
787
 
                       receive_len);
788
 
 
789
 
                dump_smb(out_buf, 92);
790
 
                /* convert the length into a more usable form */
791
 
                if ((receive_len > 24) &&
792
 
                    (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
793
 
                                             SECMODE_SIGN_ENABLED))) {
794
 
                        rc = cifs_verify_signature(out_buf,
795
 
                                                ses->server,
796
 
                                                midQ->sequence_number+1);
797
 
                        if (rc) {
798
 
                                cERROR(1, "Unexpected SMB signature");
799
 
                                /* BB FIXME add code to kill session */
800
 
                        }
801
 
                }
802
 
 
803
 
                *pbytes_returned = out_buf->smb_buf_length;
804
 
 
805
 
                /* BB special case reconnect tid and uid here? */
806
 
                rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
807
 
 
808
 
                /* convert ByteCount if necessary */
809
 
                if (receive_len >= sizeof(struct smb_hdr) - 4
810
 
                    /* do not count RFC1001 header */  +
811
 
                    (2 * out_buf->WordCount) + 2 /* bcc */ )
812
 
                        put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf);
813
 
        } else {
814
 
                rc = -EIO;
815
 
                cERROR(1, "Bad MID state?");
816
 
        }
817
 
 
 
749
        *pbytes_returned = be32_to_cpu(midQ->resp_buf->smb_buf_length);
 
750
        memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
 
751
        rc = cifs_check_receive(midQ, ses->server, 0);
818
752
out:
819
753
        delete_mid(midQ);
820
754
        atomic_dec(&ses->server->inFlight);
827
761
   blocking lock to return. */
828
762
 
829
763
static int
830
 
send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
 
764
send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
831
765
                        struct smb_hdr *in_buf,
832
766
                        struct smb_hdr *out_buf)
833
767
{
834
768
        int bytes_returned;
835
 
        struct cifsSesInfo *ses = tcon->ses;
 
769
        struct cifs_ses *ses = tcon->ses;
836
770
        LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
837
771
 
838
772
        /* We just modify the current in_buf to change
849
783
}
850
784
 
851
785
int
852
 
SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
 
786
SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
853
787
            struct smb_hdr *in_buf, struct smb_hdr *out_buf,
854
788
            int *pbytes_returned)
855
789
{
856
790
        int rc = 0;
857
791
        int rstart = 0;
858
 
        unsigned int receive_len;
859
792
        struct mid_q_entry *midQ;
860
 
        struct cifsSesInfo *ses;
 
793
        struct cifs_ses *ses;
861
794
 
862
795
        if (tcon == NULL || tcon->ses == NULL) {
863
796
                cERROR(1, "Null smb session");
877
810
           to the same server. We may make this configurable later or
878
811
           use ses->maxReq */
879
812
 
880
 
        if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
 
813
        if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
 
814
                        MAX_CIFS_HDR_SIZE - 4) {
881
815
                cERROR(1, "Illegal length, greater than maximum frame, %d",
882
 
                           in_buf->smb_buf_length);
 
816
                           be32_to_cpu(in_buf->smb_buf_length));
883
817
                return -EIO;
884
818
        }
885
819
 
910
844
#ifdef CONFIG_CIFS_STATS2
911
845
        atomic_inc(&ses->server->inSend);
912
846
#endif
913
 
        rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
 
847
        rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
914
848
#ifdef CONFIG_CIFS_STATS2
915
849
        atomic_dec(&ses->server->inSend);
916
850
        midQ->when_sent = jiffies;
973
907
                rstart = 1;
974
908
        }
975
909
 
976
 
        rc = sync_mid_result(midQ, ses->server);
 
910
        rc = cifs_sync_mid_result(midQ, ses->server);
977
911
        if (rc != 0)
978
912
                return rc;
979
913
 
980
 
        receive_len = midQ->resp_buf->smb_buf_length;
981
 
        if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
982
 
                cERROR(1, "Frame too large received.  Length: %d  Xid: %d",
983
 
                        receive_len, xid);
984
 
                rc = -EIO;
985
 
                goto out;
986
 
        }
987
 
 
988
914
        /* rcvd frame is ok */
989
 
 
990
 
        if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
 
915
        if (out_buf == NULL || midQ->midState != MID_RESPONSE_RECEIVED) {
991
916
                rc = -EIO;
992
917
                cERROR(1, "Bad MID state?");
993
918
                goto out;
994
919
        }
995
920
 
996
 
        out_buf->smb_buf_length = receive_len;
997
 
        memcpy((char *)out_buf + 4,
998
 
               (char *)midQ->resp_buf + 4,
999
 
               receive_len);
1000
 
 
1001
 
        dump_smb(out_buf, 92);
1002
 
        /* convert the length into a more usable form */
1003
 
        if ((receive_len > 24) &&
1004
 
            (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1005
 
                                     SECMODE_SIGN_ENABLED))) {
1006
 
                rc = cifs_verify_signature(out_buf,
1007
 
                                           ses->server,
1008
 
                                           midQ->sequence_number+1);
1009
 
                if (rc) {
1010
 
                        cERROR(1, "Unexpected SMB signature");
1011
 
                        /* BB FIXME add code to kill session */
1012
 
                }
1013
 
        }
1014
 
 
1015
 
        *pbytes_returned = out_buf->smb_buf_length;
1016
 
 
1017
 
        /* BB special case reconnect tid and uid here? */
1018
 
        rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1019
 
 
1020
 
        /* convert ByteCount if necessary */
1021
 
        if (receive_len >= sizeof(struct smb_hdr) - 4
1022
 
            /* do not count RFC1001 header */  +
1023
 
            (2 * out_buf->WordCount) + 2 /* bcc */ )
1024
 
                put_bcc(get_bcc_le(out_buf), out_buf);
1025
 
 
 
921
        *pbytes_returned = be32_to_cpu(midQ->resp_buf->smb_buf_length);
 
922
        memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
 
923
        rc = cifs_check_receive(midQ, ses->server, 0);
1026
924
out:
1027
925
        delete_mid(midQ);
1028
926
        if (rstart && rc == -EACCES)