4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Copyright (c) 2000-2001 Boris Popov
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * All rights reserved.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Redistribution and use in source and binary forms, with or without
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * modification, are permitted provided that the following conditions
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * are met:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 1. Redistributions of source code must retain the above copyright
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * notice, this list of conditions and the following disclaimer.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 2. Redistributions in binary form must reproduce the above copyright
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * notice, this list of conditions and the following disclaimer in the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * documentation and/or other materials provided with the distribution.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 3. All advertising materials mentioning features or use of this software
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * must display the following acknowledgement:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This product includes software developed by Boris Popov.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 4. Neither the name of the author nor the names of any co-contributors
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * may be used to endorse or promote products derived from this software
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * without specific prior written permission.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * SUCH DAMAGE.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * $Id: smb_iod.c,v 1.32 2005/02/12 00:17:09 lindak Exp $
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
42645588b93573e79aaead58bdaf7857c3736401Gordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
42645588b93573e79aaead58bdaf7857c3736401Gordon Ross * Use is subject to license terms.
42645588b93573e79aaead58bdaf7857c3736401Gordon Ross */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef DEBUG
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/* See sys/queue.h */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#define QUEUEDEBUG 1
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/param.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/systm.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/atomic.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/proc.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/thread.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <sys/file.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/kmem.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/unistd.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/mount.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/vnode.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/types.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/ddi.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/sunddi.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/stream.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/strsun.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/time.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/class.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/disp.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/cmn_err.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/zone.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/sdt.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_osdep.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_conn.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_rq.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_subr.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_tran.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_trantcp.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint smb_iod_send_echo(smb_vc_t *);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This is set/cleared when smbfs loads/unloads
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * No locks should be necessary, because smbfs
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * can't unload until all the mounts are gone.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic smb_fscb_t *fscb;
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Rossvoid
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_fscb_set(smb_fscb_t *cb)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow fscb = cb;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic void
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_iod_share_disconnected(smb_share_t *ssp)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_share_invalidate(ssp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* smbfs_dead() */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (fscb && fscb->fscb_disconn) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross fscb->fscb_disconn(ssp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * State changes are important and infrequent.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Make them easily observable via dtrace.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossvoid
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_iod_newstate(struct smb_vc *vcp, int state)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross vcp->vc_state = state;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/* Lock Held version of the next function. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic inline void
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_iod_rqprocessed_LH(
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int flags)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_flags |= flags;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_lerror = error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_rpgen++;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_state = SMBRQ_NOTIFIED;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow cv_broadcast(&rqp->sr_cond);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic void
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_iod_rqprocessed(
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int flags)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBRQ_LOCK(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_iod_rqprocessed_LH(rqp, error, flags);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBRQ_UNLOCK(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic void
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_iod_invrq(struct smb_vc *vcp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Invalidate all outstanding requests for this connection
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_enter(&vcp->iod_rqlock, RW_READER);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow TAILQ_FOREACH(rqp, &vcp->iod_rqlist, sr_link) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_iod_rqprocessed(rqp, ENOTCONN, SMBR_RESTART);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_exit(&vcp->iod_rqlock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Called by smb_vc_rele, smb_vc_kill, and by the driver
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * close entry point if the IOD closes its dev handle.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Forcibly kill the connection and IOD.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Rossvoid
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_iod_disconnect(struct smb_vc *vcp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Inform everyone of the state change.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (vcp->vc_state != SMBIOD_ST_DEAD) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_iod_newstate(vcp, SMBIOD_ST_DEAD);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross cv_broadcast(&vcp->vc_statechg);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Let's be safe here and avoid doing any
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * call across the network while trying to
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * shut things down. If we just disconnect,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the server will take care of the logoff.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross SMB_TRAN_DISCONNECT(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * If we have an IOD, it should immediately notice
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * that its connection has closed. But in case
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * it doesn't, let's also send it a signal.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
3ce9ce383e93f64f4baed13c5a0a28d7a5f1b71eBayard Bell SMB_VC_LOCK(vcp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (vcp->iod_thr != NULL &&
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross vcp->iod_thr != curthread) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross tsignal(vcp->iod_thr, SIGKILL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
3ce9ce383e93f64f4baed13c5a0a28d7a5f1b71eBayard Bell SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Send one request.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Called by _addrq (for internal requests)
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * and _sendall (via _addrq, _multirq, _waitrq)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_iod_sendrq(struct smb_rq *rqp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_vc *vcp = rqp->sr_vc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mblk_t *m;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(SEMA_HELD(&vcp->vc_sendlock));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(RW_READ_HELD(&vcp->iod_rqlock));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Note: Anything special for SMBR_INTERNAL here?
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross SMBIODEBUG("bad vc_state=%d\n", vcp->vc_state);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (ENOTCONN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * On the first send, set the MID and (maybe)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * the signing sequence numbers. The increments
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * here are serialized by vc_sendlock
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp->sr_sendcnt == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rqp->sr_mid = vcp->vc_next_mid++;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (rqp->sr_rqflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * We're signing requests and verifying
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * signatures on responses. Set the
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * sequence numbers of the request and
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * response here, used in smb_rq_verify.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rqp->sr_seqno = vcp->vc_next_seq++;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rqp->sr_rseqno = vcp->vc_next_seq++;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Fill in UID, TID, MID, etc. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_rq_fillhdr(rqp);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross /*
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * Sign the message now that we're finally done
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross * filling in the SMB header fields, etc.
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross */
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross if (rqp->sr_rqflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross smb_rq_sign(rqp);
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp->sr_sendcnt++ >= 60/SMBSBTIMO) { /* one minute */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_iod_rqprocessed(rqp, rqp->sr_lerror, SMBR_RESTART);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If all attempts to send a request failed, then
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * something is seriously hosed.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (ENOTCONN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Replaced m_copym() with Solaris copymsg() which does the same
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * work when we want to do a M_COPYALL.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * m = m_copym(rqp->sr_rq.mb_top, 0, M_COPYALL, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m = copymsg(rqp->sr_rq.mb_top);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef DTRACE_PROBE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow DTRACE_PROBE2(smb_iod_sendrq,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (smb_rq_t *), rqp, (mblk_t *), m);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#else
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBIODEBUG("M:%04x, P:%04x, U:%04x, T:%04x\n", rqp->sr_mid, 0, 0, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m_dumpm(m);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (m != NULL) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross error = SMB_TRAN_SEND(vcp, m);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross m = 0; /* consumed by SEND */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross } else
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross error = ENOBUFS;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rqp->sr_lerror = error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBRQ_LOCK(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_flags |= SMBR_SENT;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_state = SMBRQ_SENT;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp->sr_flags & SMBR_SENDWAIT)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow cv_broadcast(&rqp->sr_cond);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBRQ_UNLOCK(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Check for fatal errors
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (SMB_TRAN_FATAL(vcp, error)) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * No further attempts should be made
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("TRAN_SEND returned fatal error %d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (ENOTCONN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("TRAN_SEND returned non-fatal error %d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef APPLE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* If proc waiting on rqp was signaled... */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (smb_rq_intr(rqp))
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_iod_rqprocessed(rqp, EINTR, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_iod_recv1(struct smb_vc *vcp, mblk_t **mpp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mblk_t *m;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uchar_t *hp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowtop:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m = NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross error = SMB_TRAN_RECV(vcp, &m);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error == EAGAIN)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto top;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(m);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m = m_pullup(m, SMB_HDRLEN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (m == NULL) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (ENOSR);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Check the SMB header
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow hp = mtod(m, uchar_t *);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (bcmp(hp, SMB_SIGNATURE, SMB_SIGLEN) != 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m_freem(m);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EPROTO);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *mpp = m;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Process incoming packets
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This is the "reader" loop, run by the IOD thread
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * while in state SMBIOD_ST_VCACTIVE. The loop now
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * simply blocks in the socket recv until either a
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * message arrives, or a disconnect.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Any non-zero error means the IOD should terminate.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_iod_recvall(struct smb_vc *vcp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mblk_t *m;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uchar_t *hp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ushort_t mid;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int error = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int etime_count = 0; /* for "server not responding", etc. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow for (;;) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Check whether someone "killed" this VC,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * or is asking the IOD to terminate.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBIODEBUG("bad vc_state=%d\n", vcp->vc_state);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross error = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->iod_flags & SMBIOD_SHUTDOWN) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBIODEBUG("SHUTDOWN set\n");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* This IOD thread will terminate. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross SMB_VC_LOCK(vcp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_iod_newstate(vcp, SMBIOD_ST_DEAD);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross cv_broadcast(&vcp->vc_statechg);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross SMB_VC_UNLOCK(vcp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross error = EINTR;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_iod_recv1(vcp, &m);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (error == ETIME &&
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross vcp->iod_rqlist.tqh_first != NULL) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Nothing received for 15 seconds and
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * we have requests in the queue.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow etime_count++;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Once, at 15 sec. notify callbacks
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * and print the warning message.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (etime_count == 1) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Was: smb_iod_notify_down(vcp); */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (fscb && fscb->fscb_down)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_vc_walkshares(vcp,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross fscb->fscb_down);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow zprintf(vcp->vc_zoneid,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow "SMB server %s not responding\n",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_srvname);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * At 30 sec. try sending an echo, and then
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * once a minute thereafter.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((etime_count & 3) == 2) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross (void) smb_iod_send_echo(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow continue;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross } /* ETIME && requests in queue */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error == ETIME) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If the IOD thread holds the last reference
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * to this VC, let the IOD thread terminate.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_co.co_usecount > 1)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow continue;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (vcp->vc_co.co_usecount == 1) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_iod_newstate(vcp, SMBIOD_ST_DEAD);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross error = 0;
42645588b93573e79aaead58bdaf7857c3736401Gordon Ross break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow continue;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } /* error == ETIME */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * The recv. above returned some error
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * we can't continue from i.e. ENOTCONN.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * It's dangerous to continue here.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * (possible infinite loop!)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * If we have requests enqueued, next
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * state is reconnecting, else idle.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int state;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross SMB_VC_LOCK(vcp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross state = (vcp->iod_rqlist.tqh_first != NULL) ?
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross SMBIOD_ST_RECONNECT : SMBIOD_ST_IDLE;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_iod_newstate(vcp, state);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross cv_broadcast(&vcp->vc_statechg);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross SMB_VC_UNLOCK(vcp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross error = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Received something. Yea!
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (etime_count) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow etime_count = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow zprintf(vcp->vc_zoneid, "SMB server %s OK\n",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_srvname);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Was: smb_iod_notify_up(vcp); */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (fscb && fscb->fscb_up)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_vc_walkshares(vcp, fscb->fscb_up);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Have an SMB packet. The SMB header was
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * checked in smb_iod_recv1().
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Find the request...
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow hp = mtod(m, uchar_t *);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mid = letohs(SMB_HDRMID(hp));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBIODEBUG("mid %04x\n", (uint_t)mid);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_enter(&vcp->iod_rqlock, RW_READER);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow TAILQ_FOREACH(rqp, &vcp->iod_rqlist, sr_link) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp->sr_mid != mid)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow continue;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow DTRACE_PROBE2(smb_iod_recvrq,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (smb_rq_t *), rqp, (mblk_t *), m);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m_dumpm(m);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBRQ_LOCK(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp->sr_rp.md_top == NULL) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_initm(&rqp->sr_rp, m);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp->sr_flags & SMBR_MULTIPACKET) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow md_append_record(&rqp->sr_rp, m);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBRQ_UNLOCK(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("duplicate response %d "
4bff34e37def8a90f9194d81bc345c52ba20086athurlow "(ignored)\n", mid);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_iod_rqprocessed_LH(rqp, 0, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBRQ_UNLOCK(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp == NULL) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int cmd = SMB_HDRCMD(hp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (cmd != SMB_COM_ECHO)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBSDEBUG("drop resp: mid %d, cmd %d\n",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (uint_t)mid, cmd);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/* smb_printrqlist(vcp); */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m_freem(m);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_exit(&vcp->iod_rqlock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * The IOD receiver thread has requests pending and
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * has not received anything in a while. Try to
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * send an SMB echo request. It's tricky to do a
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * send from the IOD thread because we can't block.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Using tmo=SMBNOREPLYWAIT in the request
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * so smb_rq_reply will skip smb_iod_waitrq.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * The smb_smb_echo call uses SMBR_INTERNAL
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * to avoid calling smb_iod_sendall().
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_iod_send_echo(smb_vc_t *vcp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_cred_t scred;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int err;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_credinit(&scred, NULL);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_smb_echo(vcp, &scred, SMBNOREPLYWAIT);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_credrele(&scred);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * The IOD thread is now just a "reader",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * so no more smb_iod_request(). Yea!
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Place request in the queue, and send it now if possible.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Called with no locks held.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_iod_addrq(struct smb_rq *rqp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_vc *vcp = rqp->sr_vc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error, save_newrq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(rqp->sr_cred);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * State should be correct after the check in
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * smb_rq_enqueue(), but we dropped locks...
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross SMBIODEBUG("bad vc_state=%d\n", vcp->vc_state);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (ENOTCONN);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Requests from the IOD itself are marked _INTERNAL,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * and get some special treatment to avoid blocking
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * the reader thread (so we don't deadlock).
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * The request is not yet on the queue, so we can
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * modify it's state here without locks.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Only thing using this now is ECHO.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_owner = curthread;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (rqp->sr_owner == vcp->iod_thr) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rqp->sr_flags |= SMBR_INTERNAL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * This is a request from the IOD thread.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Always send directly from this thread.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Note lock order: iod_rqlist, vc_sendlock
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_enter(&vcp->iod_rqlock, RW_WRITER);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow TAILQ_INSERT_HEAD(&vcp->iod_rqlist, rqp, sr_link);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_downgrade(&vcp->iod_rqlock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Note: iod_sendrq expects vc_sendlock,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * so take that here, but carefully:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Never block the IOD thread here.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (sema_tryp(&vcp->vc_sendlock) == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross SMBIODEBUG("sendlock busy\n");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross error = EAGAIN;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Have vc_sendlock */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_iod_sendrq(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sema_v(&vcp->vc_sendlock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_exit(&vcp->iod_rqlock);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * In the non-error case, _removerq
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * is done by either smb_rq_reply
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * or smb_iod_waitrq.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_iod_removerq(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_enter(&vcp->iod_rqlock, RW_WRITER);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow TAILQ_INSERT_TAIL(&vcp->iod_rqlist, rqp, sr_link);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* iod_rqlock/WRITER protects iod_newrq */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow save_newrq = vcp->iod_newrq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->iod_newrq++;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_exit(&vcp->iod_rqlock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Now send any requests that need to be sent,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * including the one we just put on the list.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Only the thread that found iod_newrq==0
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * needs to run the send loop.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (save_newrq == 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_iod_sendall(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Mark an SMBR_MULTIPACKET request as
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * needing another send. Similar to the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * "normal" part of smb_iod_addrq.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_iod_multirq(struct smb_rq *rqp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_vc *vcp = rqp->sr_vc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int save_newrq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(rqp->sr_flags & SMBR_MULTIPACKET);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp->sr_flags & SMBR_INTERNAL)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EINVAL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBIODEBUG("bad vc_state=%d\n", vcp->vc_state);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (ENOTCONN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_enter(&vcp->iod_rqlock, RW_WRITER);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Already on iod_rqlist, just reset state. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_state = SMBRQ_NOTSENT;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* iod_rqlock/WRITER protects iod_newrq */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow save_newrq = vcp->iod_newrq;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->iod_newrq++;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_exit(&vcp->iod_rqlock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Now send any requests that need to be sent,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * including the one we just marked NOTSENT.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Only the thread that found iod_newrq==0
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * needs to run the send loop.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (save_newrq == 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_iod_sendall(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Rossvoid
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_iod_removerq(struct smb_rq *rqp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_vc *vcp = rqp->sr_vc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_enter(&vcp->iod_rqlock, RW_WRITER);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef QUEUEDEBUG
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Make sure we have not already removed it.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * See sys/queue.h QUEUEDEBUG_TAILQ_POSTREMOVE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * XXX: Don't like the constant 1 here...
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(rqp->sr_link.tqe_next != (void *)1L);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow TAILQ_REMOVE(&vcp->iod_rqlist, rqp, sr_link);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_exit(&vcp->iod_rqlock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Wait for a request to complete.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * For normal requests, we need to deal with
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * ioc_muxcnt dropping below vc_maxmux by
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * making arrangements to send more...
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_iod_waitrq(struct smb_rq *rqp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_vc *vcp = rqp->sr_vc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow clock_t tr, tmo1, tmo2;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error, rc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp->sr_flags & SMBR_INTERNAL) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT((rqp->sr_flags & SMBR_MULTIPACKET) == 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_iod_removerq(rqp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (EAGAIN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Make sure this is NOT the IOD thread,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * or the wait below will stop the reader.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(curthread != vcp->iod_thr);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBRQ_LOCK(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * First, wait for the request to be sent. Normally the send
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * has already happened by the time we get here. However, if
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * we have more than maxmux entries in the request list, our
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * request may not be sent until other requests complete.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * The wait in this case is due to local I/O demands, so
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * we don't want the server response timeout to apply.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If a request is allowed to interrupt this wait, then the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * request is cancelled and never sent OTW. Some kinds of
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * requests should never be cancelled (i.e. close) and those
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * are marked SMBR_NOINTR_SEND so they either go eventually,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * or a connection close will terminate them with ENOTCONN.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow while (rqp->sr_state == SMBRQ_NOTSENT) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_flags |= SMBR_SENDWAIT;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp->sr_flags & SMBR_NOINTR_SEND) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow cv_wait(&rqp->sr_cond, &rqp->sr_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rc = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rc = cv_wait_sig(&rqp->sr_cond, &rqp->sr_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_flags &= ~SMBR_SENDWAIT;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rc == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross SMBIODEBUG("EINTR in sendwait, rqp=%p\n", rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EINTR;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto out;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * The request has been sent. Now wait for the response,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * with the timeout specified for this request.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Compute all the deadlines now, so we effectively
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * start the timer(s) after the request is sent.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (smb_timo_notice && (smb_timo_notice < rqp->sr_timo))
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni tmo1 = SEC_TO_TICK(smb_timo_notice);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tmo1 = 0;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni tmo2 = ddi_get_lbolt() + SEC_TO_TICK(rqp->sr_timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * As above, we don't want to allow interrupt for some
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * requests like open, because we could miss a succesful
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * response and therefore "leak" a FID. Such requests
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * are marked SMBR_NOINTR_RECV to prevent that.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If "slow server" warnings are enabled, wait first
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * for the "notice" timeout, and warn if expired.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (tmo1 && rqp->sr_rpgen == rqp->sr_rplast) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp->sr_flags & SMBR_NOINTR_RECV)
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni tr = cv_reltimedwait(&rqp->sr_cond,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &rqp->sr_lock, tmo1, TR_CLOCK_TICK);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni tr = cv_reltimedwait_sig(&rqp->sr_cond,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &rqp->sr_lock, tmo1, TR_CLOCK_TICK);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (tr == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EINTR;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto out;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (tr < 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef DTRACE_PROBE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow DTRACE_PROBE1(smb_iod_waitrq1,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (smb_rq_t *), rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef NOT_YET
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Want this to go ONLY to the user. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uprintf("SMB server %s has not responded"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow " to request %d after %d seconds..."
4bff34e37def8a90f9194d81bc345c52ba20086athurlow " (still waiting).\n", vcp->vc_srvname,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_mid, smb_timo_notice);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Keep waiting until tmo2 is expired.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow while (rqp->sr_rpgen == rqp->sr_rplast) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp->sr_flags & SMBR_NOINTR_RECV)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tr = cv_timedwait(&rqp->sr_cond,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow &rqp->sr_lock, tmo2);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tr = cv_timedwait_sig(&rqp->sr_cond,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow &rqp->sr_lock, tmo2);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (tr == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EINTR;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto out;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (tr < 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef DTRACE_PROBE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow DTRACE_PROBE1(smb_iod_waitrq2,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (smb_rq_t *), rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef NOT_YET
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Want this to go ONLY to the user. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uprintf("SMB server %s has not responded"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow " to request %d after %d seconds..."
4bff34e37def8a90f9194d81bc345c52ba20086athurlow " (giving up).\n", vcp->vc_srvname,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_mid, rqp->sr_timo);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = ETIME;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto out;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* got wakeup */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = rqp->sr_lerror;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rqp->sr_rplast++;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowout:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBRQ_UNLOCK(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * MULTIPACKET request must stay in the list.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * They may need additional responses.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((rqp->sr_flags & SMBR_MULTIPACKET) == 0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_iod_removerq(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Some request has been completed.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If we reached the mux limit,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * re-run the send loop...
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (vcp->iod_muxfull)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_iod_sendall(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Shutdown all outstanding I/O requests on the specified share with
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * ENXIO; used when unmounting a share. (There shouldn't be any for a
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * non-forced unmount; if this is a forced unmount, we have to shutdown
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the requests as part of the unmount process.)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowvoid
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_iod_shutdown_share(struct smb_share *ssp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_vc *vcp = SSTOVC(ssp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Loop through the list of requests and shutdown the ones
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * that are for the specified share.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_enter(&vcp->iod_rqlock, RW_READER);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow TAILQ_FOREACH(rqp, &vcp->iod_rqlist, sr_link) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp->sr_state != SMBRQ_NOTIFIED && rqp->sr_share == ssp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_iod_rqprocessed(rqp, EIO, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_exit(&vcp->iod_rqlock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Send all requests that need sending.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Called from _addrq, _multirq, _waitrq
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossvoid
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_iod_sendall(smb_vc_t *vcp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct smb_rq *rqp;
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross int error, muxcnt;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Clear "newrq" to make sure threads adding
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * new requests will run this function again.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_enter(&vcp->iod_rqlock, RW_WRITER);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->iod_newrq = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We only read iod_rqlist, so downgrade rwlock.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This allows the IOD to handle responses while
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * some requesting thread may be blocked in send.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_downgrade(&vcp->iod_rqlock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Serialize to prevent multiple senders.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Note lock order: iod_rqlock, vc_sendlock
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sema_p(&vcp->vc_sendlock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Walk the list of requests and send when possible.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We avoid having more than vc_maxmux requests
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * outstanding to the server by traversing only
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * vc_maxmux entries into this list. Simple!
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(vcp->vc_maxmux > 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = muxcnt = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow TAILQ_FOREACH(rqp, &vcp->iod_rqlist, sr_link) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = ENOTCONN; /* stop everything! */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rqp->sr_state == SMBRQ_NOTSENT) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = smb_iod_sendrq(rqp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (++muxcnt == vcp->vc_maxmux) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBIODEBUG("muxcnt == vc_maxmux\n");
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If we have vc_maxmux requests outstanding,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * arrange for _waitrq to call _sendall as
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * requests are completed.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->iod_muxfull =
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (muxcnt < vcp->vc_maxmux) ? 0 : 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow sema_v(&vcp->vc_sendlock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rw_exit(&vcp->iod_rqlock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_iod_vc_work(struct smb_vc *vcp, cred_t *cr)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross struct file *fp = NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int err = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * This is called by the one-and-only
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * IOD thread for this VC.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ASSERT(vcp->iod_thr == curthread);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Get the network transport file pointer,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * and "loan" it to our transport module.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if ((fp = getf(vcp->vc_tran_fd)) == NULL) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = EBADF;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if ((err = SMB_TRAN_LOAN_FP(vcp, fp, cr)) != 0)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * In case of reconnect, tell any enqueued requests
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * then can GO!
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross vcp->vc_genid++; /* possibly new connection */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_iod_newstate(vcp, SMBIOD_ST_VCACTIVE);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross cv_broadcast(&vcp->vc_statechg);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * The above cv_broadcast should be sufficient to
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * get requests going again.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * If we have a callback function, run it.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Was: smb_iod_notify_connected()
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (fscb && fscb->fscb_connect)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_vc_walkshares(vcp, fscb->fscb_connect);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Run the "reader" loop.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_iod_recvall(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * The reader loop returned, so we must have a
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * new state. (disconnected or reconnecting)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Notify shares of the disconnect.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Was: smb_iod_notify_disconnect()
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_vc_walkshares(vcp, smb_iod_share_disconnected);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * The reader loop function returns only when
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * there's been an error on the connection, or
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * this VC has no more references. It also
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * updates the state before it returns.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Tell any requests to give up or restart.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_iod_invrq(vcp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossout:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Recall the file descriptor loan. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross (void) SMB_TRAN_LOAN_FP(vcp, NULL, cr);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (fp != NULL) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross releasef(vcp->vc_tran_fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Wait around for someone to ask to use this VC.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * If the VC has only the IOD reference, then
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * wait only a minute or so, then drop it.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_iod_vc_idle(struct smb_vc *vcp)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni clock_t tr, delta = SEC_TO_TICK(15);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int err = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * This is called by the one-and-only
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * IOD thread for this VC.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ASSERT(vcp->iod_thr == curthread);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross SMB_VC_LOCK(vcp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross while (vcp->vc_state == SMBIOD_ST_IDLE) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni tr = cv_reltimedwait_sig(&vcp->iod_idle, &vcp->vc_lock,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni delta, TR_CLOCK_TICK);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (tr == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = EINTR;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (tr < 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* timeout */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (vcp->vc_co.co_usecount == 1) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Let this IOD terminate. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_iod_newstate(vcp, SMBIOD_ST_DEAD);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* nobody to cv_broadcast */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * After a failed reconnect attempt, smbiod will
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * call this to make current requests error out.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_iod_vc_rcfail(struct smb_vc *vcp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni clock_t tr;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int err = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * This is called by the one-and-only
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * IOD thread for this VC.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ASSERT(vcp->iod_thr == curthread);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (vcp->vc_state != SMBIOD_ST_RECONNECT)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (EINVAL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_iod_newstate(vcp, SMBIOD_ST_RCFAILED);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross cv_broadcast(&vcp->vc_statechg);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Short wait here for two reasons:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * (1) Give requests a chance to error out.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * (2) Prevent immediate retry.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni tr = cv_reltimedwait_sig(&vcp->iod_idle, &vcp->vc_lock,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni SEC_TO_TICK(5), TR_CLOCK_TICK);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (tr == 0)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = EINTR;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_iod_newstate(vcp, SMBIOD_ST_IDLE);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross cv_broadcast(&vcp->vc_statechg);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_UNLOCK(vcp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Ask the IOD to reconnect (if not already underway)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * then wait for the reconnect to finish.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowint
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_iod_reconnect(struct smb_vc *vcp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int err = 0, rv;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMB_VC_LOCK(vcp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossagain:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross switch (vcp->vc_state) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case SMBIOD_ST_IDLE:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_iod_newstate(vcp, SMBIOD_ST_RECONNECT);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross cv_signal(&vcp->iod_idle);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* FALLTHROUGH */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case SMBIOD_ST_RECONNECT:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rv = cv_wait_sig(&vcp->vc_statechg, &vcp->vc_lock);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (rv == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = EINTR;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto again;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case SMBIOD_ST_VCACTIVE:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = 0; /* success! */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case SMBIOD_ST_RCFAILED:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross case SMBIOD_ST_DEAD:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross default:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = ENOTCONN;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross SMB_VC_UNLOCK(vcp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}