linux/fs/cifs/transport.c
<<
>>
Prefs
   1/*
   2 *   fs/cifs/transport.c
   3 *
   4 *   Copyright (C) International Business Machines  Corp., 2002,2008
   5 *   Author(s): Steve French (sfrench@us.ibm.com)
   6 *   Jeremy Allison (jra@samba.org) 2006.
   7 *
   8 *   This library is free software; you can redistribute it and/or modify
   9 *   it under the terms of the GNU Lesser General Public License as published
  10 *   by the Free Software Foundation; either version 2.1 of the License, or
  11 *   (at your option) any later version.
  12 *
  13 *   This library is distributed in the hope that it will be useful,
  14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  16 *   the GNU Lesser General Public License for more details.
  17 *
  18 *   You should have received a copy of the GNU Lesser General Public License
  19 *   along with this library; if not, write to the Free Software
  20 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21 */
  22
  23#include <linux/fs.h>
  24#include <linux/list.h>
  25#include <linux/gfp.h>
  26#include <linux/wait.h>
  27#include <linux/net.h>
  28#include <linux/delay.h>
  29#include <asm/uaccess.h>
  30#include <asm/processor.h>
  31#include <linux/mempool.h>
  32#include "cifspdu.h"
  33#include "cifsglob.h"
  34#include "cifsproto.h"
  35#include "cifs_debug.h"
  36
  37extern mempool_t *cifs_mid_poolp;
  38
  39static void
  40wake_up_task(struct mid_q_entry *mid)
  41{
  42        wake_up_process(mid->callback_data);
  43}
  44
  45struct mid_q_entry *
  46AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
  47{
  48        struct mid_q_entry *temp;
  49
  50        if (server == NULL) {
  51                cERROR(1, "Null TCP session in AllocMidQEntry");
  52                return NULL;
  53        }
  54
  55        temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
  56        if (temp == NULL)
  57                return temp;
  58        else {
  59                memset(temp, 0, sizeof(struct mid_q_entry));
  60                temp->mid = smb_buffer->Mid;    /* always LE */
  61                temp->pid = current->pid;
  62                temp->command = smb_buffer->Command;
  63                cFYI(1, "For smb_command %d", temp->command);
  64        /*      do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
  65                /* when mid allocated can be before when sent */
  66                temp->when_alloc = jiffies;
  67
  68                /*
  69                 * The default is for the mid to be synchronous, so the
  70                 * default callback just wakes up the current task.
  71                 */
  72                temp->callback = wake_up_task;
  73                temp->callback_data = current;
  74        }
  75
  76        atomic_inc(&midCount);
  77        temp->midState = MID_REQUEST_ALLOCATED;
  78        return temp;
  79}
  80
  81void
  82DeleteMidQEntry(struct mid_q_entry *midEntry)
  83{
  84#ifdef CONFIG_CIFS_STATS2
  85        unsigned long now;
  86#endif
  87        midEntry->midState = MID_FREE;
  88        atomic_dec(&midCount);
  89        if (midEntry->largeBuf)
  90                cifs_buf_release(midEntry->resp_buf);
  91        else
  92                cifs_small_buf_release(midEntry->resp_buf);
  93#ifdef CONFIG_CIFS_STATS2
  94        now = jiffies;
  95        /* commands taking longer than one second are indications that
  96           something is wrong, unless it is quite a slow link or server */
  97        if ((now - midEntry->when_alloc) > HZ) {
  98                if ((cifsFYI & CIFS_TIMER) &&
  99                   (midEntry->command != SMB_COM_LOCKING_ANDX)) {
 100                        printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
 101                               midEntry->command, midEntry->mid);
 102                        printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
 103                               now - midEntry->when_alloc,
 104                               now - midEntry->when_sent,
 105                               now - midEntry->when_received);
 106                }
 107        }
 108#endif
 109        mempool_free(midEntry, cifs_mid_poolp);
 110}
 111
 112static void
 113delete_mid(struct mid_q_entry *mid)
 114{
 115        spin_lock(&GlobalMid_Lock);
 116        list_del(&mid->qhead);
 117        spin_unlock(&GlobalMid_Lock);
 118
 119        DeleteMidQEntry(mid);
 120}
 121
 122static int
 123smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
 124{
 125        int rc = 0;
 126        int i = 0;
 127        struct msghdr smb_msg;
 128        struct smb_hdr *smb_buffer = iov[0].iov_base;
 129        unsigned int len = iov[0].iov_len;
 130        unsigned int total_len;
 131        int first_vec = 0;
 132        unsigned int smb_buf_length = smb_buffer->smb_buf_length;
 133        struct socket *ssocket = server->ssocket;
 134
 135        if (ssocket == NULL)
 136                return -ENOTSOCK; /* BB eventually add reconnect code here */
 137
 138        smb_msg.msg_name = (struct sockaddr *) &server->dstaddr;
 139        smb_msg.msg_namelen = sizeof(struct sockaddr);
 140        smb_msg.msg_control = NULL;
 141        smb_msg.msg_controllen = 0;
 142        if (server->noblocksnd)
 143                smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
 144        else
 145                smb_msg.msg_flags = MSG_NOSIGNAL;
 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        total_len = 0;
 154        for (i = 0; i < n_vec; i++)
 155                total_len += iov[i].iov_len;
 156
 157        smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
 158        cFYI(1, "Sending smb:  total_len %d", total_len);
 159        dump_smb(smb_buffer, len);
 160
 161        i = 0;
 162        while (total_len) {
 163                rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
 164                                    n_vec - first_vec, total_len);
 165                if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
 166                        i++;
 167                        /* if blocking send we try 3 times, since each can block
 168                           for 5 seconds. For nonblocking  we have to try more
 169                           but wait increasing amounts of time allowing time for
 170                           socket to clear.  The overall time we wait in either
 171                           case to send on the socket is about 15 seconds.
 172                           Similarly we wait for 15 seconds for
 173                           a response from the server in SendReceive[2]
 174                           for the server to send a response back for
 175                           most types of requests (except SMB Write
 176                           past end of file which can be slow, and
 177                           blocking lock operations). NFS waits slightly longer
 178                           than CIFS, but this can make it take longer for
 179                           nonresponsive servers to be detected and 15 seconds
 180                           is more than enough time for modern networks to
 181                           send a packet.  In most cases if we fail to send
 182                           after the retries we will kill the socket and
 183                           reconnect which may clear the network problem.
 184                        */
 185                        if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
 186                                cERROR(1, "sends on sock %p stuck for 15 seconds",
 187                                    ssocket);
 188                                rc = -EAGAIN;
 189                                break;
 190                        }
 191                        msleep(1 << i);
 192                        continue;
 193                }
 194                if (rc < 0)
 195                        break;
 196
 197                if (rc == total_len) {
 198                        total_len = 0;
 199                        break;
 200                } else if (rc > total_len) {
 201                        cERROR(1, "sent %d requested %d", rc, total_len);
 202                        break;
 203                }
 204                if (rc == 0) {
 205                        /* should never happen, letting socket clear before
 206                           retrying is our only obvious option here */
 207                        cERROR(1, "tcp sent no data");
 208                        msleep(500);
 209                        continue;
 210                }
 211                total_len -= rc;
 212                /* the line below resets i */
 213                for (i = first_vec; i < n_vec; i++) {
 214                        if (iov[i].iov_len) {
 215                                if (rc > iov[i].iov_len) {
 216                                        rc -= iov[i].iov_len;
 217                                        iov[i].iov_len = 0;
 218                                } else {
 219                                        iov[i].iov_base += rc;
 220                                        iov[i].iov_len -= rc;
 221                                        first_vec = i;
 222                                        break;
 223                                }
 224                        }
 225                }
 226                i = 0; /* in case we get ENOSPC on the next send */
 227        }
 228
 229        if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
 230                cFYI(1, "partial send (%d remaining), terminating session",
 231                        total_len);
 232                /* If we have only sent part of an SMB then the next SMB
 233                   could be taken as the remainder of this one.  We need
 234                   to kill the socket so the server throws away the partial
 235                   SMB */
 236                server->tcpStatus = CifsNeedReconnect;
 237        }
 238
 239        if (rc < 0 && rc != -EINTR)
 240                cERROR(1, "Error %d sending data on socket to server", rc);
 241        else
 242                rc = 0;
 243
 244        /* Don't want to modify the buffer as a
 245           side effect of this call. */
 246        smb_buffer->smb_buf_length = smb_buf_length;
 247
 248        return rc;
 249}
 250
 251int
 252smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
 253         unsigned int smb_buf_length)
 254{
 255        struct kvec iov;
 256
 257        iov.iov_base = smb_buffer;
 258        iov.iov_len = smb_buf_length + 4;
 259
 260        return smb_sendv(server, &iov, 1);
 261}
 262
 263static int wait_for_free_request(struct TCP_Server_Info *server,
 264                                 const int long_op)
 265{
 266        if (long_op == CIFS_ASYNC_OP) {
 267                /* oplock breaks must not be held up */
 268                atomic_inc(&server->inFlight);
 269                return 0;
 270        }
 271
 272        spin_lock(&GlobalMid_Lock);
 273        while (1) {
 274                if (atomic_read(&server->inFlight) >= cifs_max_pending) {
 275                        spin_unlock(&GlobalMid_Lock);
 276#ifdef CONFIG_CIFS_STATS2
 277                        atomic_inc(&server->num_waiters);
 278#endif
 279                        wait_event(server->request_q,
 280                                   atomic_read(&server->inFlight)
 281                                     < cifs_max_pending);
 282#ifdef CONFIG_CIFS_STATS2
 283                        atomic_dec(&server->num_waiters);
 284#endif
 285                        spin_lock(&GlobalMid_Lock);
 286                } else {
 287                        if (server->tcpStatus == CifsExiting) {
 288                                spin_unlock(&GlobalMid_Lock);
 289                                return -ENOENT;
 290                        }
 291
 292                        /* can not count locking commands against total
 293                           as they are allowed to block on server */
 294
 295                        /* update # of requests on the wire to server */
 296                        if (long_op != CIFS_BLOCKING_OP)
 297                                atomic_inc(&server->inFlight);
 298                        spin_unlock(&GlobalMid_Lock);
 299                        break;
 300                }
 301        }
 302        return 0;
 303}
 304
 305static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
 306                        struct mid_q_entry **ppmidQ)
 307{
 308        if (ses->server->tcpStatus == CifsExiting) {
 309                return -ENOENT;
 310        }
 311
 312        if (ses->server->tcpStatus == CifsNeedReconnect) {
 313                cFYI(1, "tcp session dead - return to caller to retry");
 314                return -EAGAIN;
 315        }
 316
 317        if (ses->status != CifsGood) {
 318                /* check if SMB session is bad because we are setting it up */
 319                if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
 320                        (in_buf->Command != SMB_COM_NEGOTIATE))
 321                        return -EAGAIN;
 322                /* else ok - we are setting up session */
 323        }
 324        *ppmidQ = AllocMidQEntry(in_buf, ses->server);
 325        if (*ppmidQ == NULL)
 326                return -ENOMEM;
 327        spin_lock(&GlobalMid_Lock);
 328        list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
 329        spin_unlock(&GlobalMid_Lock);
 330        return 0;
 331}
 332
 333static int
 334wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
 335{
 336        int error;
 337
 338        error = wait_event_killable(server->response_q,
 339                                    midQ->midState != MID_REQUEST_SUBMITTED);
 340        if (error < 0)
 341                return -ERESTARTSYS;
 342
 343        return 0;
 344}
 345
 346
 347/*
 348 * Send a SMB request and set the callback function in the mid to handle
 349 * the result. Caller is responsible for dealing with timeouts.
 350 */
 351int
 352cifs_call_async(struct TCP_Server_Info *server, struct smb_hdr *in_buf,
 353                mid_callback_t *callback, void *cbdata)
 354{
 355        int rc;
 356        struct mid_q_entry *mid;
 357
 358        rc = wait_for_free_request(server, CIFS_ASYNC_OP);
 359        if (rc)
 360                return rc;
 361
 362        /* enable signing if server requires it */
 363        if (server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 364                in_buf->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 365
 366        mutex_lock(&server->srv_mutex);
 367        mid = AllocMidQEntry(in_buf, server);
 368        if (mid == NULL) {
 369                mutex_unlock(&server->srv_mutex);
 370                return -ENOMEM;
 371        }
 372
 373        /* put it on the pending_mid_q */
 374        spin_lock(&GlobalMid_Lock);
 375        list_add_tail(&mid->qhead, &server->pending_mid_q);
 376        spin_unlock(&GlobalMid_Lock);
 377
 378        rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
 379        if (rc) {
 380                mutex_unlock(&server->srv_mutex);
 381                goto out_err;
 382        }
 383
 384        mid->callback = callback;
 385        mid->callback_data = cbdata;
 386        mid->midState = MID_REQUEST_SUBMITTED;
 387#ifdef CONFIG_CIFS_STATS2
 388        atomic_inc(&server->inSend);
 389#endif
 390        rc = smb_send(server, in_buf, in_buf->smb_buf_length);
 391#ifdef CONFIG_CIFS_STATS2
 392        atomic_dec(&server->inSend);
 393        mid->when_sent = jiffies;
 394#endif
 395        mutex_unlock(&server->srv_mutex);
 396        if (rc)
 397                goto out_err;
 398
 399        return rc;
 400out_err:
 401        delete_mid(mid);
 402        atomic_dec(&server->inFlight);
 403        wake_up(&server->request_q);
 404        return rc;
 405}
 406
 407/*
 408 *
 409 * Send an SMB Request.  No response info (other than return code)
 410 * needs to be parsed.
 411 *
 412 * flags indicate the type of request buffer and how long to wait
 413 * and whether to log NT STATUS code (error) before mapping it to POSIX error
 414 *
 415 */
 416int
 417SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
 418                struct smb_hdr *in_buf, int flags)
 419{
 420        int rc;
 421        struct kvec iov[1];
 422        int resp_buf_type;
 423
 424        iov[0].iov_base = (char *)in_buf;
 425        iov[0].iov_len = in_buf->smb_buf_length + 4;
 426        flags |= CIFS_NO_RESP;
 427        rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
 428        cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
 429
 430        return rc;
 431}
 432
 433static int
 434sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
 435{
 436        int rc = 0;
 437
 438        cFYI(1, "%s: cmd=%d mid=%d state=%d", __func__, mid->command,
 439                mid->mid, mid->midState);
 440
 441        spin_lock(&GlobalMid_Lock);
 442        /* ensure that it's no longer on the pending_mid_q */
 443        list_del_init(&mid->qhead);
 444
 445        switch (mid->midState) {
 446        case MID_RESPONSE_RECEIVED:
 447                spin_unlock(&GlobalMid_Lock);
 448                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        case MID_RETRY_NEEDED:
 458                rc = -EAGAIN;
 459                break;
 460        case MID_RESPONSE_MALFORMED:
 461                rc = -EIO;
 462                break;
 463        default:
 464                cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
 465                        mid->mid, mid->midState);
 466                rc = -EIO;
 467        }
 468        spin_unlock(&GlobalMid_Lock);
 469
 470        DeleteMidQEntry(mid);
 471        return rc;
 472}
 473
 474/*
 475 * An NT cancel request header looks just like the original request except:
 476 *
 477 * The Command is SMB_COM_NT_CANCEL
 478 * The WordCount is zeroed out
 479 * The ByteCount is zeroed out
 480 *
 481 * This function mangles an existing request buffer into a
 482 * SMB_COM_NT_CANCEL request and then sends it.
 483 */
 484static int
 485send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf,
 486                struct mid_q_entry *mid)
 487{
 488        int rc = 0;
 489
 490        /* -4 for RFC1001 length and +2 for BCC field */
 491        in_buf->smb_buf_length = sizeof(struct smb_hdr) - 4  + 2;
 492        in_buf->Command = SMB_COM_NT_CANCEL;
 493        in_buf->WordCount = 0;
 494        put_bcc_le(0, in_buf);
 495
 496        mutex_lock(&server->srv_mutex);
 497        rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
 498        if (rc) {
 499                mutex_unlock(&server->srv_mutex);
 500                return rc;
 501        }
 502        rc = smb_send(server, in_buf, in_buf->smb_buf_length);
 503        mutex_unlock(&server->srv_mutex);
 504
 505        cFYI(1, "issued NT_CANCEL for mid %u, rc = %d",
 506                in_buf->Mid, rc);
 507
 508        return rc;
 509}
 510
 511int
 512SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
 513             struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
 514             const int flags)
 515{
 516        int rc = 0;
 517        int long_op;
 518        unsigned int receive_len;
 519        struct mid_q_entry *midQ;
 520        struct smb_hdr *in_buf = iov[0].iov_base;
 521
 522        long_op = flags & CIFS_TIMEOUT_MASK;
 523
 524        *pRespBufType = CIFS_NO_BUFFER;  /* no response buf yet */
 525
 526        if ((ses == NULL) || (ses->server == NULL)) {
 527                cifs_small_buf_release(in_buf);
 528                cERROR(1, "Null session");
 529                return -EIO;
 530        }
 531
 532        if (ses->server->tcpStatus == CifsExiting) {
 533                cifs_small_buf_release(in_buf);
 534                return -ENOENT;
 535        }
 536
 537        /* Ensure that we do not send more than 50 overlapping requests
 538           to the same server. We may make this configurable later or
 539           use ses->maxReq */
 540
 541        rc = wait_for_free_request(ses->server, long_op);
 542        if (rc) {
 543                cifs_small_buf_release(in_buf);
 544                return rc;
 545        }
 546
 547        /* make sure that we sign in the same order that we send on this socket
 548           and avoid races inside tcp sendmsg code that could cause corruption
 549           of smb data */
 550
 551        mutex_lock(&ses->server->srv_mutex);
 552
 553        rc = allocate_mid(ses, in_buf, &midQ);
 554        if (rc) {
 555                mutex_unlock(&ses->server->srv_mutex);
 556                cifs_small_buf_release(in_buf);
 557                /* Update # of requests on wire to server */
 558                atomic_dec(&ses->server->inFlight);
 559                wake_up(&ses->server->request_q);
 560                return rc;
 561        }
 562        rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
 563        if (rc) {
 564                mutex_unlock(&ses->server->srv_mutex);
 565                cifs_small_buf_release(in_buf);
 566                goto out;
 567        }
 568
 569        midQ->midState = MID_REQUEST_SUBMITTED;
 570#ifdef CONFIG_CIFS_STATS2
 571        atomic_inc(&ses->server->inSend);
 572#endif
 573        rc = smb_sendv(ses->server, iov, n_vec);
 574#ifdef CONFIG_CIFS_STATS2
 575        atomic_dec(&ses->server->inSend);
 576        midQ->when_sent = jiffies;
 577#endif
 578
 579        mutex_unlock(&ses->server->srv_mutex);
 580
 581        if (rc < 0) {
 582                cifs_small_buf_release(in_buf);
 583                goto out;
 584        }
 585
 586        if (long_op == CIFS_ASYNC_OP) {
 587                cifs_small_buf_release(in_buf);
 588                goto out;
 589        }
 590
 591        rc = wait_for_response(ses->server, midQ);
 592        if (rc != 0) {
 593                send_nt_cancel(ses->server, in_buf, midQ);
 594                spin_lock(&GlobalMid_Lock);
 595                if (midQ->midState == MID_REQUEST_SUBMITTED) {
 596                        midQ->callback = DeleteMidQEntry;
 597                        spin_unlock(&GlobalMid_Lock);
 598                        cifs_small_buf_release(in_buf);
 599                        atomic_dec(&ses->server->inFlight);
 600                        wake_up(&ses->server->request_q);
 601                        return rc;
 602                }
 603                spin_unlock(&GlobalMid_Lock);
 604        }
 605
 606        cifs_small_buf_release(in_buf);
 607
 608        rc = sync_mid_result(midQ, ses->server);
 609        if (rc != 0) {
 610                atomic_dec(&ses->server->inFlight);
 611                wake_up(&ses->server->request_q);
 612                return rc;
 613        }
 614
 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 {
 664                rc = -EIO;
 665                cFYI(1, "Bad MID state?");
 666        }
 667
 668out:
 669        delete_mid(midQ);
 670        atomic_dec(&ses->server->inFlight);
 671        wake_up(&ses->server->request_q);
 672
 673        return rc;
 674}
 675
 676int
 677SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
 678            struct smb_hdr *in_buf, struct smb_hdr *out_buf,
 679            int *pbytes_returned, const int long_op)
 680{
 681        int rc = 0;
 682        unsigned int receive_len;
 683        struct mid_q_entry *midQ;
 684
 685        if (ses == NULL) {
 686                cERROR(1, "Null smb session");
 687                return -EIO;
 688        }
 689        if (ses->server == NULL) {
 690                cERROR(1, "Null tcp session");
 691                return -EIO;
 692        }
 693
 694        if (ses->server->tcpStatus == CifsExiting)
 695                return -ENOENT;
 696
 697        /* Ensure that we do not send more than 50 overlapping requests
 698           to the same server. We may make this configurable later or
 699           use ses->maxReq */
 700
 701        if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
 702                cERROR(1, "Illegal length, greater than maximum frame, %d",
 703                           in_buf->smb_buf_length);
 704                return -EIO;
 705        }
 706
 707        rc = wait_for_free_request(ses->server, long_op);
 708        if (rc)
 709                return rc;
 710
 711        /* make sure that we sign in the same order that we send on this socket
 712           and avoid races inside tcp sendmsg code that could cause corruption
 713           of smb data */
 714
 715        mutex_lock(&ses->server->srv_mutex);
 716
 717        rc = allocate_mid(ses, in_buf, &midQ);
 718        if (rc) {
 719                mutex_unlock(&ses->server->srv_mutex);
 720                /* Update # of requests on wire to server */
 721                atomic_dec(&ses->server->inFlight);
 722                wake_up(&ses->server->request_q);
 723                return rc;
 724        }
 725
 726        rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
 727        if (rc) {
 728                mutex_unlock(&ses->server->srv_mutex);
 729                goto out;
 730        }
 731
 732        midQ->midState = MID_REQUEST_SUBMITTED;
 733#ifdef CONFIG_CIFS_STATS2
 734        atomic_inc(&ses->server->inSend);
 735#endif
 736        rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
 737#ifdef CONFIG_CIFS_STATS2
 738        atomic_dec(&ses->server->inSend);
 739        midQ->when_sent = jiffies;
 740#endif
 741        mutex_unlock(&ses->server->srv_mutex);
 742
 743        if (rc < 0)
 744                goto out;
 745
 746        if (long_op == CIFS_ASYNC_OP)
 747                goto out;
 748
 749        rc = wait_for_response(ses->server, midQ);
 750        if (rc != 0) {
 751                send_nt_cancel(ses->server, in_buf, midQ);
 752                spin_lock(&GlobalMid_Lock);
 753                if (midQ->midState == MID_REQUEST_SUBMITTED) {
 754                        /* no longer considered to be "in-flight" */
 755                        midQ->callback = DeleteMidQEntry;
 756                        spin_unlock(&GlobalMid_Lock);
 757                        atomic_dec(&ses->server->inFlight);
 758                        wake_up(&ses->server->request_q);
 759                        return rc;
 760                }
 761                spin_unlock(&GlobalMid_Lock);
 762        }
 763
 764        rc = sync_mid_result(midQ, ses->server);
 765        if (rc != 0) {
 766                atomic_dec(&ses->server->inFlight);
 767                wake_up(&ses->server->request_q);
 768                return rc;
 769        }
 770
 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);
 776                rc = -EIO;
 777                goto out;
 778        }
 779
 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
 818out:
 819        delete_mid(midQ);
 820        atomic_dec(&ses->server->inFlight);
 821        wake_up(&ses->server->request_q);
 822
 823        return rc;
 824}
 825
 826/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
 827   blocking lock to return. */
 828
 829static int
 830send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
 831                        struct smb_hdr *in_buf,
 832                        struct smb_hdr *out_buf)
 833{
 834        int bytes_returned;
 835        struct cifsSesInfo *ses = tcon->ses;
 836        LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
 837
 838        /* We just modify the current in_buf to change
 839           the type of lock from LOCKING_ANDX_SHARED_LOCK
 840           or LOCKING_ANDX_EXCLUSIVE_LOCK to
 841           LOCKING_ANDX_CANCEL_LOCK. */
 842
 843        pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
 844        pSMB->Timeout = 0;
 845        pSMB->hdr.Mid = GetNextMid(ses->server);
 846
 847        return SendReceive(xid, ses, in_buf, out_buf,
 848                        &bytes_returned, 0);
 849}
 850
 851int
 852SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
 853            struct smb_hdr *in_buf, struct smb_hdr *out_buf,
 854            int *pbytes_returned)
 855{
 856        int rc = 0;
 857        int rstart = 0;
 858        unsigned int receive_len;
 859        struct mid_q_entry *midQ;
 860        struct cifsSesInfo *ses;
 861
 862        if (tcon == NULL || tcon->ses == NULL) {
 863                cERROR(1, "Null smb session");
 864                return -EIO;
 865        }
 866        ses = tcon->ses;
 867
 868        if (ses->server == NULL) {
 869                cERROR(1, "Null tcp session");
 870                return -EIO;
 871        }
 872
 873        if (ses->server->tcpStatus == CifsExiting)
 874                return -ENOENT;
 875
 876        /* Ensure that we do not send more than 50 overlapping requests
 877           to the same server. We may make this configurable later or
 878           use ses->maxReq */
 879
 880        if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
 881                cERROR(1, "Illegal length, greater than maximum frame, %d",
 882                           in_buf->smb_buf_length);
 883                return -EIO;
 884        }
 885
 886        rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP);
 887        if (rc)
 888                return rc;
 889
 890        /* make sure that we sign in the same order that we send on this socket
 891           and avoid races inside tcp sendmsg code that could cause corruption
 892           of smb data */
 893
 894        mutex_lock(&ses->server->srv_mutex);
 895
 896        rc = allocate_mid(ses, in_buf, &midQ);
 897        if (rc) {
 898                mutex_unlock(&ses->server->srv_mutex);
 899                return rc;
 900        }
 901
 902        rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
 903        if (rc) {
 904                delete_mid(midQ);
 905                mutex_unlock(&ses->server->srv_mutex);
 906                return rc;
 907        }
 908
 909        midQ->midState = MID_REQUEST_SUBMITTED;
 910#ifdef CONFIG_CIFS_STATS2
 911        atomic_inc(&ses->server->inSend);
 912#endif
 913        rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
 914#ifdef CONFIG_CIFS_STATS2
 915        atomic_dec(&ses->server->inSend);
 916        midQ->when_sent = jiffies;
 917#endif
 918        mutex_unlock(&ses->server->srv_mutex);
 919
 920        if (rc < 0) {
 921                delete_mid(midQ);
 922                return rc;
 923        }
 924
 925        /* Wait for a reply - allow signals to interrupt. */
 926        rc = wait_event_interruptible(ses->server->response_q,
 927                (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
 928                ((ses->server->tcpStatus != CifsGood) &&
 929                 (ses->server->tcpStatus != CifsNew)));
 930
 931        /* Were we interrupted by a signal ? */
 932        if ((rc == -ERESTARTSYS) &&
 933                (midQ->midState == MID_REQUEST_SUBMITTED) &&
 934                ((ses->server->tcpStatus == CifsGood) ||
 935                 (ses->server->tcpStatus == CifsNew))) {
 936
 937                if (in_buf->Command == SMB_COM_TRANSACTION2) {
 938                        /* POSIX lock. We send a NT_CANCEL SMB to cause the
 939                           blocking lock to return. */
 940                        rc = send_nt_cancel(ses->server, in_buf, midQ);
 941                        if (rc) {
 942                                delete_mid(midQ);
 943                                return rc;
 944                        }
 945                } else {
 946                        /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
 947                           to cause the blocking lock to return. */
 948
 949                        rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
 950
 951                        /* If we get -ENOLCK back the lock may have
 952                           already been removed. Don't exit in this case. */
 953                        if (rc && rc != -ENOLCK) {
 954                                delete_mid(midQ);
 955                                return rc;
 956                        }
 957                }
 958
 959                rc = wait_for_response(ses->server, midQ);
 960                if (rc) {
 961                        send_nt_cancel(ses->server, in_buf, midQ);
 962                        spin_lock(&GlobalMid_Lock);
 963                        if (midQ->midState == MID_REQUEST_SUBMITTED) {
 964                                /* no longer considered to be "in-flight" */
 965                                midQ->callback = DeleteMidQEntry;
 966                                spin_unlock(&GlobalMid_Lock);
 967                                return rc;
 968                        }
 969                        spin_unlock(&GlobalMid_Lock);
 970                }
 971
 972                /* We got the response - restart system call. */
 973                rstart = 1;
 974        }
 975
 976        rc = sync_mid_result(midQ, ses->server);
 977        if (rc != 0)
 978                return rc;
 979
 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        /* rcvd frame is ok */
 989
 990        if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
 991                rc = -EIO;
 992                cERROR(1, "Bad MID state?");
 993                goto out;
 994        }
 995
 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
1026out:
1027        delete_mid(midQ);
1028        if (rstart && rc == -EACCES)
1029                return -ERESTARTSYS;
1030        return rc;
1031}
1032