1 /*
   2  * Copyright (c) 2000-2001 Boris Popov
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. All advertising materials mentioning features or use of this software
  14  *    must display the following acknowledgement:
  15  *    This product includes software developed by Boris Popov.
  16  * 4. Neither the name of the author nor the names of any co-contributors
  17  *    may be used to endorse or promote products derived from this software
  18  *    without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30  * SUCH DAMAGE.
  31  *
  32  * $Id: smb_iod.c,v 1.32 2005/02/12 00:17:09 lindak Exp $
  33  */
  34 
  35 /*
  36  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  37  * Use is subject to license terms.
  38  */
  39 
  40 #ifdef DEBUG
  41 /* See sys/queue.h */
  42 #define QUEUEDEBUG 1
  43 #endif
  44 
  45 #include <sys/param.h>
  46 #include <sys/systm.h>
  47 #include <sys/atomic.h>
  48 #include <sys/proc.h>
  49 #include <sys/thread.h>
  50 #include <sys/file.h>
  51 #include <sys/kmem.h>
  52 #include <sys/unistd.h>
  53 #include <sys/mount.h>
  54 #include <sys/vnode.h>
  55 #include <sys/types.h>
  56 #include <sys/ddi.h>
  57 #include <sys/sunddi.h>
  58 #include <sys/stream.h>
  59 #include <sys/strsun.h>
  60 #include <sys/time.h>
  61 #include <sys/class.h>
  62 #include <sys/disp.h>
  63 #include <sys/cmn_err.h>
  64 #include <sys/zone.h>
  65 #include <sys/sdt.h>
  66 
  67 #include <netsmb/smb_osdep.h>
  68 
  69 #include <netsmb/smb.h>
  70 #include <netsmb/smb_conn.h>
  71 #include <netsmb/smb_rq.h>
  72 #include <netsmb/smb_subr.h>
  73 #include <netsmb/smb_tran.h>
  74 #include <netsmb/smb_trantcp.h>
  75 
  76 int smb_iod_send_echo(smb_vc_t *);
  77 
  78 /*
  79  * This is set/cleared when smbfs loads/unloads
  80  * No locks should be necessary, because smbfs
  81  * can't unload until all the mounts are gone.
  82  */
  83 static smb_fscb_t *fscb;
  84 void
  85 smb_fscb_set(smb_fscb_t *cb)
  86 {
  87         fscb = cb;
  88 }
  89 
  90 static void
  91 smb_iod_share_disconnected(smb_share_t *ssp)
  92 {
  93 
  94         smb_share_invalidate(ssp);
  95 
  96         /* smbfs_dead() */
  97         if (fscb && fscb->fscb_disconn) {
  98                 fscb->fscb_disconn(ssp);
  99         }
 100 }
 101 
 102 /*
 103  * State changes are important and infrequent.
 104  * Make them easily observable via dtrace.
 105  */
 106 void
 107 smb_iod_newstate(struct smb_vc *vcp, int state)
 108 {
 109         vcp->vc_state = state;
 110 }
 111 
 112 /* Lock Held version of the next function. */
 113 static inline void
 114 smb_iod_rqprocessed_LH(
 115         struct smb_rq *rqp,
 116         int error,
 117         int flags)
 118 {
 119         rqp->sr_flags |= flags;
 120         rqp->sr_lerror = error;
 121         rqp->sr_rpgen++;
 122         rqp->sr_state = SMBRQ_NOTIFIED;
 123         cv_broadcast(&rqp->sr_cond);
 124 }
 125 
 126 static void
 127 smb_iod_rqprocessed(
 128         struct smb_rq *rqp,
 129         int error,
 130         int flags)
 131 {
 132 
 133         SMBRQ_LOCK(rqp);
 134         smb_iod_rqprocessed_LH(rqp, error, flags);
 135         SMBRQ_UNLOCK(rqp);
 136 }
 137 
 138 static void
 139 smb_iod_invrq(struct smb_vc *vcp)
 140 {
 141         struct smb_rq *rqp;
 142 
 143         /*
 144          * Invalidate all outstanding requests for this connection
 145          */
 146         rw_enter(&vcp->iod_rqlock, RW_READER);
 147         TAILQ_FOREACH(rqp, &vcp->iod_rqlist, sr_link) {
 148                 smb_iod_rqprocessed(rqp, ENOTCONN, SMBR_RESTART);
 149         }
 150         rw_exit(&vcp->iod_rqlock);
 151 }
 152 
 153 /*
 154  * Called by smb_vc_rele, smb_vc_kill, and by the driver
 155  * close entry point if the IOD closes its dev handle.
 156  *
 157  * Forcibly kill the connection and IOD.
 158  */
 159 void
 160 smb_iod_disconnect(struct smb_vc *vcp)
 161 {
 162 
 163         /*
 164          * Inform everyone of the state change.
 165          */
 166         SMB_VC_LOCK(vcp);
 167         if (vcp->vc_state != SMBIOD_ST_DEAD) {
 168                 smb_iod_newstate(vcp, SMBIOD_ST_DEAD);
 169                 cv_broadcast(&vcp->vc_statechg);
 170         }
 171         SMB_VC_UNLOCK(vcp);
 172 
 173         /*
 174          * Let's be safe here and avoid doing any
 175          * call across the network while trying to
 176          * shut things down.  If we just disconnect,
 177          * the server will take care of the logoff.
 178          */
 179         SMB_TRAN_DISCONNECT(vcp);
 180 
 181         /*
 182          * If we have an IOD, it should immediately notice
 183          * that its connection has closed.  But in case
 184          * it doesn't, let's also send it a signal.
 185          */
 186         SMB_VC_LOCK(vcp);
 187         if (vcp->iod_thr != NULL &&
 188             vcp->iod_thr != curthread) {
 189                 tsignal(vcp->iod_thr, SIGKILL);
 190         }
 191         SMB_VC_UNLOCK(vcp);
 192 }
 193 
 194 /*
 195  * Send one request.
 196  *
 197  * Called by _addrq (for internal requests)
 198  * and _sendall (via _addrq, _multirq, _waitrq)
 199  */
 200 static int
 201 smb_iod_sendrq(struct smb_rq *rqp)
 202 {
 203         struct smb_vc *vcp = rqp->sr_vc;
 204         mblk_t *m;
 205         int error;
 206 
 207         ASSERT(vcp);
 208         ASSERT(SEMA_HELD(&vcp->vc_sendlock));
 209         ASSERT(RW_READ_HELD(&vcp->iod_rqlock));
 210 
 211         /*
 212          * Note: Anything special for SMBR_INTERNAL here?
 213          */
 214         if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
 215                 SMBIODEBUG("bad vc_state=%d\n", vcp->vc_state);
 216                 return (ENOTCONN);
 217         }
 218 
 219 
 220         /*
 221          * On the first send, set the MID and (maybe)
 222          * the signing sequence numbers.  The increments
 223          * here are serialized by vc_sendlock
 224          */
 225         if (rqp->sr_sendcnt == 0) {
 226 
 227                 rqp->sr_mid = vcp->vc_next_mid++;
 228 
 229                 if (rqp->sr_rqflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) {
 230                         /*
 231                          * We're signing requests and verifying
 232                          * signatures on responses.  Set the
 233                          * sequence numbers of the request and
 234                          * response here, used in smb_rq_verify.
 235                          */
 236                         rqp->sr_seqno = vcp->vc_next_seq++;
 237                         rqp->sr_rseqno = vcp->vc_next_seq++;
 238                 }
 239 
 240                 /* Fill in UID, TID, MID, etc. */
 241                 smb_rq_fillhdr(rqp);
 242 
 243                 /*
 244                  * Sign the message now that we're finally done
 245                  * filling in the SMB header fields, etc.
 246                  */
 247                 if (rqp->sr_rqflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) {
 248                         smb_rq_sign(rqp);
 249                 }
 250         }
 251         if (rqp->sr_sendcnt++ >= 60/SMBSBTIMO) { /* one minute */
 252                 smb_iod_rqprocessed(rqp, rqp->sr_lerror, SMBR_RESTART);
 253                 /*
 254                  * If all attempts to send a request failed, then
 255                  * something is seriously hosed.
 256                  */
 257                 return (ENOTCONN);
 258         }
 259 
 260         /*
 261          * Replaced m_copym() with Solaris copymsg() which does the same
 262          * work when we want to do a M_COPYALL.
 263          * m = m_copym(rqp->sr_rq.mb_top, 0, M_COPYALL, 0);
 264          */
 265         m = copymsg(rqp->sr_rq.mb_top);
 266 
 267 #ifdef DTRACE_PROBE
 268         DTRACE_PROBE2(smb_iod_sendrq,
 269             (smb_rq_t *), rqp, (mblk_t *), m);
 270 #else
 271         SMBIODEBUG("M:%04x, P:%04x, U:%04x, T:%04x\n", rqp->sr_mid, 0, 0, 0);
 272 #endif
 273         m_dumpm(m);
 274 
 275         if (m != NULL) {
 276                 error = SMB_TRAN_SEND(vcp, m);
 277                 m = 0; /* consumed by SEND */
 278         } else
 279                 error = ENOBUFS;
 280 
 281         rqp->sr_lerror = error;
 282         if (error == 0) {
 283                 SMBRQ_LOCK(rqp);
 284                 rqp->sr_flags |= SMBR_SENT;
 285                 rqp->sr_state = SMBRQ_SENT;
 286                 if (rqp->sr_flags & SMBR_SENDWAIT)
 287                         cv_broadcast(&rqp->sr_cond);
 288                 SMBRQ_UNLOCK(rqp);
 289                 return (0);
 290         }
 291         /*
 292          * Check for fatal errors
 293          */
 294         if (SMB_TRAN_FATAL(vcp, error)) {
 295                 /*
 296                  * No further attempts should be made
 297                  */
 298                 SMBSDEBUG("TRAN_SEND returned fatal error %d\n", error);
 299                 return (ENOTCONN);
 300         }
 301         if (error)
 302                 SMBSDEBUG("TRAN_SEND returned non-fatal error %d\n", error);
 303 
 304 #ifdef APPLE
 305         /* If proc waiting on rqp was signaled... */
 306         if (smb_rq_intr(rqp))
 307                 smb_iod_rqprocessed(rqp, EINTR, 0);
 308 #endif
 309 
 310         return (0);
 311 }
 312 
 313 static int
 314 smb_iod_recv1(struct smb_vc *vcp, mblk_t **mpp)
 315 {
 316         mblk_t *m;
 317         uchar_t *hp;
 318         int error;
 319 
 320 top:
 321         m = NULL;
 322         error = SMB_TRAN_RECV(vcp, &m);
 323         if (error == EAGAIN)
 324                 goto top;
 325         if (error)
 326                 return (error);
 327         ASSERT(m);
 328 
 329         m = m_pullup(m, SMB_HDRLEN);
 330         if (m == NULL) {
 331                 return (ENOSR);
 332         }
 333 
 334         /*
 335          * Check the SMB header
 336          */
 337         hp = mtod(m, uchar_t *);
 338         if (bcmp(hp, SMB_SIGNATURE, SMB_SIGLEN) != 0) {
 339                 m_freem(m);
 340                 return (EPROTO);
 341         }
 342 
 343         *mpp = m;
 344         return (0);
 345 }
 346 
 347 /*
 348  * Process incoming packets
 349  *
 350  * This is the "reader" loop, run by the IOD thread
 351  * while in state SMBIOD_ST_VCACTIVE.  The loop now
 352  * simply blocks in the socket recv until either a
 353  * message arrives, or a disconnect.
 354  *
 355  * Any non-zero error means the IOD should terminate.
 356  */
 357 int
 358 smb_iod_recvall(struct smb_vc *vcp)
 359 {
 360         struct smb_rq *rqp;
 361         mblk_t *m;
 362         uchar_t *hp;
 363         ushort_t mid;
 364         int error = 0;
 365         int etime_count = 0; /* for "server not responding", etc. */
 366 
 367         for (;;) {
 368                 /*
 369                  * Check whether someone "killed" this VC,
 370                  * or is asking the IOD to terminate.
 371                  */
 372 
 373                 if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
 374                         SMBIODEBUG("bad vc_state=%d\n", vcp->vc_state);
 375                         error = 0;
 376                         break;
 377                 }
 378 
 379                 if (vcp->iod_flags & SMBIOD_SHUTDOWN) {
 380                         SMBIODEBUG("SHUTDOWN set\n");
 381                         /* This IOD thread will terminate. */
 382                         SMB_VC_LOCK(vcp);
 383                         smb_iod_newstate(vcp, SMBIOD_ST_DEAD);
 384                         cv_broadcast(&vcp->vc_statechg);
 385                         SMB_VC_UNLOCK(vcp);
 386                         error = EINTR;
 387                         break;
 388                 }
 389 
 390                 m = NULL;
 391                 error = smb_iod_recv1(vcp, &m);
 392 
 393                 if (error == ETIME &&
 394                     vcp->iod_rqlist.tqh_first != NULL) {
 395                         /*
 396                          * Nothing received for 15 seconds and
 397                          * we have requests in the queue.
 398                          */
 399                         etime_count++;
 400 
 401                         /*
 402                          * Once, at 15 sec. notify callbacks
 403                          * and print the warning message.
 404                          */
 405                         if (etime_count == 1) {
 406                                 /* Was: smb_iod_notify_down(vcp); */
 407                                 if (fscb && fscb->fscb_down)
 408                                         smb_vc_walkshares(vcp,
 409                                             fscb->fscb_down);
 410                                 zprintf(vcp->vc_zoneid,
 411                                     "SMB server %s not responding\n",
 412                                     vcp->vc_srvname);
 413                         }
 414 
 415                         /*
 416                          * At 30 sec. try sending an echo, and then
 417                          * once a minute thereafter.
 418                          */
 419                         if ((etime_count & 3) == 2) {
 420                                 (void) smb_iod_send_echo(vcp);
 421                         }
 422 
 423                         continue;
 424                 } /* ETIME && requests in queue */
 425 
 426                 if (error == ETIME) {
 427                         /*
 428                          * If the IOD thread holds the last reference
 429                          * to this VC, let the IOD thread terminate.
 430                          */
 431                         if (vcp->vc_co.co_usecount > 1)
 432                                 continue;
 433                         SMB_VC_LOCK(vcp);
 434                         if (vcp->vc_co.co_usecount == 1) {
 435                                 smb_iod_newstate(vcp, SMBIOD_ST_DEAD);
 436                                 SMB_VC_UNLOCK(vcp);
 437                                 error = 0;
 438                                 break;
 439                         }
 440                         SMB_VC_UNLOCK(vcp);
 441                         continue;
 442                 } /* error == ETIME */
 443 
 444                 if (error) {
 445                         /*
 446                          * The recv. above returned some error
 447                          * we can't continue from i.e. ENOTCONN.
 448                          * It's dangerous to continue here.
 449                          * (possible infinite loop!)
 450                          *
 451                          * If we have requests enqueued, next
 452                          * state is reconnecting, else idle.
 453                          */
 454                         int state;
 455                         SMB_VC_LOCK(vcp);
 456                         state = (vcp->iod_rqlist.tqh_first != NULL) ?
 457                             SMBIOD_ST_RECONNECT : SMBIOD_ST_IDLE;
 458                         smb_iod_newstate(vcp, state);
 459                         cv_broadcast(&vcp->vc_statechg);
 460                         SMB_VC_UNLOCK(vcp);
 461                         error = 0;
 462                         break;
 463                 }
 464 
 465                 /*
 466                  * Received something.  Yea!
 467                  */
 468                 if (etime_count) {
 469                         etime_count = 0;
 470 
 471                         zprintf(vcp->vc_zoneid, "SMB server %s OK\n",
 472                             vcp->vc_srvname);
 473 
 474                         /* Was: smb_iod_notify_up(vcp); */
 475                         if (fscb && fscb->fscb_up)
 476                                 smb_vc_walkshares(vcp, fscb->fscb_up);
 477                 }
 478 
 479                 /*
 480                  * Have an SMB packet.  The SMB header was
 481                  * checked in smb_iod_recv1().
 482                  * Find the request...
 483                  */
 484                 hp = mtod(m, uchar_t *);
 485                 /*LINTED*/
 486                 mid = letohs(SMB_HDRMID(hp));
 487                 SMBIODEBUG("mid %04x\n", (uint_t)mid);
 488 
 489                 rw_enter(&vcp->iod_rqlock, RW_READER);
 490                 TAILQ_FOREACH(rqp, &vcp->iod_rqlist, sr_link) {
 491 
 492                         if (rqp->sr_mid != mid)
 493                                 continue;
 494 
 495                         DTRACE_PROBE2(smb_iod_recvrq,
 496                             (smb_rq_t *), rqp, (mblk_t *), m);
 497                         m_dumpm(m);
 498 
 499                         SMBRQ_LOCK(rqp);
 500                         if (rqp->sr_rp.md_top == NULL) {
 501                                 md_initm(&rqp->sr_rp, m);
 502                         } else {
 503                                 if (rqp->sr_flags & SMBR_MULTIPACKET) {
 504                                         md_append_record(&rqp->sr_rp, m);
 505                                 } else {
 506                                         SMBRQ_UNLOCK(rqp);
 507                                         SMBSDEBUG("duplicate response %d "
 508                                             "(ignored)\n", mid);
 509                                         break;
 510                                 }
 511                         }
 512                         smb_iod_rqprocessed_LH(rqp, 0, 0);
 513                         SMBRQ_UNLOCK(rqp);
 514                         break;
 515                 }
 516 
 517                 if (rqp == NULL) {
 518                         int cmd = SMB_HDRCMD(hp);
 519 
 520                         if (cmd != SMB_COM_ECHO)
 521                                 SMBSDEBUG("drop resp: mid %d, cmd %d\n",
 522                                     (uint_t)mid, cmd);
 523 /*                      smb_printrqlist(vcp); */
 524                         m_freem(m);
 525                 }
 526                 rw_exit(&vcp->iod_rqlock);
 527 
 528         }
 529 
 530         return (error);
 531 }
 532 
 533 /*
 534  * The IOD receiver thread has requests pending and
 535  * has not received anything in a while.  Try to
 536  * send an SMB echo request.  It's tricky to do a
 537  * send from the IOD thread because we can't block.
 538  *
 539  * Using tmo=SMBNOREPLYWAIT in the request
 540  * so smb_rq_reply will skip smb_iod_waitrq.
 541  * The smb_smb_echo call uses SMBR_INTERNAL
 542  * to avoid calling smb_iod_sendall().
 543  */
 544 int
 545 smb_iod_send_echo(smb_vc_t *vcp)
 546 {
 547         smb_cred_t scred;
 548         int err;
 549 
 550         smb_credinit(&scred, NULL);
 551         err = smb_smb_echo(vcp, &scred, SMBNOREPLYWAIT);
 552         smb_credrele(&scred);
 553         return (err);
 554 }
 555 
 556 /*
 557  * The IOD thread is now just a "reader",
 558  * so no more smb_iod_request().  Yea!
 559  */
 560 
 561 /*
 562  * Place request in the queue, and send it now if possible.
 563  * Called with no locks held.
 564  */
 565 int
 566 smb_iod_addrq(struct smb_rq *rqp)
 567 {
 568         struct smb_vc *vcp = rqp->sr_vc;
 569         int error, save_newrq;
 570 
 571         ASSERT(rqp->sr_cred);
 572 
 573         /*
 574          * State should be correct after the check in
 575          * smb_rq_enqueue(), but we dropped locks...
 576          */
 577         if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
 578                 SMBIODEBUG("bad vc_state=%d\n", vcp->vc_state);
 579                 return (ENOTCONN);
 580         }
 581 
 582         /*
 583          * Requests from the IOD itself are marked _INTERNAL,
 584          * and get some special treatment to avoid blocking
 585          * the reader thread (so we don't deadlock).
 586          * The request is not yet on the queue, so we can
 587          * modify it's state here without locks.
 588          * Only thing using this now is ECHO.
 589          */
 590         rqp->sr_owner = curthread;
 591         if (rqp->sr_owner == vcp->iod_thr) {
 592                 rqp->sr_flags |= SMBR_INTERNAL;
 593 
 594                 /*
 595                  * This is a request from the IOD thread.
 596                  * Always send directly from this thread.
 597                  * Note lock order: iod_rqlist, vc_sendlock
 598                  */
 599                 rw_enter(&vcp->iod_rqlock, RW_WRITER);
 600                 TAILQ_INSERT_HEAD(&vcp->iod_rqlist, rqp, sr_link);
 601                 rw_downgrade(&vcp->iod_rqlock);
 602 
 603                 /*
 604                  * Note: iod_sendrq expects vc_sendlock,
 605                  * so take that here, but carefully:
 606                  * Never block the IOD thread here.
 607                  */
 608                 if (sema_tryp(&vcp->vc_sendlock) == 0) {
 609                         SMBIODEBUG("sendlock busy\n");
 610                         error = EAGAIN;
 611                 } else {
 612                         /* Have vc_sendlock */
 613                         error = smb_iod_sendrq(rqp);
 614                         sema_v(&vcp->vc_sendlock);
 615                 }
 616 
 617                 rw_exit(&vcp->iod_rqlock);
 618 
 619                 /*
 620                  * In the non-error case, _removerq
 621                  * is done by either smb_rq_reply
 622                  * or smb_iod_waitrq.
 623                  */
 624                 if (error)
 625                         smb_iod_removerq(rqp);
 626 
 627                 return (error);
 628         }
 629 
 630         rw_enter(&vcp->iod_rqlock, RW_WRITER);
 631 
 632         TAILQ_INSERT_TAIL(&vcp->iod_rqlist, rqp, sr_link);
 633         /* iod_rqlock/WRITER protects iod_newrq */
 634         save_newrq = vcp->iod_newrq;
 635         vcp->iod_newrq++;
 636 
 637         rw_exit(&vcp->iod_rqlock);
 638 
 639         /*
 640          * Now send any requests that need to be sent,
 641          * including the one we just put on the list.
 642          * Only the thread that found iod_newrq==0
 643          * needs to run the send loop.
 644          */
 645         if (save_newrq == 0)
 646                 smb_iod_sendall(vcp);
 647 
 648         return (0);
 649 }
 650 
 651 /*
 652  * Mark an SMBR_MULTIPACKET request as
 653  * needing another send.  Similar to the
 654  * "normal" part of smb_iod_addrq.
 655  */
 656 int
 657 smb_iod_multirq(struct smb_rq *rqp)
 658 {
 659         struct smb_vc *vcp = rqp->sr_vc;
 660         int save_newrq;
 661 
 662         ASSERT(rqp->sr_flags & SMBR_MULTIPACKET);
 663 
 664         if (rqp->sr_flags & SMBR_INTERNAL)
 665                 return (EINVAL);
 666 
 667         if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
 668                 SMBIODEBUG("bad vc_state=%d\n", vcp->vc_state);
 669                 return (ENOTCONN);
 670         }
 671 
 672         rw_enter(&vcp->iod_rqlock, RW_WRITER);
 673 
 674         /* Already on iod_rqlist, just reset state. */
 675         rqp->sr_state = SMBRQ_NOTSENT;
 676 
 677         /* iod_rqlock/WRITER protects iod_newrq */
 678         save_newrq = vcp->iod_newrq;
 679         vcp->iod_newrq++;
 680 
 681         rw_exit(&vcp->iod_rqlock);
 682 
 683         /*
 684          * Now send any requests that need to be sent,
 685          * including the one we just marked NOTSENT.
 686          * Only the thread that found iod_newrq==0
 687          * needs to run the send loop.
 688          */
 689         if (save_newrq == 0)
 690                 smb_iod_sendall(vcp);
 691 
 692         return (0);
 693 }
 694 
 695 
 696 void
 697 smb_iod_removerq(struct smb_rq *rqp)
 698 {
 699         struct smb_vc *vcp = rqp->sr_vc;
 700 
 701         rw_enter(&vcp->iod_rqlock, RW_WRITER);
 702 #ifdef QUEUEDEBUG
 703         /*
 704          * Make sure we have not already removed it.
 705          * See sys/queue.h QUEUEDEBUG_TAILQ_POSTREMOVE
 706          * XXX: Don't like the constant 1 here...
 707          */
 708         ASSERT(rqp->sr_link.tqe_next != (void *)1L);
 709 #endif
 710         TAILQ_REMOVE(&vcp->iod_rqlist, rqp, sr_link);
 711         rw_exit(&vcp->iod_rqlock);
 712 }
 713 
 714 
 715 
 716 /*
 717  * Wait for a request to complete.
 718  *
 719  * For normal requests, we need to deal with
 720  * ioc_muxcnt dropping below vc_maxmux by
 721  * making arrangements to send more...
 722  */
 723 int
 724 smb_iod_waitrq(struct smb_rq *rqp)
 725 {
 726         struct smb_vc *vcp = rqp->sr_vc;
 727         clock_t tr, tmo1, tmo2;
 728         int error, rc;
 729 
 730         if (rqp->sr_flags & SMBR_INTERNAL) {
 731                 ASSERT((rqp->sr_flags & SMBR_MULTIPACKET) == 0);
 732                 smb_iod_removerq(rqp);
 733                 return (EAGAIN);
 734         }
 735 
 736         /*
 737          * Make sure this is NOT the IOD thread,
 738          * or the wait below will stop the reader.
 739          */
 740         ASSERT(curthread != vcp->iod_thr);
 741 
 742         SMBRQ_LOCK(rqp);
 743 
 744         /*
 745          * First, wait for the request to be sent.  Normally the send
 746          * has already happened by the time we get here.  However, if
 747          * we have more than maxmux entries in the request list, our
 748          * request may not be sent until other requests complete.
 749          * The wait in this case is due to local I/O demands, so
 750          * we don't want the server response timeout to apply.
 751          *
 752          * If a request is allowed to interrupt this wait, then the
 753          * request is cancelled and never sent OTW.  Some kinds of
 754          * requests should never be cancelled (i.e. close) and those
 755          * are marked SMBR_NOINTR_SEND so they either go eventually,
 756          * or a connection close will terminate them with ENOTCONN.
 757          */
 758         while (rqp->sr_state == SMBRQ_NOTSENT) {
 759                 rqp->sr_flags |= SMBR_SENDWAIT;
 760                 if (rqp->sr_flags & SMBR_NOINTR_SEND) {
 761                         cv_wait(&rqp->sr_cond, &rqp->sr_lock);
 762                         rc = 1;
 763                 } else
 764                         rc = cv_wait_sig(&rqp->sr_cond, &rqp->sr_lock);
 765                 rqp->sr_flags &= ~SMBR_SENDWAIT;
 766                 if (rc == 0) {
 767                         SMBIODEBUG("EINTR in sendwait, rqp=%p\n", rqp);
 768                         error = EINTR;
 769                         goto out;
 770                 }
 771         }
 772 
 773         /*
 774          * The request has been sent.  Now wait for the response,
 775          * with the timeout specified for this request.
 776          * Compute all the deadlines now, so we effectively
 777          * start the timer(s) after the request is sent.
 778          */
 779         if (smb_timo_notice && (smb_timo_notice < rqp->sr_timo))
 780                 tmo1 = SEC_TO_TICK(smb_timo_notice);
 781         else
 782                 tmo1 = 0;
 783         tmo2 = ddi_get_lbolt() + SEC_TO_TICK(rqp->sr_timo);
 784 
 785         /*
 786          * As above, we don't want to allow interrupt for some
 787          * requests like open, because we could miss a succesful
 788          * response and therefore "leak" a FID.  Such requests
 789          * are marked SMBR_NOINTR_RECV to prevent that.
 790          *
 791          * If "slow server" warnings are enabled, wait first
 792          * for the "notice" timeout, and warn if expired.
 793          */
 794         if (tmo1 && rqp->sr_rpgen == rqp->sr_rplast) {
 795                 if (rqp->sr_flags & SMBR_NOINTR_RECV)
 796                         tr = cv_reltimedwait(&rqp->sr_cond,
 797                             &rqp->sr_lock, tmo1, TR_CLOCK_TICK);
 798                 else
 799                         tr = cv_reltimedwait_sig(&rqp->sr_cond,
 800                             &rqp->sr_lock, tmo1, TR_CLOCK_TICK);
 801                 if (tr == 0) {
 802                         error = EINTR;
 803                         goto out;
 804                 }
 805                 if (tr < 0) {
 806 #ifdef DTRACE_PROBE
 807                         DTRACE_PROBE1(smb_iod_waitrq1,
 808                             (smb_rq_t *), rqp);
 809 #endif
 810 #ifdef NOT_YET
 811                         /* Want this to go ONLY to the user. */
 812                         uprintf("SMB server %s has not responded"
 813                             " to request %d after %d seconds..."
 814                             " (still waiting).\n", vcp->vc_srvname,
 815                             rqp->sr_mid, smb_timo_notice);
 816 #endif
 817                 }
 818         }
 819 
 820         /*
 821          * Keep waiting until tmo2 is expired.
 822          */
 823         while (rqp->sr_rpgen == rqp->sr_rplast) {
 824                 if (rqp->sr_flags & SMBR_NOINTR_RECV)
 825                         tr = cv_timedwait(&rqp->sr_cond,
 826                             &rqp->sr_lock, tmo2);
 827                 else
 828                         tr = cv_timedwait_sig(&rqp->sr_cond,
 829                             &rqp->sr_lock, tmo2);
 830                 if (tr == 0) {
 831                         error = EINTR;
 832                         goto out;
 833                 }
 834                 if (tr < 0) {
 835 #ifdef DTRACE_PROBE
 836                         DTRACE_PROBE1(smb_iod_waitrq2,
 837                             (smb_rq_t *), rqp);
 838 #endif
 839 #ifdef NOT_YET
 840                         /* Want this to go ONLY to the user. */
 841                         uprintf("SMB server %s has not responded"
 842                             " to request %d after %d seconds..."
 843                             " (giving up).\n", vcp->vc_srvname,
 844                             rqp->sr_mid, rqp->sr_timo);
 845 #endif
 846                         error = ETIME;
 847                         goto out;
 848                 }
 849                 /* got wakeup */
 850         }
 851         error = rqp->sr_lerror;
 852         rqp->sr_rplast++;
 853 
 854 out:
 855         SMBRQ_UNLOCK(rqp);
 856 
 857         /*
 858          * MULTIPACKET request must stay in the list.
 859          * They may need additional responses.
 860          */
 861         if ((rqp->sr_flags & SMBR_MULTIPACKET) == 0)
 862                 smb_iod_removerq(rqp);
 863 
 864         /*
 865          * Some request has been completed.
 866          * If we reached the mux limit,
 867          * re-run the send loop...
 868          */
 869         if (vcp->iod_muxfull)
 870                 smb_iod_sendall(vcp);
 871 
 872         return (error);
 873 }
 874 
 875 /*
 876  * Shutdown all outstanding I/O requests on the specified share with
 877  * ENXIO; used when unmounting a share.  (There shouldn't be any for a
 878  * non-forced unmount; if this is a forced unmount, we have to shutdown
 879  * the requests as part of the unmount process.)
 880  */
 881 void
 882 smb_iod_shutdown_share(struct smb_share *ssp)
 883 {
 884         struct smb_vc *vcp = SSTOVC(ssp);
 885         struct smb_rq *rqp;
 886 
 887         /*
 888          * Loop through the list of requests and shutdown the ones
 889          * that are for the specified share.
 890          */
 891         rw_enter(&vcp->iod_rqlock, RW_READER);
 892         TAILQ_FOREACH(rqp, &vcp->iod_rqlist, sr_link) {
 893                 if (rqp->sr_state != SMBRQ_NOTIFIED && rqp->sr_share == ssp)
 894                         smb_iod_rqprocessed(rqp, EIO, 0);
 895         }
 896         rw_exit(&vcp->iod_rqlock);
 897 }
 898 
 899 /*
 900  * Send all requests that need sending.
 901  * Called from _addrq, _multirq, _waitrq
 902  */
 903 void
 904 smb_iod_sendall(smb_vc_t *vcp)
 905 {
 906         struct smb_rq *rqp;
 907         int error, muxcnt;
 908 
 909         /*
 910          * Clear "newrq" to make sure threads adding
 911          * new requests will run this function again.
 912          */
 913         rw_enter(&vcp->iod_rqlock, RW_WRITER);
 914         vcp->iod_newrq = 0;
 915 
 916         /*
 917          * We only read iod_rqlist, so downgrade rwlock.
 918          * This allows the IOD to handle responses while
 919          * some requesting thread may be blocked in send.
 920          */
 921         rw_downgrade(&vcp->iod_rqlock);
 922 
 923         /*
 924          * Serialize to prevent multiple senders.
 925          * Note lock order: iod_rqlock, vc_sendlock
 926          */
 927         sema_p(&vcp->vc_sendlock);
 928 
 929         /*
 930          * Walk the list of requests and send when possible.
 931          * We avoid having more than vc_maxmux requests
 932          * outstanding to the server by traversing only
 933          * vc_maxmux entries into this list.  Simple!
 934          */
 935         ASSERT(vcp->vc_maxmux > 0);
 936         error = muxcnt = 0;
 937         TAILQ_FOREACH(rqp, &vcp->iod_rqlist, sr_link) {
 938 
 939                 if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
 940                         error = ENOTCONN; /* stop everything! */
 941                         break;
 942                 }
 943 
 944                 if (rqp->sr_state == SMBRQ_NOTSENT) {
 945                         error = smb_iod_sendrq(rqp);
 946                         if (error)
 947                                 break;
 948                 }
 949 
 950                 if (++muxcnt == vcp->vc_maxmux) {
 951                         SMBIODEBUG("muxcnt == vc_maxmux\n");
 952                         break;
 953                 }
 954 
 955         }
 956 
 957         /*
 958          * If we have vc_maxmux requests outstanding,
 959          * arrange for _waitrq to call _sendall as
 960          * requests are completed.
 961          */
 962         vcp->iod_muxfull =
 963             (muxcnt < vcp->vc_maxmux) ? 0 : 1;
 964 
 965         sema_v(&vcp->vc_sendlock);
 966         rw_exit(&vcp->iod_rqlock);
 967 }
 968 
 969 int
 970 smb_iod_vc_work(struct smb_vc *vcp, cred_t *cr)
 971 {
 972         struct file *fp = NULL;
 973         int err = 0;
 974 
 975         /*
 976          * This is called by the one-and-only
 977          * IOD thread for this VC.
 978          */
 979         ASSERT(vcp->iod_thr == curthread);
 980 
 981         /*
 982          * Get the network transport file pointer,
 983          * and "loan" it to our transport module.
 984          */
 985         if ((fp = getf(vcp->vc_tran_fd)) == NULL) {
 986                 err = EBADF;
 987                 goto out;
 988         }
 989         if ((err = SMB_TRAN_LOAN_FP(vcp, fp, cr)) != 0)
 990                 goto out;
 991 
 992         /*
 993          * In case of reconnect, tell any enqueued requests
 994          * then can GO!
 995          */
 996         SMB_VC_LOCK(vcp);
 997         vcp->vc_genid++;     /* possibly new connection */
 998         smb_iod_newstate(vcp, SMBIOD_ST_VCACTIVE);
 999         cv_broadcast(&vcp->vc_statechg);
1000         SMB_VC_UNLOCK(vcp);
1001 
1002         /*
1003          * The above cv_broadcast should be sufficient to
1004          * get requests going again.
1005          *
1006          * If we have a callback function, run it.
1007          * Was: smb_iod_notify_connected()
1008          */
1009         if (fscb && fscb->fscb_connect)
1010                 smb_vc_walkshares(vcp, fscb->fscb_connect);
1011 
1012         /*
1013          * Run the "reader" loop.
1014          */
1015         err = smb_iod_recvall(vcp);
1016 
1017         /*
1018          * The reader loop returned, so we must have a
1019          * new state.  (disconnected or reconnecting)
1020          *
1021          * Notify shares of the disconnect.
1022          * Was: smb_iod_notify_disconnect()
1023          */
1024         smb_vc_walkshares(vcp, smb_iod_share_disconnected);
1025 
1026         /*
1027          * The reader loop function returns only when
1028          * there's been an error on the connection, or
1029          * this VC has no more references.  It also
1030          * updates the state before it returns.
1031          *
1032          * Tell any requests to give up or restart.
1033          */
1034         smb_iod_invrq(vcp);
1035 
1036 out:
1037         /* Recall the file descriptor loan. */
1038         (void) SMB_TRAN_LOAN_FP(vcp, NULL, cr);
1039         if (fp != NULL) {
1040                 releasef(vcp->vc_tran_fd);
1041         }
1042 
1043         return (err);
1044 }
1045 
1046 /*
1047  * Wait around for someone to ask to use this VC.
1048  * If the VC has only the IOD reference, then
1049  * wait only a minute or so, then drop it.
1050  */
1051 int
1052 smb_iod_vc_idle(struct smb_vc *vcp)
1053 {
1054         clock_t tr, delta = SEC_TO_TICK(15);
1055         int err = 0;
1056 
1057         /*
1058          * This is called by the one-and-only
1059          * IOD thread for this VC.
1060          */
1061         ASSERT(vcp->iod_thr == curthread);
1062 
1063         SMB_VC_LOCK(vcp);
1064         while (vcp->vc_state == SMBIOD_ST_IDLE) {
1065                 tr = cv_reltimedwait_sig(&vcp->iod_idle, &vcp->vc_lock,
1066                     delta, TR_CLOCK_TICK);
1067                 if (tr == 0) {
1068                         err = EINTR;
1069                         break;
1070                 }
1071                 if (tr < 0) {
1072                         /* timeout */
1073                         if (vcp->vc_co.co_usecount == 1) {
1074                                 /* Let this IOD terminate. */
1075                                 smb_iod_newstate(vcp, SMBIOD_ST_DEAD);
1076                                 /* nobody to cv_broadcast */
1077                                 break;
1078                         }
1079                 }
1080         }
1081         SMB_VC_UNLOCK(vcp);
1082 
1083         return (err);
1084 }
1085 
1086 /*
1087  * After a failed reconnect attempt, smbiod will
1088  * call this to make current requests error out.
1089  */
1090 int
1091 smb_iod_vc_rcfail(struct smb_vc *vcp)
1092 {
1093         clock_t tr;
1094         int err = 0;
1095 
1096         /*
1097          * This is called by the one-and-only
1098          * IOD thread for this VC.
1099          */
1100         ASSERT(vcp->iod_thr == curthread);
1101 
1102         if (vcp->vc_state != SMBIOD_ST_RECONNECT)
1103                 return (EINVAL);
1104 
1105         SMB_VC_LOCK(vcp);
1106 
1107         smb_iod_newstate(vcp, SMBIOD_ST_RCFAILED);
1108         cv_broadcast(&vcp->vc_statechg);
1109 
1110         /*
1111          * Short wait here for two reasons:
1112          * (1) Give requests a chance to error out.
1113          * (2) Prevent immediate retry.
1114          */
1115         tr = cv_reltimedwait_sig(&vcp->iod_idle, &vcp->vc_lock,
1116             SEC_TO_TICK(5), TR_CLOCK_TICK);
1117         if (tr == 0)
1118                 err = EINTR;
1119 
1120         smb_iod_newstate(vcp, SMBIOD_ST_IDLE);
1121         cv_broadcast(&vcp->vc_statechg);
1122 
1123         SMB_VC_UNLOCK(vcp);
1124 
1125         return (err);
1126 }
1127 
1128 /*
1129  * Ask the IOD to reconnect (if not already underway)
1130  * then wait for the reconnect to finish.
1131  */
1132 int
1133 smb_iod_reconnect(struct smb_vc *vcp)
1134 {
1135         int err = 0, rv;
1136 
1137         SMB_VC_LOCK(vcp);
1138 again:
1139         switch (vcp->vc_state) {
1140 
1141         case SMBIOD_ST_IDLE:
1142                 smb_iod_newstate(vcp, SMBIOD_ST_RECONNECT);
1143                 cv_signal(&vcp->iod_idle);
1144                 /* FALLTHROUGH */
1145 
1146         case SMBIOD_ST_RECONNECT:
1147                 rv = cv_wait_sig(&vcp->vc_statechg, &vcp->vc_lock);
1148                 if (rv == 0) {
1149                         err = EINTR;
1150                         break;
1151                 }
1152                 goto again;
1153 
1154         case SMBIOD_ST_VCACTIVE:
1155                 err = 0; /* success! */
1156                 break;
1157 
1158         case SMBIOD_ST_RCFAILED:
1159         case SMBIOD_ST_DEAD:
1160         default:
1161                 err = ENOTCONN;
1162                 break;
1163         }
1164 
1165         SMB_VC_UNLOCK(vcp);
1166         return (err);
1167 }