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 <linux/freezer.h>
  30#include <asm/uaccess.h>
  31#include <asm/processor.h>
  32#include <linux/mempool.h>
  33#include "cifspdu.h"
  34#include "cifsglob.h"
  35#include "cifsproto.h"
  36#include "cifs_debug.h"
  37
  38void
  39cifs_wake_up_task(struct mid_q_entry *mid)
  40{
  41        wake_up_process(mid->callback_data);
  42}
  43
  44struct mid_q_entry *
  45AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
  46{
  47        struct mid_q_entry *temp;
  48
  49        if (server == NULL) {
  50                cERROR(1, "Null TCP session in AllocMidQEntry");
  51                return NULL;
  52        }
  53
  54        temp = mempool_alloc(cifs_mid_poolp, 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 = cpu_to_le16(smb_buffer->Command);
  62                cFYI(1, "For smb_command %d", smb_buffer->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->server = server;
  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 = cifs_wake_up_task;
  73                temp->callback_data = current;
  74        }
  75
  76        atomic_inc(&midCount);
  77        temp->mid_state = MID_REQUEST_ALLOCATED;
  78        return temp;
  79}
  80
  81void
  82DeleteMidQEntry(struct mid_q_entry *midEntry)
  83{
  84#ifdef CONFIG_CIFS_STATS2
  85        __le16 command = midEntry->server->vals->lock_cmd;
  86        unsigned long now;
  87#endif
  88        midEntry->mid_state = MID_FREE;
  89        atomic_dec(&midCount);
  90        if (midEntry->large_buf)
  91                cifs_buf_release(midEntry->resp_buf);
  92        else
  93                cifs_small_buf_release(midEntry->resp_buf);
  94#ifdef CONFIG_CIFS_STATS2
  95        now = jiffies;
  96        /* commands taking longer than one second are indications that
  97           something is wrong, unless it is quite a slow link or server */
  98        if ((now - midEntry->when_alloc) > HZ) {
  99                if ((cifsFYI & CIFS_TIMER) && (midEntry->command != command)) {
 100                        printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %llu",
 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        unsigned int len = iov[0].iov_len;
 129        unsigned int total_len;
 130        int first_vec = 0;
 131        unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
 132        struct socket *ssocket = server->ssocket;
 133
 134        if (ssocket == NULL)
 135                return -ENOTSOCK; /* BB eventually add reconnect code here */
 136
 137        smb_msg.msg_name = (struct sockaddr *) &server->dstaddr;
 138        smb_msg.msg_namelen = sizeof(struct sockaddr);
 139        smb_msg.msg_control = NULL;
 140        smb_msg.msg_controllen = 0;
 141        if (server->noblocksnd)
 142                smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
 143        else
 144                smb_msg.msg_flags = MSG_NOSIGNAL;
 145
 146        total_len = 0;
 147        for (i = 0; i < n_vec; i++)
 148                total_len += iov[i].iov_len;
 149
 150        cFYI(1, "Sending smb:  total_len %d", total_len);
 151        dump_smb(iov[0].iov_base, len);
 152
 153        i = 0;
 154        while (total_len) {
 155                rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
 156                                    n_vec - first_vec, total_len);
 157                if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
 158                        i++;
 159                        /*
 160                         * If blocking send we try 3 times, since each can block
 161                         * for 5 seconds. For nonblocking  we have to try more
 162                         * but wait increasing amounts of time allowing time for
 163                         * socket to clear.  The overall time we wait in either
 164                         * case to send on the socket is about 15 seconds.
 165                         * Similarly we wait for 15 seconds for a response from
 166                         * the server in SendReceive[2] for the server to send
 167                         * a response back for most types of requests (except
 168                         * SMB Write past end of file which can be slow, and
 169                         * blocking lock operations). NFS waits slightly longer
 170                         * than CIFS, but this can make it take longer for
 171                         * nonresponsive servers to be detected and 15 seconds
 172                         * is more than enough time for modern networks to
 173                         * send a packet.  In most cases if we fail to send
 174                         * after the retries we will kill the socket and
 175                         * reconnect which may clear the network problem.
 176                         */
 177                        if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
 178                                cERROR(1, "sends on sock %p stuck for 15 seconds",
 179                                    ssocket);
 180                                rc = -EAGAIN;
 181                                break;
 182                        }
 183                        msleep(1 << i);
 184                        continue;
 185                }
 186                if (rc < 0)
 187                        break;
 188
 189                if (rc == total_len) {
 190                        total_len = 0;
 191                        break;
 192                } else if (rc > total_len) {
 193                        cERROR(1, "sent %d requested %d", rc, total_len);
 194                        break;
 195                }
 196                if (rc == 0) {
 197                        /* should never happen, letting socket clear before
 198                           retrying is our only obvious option here */
 199                        cERROR(1, "tcp sent no data");
 200                        msleep(500);
 201                        continue;
 202                }
 203                total_len -= rc;
 204                /* the line below resets i */
 205                for (i = first_vec; i < n_vec; i++) {
 206                        if (iov[i].iov_len) {
 207                                if (rc > iov[i].iov_len) {
 208                                        rc -= iov[i].iov_len;
 209                                        iov[i].iov_len = 0;
 210                                } else {
 211                                        iov[i].iov_base += rc;
 212                                        iov[i].iov_len -= rc;
 213                                        first_vec = i;
 214                                        break;
 215                                }
 216                        }
 217                }
 218                i = 0; /* in case we get ENOSPC on the next send */
 219        }
 220
 221        if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
 222                cFYI(1, "partial send (%d remaining), terminating session",
 223                        total_len);
 224                /* If we have only sent part of an SMB then the next SMB
 225                   could be taken as the remainder of this one.  We need
 226                   to kill the socket so the server throws away the partial
 227                   SMB */
 228                server->tcpStatus = CifsNeedReconnect;
 229        }
 230
 231        if (rc < 0 && rc != -EINTR)
 232                cERROR(1, "Error %d sending data on socket to server", rc);
 233        else
 234                rc = 0;
 235
 236        return rc;
 237}
 238
 239int
 240smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
 241         unsigned int smb_buf_length)
 242{
 243        struct kvec iov;
 244
 245        iov.iov_base = smb_buffer;
 246        iov.iov_len = smb_buf_length + 4;
 247
 248        return smb_sendv(server, &iov, 1);
 249}
 250
 251static int
 252wait_for_free_credits(struct TCP_Server_Info *server, const int timeout,
 253                      int *credits)
 254{
 255        int rc;
 256
 257        spin_lock(&server->req_lock);
 258        if (timeout == CIFS_ASYNC_OP) {
 259                /* oplock breaks must not be held up */
 260                server->in_flight++;
 261                *credits -= 1;
 262                spin_unlock(&server->req_lock);
 263                return 0;
 264        }
 265
 266        while (1) {
 267                if (*credits <= 0) {
 268                        spin_unlock(&server->req_lock);
 269                        cifs_num_waiters_inc(server);
 270                        rc = wait_event_killable(server->request_q,
 271                                                 has_credits(server, credits));
 272                        cifs_num_waiters_dec(server);
 273                        if (rc)
 274                                return rc;
 275                        spin_lock(&server->req_lock);
 276                } else {
 277                        if (server->tcpStatus == CifsExiting) {
 278                                spin_unlock(&server->req_lock);
 279                                return -ENOENT;
 280                        }
 281
 282                        /*
 283                         * Can not count locking commands against total
 284                         * as they are allowed to block on server.
 285                         */
 286
 287                        /* update # of requests on the wire to server */
 288                        if (timeout != CIFS_BLOCKING_OP) {
 289                                *credits -= 1;
 290                                server->in_flight++;
 291                        }
 292                        spin_unlock(&server->req_lock);
 293                        break;
 294                }
 295        }
 296        return 0;
 297}
 298
 299static int
 300wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
 301                      const int optype)
 302{
 303        return wait_for_free_credits(server, timeout,
 304                                server->ops->get_credits_field(server, optype));
 305}
 306
 307static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
 308                        struct mid_q_entry **ppmidQ)
 309{
 310        if (ses->server->tcpStatus == CifsExiting) {
 311                return -ENOENT;
 312        }
 313
 314        if (ses->server->tcpStatus == CifsNeedReconnect) {
 315                cFYI(1, "tcp session dead - return to caller to retry");
 316                return -EAGAIN;
 317        }
 318
 319        if (ses->status != CifsGood) {
 320                /* check if SMB session is bad because we are setting it up */
 321                if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
 322                        (in_buf->Command != SMB_COM_NEGOTIATE))
 323                        return -EAGAIN;
 324                /* else ok - we are setting up session */
 325        }
 326        *ppmidQ = AllocMidQEntry(in_buf, ses->server);
 327        if (*ppmidQ == NULL)
 328                return -ENOMEM;
 329        spin_lock(&GlobalMid_Lock);
 330        list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
 331        spin_unlock(&GlobalMid_Lock);
 332        return 0;
 333}
 334
 335static int
 336wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
 337{
 338        int error;
 339
 340        error = wait_event_freezekillable(server->response_q,
 341                                    midQ->mid_state != MID_REQUEST_SUBMITTED);
 342        if (error < 0)
 343                return -ERESTARTSYS;
 344
 345        return 0;
 346}
 347
 348int
 349cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
 350                         unsigned int nvec, struct mid_q_entry **ret_mid)
 351{
 352        int rc;
 353        struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base;
 354        struct mid_q_entry *mid;
 355
 356        /* enable signing if server requires it */
 357        if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 358                hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 359
 360        mid = AllocMidQEntry(hdr, server);
 361        if (mid == NULL)
 362                return -ENOMEM;
 363
 364        rc = cifs_sign_smbv(iov, nvec, server, &mid->sequence_number);
 365        if (rc) {
 366                DeleteMidQEntry(mid);
 367                return rc;
 368        }
 369
 370        *ret_mid = mid;
 371        return 0;
 372}
 373
 374/*
 375 * Send a SMB request and set the callback function in the mid to handle
 376 * the result. Caller is responsible for dealing with timeouts.
 377 */
 378int
 379cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
 380                unsigned int nvec, mid_receive_t *receive,
 381                mid_callback_t *callback, void *cbdata, const int flags)
 382{
 383        int rc, timeout, optype;
 384        struct mid_q_entry *mid;
 385
 386        timeout = flags & CIFS_TIMEOUT_MASK;
 387        optype = flags & CIFS_OP_MASK;
 388
 389        rc = wait_for_free_request(server, timeout, optype);
 390        if (rc)
 391                return rc;
 392
 393        mutex_lock(&server->srv_mutex);
 394        rc = server->ops->setup_async_request(server, iov, nvec, &mid);
 395        if (rc) {
 396                mutex_unlock(&server->srv_mutex);
 397                add_credits(server, 1, optype);
 398                wake_up(&server->request_q);
 399                return rc;
 400        }
 401
 402        mid->receive = receive;
 403        mid->callback = callback;
 404        mid->callback_data = cbdata;
 405        mid->mid_state = MID_REQUEST_SUBMITTED;
 406
 407        /* put it on the pending_mid_q */
 408        spin_lock(&GlobalMid_Lock);
 409        list_add_tail(&mid->qhead, &server->pending_mid_q);
 410        spin_unlock(&GlobalMid_Lock);
 411
 412
 413        cifs_in_send_inc(server);
 414        rc = smb_sendv(server, iov, nvec);
 415        cifs_in_send_dec(server);
 416        cifs_save_when_sent(mid);
 417        mutex_unlock(&server->srv_mutex);
 418
 419        if (rc == 0)
 420                return 0;
 421
 422        delete_mid(mid);
 423        add_credits(server, 1, optype);
 424        wake_up(&server->request_q);
 425        return rc;
 426}
 427
 428/*
 429 *
 430 * Send an SMB Request.  No response info (other than return code)
 431 * needs to be parsed.
 432 *
 433 * flags indicate the type of request buffer and how long to wait
 434 * and whether to log NT STATUS code (error) before mapping it to POSIX error
 435 *
 436 */
 437int
 438SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
 439                 char *in_buf, int flags)
 440{
 441        int rc;
 442        struct kvec iov[1];
 443        int resp_buf_type;
 444
 445        iov[0].iov_base = in_buf;
 446        iov[0].iov_len = get_rfc1002_length(in_buf) + 4;
 447        flags |= CIFS_NO_RESP;
 448        rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
 449        cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
 450
 451        return rc;
 452}
 453
 454static int
 455cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
 456{
 457        int rc = 0;
 458
 459        cFYI(1, "%s: cmd=%d mid=%llu state=%d", __func__,
 460             le16_to_cpu(mid->command), mid->mid, mid->mid_state);
 461
 462        spin_lock(&GlobalMid_Lock);
 463        switch (mid->mid_state) {
 464        case MID_RESPONSE_RECEIVED:
 465                spin_unlock(&GlobalMid_Lock);
 466                return rc;
 467        case MID_RETRY_NEEDED:
 468                rc = -EAGAIN;
 469                break;
 470        case MID_RESPONSE_MALFORMED:
 471                rc = -EIO;
 472                break;
 473        case MID_SHUTDOWN:
 474                rc = -EHOSTDOWN;
 475                break;
 476        default:
 477                list_del_init(&mid->qhead);
 478                cERROR(1, "%s: invalid mid state mid=%llu state=%d", __func__,
 479                       mid->mid, mid->mid_state);
 480                rc = -EIO;
 481        }
 482        spin_unlock(&GlobalMid_Lock);
 483
 484        DeleteMidQEntry(mid);
 485        return rc;
 486}
 487
 488static inline int
 489send_cancel(struct TCP_Server_Info *server, void *buf, struct mid_q_entry *mid)
 490{
 491        return server->ops->send_cancel ?
 492                                server->ops->send_cancel(server, buf, mid) : 0;
 493}
 494
 495int
 496cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
 497                   bool log_error)
 498{
 499        unsigned int len = get_rfc1002_length(mid->resp_buf) + 4;
 500
 501        dump_smb(mid->resp_buf, min_t(u32, 92, len));
 502
 503        /* convert the length into a more usable form */
 504        if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
 505                struct kvec iov;
 506                int rc = 0;
 507
 508                iov.iov_base = mid->resp_buf;
 509                iov.iov_len = len;
 510                /* FIXME: add code to kill session */
 511                rc = cifs_verify_signature(&iov, 1, server,
 512                                           mid->sequence_number + 1);
 513                if (rc)
 514                        cERROR(1, "SMB signature verification returned error = "
 515                               "%d", rc);
 516        }
 517
 518        /* BB special case reconnect tid and uid here? */
 519        return map_smb_to_linux_error(mid->resp_buf, log_error);
 520}
 521
 522int
 523cifs_setup_request(struct cifs_ses *ses, struct kvec *iov,
 524                   unsigned int nvec, struct mid_q_entry **ret_mid)
 525{
 526        int rc;
 527        struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base;
 528        struct mid_q_entry *mid;
 529
 530        rc = allocate_mid(ses, hdr, &mid);
 531        if (rc)
 532                return rc;
 533        rc = cifs_sign_smbv(iov, nvec, ses->server, &mid->sequence_number);
 534        if (rc)
 535                delete_mid(mid);
 536        *ret_mid = mid;
 537        return rc;
 538}
 539
 540int
 541SendReceive2(const unsigned int xid, struct cifs_ses *ses,
 542             struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
 543             const int flags)
 544{
 545        int rc = 0;
 546        int timeout, optype;
 547        struct mid_q_entry *midQ;
 548        char *buf = iov[0].iov_base;
 549        unsigned int credits = 1;
 550
 551        timeout = flags & CIFS_TIMEOUT_MASK;
 552        optype = flags & CIFS_OP_MASK;
 553
 554        *resp_buf_type = CIFS_NO_BUFFER;  /* no response buf yet */
 555
 556        if ((ses == NULL) || (ses->server == NULL)) {
 557                cifs_small_buf_release(buf);
 558                cERROR(1, "Null session");
 559                return -EIO;
 560        }
 561
 562        if (ses->server->tcpStatus == CifsExiting) {
 563                cifs_small_buf_release(buf);
 564                return -ENOENT;
 565        }
 566
 567        /*
 568         * Ensure that we do not send more than 50 overlapping requests
 569         * to the same server. We may make this configurable later or
 570         * use ses->maxReq.
 571         */
 572
 573        rc = wait_for_free_request(ses->server, timeout, optype);
 574        if (rc) {
 575                cifs_small_buf_release(buf);
 576                return rc;
 577        }
 578
 579        /*
 580         * Make sure that we sign in the same order that we send on this socket
 581         * and avoid races inside tcp sendmsg code that could cause corruption
 582         * of smb data.
 583         */
 584
 585        mutex_lock(&ses->server->srv_mutex);
 586
 587        rc = ses->server->ops->setup_request(ses, iov, n_vec, &midQ);
 588        if (rc) {
 589                mutex_unlock(&ses->server->srv_mutex);
 590                cifs_small_buf_release(buf);
 591                /* Update # of requests on wire to server */
 592                add_credits(ses->server, 1, optype);
 593                return rc;
 594        }
 595
 596        midQ->mid_state = MID_REQUEST_SUBMITTED;
 597        cifs_in_send_inc(ses->server);
 598        rc = smb_sendv(ses->server, iov, n_vec);
 599        cifs_in_send_dec(ses->server);
 600        cifs_save_when_sent(midQ);
 601
 602        mutex_unlock(&ses->server->srv_mutex);
 603
 604        if (rc < 0) {
 605                cifs_small_buf_release(buf);
 606                goto out;
 607        }
 608
 609        if (timeout == CIFS_ASYNC_OP) {
 610                cifs_small_buf_release(buf);
 611                goto out;
 612        }
 613
 614        rc = wait_for_response(ses->server, midQ);
 615        if (rc != 0) {
 616                send_cancel(ses->server, buf, midQ);
 617                spin_lock(&GlobalMid_Lock);
 618                if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
 619                        midQ->callback = DeleteMidQEntry;
 620                        spin_unlock(&GlobalMid_Lock);
 621                        cifs_small_buf_release(buf);
 622                        add_credits(ses->server, 1, optype);
 623                        return rc;
 624                }
 625                spin_unlock(&GlobalMid_Lock);
 626        }
 627
 628        cifs_small_buf_release(buf);
 629
 630        rc = cifs_sync_mid_result(midQ, ses->server);
 631        if (rc != 0) {
 632                add_credits(ses->server, 1, optype);
 633                return rc;
 634        }
 635
 636        if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) {
 637                rc = -EIO;
 638                cFYI(1, "Bad MID state?");
 639                goto out;
 640        }
 641
 642        buf = (char *)midQ->resp_buf;
 643        iov[0].iov_base = buf;
 644        iov[0].iov_len = get_rfc1002_length(buf) + 4;
 645        if (midQ->large_buf)
 646                *resp_buf_type = CIFS_LARGE_BUFFER;
 647        else
 648                *resp_buf_type = CIFS_SMALL_BUFFER;
 649
 650        credits = ses->server->ops->get_credits(midQ);
 651
 652        rc = ses->server->ops->check_receive(midQ, ses->server,
 653                                             flags & CIFS_LOG_ERROR);
 654
 655        /* mark it so buf will not be freed by delete_mid */
 656        if ((flags & CIFS_NO_RESP) == 0)
 657                midQ->resp_buf = NULL;
 658out:
 659        delete_mid(midQ);
 660        add_credits(ses->server, credits, optype);
 661
 662        return rc;
 663}
 664
 665int
 666SendReceive(const unsigned int xid, struct cifs_ses *ses,
 667            struct smb_hdr *in_buf, struct smb_hdr *out_buf,
 668            int *pbytes_returned, const int timeout)
 669{
 670        int rc = 0;
 671        struct mid_q_entry *midQ;
 672
 673        if (ses == NULL) {
 674                cERROR(1, "Null smb session");
 675                return -EIO;
 676        }
 677        if (ses->server == NULL) {
 678                cERROR(1, "Null tcp session");
 679                return -EIO;
 680        }
 681
 682        if (ses->server->tcpStatus == CifsExiting)
 683                return -ENOENT;
 684
 685        /* Ensure that we do not send more than 50 overlapping requests
 686           to the same server. We may make this configurable later or
 687           use ses->maxReq */
 688
 689        if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
 690                        MAX_CIFS_HDR_SIZE - 4) {
 691                cERROR(1, "Illegal length, greater than maximum frame, %d",
 692                           be32_to_cpu(in_buf->smb_buf_length));
 693                return -EIO;
 694        }
 695
 696        rc = wait_for_free_request(ses->server, timeout, 0);
 697        if (rc)
 698                return rc;
 699
 700        /* make sure that we sign in the same order that we send on this socket
 701           and avoid races inside tcp sendmsg code that could cause corruption
 702           of smb data */
 703
 704        mutex_lock(&ses->server->srv_mutex);
 705
 706        rc = allocate_mid(ses, in_buf, &midQ);
 707        if (rc) {
 708                mutex_unlock(&ses->server->srv_mutex);
 709                /* Update # of requests on wire to server */
 710                add_credits(ses->server, 1, 0);
 711                return rc;
 712        }
 713
 714        rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
 715        if (rc) {
 716                mutex_unlock(&ses->server->srv_mutex);
 717                goto out;
 718        }
 719
 720        midQ->mid_state = MID_REQUEST_SUBMITTED;
 721
 722        cifs_in_send_inc(ses->server);
 723        rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
 724        cifs_in_send_dec(ses->server);
 725        cifs_save_when_sent(midQ);
 726        mutex_unlock(&ses->server->srv_mutex);
 727
 728        if (rc < 0)
 729                goto out;
 730
 731        if (timeout == CIFS_ASYNC_OP)
 732                goto out;
 733
 734        rc = wait_for_response(ses->server, midQ);
 735        if (rc != 0) {
 736                send_cancel(ses->server, in_buf, midQ);
 737                spin_lock(&GlobalMid_Lock);
 738                if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
 739                        /* no longer considered to be "in-flight" */
 740                        midQ->callback = DeleteMidQEntry;
 741                        spin_unlock(&GlobalMid_Lock);
 742                        add_credits(ses->server, 1, 0);
 743                        return rc;
 744                }
 745                spin_unlock(&GlobalMid_Lock);
 746        }
 747
 748        rc = cifs_sync_mid_result(midQ, ses->server);
 749        if (rc != 0) {
 750                add_credits(ses->server, 1, 0);
 751                return rc;
 752        }
 753
 754        if (!midQ->resp_buf || !out_buf ||
 755            midQ->mid_state != MID_RESPONSE_RECEIVED) {
 756                rc = -EIO;
 757                cERROR(1, "Bad MID state?");
 758                goto out;
 759        }
 760
 761        *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
 762        memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
 763        rc = cifs_check_receive(midQ, ses->server, 0);
 764out:
 765        delete_mid(midQ);
 766        add_credits(ses->server, 1, 0);
 767
 768        return rc;
 769}
 770
 771/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
 772   blocking lock to return. */
 773
 774static int
 775send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
 776                        struct smb_hdr *in_buf,
 777                        struct smb_hdr *out_buf)
 778{
 779        int bytes_returned;
 780        struct cifs_ses *ses = tcon->ses;
 781        LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
 782
 783        /* We just modify the current in_buf to change
 784           the type of lock from LOCKING_ANDX_SHARED_LOCK
 785           or LOCKING_ANDX_EXCLUSIVE_LOCK to
 786           LOCKING_ANDX_CANCEL_LOCK. */
 787
 788        pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
 789        pSMB->Timeout = 0;
 790        pSMB->hdr.Mid = get_next_mid(ses->server);
 791
 792        return SendReceive(xid, ses, in_buf, out_buf,
 793                        &bytes_returned, 0);
 794}
 795
 796int
 797SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
 798            struct smb_hdr *in_buf, struct smb_hdr *out_buf,
 799            int *pbytes_returned)
 800{
 801        int rc = 0;
 802        int rstart = 0;
 803        struct mid_q_entry *midQ;
 804        struct cifs_ses *ses;
 805
 806        if (tcon == NULL || tcon->ses == NULL) {
 807                cERROR(1, "Null smb session");
 808                return -EIO;
 809        }
 810        ses = tcon->ses;
 811
 812        if (ses->server == NULL) {
 813                cERROR(1, "Null tcp session");
 814                return -EIO;
 815        }
 816
 817        if (ses->server->tcpStatus == CifsExiting)
 818                return -ENOENT;
 819
 820        /* Ensure that we do not send more than 50 overlapping requests
 821           to the same server. We may make this configurable later or
 822           use ses->maxReq */
 823
 824        if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
 825                        MAX_CIFS_HDR_SIZE - 4) {
 826                cERROR(1, "Illegal length, greater than maximum frame, %d",
 827                           be32_to_cpu(in_buf->smb_buf_length));
 828                return -EIO;
 829        }
 830
 831        rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, 0);
 832        if (rc)
 833                return rc;
 834
 835        /* make sure that we sign in the same order that we send on this socket
 836           and avoid races inside tcp sendmsg code that could cause corruption
 837           of smb data */
 838
 839        mutex_lock(&ses->server->srv_mutex);
 840
 841        rc = allocate_mid(ses, in_buf, &midQ);
 842        if (rc) {
 843                mutex_unlock(&ses->server->srv_mutex);
 844                return rc;
 845        }
 846
 847        rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
 848        if (rc) {
 849                delete_mid(midQ);
 850                mutex_unlock(&ses->server->srv_mutex);
 851                return rc;
 852        }
 853
 854        midQ->mid_state = MID_REQUEST_SUBMITTED;
 855        cifs_in_send_inc(ses->server);
 856        rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
 857        cifs_in_send_dec(ses->server);
 858        cifs_save_when_sent(midQ);
 859        mutex_unlock(&ses->server->srv_mutex);
 860
 861        if (rc < 0) {
 862                delete_mid(midQ);
 863                return rc;
 864        }
 865
 866        /* Wait for a reply - allow signals to interrupt. */
 867        rc = wait_event_interruptible(ses->server->response_q,
 868                (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) ||
 869                ((ses->server->tcpStatus != CifsGood) &&
 870                 (ses->server->tcpStatus != CifsNew)));
 871
 872        /* Were we interrupted by a signal ? */
 873        if ((rc == -ERESTARTSYS) &&
 874                (midQ->mid_state == MID_REQUEST_SUBMITTED) &&
 875                ((ses->server->tcpStatus == CifsGood) ||
 876                 (ses->server->tcpStatus == CifsNew))) {
 877
 878                if (in_buf->Command == SMB_COM_TRANSACTION2) {
 879                        /* POSIX lock. We send a NT_CANCEL SMB to cause the
 880                           blocking lock to return. */
 881                        rc = send_cancel(ses->server, in_buf, midQ);
 882                        if (rc) {
 883                                delete_mid(midQ);
 884                                return rc;
 885                        }
 886                } else {
 887                        /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
 888                           to cause the blocking lock to return. */
 889
 890                        rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
 891
 892                        /* If we get -ENOLCK back the lock may have
 893                           already been removed. Don't exit in this case. */
 894                        if (rc && rc != -ENOLCK) {
 895                                delete_mid(midQ);
 896                                return rc;
 897                        }
 898                }
 899
 900                rc = wait_for_response(ses->server, midQ);
 901                if (rc) {
 902                        send_cancel(ses->server, in_buf, midQ);
 903                        spin_lock(&GlobalMid_Lock);
 904                        if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
 905                                /* no longer considered to be "in-flight" */
 906                                midQ->callback = DeleteMidQEntry;
 907                                spin_unlock(&GlobalMid_Lock);
 908                                return rc;
 909                        }
 910                        spin_unlock(&GlobalMid_Lock);
 911                }
 912
 913                /* We got the response - restart system call. */
 914                rstart = 1;
 915        }
 916
 917        rc = cifs_sync_mid_result(midQ, ses->server);
 918        if (rc != 0)
 919                return rc;
 920
 921        /* rcvd frame is ok */
 922        if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) {
 923                rc = -EIO;
 924                cERROR(1, "Bad MID state?");
 925                goto out;
 926        }
 927
 928        *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
 929        memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
 930        rc = cifs_check_receive(midQ, ses->server, 0);
 931out:
 932        delete_mid(midQ);
 933        if (rstart && rc == -EACCES)
 934                return -ERESTARTSYS;
 935        return rc;
 936}
 937
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.