linux/fs/cifs/transport.c
<<
>>
Prefs
   1/*
   2 *   fs/cifs/transport.c
   3 *
   4 *   Copyright (C) International Business Machines  Corp., 2002,2007
   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/wait.h>
  26#include <linux/net.h>
  27#include <linux/delay.h>
  28#include <asm/uaccess.h>
  29#include <asm/processor.h>
  30#include <linux/mempool.h>
  31#include "cifspdu.h"
  32#include "cifsglob.h"
  33#include "cifsproto.h"
  34#include "cifs_debug.h"
  35
  36extern mempool_t *cifs_mid_poolp;
  37extern struct kmem_cache *cifs_oplock_cachep;
  38
  39static struct mid_q_entry *
  40AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
  41{
  42        struct mid_q_entry *temp;
  43
  44        if (ses == NULL) {
  45                cERROR(1, ("Null session passed in to AllocMidQEntry"));
  46                return NULL;
  47        }
  48        if (ses->server == NULL) {
  49                cERROR(1, ("Null TCP session in AllocMidQEntry"));
  50                return NULL;
  51        }
  52
  53        temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,
  54                                                    GFP_KERNEL | GFP_NOFS);
  55        if (temp == NULL)
  56                return temp;
  57        else {
  58                memset(temp, 0, sizeof(struct mid_q_entry));
  59                temp->mid = smb_buffer->Mid;    /* always LE */
  60                temp->pid = current->pid;
  61                temp->command = smb_buffer->Command;
  62                cFYI(1, ("For smb_command %d", temp->command));
  63        /*      do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
  64                /* when mid allocated can be before when sent */
  65                temp->when_alloc = jiffies;
  66                temp->ses = ses;
  67                temp->tsk = current;
  68        }
  69
  70        spin_lock(&GlobalMid_Lock);
  71        list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
  72        atomic_inc(&midCount);
  73        temp->midState = MID_REQUEST_ALLOCATED;
  74        spin_unlock(&GlobalMid_Lock);
  75        return temp;
  76}
  77
  78static void
  79DeleteMidQEntry(struct mid_q_entry *midEntry)
  80{
  81#ifdef CONFIG_CIFS_STATS2
  82        unsigned long now;
  83#endif
  84        spin_lock(&GlobalMid_Lock);
  85        midEntry->midState = MID_FREE;
  86        list_del(&midEntry->qhead);
  87        atomic_dec(&midCount);
  88        spin_unlock(&GlobalMid_Lock);
  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
 112struct oplock_q_entry *
 113AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon)
 114{
 115        struct oplock_q_entry *temp;
 116        if ((pinode == NULL) || (tcon == NULL)) {
 117                cERROR(1, ("Null parms passed to AllocOplockQEntry"));
 118                return NULL;
 119        }
 120        temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
 121                                                       GFP_KERNEL);
 122        if (temp == NULL)
 123                return temp;
 124        else {
 125                temp->pinode = pinode;
 126                temp->tcon = tcon;
 127                temp->netfid = fid;
 128                spin_lock(&GlobalMid_Lock);
 129                list_add_tail(&temp->qhead, &GlobalOplock_Q);
 130                spin_unlock(&GlobalMid_Lock);
 131        }
 132        return temp;
 133
 134}
 135
 136void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry)
 137{
 138        spin_lock(&GlobalMid_Lock);
 139    /* should we check if list empty first? */
 140        list_del(&oplockEntry->qhead);
 141        spin_unlock(&GlobalMid_Lock);
 142        kmem_cache_free(cifs_oplock_cachep, oplockEntry);
 143}
 144
 145int
 146smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
 147         unsigned int smb_buf_length, struct sockaddr *sin)
 148{
 149        int rc = 0;
 150        int i = 0;
 151        struct msghdr smb_msg;
 152        struct kvec iov;
 153        unsigned len = smb_buf_length + 4;
 154
 155        if (ssocket == NULL)
 156                return -ENOTSOCK; /* BB eventually add reconnect code here */
 157        iov.iov_base = smb_buffer;
 158        iov.iov_len = len;
 159
 160        smb_msg.msg_name = sin;
 161        smb_msg.msg_namelen = sizeof(struct sockaddr);
 162        smb_msg.msg_control = NULL;
 163        smb_msg.msg_controllen = 0;
 164        smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
 165
 166        /* smb header is converted in header_assemble. bcc and rest of SMB word
 167           area, and byte area if necessary, is converted to littleendian in
 168           cifssmb.c and RFC1001 len is converted to bigendian in smb_send
 169           Flags2 is converted in SendReceive */
 170
 171        smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
 172        cFYI(1, ("Sending smb of length %d", smb_buf_length));
 173        dump_smb(smb_buffer, len);
 174
 175        while (len > 0) {
 176                rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
 177                if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
 178                        i++;
 179                /* smaller timeout here than send2 since smaller size */
 180                /* Although it may not be required, this also is smaller
 181                   oplock break time */
 182                        if (i > 12) {
 183                                cERROR(1,
 184                                   ("sends on sock %p stuck for 7 seconds",
 185                                    ssocket));
 186                                rc = -EAGAIN;
 187                                break;
 188                        }
 189                        msleep(1 << i);
 190                        continue;
 191                }
 192                if (rc < 0)
 193                        break;
 194                else
 195                        i = 0; /* reset i after each successful send */
 196                iov.iov_base += rc;
 197                iov.iov_len -= rc;
 198                len -= rc;
 199        }
 200
 201        if (rc < 0) {
 202                cERROR(1, ("Error %d sending data on socket to server", rc));
 203        } else {
 204                rc = 0;
 205        }
 206
 207        /* Don't want to modify the buffer as a
 208           side effect of this call. */
 209        smb_buffer->smb_buf_length = smb_buf_length;
 210
 211        return rc;
 212}
 213
 214static int
 215smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
 216          struct sockaddr *sin)
 217{
 218        int rc = 0;
 219        int i = 0;
 220        struct msghdr smb_msg;
 221        struct smb_hdr *smb_buffer = iov[0].iov_base;
 222        unsigned int len = iov[0].iov_len;
 223        unsigned int total_len;
 224        int first_vec = 0;
 225        unsigned int smb_buf_length = smb_buffer->smb_buf_length;
 226
 227        if (ssocket == NULL)
 228                return -ENOTSOCK; /* BB eventually add reconnect code here */
 229
 230        smb_msg.msg_name = sin;
 231        smb_msg.msg_namelen = sizeof(struct sockaddr);
 232        smb_msg.msg_control = NULL;
 233        smb_msg.msg_controllen = 0;
 234        smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
 235
 236        /* smb header is converted in header_assemble. bcc and rest of SMB word
 237           area, and byte area if necessary, is converted to littleendian in
 238           cifssmb.c and RFC1001 len is converted to bigendian in smb_send
 239           Flags2 is converted in SendReceive */
 240
 241
 242        total_len = 0;
 243        for (i = 0; i < n_vec; i++)
 244                total_len += iov[i].iov_len;
 245
 246        smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
 247        cFYI(1, ("Sending smb:  total_len %d", total_len));
 248        dump_smb(smb_buffer, len);
 249
 250        while (total_len) {
 251                rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
 252                                    n_vec - first_vec, total_len);
 253                if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
 254                        i++;
 255                        if (i >= 14) {
 256                                cERROR(1,
 257                                   ("sends on sock %p stuck for 15 seconds",
 258                                    ssocket));
 259                                rc = -EAGAIN;
 260                                break;
 261                        }
 262                        msleep(1 << i);
 263                        continue;
 264                }
 265                if (rc < 0)
 266                        break;
 267
 268                if (rc >= total_len) {
 269                        WARN_ON(rc > total_len);
 270                        break;
 271                }
 272                if (rc == 0) {
 273                        /* should never happen, letting socket clear before
 274                           retrying is our only obvious option here */
 275                        cERROR(1, ("tcp sent no data"));
 276                        msleep(500);
 277                        continue;
 278                }
 279                total_len -= rc;
 280                /* the line below resets i */
 281                for (i = first_vec; i < n_vec; i++) {
 282                        if (iov[i].iov_len) {
 283                                if (rc > iov[i].iov_len) {
 284                                        rc -= iov[i].iov_len;
 285                                        iov[i].iov_len = 0;
 286                                } else {
 287                                        iov[i].iov_base += rc;
 288                                        iov[i].iov_len -= rc;
 289                                        first_vec = i;
 290                                        break;
 291                                }
 292                        }
 293                }
 294                i = 0; /* in case we get ENOSPC on the next send */
 295        }
 296
 297        if (rc < 0) {
 298                cERROR(1, ("Error %d sending data on socket to server", rc));
 299        } else
 300                rc = 0;
 301
 302        /* Don't want to modify the buffer as a
 303           side effect of this call. */
 304        smb_buffer->smb_buf_length = smb_buf_length;
 305
 306        return rc;
 307}
 308
 309static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
 310{
 311        if (long_op == CIFS_ASYNC_OP) {
 312                /* oplock breaks must not be held up */
 313                atomic_inc(&ses->server->inFlight);
 314        } else {
 315                spin_lock(&GlobalMid_Lock);
 316                while (1) {
 317                        if (atomic_read(&ses->server->inFlight) >=
 318                                        cifs_max_pending){
 319                                spin_unlock(&GlobalMid_Lock);
 320#ifdef CONFIG_CIFS_STATS2
 321                                atomic_inc(&ses->server->num_waiters);
 322#endif
 323                                wait_event(ses->server->request_q,
 324                                        atomic_read(&ses->server->inFlight)
 325                                         < cifs_max_pending);
 326#ifdef CONFIG_CIFS_STATS2
 327                                atomic_dec(&ses->server->num_waiters);
 328#endif
 329                                spin_lock(&GlobalMid_Lock);
 330                        } else {
 331                                if (ses->server->tcpStatus == CifsExiting) {
 332                                        spin_unlock(&GlobalMid_Lock);
 333                                        return -ENOENT;
 334                                }
 335
 336                                /* can not count locking commands against total
 337                                   as they are allowed to block on server */
 338
 339                                /* update # of requests on the wire to server */
 340                                if (long_op != CIFS_BLOCKING_OP)
 341                                        atomic_inc(&ses->server->inFlight);
 342                                spin_unlock(&GlobalMid_Lock);
 343                                break;
 344                        }
 345                }
 346        }
 347        return 0;
 348}
 349
 350static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
 351                        struct mid_q_entry **ppmidQ)
 352{
 353        if (ses->server->tcpStatus == CifsExiting) {
 354                return -ENOENT;
 355        } else if (ses->server->tcpStatus == CifsNeedReconnect) {
 356                cFYI(1, ("tcp session dead - return to caller to retry"));
 357                return -EAGAIN;
 358        } else if (ses->status != CifsGood) {
 359                /* check if SMB session is bad because we are setting it up */
 360                if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
 361                        (in_buf->Command != SMB_COM_NEGOTIATE)) {
 362                        return -EAGAIN;
 363                } /* else ok - we are setting up session */
 364        }
 365        *ppmidQ = AllocMidQEntry(in_buf, ses);
 366        if (*ppmidQ == NULL)
 367                return -ENOMEM;
 368        return 0;
 369}
 370
 371static int wait_for_response(struct cifsSesInfo *ses,
 372                        struct mid_q_entry *midQ,
 373                        unsigned long timeout,
 374                        unsigned long time_to_wait)
 375{
 376        unsigned long curr_timeout;
 377
 378        for (;;) {
 379                curr_timeout = timeout + jiffies;
 380                wait_event(ses->server->response_q,
 381                        (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
 382                        time_after(jiffies, curr_timeout) ||
 383                        ((ses->server->tcpStatus != CifsGood) &&
 384                         (ses->server->tcpStatus != CifsNew)));
 385
 386                if (time_after(jiffies, curr_timeout) &&
 387                        (midQ->midState == MID_REQUEST_SUBMITTED) &&
 388                        ((ses->server->tcpStatus == CifsGood) ||
 389                         (ses->server->tcpStatus == CifsNew))) {
 390
 391                        unsigned long lrt;
 392
 393                        /* We timed out. Is the server still
 394                           sending replies ? */
 395                        spin_lock(&GlobalMid_Lock);
 396                        lrt = ses->server->lstrp;
 397                        spin_unlock(&GlobalMid_Lock);
 398
 399                        /* Calculate time_to_wait past last receive time.
 400                         Although we prefer not to time out if the
 401                         server is still responding - we will time
 402                         out if the server takes more than 15 (or 45
 403                         or 180) seconds to respond to this request
 404                         and has not responded to any request from
 405                         other threads on the client within 10 seconds */
 406                        lrt += time_to_wait;
 407                        if (time_after(jiffies, lrt)) {
 408                                /* No replies for time_to_wait. */
 409                                cERROR(1, ("server not responding"));
 410                                return -1;
 411                        }
 412                } else {
 413                        return 0;
 414                }
 415        }
 416}
 417
 418
 419/*
 420 *
 421 * Send an SMB Request.  No response info (other than return code)
 422 * needs to be parsed.
 423 *
 424 * flags indicate the type of request buffer and how long to wait
 425 * and whether to log NT STATUS code (error) before mapping it to POSIX error
 426 *
 427 */
 428int
 429SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
 430                struct smb_hdr *in_buf, int flags)
 431{
 432        int rc;
 433        struct kvec iov[1];
 434        int resp_buf_type;
 435
 436        iov[0].iov_base = (char *)in_buf;
 437        iov[0].iov_len = in_buf->smb_buf_length + 4;
 438        flags |= CIFS_NO_RESP;
 439        rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
 440#ifdef CONFIG_CIFS_DEBUG2
 441        cFYI(1, ("SendRcvNoR flags %d rc %d", flags, rc));
 442#endif
 443        return rc;
 444}
 445
 446int
 447SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
 448             struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
 449             const int flags)
 450{
 451        int rc = 0;
 452        int long_op;
 453        unsigned int receive_len;
 454        unsigned long timeout;
 455        struct mid_q_entry *midQ;
 456        struct smb_hdr *in_buf = iov[0].iov_base;
 457
 458        long_op = flags & CIFS_TIMEOUT_MASK;
 459
 460        *pRespBufType = CIFS_NO_BUFFER;  /* no response buf yet */
 461
 462        if ((ses == NULL) || (ses->server == NULL)) {
 463                cifs_small_buf_release(in_buf);
 464                cERROR(1, ("Null session"));
 465                return -EIO;
 466        }
 467
 468        if (ses->server->tcpStatus == CifsExiting) {
 469                cifs_small_buf_release(in_buf);
 470                return -ENOENT;
 471        }
 472
 473        /* Ensure that we do not send more than 50 overlapping requests
 474           to the same server. We may make this configurable later or
 475           use ses->maxReq */
 476
 477        rc = wait_for_free_request(ses, long_op);
 478        if (rc) {
 479                cifs_small_buf_release(in_buf);
 480                return rc;
 481        }
 482
 483        /* make sure that we sign in the same order that we send on this socket
 484           and avoid races inside tcp sendmsg code that could cause corruption
 485           of smb data */
 486
 487        down(&ses->server->tcpSem);
 488
 489        rc = allocate_mid(ses, in_buf, &midQ);
 490        if (rc) {
 491                up(&ses->server->tcpSem);
 492                cifs_small_buf_release(in_buf);
 493                /* Update # of requests on wire to server */
 494                atomic_dec(&ses->server->inFlight);
 495                wake_up(&ses->server->request_q);
 496                return rc;
 497        }
 498        rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
 499
 500        midQ->midState = MID_REQUEST_SUBMITTED;
 501#ifdef CONFIG_CIFS_STATS2
 502        atomic_inc(&ses->server->inSend);
 503#endif
 504        rc = smb_send2(ses->server->ssocket, iov, n_vec,
 505                      (struct sockaddr *) &(ses->server->addr.sockAddr));
 506#ifdef CONFIG_CIFS_STATS2
 507        atomic_dec(&ses->server->inSend);
 508        midQ->when_sent = jiffies;
 509#endif
 510
 511        up(&ses->server->tcpSem);
 512        cifs_small_buf_release(in_buf);
 513
 514        if (rc < 0)
 515                goto out;
 516
 517        if (long_op == CIFS_STD_OP)
 518                timeout = 15 * HZ;
 519        else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
 520                timeout = 180 * HZ;
 521        else if (long_op == CIFS_LONG_OP)
 522                timeout = 45 * HZ; /* should be greater than
 523                        servers oplock break timeout (about 43 seconds) */
 524        else if (long_op == CIFS_ASYNC_OP)
 525                goto out;
 526        else if (long_op == CIFS_BLOCKING_OP)
 527                timeout = 0x7FFFFFFF; /*  large, but not so large as to wrap */
 528        else {
 529                cERROR(1, ("unknown timeout flag %d", long_op));
 530                rc = -EIO;
 531                goto out;
 532        }
 533
 534        /* wait for 15 seconds or until woken up due to response arriving or
 535           due to last connection to this server being unmounted */
 536        if (signal_pending(current)) {
 537                /* if signal pending do not hold up user for full smb timeout
 538                but we still give response a chance to complete */
 539                timeout = 2 * HZ;
 540        }
 541
 542        /* No user interrupts in wait - wreaks havoc with performance */
 543        wait_for_response(ses, midQ, timeout, 10 * HZ);
 544
 545        spin_lock(&GlobalMid_Lock);
 546        if (midQ->resp_buf) {
 547                spin_unlock(&GlobalMid_Lock);
 548                receive_len = midQ->resp_buf->smb_buf_length;
 549        } else {
 550                cERROR(1, ("No response to cmd %d mid %d",
 551                        midQ->command, midQ->mid));
 552                if (midQ->midState == MID_REQUEST_SUBMITTED) {
 553                        if (ses->server->tcpStatus == CifsExiting)
 554                                rc = -EHOSTDOWN;
 555                        else {
 556                                ses->server->tcpStatus = CifsNeedReconnect;
 557                                midQ->midState = MID_RETRY_NEEDED;
 558                        }
 559                }
 560
 561                if (rc != -EHOSTDOWN) {
 562                        if (midQ->midState == MID_RETRY_NEEDED) {
 563                                rc = -EAGAIN;
 564                                cFYI(1, ("marking request for retry"));
 565                        } else {
 566                                rc = -EIO;
 567                        }
 568                }
 569                spin_unlock(&GlobalMid_Lock);
 570                DeleteMidQEntry(midQ);
 571                /* Update # of requests on wire to server */
 572                atomic_dec(&ses->server->inFlight);
 573                wake_up(&ses->server->request_q);
 574                return rc;
 575        }
 576
 577        if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
 578                cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
 579                        receive_len, xid));
 580                rc = -EIO;
 581        } else {                /* rcvd frame is ok */
 582                if (midQ->resp_buf &&
 583                        (midQ->midState == MID_RESPONSE_RECEIVED)) {
 584
 585                        iov[0].iov_base = (char *)midQ->resp_buf;
 586                        if (midQ->largeBuf)
 587                                *pRespBufType = CIFS_LARGE_BUFFER;
 588                        else
 589                                *pRespBufType = CIFS_SMALL_BUFFER;
 590                        iov[0].iov_len = receive_len + 4;
 591
 592                        dump_smb(midQ->resp_buf, 80);
 593                        /* convert the length into a more usable form */
 594                        if ((receive_len > 24) &&
 595                           (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
 596                                        SECMODE_SIGN_ENABLED))) {
 597                                rc = cifs_verify_signature(midQ->resp_buf,
 598                                                &ses->server->mac_signing_key,
 599                                                midQ->sequence_number+1);
 600                                if (rc) {
 601                                        cERROR(1, ("Unexpected SMB signature"));
 602                                        /* BB FIXME add code to kill session */
 603                                }
 604                        }
 605
 606                        /* BB special case reconnect tid and uid here? */
 607                        rc = map_smb_to_linux_error(midQ->resp_buf,
 608                                                flags & CIFS_LOG_ERROR);
 609
 610                        /* convert ByteCount if necessary */
 611                        if (receive_len >= sizeof(struct smb_hdr) - 4
 612                            /* do not count RFC1001 header */  +
 613                            (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
 614                                BCC(midQ->resp_buf) =
 615                                        le16_to_cpu(BCC_LE(midQ->resp_buf));
 616                        if ((flags & CIFS_NO_RESP) == 0)
 617                                midQ->resp_buf = NULL;  /* mark it so buf will
 618                                                           not be freed by
 619                                                           DeleteMidQEntry */
 620                } else {
 621                        rc = -EIO;
 622                        cFYI(1, ("Bad MID state?"));
 623                }
 624        }
 625
 626out:
 627        DeleteMidQEntry(midQ);
 628        atomic_dec(&ses->server->inFlight);
 629        wake_up(&ses->server->request_q);
 630
 631        return rc;
 632}
 633
 634int
 635SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
 636            struct smb_hdr *in_buf, struct smb_hdr *out_buf,
 637            int *pbytes_returned, const int long_op)
 638{
 639        int rc = 0;
 640        unsigned int receive_len;
 641        unsigned long timeout;
 642        struct mid_q_entry *midQ;
 643
 644        if (ses == NULL) {
 645                cERROR(1, ("Null smb session"));
 646                return -EIO;
 647        }
 648        if (ses->server == NULL) {
 649                cERROR(1, ("Null tcp session"));
 650                return -EIO;
 651        }
 652
 653        if (ses->server->tcpStatus == CifsExiting)
 654                return -ENOENT;
 655
 656        /* Ensure that we do not send more than 50 overlapping requests
 657           to the same server. We may make this configurable later or
 658           use ses->maxReq */
 659
 660        rc = wait_for_free_request(ses, long_op);
 661        if (rc)
 662                return rc;
 663
 664        /* make sure that we sign in the same order that we send on this socket
 665           and avoid races inside tcp sendmsg code that could cause corruption
 666           of smb data */
 667
 668        down(&ses->server->tcpSem);
 669
 670        rc = allocate_mid(ses, in_buf, &midQ);
 671        if (rc) {
 672                up(&ses->server->tcpSem);
 673                /* Update # of requests on wire to server */
 674                atomic_dec(&ses->server->inFlight);
 675                wake_up(&ses->server->request_q);
 676                return rc;
 677        }
 678
 679        if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
 680                cERROR(1, ("Illegal length, greater than maximum frame, %d",
 681                        in_buf->smb_buf_length));
 682                DeleteMidQEntry(midQ);
 683                up(&ses->server->tcpSem);
 684                /* Update # of requests on wire to server */
 685                atomic_dec(&ses->server->inFlight);
 686                wake_up(&ses->server->request_q);
 687                return -EIO;
 688        }
 689
 690        rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
 691
 692        midQ->midState = MID_REQUEST_SUBMITTED;
 693#ifdef CONFIG_CIFS_STATS2
 694        atomic_inc(&ses->server->inSend);
 695#endif
 696        rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
 697                      (struct sockaddr *) &(ses->server->addr.sockAddr));
 698#ifdef CONFIG_CIFS_STATS2
 699        atomic_dec(&ses->server->inSend);
 700        midQ->when_sent = jiffies;
 701#endif
 702        up(&ses->server->tcpSem);
 703
 704        if (rc < 0)
 705                goto out;
 706
 707        if (long_op == CIFS_STD_OP)
 708                timeout = 15 * HZ;
 709        /* wait for 15 seconds or until woken up due to response arriving or
 710           due to last connection to this server being unmounted */
 711        else if (long_op == CIFS_ASYNC_OP)
 712                goto out;
 713        else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
 714                timeout = 180 * HZ;
 715        else if (long_op == CIFS_LONG_OP)
 716                timeout = 45 * HZ; /* should be greater than
 717                        servers oplock break timeout (about 43 seconds) */
 718        else if (long_op == CIFS_BLOCKING_OP)
 719                timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
 720        else {
 721                cERROR(1, ("unknown timeout flag %d", long_op));
 722                rc = -EIO;
 723                goto out;
 724        }
 725
 726        if (signal_pending(current)) {
 727                /* if signal pending do not hold up user for full smb timeout
 728                but we still give response a chance to complete */
 729                timeout = 2 * HZ;
 730        }
 731
 732        /* No user interrupts in wait - wreaks havoc with performance */
 733        wait_for_response(ses, midQ, timeout, 10 * HZ);
 734
 735        spin_lock(&GlobalMid_Lock);
 736        if (midQ->resp_buf) {
 737                spin_unlock(&GlobalMid_Lock);
 738                receive_len = midQ->resp_buf->smb_buf_length;
 739        } else {
 740                cERROR(1, ("No response for cmd %d mid %d",
 741                          midQ->command, midQ->mid));
 742                if (midQ->midState == MID_REQUEST_SUBMITTED) {
 743                        if (ses->server->tcpStatus == CifsExiting)
 744                                rc = -EHOSTDOWN;
 745                        else {
 746                                ses->server->tcpStatus = CifsNeedReconnect;
 747                                midQ->midState = MID_RETRY_NEEDED;
 748                        }
 749                }
 750
 751                if (rc != -EHOSTDOWN) {
 752                        if (midQ->midState == MID_RETRY_NEEDED) {
 753                                rc = -EAGAIN;
 754                                cFYI(1, ("marking request for retry"));
 755                        } else {
 756                                rc = -EIO;
 757                        }
 758                }
 759                spin_unlock(&GlobalMid_Lock);
 760                DeleteMidQEntry(midQ);
 761                /* Update # of requests on wire to server */
 762                atomic_dec(&ses->server->inFlight);
 763                wake_up(&ses->server->request_q);
 764                return rc;
 765        }
 766
 767        if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
 768                cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
 769                        receive_len, xid));
 770                rc = -EIO;
 771        } else {                /* rcvd frame is ok */
 772
 773                if (midQ->resp_buf && out_buf
 774                    && (midQ->midState == MID_RESPONSE_RECEIVED)) {
 775                        out_buf->smb_buf_length = receive_len;
 776                        memcpy((char *)out_buf + 4,
 777                               (char *)midQ->resp_buf + 4,
 778                               receive_len);
 779
 780                        dump_smb(out_buf, 92);
 781                        /* convert the length into a more usable form */
 782                        if ((receive_len > 24) &&
 783                           (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
 784                                        SECMODE_SIGN_ENABLED))) {
 785                                rc = cifs_verify_signature(out_buf,
 786                                                &ses->server->mac_signing_key,
 787                                                midQ->sequence_number+1);
 788                                if (rc) {
 789                                        cERROR(1, ("Unexpected SMB signature"));
 790                                        /* BB FIXME add code to kill session */
 791                                }
 792                        }
 793
 794                        *pbytes_returned = out_buf->smb_buf_length;
 795
 796                        /* BB special case reconnect tid and uid here? */
 797                        rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
 798
 799                        /* convert ByteCount if necessary */
 800                        if (receive_len >= sizeof(struct smb_hdr) - 4
 801                            /* do not count RFC1001 header */  +
 802                            (2 * out_buf->WordCount) + 2 /* bcc */ )
 803                                BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
 804                } else {
 805                        rc = -EIO;
 806                        cERROR(1, ("Bad MID state?"));
 807                }
 808        }
 809
 810out:
 811        DeleteMidQEntry(midQ);
 812        atomic_dec(&ses->server->inFlight);
 813        wake_up(&ses->server->request_q);
 814
 815        return rc;
 816}
 817
 818/* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
 819
 820static int
 821send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
 822                struct mid_q_entry *midQ)
 823{
 824        int rc = 0;
 825        struct cifsSesInfo *ses = tcon->ses;
 826        __u16 mid = in_buf->Mid;
 827
 828        header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
 829        in_buf->Mid = mid;
 830        down(&ses->server->tcpSem);
 831        rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
 832        if (rc) {
 833                up(&ses->server->tcpSem);
 834                return rc;
 835        }
 836        rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
 837              (struct sockaddr *) &(ses->server->addr.sockAddr));
 838        up(&ses->server->tcpSem);
 839        return rc;
 840}
 841
 842/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
 843   blocking lock to return. */
 844
 845static int
 846send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
 847                        struct smb_hdr *in_buf,
 848                        struct smb_hdr *out_buf)
 849{
 850        int bytes_returned;
 851        struct cifsSesInfo *ses = tcon->ses;
 852        LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
 853
 854        /* We just modify the current in_buf to change
 855           the type of lock from LOCKING_ANDX_SHARED_LOCK
 856           or LOCKING_ANDX_EXCLUSIVE_LOCK to
 857           LOCKING_ANDX_CANCEL_LOCK. */
 858
 859        pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
 860        pSMB->Timeout = 0;
 861        pSMB->hdr.Mid = GetNextMid(ses->server);
 862
 863        return SendReceive(xid, ses, in_buf, out_buf,
 864                        &bytes_returned, CIFS_STD_OP);
 865}
 866
 867int
 868SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
 869            struct smb_hdr *in_buf, struct smb_hdr *out_buf,
 870            int *pbytes_returned)
 871{
 872        int rc = 0;
 873        int rstart = 0;
 874        unsigned int receive_len;
 875        struct mid_q_entry *midQ;
 876        struct cifsSesInfo *ses;
 877
 878        if (tcon == NULL || tcon->ses == NULL) {
 879                cERROR(1, ("Null smb session"));
 880                return -EIO;
 881        }
 882        ses = tcon->ses;
 883
 884        if (ses->server == NULL) {
 885                cERROR(1, ("Null tcp session"));
 886                return -EIO;
 887        }
 888
 889        if (ses->server->tcpStatus == CifsExiting)
 890                return -ENOENT;
 891
 892        /* Ensure that we do not send more than 50 overlapping requests
 893           to the same server. We may make this configurable later or
 894           use ses->maxReq */
 895
 896        rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
 897        if (rc)
 898                return rc;
 899
 900        /* make sure that we sign in the same order that we send on this socket
 901           and avoid races inside tcp sendmsg code that could cause corruption
 902           of smb data */
 903
 904        down(&ses->server->tcpSem);
 905
 906        rc = allocate_mid(ses, in_buf, &midQ);
 907        if (rc) {
 908                up(&ses->server->tcpSem);
 909                return rc;
 910        }
 911
 912        if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
 913                up(&ses->server->tcpSem);
 914                cERROR(1, ("Illegal length, greater than maximum frame, %d",
 915                        in_buf->smb_buf_length));
 916                DeleteMidQEntry(midQ);
 917                return -EIO;
 918        }
 919
 920        rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
 921
 922        midQ->midState = MID_REQUEST_SUBMITTED;
 923#ifdef CONFIG_CIFS_STATS2
 924        atomic_inc(&ses->server->inSend);
 925#endif
 926        rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
 927                      (struct sockaddr *) &(ses->server->addr.sockAddr));
 928#ifdef CONFIG_CIFS_STATS2
 929        atomic_dec(&ses->server->inSend);
 930        midQ->when_sent = jiffies;
 931#endif
 932        up(&ses->server->tcpSem);
 933
 934        if (rc < 0) {
 935                DeleteMidQEntry(midQ);
 936                return rc;
 937        }
 938
 939        /* Wait for a reply - allow signals to interrupt. */
 940        rc = wait_event_interruptible(ses->server->response_q,
 941                (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
 942                ((ses->server->tcpStatus != CifsGood) &&
 943                 (ses->server->tcpStatus != CifsNew)));
 944
 945        /* Were we interrupted by a signal ? */
 946        if ((rc == -ERESTARTSYS) &&
 947                (midQ->midState == MID_REQUEST_SUBMITTED) &&
 948                ((ses->server->tcpStatus == CifsGood) ||
 949                 (ses->server->tcpStatus == CifsNew))) {
 950
 951                if (in_buf->Command == SMB_COM_TRANSACTION2) {
 952                        /* POSIX lock. We send a NT_CANCEL SMB to cause the
 953                           blocking lock to return. */
 954
 955                        rc = send_nt_cancel(tcon, in_buf, midQ);
 956                        if (rc) {
 957                                DeleteMidQEntry(midQ);
 958                                return rc;
 959                        }
 960                } else {
 961                        /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
 962                           to cause the blocking lock to return. */
 963
 964                        rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
 965
 966                        /* If we get -ENOLCK back the lock may have
 967                           already been removed. Don't exit in this case. */
 968                        if (rc && rc != -ENOLCK) {
 969                                DeleteMidQEntry(midQ);
 970                                return rc;
 971                        }
 972                }
 973
 974                /* Wait 5 seconds for the response. */
 975                if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
 976                        /* We got the response - restart system call. */
 977                        rstart = 1;
 978                }
 979        }
 980
 981        spin_lock(&GlobalMid_Lock);
 982        if (midQ->resp_buf) {
 983                spin_unlock(&GlobalMid_Lock);
 984                receive_len = midQ->resp_buf->smb_buf_length;
 985        } else {
 986                cERROR(1, ("No response for cmd %d mid %d",
 987                          midQ->command, midQ->mid));
 988                if (midQ->midState == MID_REQUEST_SUBMITTED) {
 989                        if (ses->server->tcpStatus == CifsExiting)
 990                                rc = -EHOSTDOWN;
 991                        else {
 992                                ses->server->tcpStatus = CifsNeedReconnect;
 993                                midQ->midState = MID_RETRY_NEEDED;
 994                        }
 995                }
 996
 997                if (rc != -EHOSTDOWN) {
 998                        if (midQ->midState == MID_RETRY_NEEDED) {
 999                                rc = -EAGAIN;
1000                                cFYI(1, ("marking request for retry"));
1001                        } else {
1002                                rc = -EIO;
1003                        }
1004                }
1005                spin_unlock(&GlobalMid_Lock);
1006                DeleteMidQEntry(midQ);
1007                return rc;
1008        }
1009
1010        if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
1011                cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
1012                        receive_len, xid));
1013                rc = -EIO;
1014        } else {                /* rcvd frame is ok */
1015
1016                if (midQ->resp_buf && out_buf
1017                    && (midQ->midState == MID_RESPONSE_RECEIVED)) {
1018                        out_buf->smb_buf_length = receive_len;
1019                        memcpy((char *)out_buf + 4,
1020                               (char *)midQ->resp_buf + 4,
1021                               receive_len);
1022
1023                        dump_smb(out_buf, 92);
1024                        /* convert the length into a more usable form */
1025                        if ((receive_len > 24) &&
1026                           (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1027                                        SECMODE_SIGN_ENABLED))) {
1028                                rc = cifs_verify_signature(out_buf,
1029                                                &ses->server->mac_signing_key,
1030                                                midQ->sequence_number+1);
1031                                if (rc) {
1032                                        cERROR(1, ("Unexpected SMB signature"));
1033                                        /* BB FIXME add code to kill session */
1034                                }
1035                        }
1036
1037                        *pbytes_returned = out_buf->smb_buf_length;
1038
1039                        /* BB special case reconnect tid and uid here? */
1040                        rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1041
1042                        /* convert ByteCount if necessary */
1043                        if (receive_len >= sizeof(struct smb_hdr) - 4
1044                            /* do not count RFC1001 header */  +
1045                            (2 * out_buf->WordCount) + 2 /* bcc */ )
1046                                BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1047                } else {
1048                        rc = -EIO;
1049                        cERROR(1, ("Bad MID state?"));
1050                }
1051        }
1052        DeleteMidQEntry(midQ);
1053        if (rstart && rc == -EACCES)
1054                return -ERESTARTSYS;
1055        return rc;
1056}
1057