123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718 |
- /*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2000-2001 Boris Popov
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
- #include <sys/cdefs.h>
- __FBSDID("$FreeBSD$");
- #include <sys/param.h>
- #include <sys/systm.h>
- #include <sys/endian.h>
- #include <sys/proc.h>
- #include <sys/kernel.h>
- #include <sys/kthread.h>
- #include <sys/malloc.h>
- #include <sys/mbuf.h>
- #include <sys/unistd.h>
- #include <netsmb/smb.h>
- #include <netsmb/smb_conn.h>
- #include <netsmb/smb_rq.h>
- #include <netsmb/smb_tran.h>
- #include <netsmb/smb_trantcp.h>
- #define SMBIOD_SLEEP_TIMO 2
- #define SMBIOD_PING_TIMO 60 /* seconds */
- #define SMB_IOD_EVLOCKPTR(iod) (&((iod)->iod_evlock))
- #define SMB_IOD_EVLOCK(iod) smb_sl_lock(&((iod)->iod_evlock))
- #define SMB_IOD_EVUNLOCK(iod) smb_sl_unlock(&((iod)->iod_evlock))
- #define SMB_IOD_RQLOCKPTR(iod) (&((iod)->iod_rqlock))
- #define SMB_IOD_RQLOCK(iod) smb_sl_lock(&((iod)->iod_rqlock))
- #define SMB_IOD_RQUNLOCK(iod) smb_sl_unlock(&((iod)->iod_rqlock))
- #define smb_iod_wakeup(iod) wakeup(&(iod)->iod_flags)
- static MALLOC_DEFINE(M_SMBIOD, "SMBIOD", "SMB network io daemon");
- static int smb_iod_next;
- static int smb_iod_sendall(struct smbiod *iod);
- static int smb_iod_disconnect(struct smbiod *iod);
- static void smb_iod_thread(void *);
- static __inline void
- smb_iod_rqprocessed(struct smb_rq *rqp, int error)
- {
- SMBRQ_SLOCK(rqp);
- rqp->sr_lerror = error;
- rqp->sr_rpgen++;
- rqp->sr_state = SMBRQ_NOTIFIED;
- wakeup(&rqp->sr_state);
- SMBRQ_SUNLOCK(rqp);
- }
- static void
- smb_iod_invrq(struct smbiod *iod)
- {
- struct smb_rq *rqp;
- /*
- * Invalidate all outstanding requests for this connection
- */
- SMB_IOD_RQLOCK(iod);
- TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
- rqp->sr_flags |= SMBR_RESTART;
- smb_iod_rqprocessed(rqp, ENOTCONN);
- }
- SMB_IOD_RQUNLOCK(iod);
- }
- static void
- smb_iod_closetran(struct smbiod *iod)
- {
- struct smb_vc *vcp = iod->iod_vc;
- struct thread *td = iod->iod_td;
- if (vcp->vc_tdata == NULL)
- return;
- SMB_TRAN_DISCONNECT(vcp, td);
- SMB_TRAN_DONE(vcp, td);
- vcp->vc_tdata = NULL;
- }
- static void
- smb_iod_dead(struct smbiod *iod)
- {
- iod->iod_state = SMBIOD_ST_DEAD;
- smb_iod_closetran(iod);
- smb_iod_invrq(iod);
- }
- static int
- smb_iod_connect(struct smbiod *iod)
- {
- struct smb_vc *vcp = iod->iod_vc;
- struct thread *td = iod->iod_td;
- int error;
- SMBIODEBUG("%d\n", iod->iod_state);
- switch(iod->iod_state) {
- case SMBIOD_ST_VCACTIVE:
- SMBERROR("called for already opened connection\n");
- return EISCONN;
- case SMBIOD_ST_DEAD:
- return ENOTCONN; /* XXX: last error code ? */
- default:
- break;
- }
- vcp->vc_genid++;
- error = 0;
- error = (int)SMB_TRAN_CREATE(vcp, td);
- if (error)
- goto fail;
- SMBIODEBUG("tcreate\n");
- if (vcp->vc_laddr) {
- error = (int)SMB_TRAN_BIND(vcp, vcp->vc_laddr, td);
- if (error)
- goto fail;
- }
- SMBIODEBUG("tbind\n");
- error = (int)SMB_TRAN_CONNECT(vcp, vcp->vc_paddr, td);
- if (error)
- goto fail;
- SMB_TRAN_SETPARAM(vcp, SMBTP_SELECTID, &iod->iod_flags);
- iod->iod_state = SMBIOD_ST_TRANACTIVE;
- SMBIODEBUG("tconnect\n");
- /* vcp->vc_mid = 0;*/
- error = (int)smb_smb_negotiate(vcp, &iod->iod_scred);
- if (error)
- goto fail;
- SMBIODEBUG("snegotiate\n");
- error = (int)smb_smb_ssnsetup(vcp, &iod->iod_scred);
- if (error)
- goto fail;
- iod->iod_state = SMBIOD_ST_VCACTIVE;
- SMBIODEBUG("completed\n");
- smb_iod_invrq(iod);
- return (0);
- fail:
- smb_iod_dead(iod);
- return (error);
- }
- static int
- smb_iod_disconnect(struct smbiod *iod)
- {
- struct smb_vc *vcp = iod->iod_vc;
- SMBIODEBUG("\n");
- if (iod->iod_state == SMBIOD_ST_VCACTIVE) {
- smb_smb_ssnclose(vcp, &iod->iod_scred);
- iod->iod_state = SMBIOD_ST_TRANACTIVE;
- }
- vcp->vc_smbuid = SMB_UID_UNKNOWN;
- smb_iod_closetran(iod);
- iod->iod_state = SMBIOD_ST_NOTCONN;
- return 0;
- }
- static int
- smb_iod_treeconnect(struct smbiod *iod, struct smb_share *ssp)
- {
- int error;
- if (iod->iod_state != SMBIOD_ST_VCACTIVE) {
- if (iod->iod_state != SMBIOD_ST_DEAD)
- return ENOTCONN;
- iod->iod_state = SMBIOD_ST_RECONNECT;
- error = smb_iod_connect(iod);
- if (error)
- return error;
- }
- SMBIODEBUG("tree reconnect\n");
- SMBS_ST_LOCK(ssp);
- ssp->ss_flags |= SMBS_RECONNECTING;
- SMBS_ST_UNLOCK(ssp);
- error = smb_smb_treeconnect(ssp, &iod->iod_scred);
- SMBS_ST_LOCK(ssp);
- ssp->ss_flags &= ~SMBS_RECONNECTING;
- SMBS_ST_UNLOCK(ssp);
- wakeup(&ssp->ss_vcgenid);
- return error;
- }
- static int
- smb_iod_sendrq(struct smbiod *iod, struct smb_rq *rqp)
- {
- struct thread *td = iod->iod_td;
- struct smb_vc *vcp = iod->iod_vc;
- struct smb_share *ssp = rqp->sr_share;
- struct mbuf *m;
- int error;
- SMBIODEBUG("iod_state = %d\n", iod->iod_state);
- switch (iod->iod_state) {
- case SMBIOD_ST_NOTCONN:
- smb_iod_rqprocessed(rqp, ENOTCONN);
- return 0;
- case SMBIOD_ST_DEAD:
- iod->iod_state = SMBIOD_ST_RECONNECT;
- return 0;
- case SMBIOD_ST_RECONNECT:
- return 0;
- default:
- break;
- }
- if (rqp->sr_sendcnt == 0) {
- #ifdef movedtoanotherplace
- if (vcp->vc_maxmux != 0 && iod->iod_muxcnt >= vcp->vc_maxmux)
- return 0;
- #endif
- le16enc(rqp->sr_rqtid, ssp ? ssp->ss_tid : SMB_TID_UNKNOWN);
- le16enc(rqp->sr_rquid, vcp ? vcp->vc_smbuid : 0);
- mb_fixhdr(&rqp->sr_rq);
- if (vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE)
- smb_rq_sign(rqp);
- }
- if (rqp->sr_sendcnt++ > 5) {
- rqp->sr_flags |= SMBR_RESTART;
- smb_iod_rqprocessed(rqp, rqp->sr_lerror);
- /*
- * If all attempts to send a request failed, then
- * something is seriously hosed.
- */
- return ENOTCONN;
- }
- SMBSDEBUG("M:%04x, P:%04x, U:%04x, T:%04x\n", rqp->sr_mid, 0, 0, 0);
- m_dumpm(rqp->sr_rq.mb_top);
- m = m_copym(rqp->sr_rq.mb_top, 0, M_COPYALL, M_WAITOK);
- error = rqp->sr_lerror = SMB_TRAN_SEND(vcp, m, td);
- if (error == 0) {
- getnanotime(&rqp->sr_timesent);
- iod->iod_lastrqsent = rqp->sr_timesent;
- rqp->sr_flags |= SMBR_SENT;
- rqp->sr_state = SMBRQ_SENT;
- return 0;
- }
- /*
- * Check for fatal errors
- */
- if (SMB_TRAN_FATAL(vcp, error)) {
- /*
- * No further attempts should be made
- */
- return ENOTCONN;
- }
- if (smb_rq_intr(rqp))
- smb_iod_rqprocessed(rqp, EINTR);
- return 0;
- }
- /*
- * Process incoming packets
- */
- static int
- smb_iod_recvall(struct smbiod *iod)
- {
- struct smb_vc *vcp = iod->iod_vc;
- struct thread *td = iod->iod_td;
- struct smb_rq *rqp;
- struct mbuf *m;
- u_char *hp;
- u_short mid;
- int error;
- switch (iod->iod_state) {
- case SMBIOD_ST_NOTCONN:
- case SMBIOD_ST_DEAD:
- case SMBIOD_ST_RECONNECT:
- return 0;
- default:
- break;
- }
- for (;;) {
- m = NULL;
- error = SMB_TRAN_RECV(vcp, &m, td);
- if (error == EWOULDBLOCK)
- break;
- if (SMB_TRAN_FATAL(vcp, error)) {
- smb_iod_dead(iod);
- break;
- }
- if (error)
- break;
- if (m == NULL) {
- SMBERROR("tran return NULL without error\n");
- error = EPIPE;
- continue;
- }
- m = m_pullup(m, SMB_HDRLEN);
- if (m == NULL)
- continue; /* wait for a good packet */
- /*
- * Now we got an entire and possibly invalid SMB packet.
- * Be careful while parsing it.
- */
- m_dumpm(m);
- hp = mtod(m, u_char*);
- if (bcmp(hp, SMB_SIGNATURE, SMB_SIGLEN) != 0) {
- m_freem(m);
- continue;
- }
- mid = SMB_HDRMID(hp);
- SMBSDEBUG("mid %04x\n", (u_int)mid);
- SMB_IOD_RQLOCK(iod);
- TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
- if (rqp->sr_mid != mid)
- continue;
- SMBRQ_SLOCK(rqp);
- if (rqp->sr_rp.md_top == NULL) {
- md_initm(&rqp->sr_rp, m);
- } else {
- if (rqp->sr_flags & SMBR_MULTIPACKET) {
- md_append_record(&rqp->sr_rp, m);
- } else {
- SMBRQ_SUNLOCK(rqp);
- SMBERROR("duplicate response %d (ignored)\n", mid);
- break;
- }
- }
- SMBRQ_SUNLOCK(rqp);
- smb_iod_rqprocessed(rqp, 0);
- break;
- }
- SMB_IOD_RQUNLOCK(iod);
- if (rqp == NULL) {
- SMBERROR("drop resp with mid %d\n", (u_int)mid);
- /* smb_printrqlist(vcp);*/
- m_freem(m);
- }
- }
- /*
- * check for interrupts
- */
- SMB_IOD_RQLOCK(iod);
- TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
- if (smb_td_intr(rqp->sr_cred->scr_td)) {
- smb_iod_rqprocessed(rqp, EINTR);
- }
- }
- SMB_IOD_RQUNLOCK(iod);
- return 0;
- }
- int
- smb_iod_request(struct smbiod *iod, int event, void *ident)
- {
- struct smbiod_event *evp;
- int error;
- SMBIODEBUG("\n");
- evp = smb_zmalloc(sizeof(*evp), M_SMBIOD, M_WAITOK);
- evp->ev_type = event;
- evp->ev_ident = ident;
- SMB_IOD_EVLOCK(iod);
- STAILQ_INSERT_TAIL(&iod->iod_evlist, evp, ev_link);
- if ((event & SMBIOD_EV_SYNC) == 0) {
- SMB_IOD_EVUNLOCK(iod);
- smb_iod_wakeup(iod);
- return 0;
- }
- smb_iod_wakeup(iod);
- msleep(evp, SMB_IOD_EVLOCKPTR(iod), PWAIT | PDROP, "90evw", 0);
- error = evp->ev_error;
- free(evp, M_SMBIOD);
- return error;
- }
- /*
- * Place request in the queue.
- * Request from smbiod have a high priority.
- */
- int
- smb_iod_addrq(struct smb_rq *rqp)
- {
- struct smb_vc *vcp = rqp->sr_vc;
- struct smbiod *iod = vcp->vc_iod;
- int error;
- SMBIODEBUG("\n");
- if (rqp->sr_cred->scr_td != NULL &&
- rqp->sr_cred->scr_td->td_proc == iod->iod_p) {
- rqp->sr_flags |= SMBR_INTERNAL;
- SMB_IOD_RQLOCK(iod);
- TAILQ_INSERT_HEAD(&iod->iod_rqlist, rqp, sr_link);
- SMB_IOD_RQUNLOCK(iod);
- for (;;) {
- if (smb_iod_sendrq(iod, rqp) != 0) {
- smb_iod_dead(iod);
- break;
- }
- /*
- * we don't need to lock state field here
- */
- if (rqp->sr_state != SMBRQ_NOTSENT)
- break;
- tsleep(&iod->iod_flags, PWAIT, "90sndw", hz);
- }
- if (rqp->sr_lerror)
- smb_iod_removerq(rqp);
- return rqp->sr_lerror;
- }
- switch (iod->iod_state) {
- case SMBIOD_ST_NOTCONN:
- return ENOTCONN;
- case SMBIOD_ST_DEAD:
- error = smb_iod_request(vcp->vc_iod, SMBIOD_EV_CONNECT | SMBIOD_EV_SYNC, NULL);
- if (error)
- return error;
- return EXDEV;
- default:
- break;
- }
- SMB_IOD_RQLOCK(iod);
- for (;;) {
- if (vcp->vc_maxmux == 0) {
- SMBERROR("maxmux == 0\n");
- break;
- }
- if (iod->iod_muxcnt < vcp->vc_maxmux)
- break;
- iod->iod_muxwant++;
- msleep(&iod->iod_muxwant, SMB_IOD_RQLOCKPTR(iod),
- PWAIT, "90mux", 0);
- }
- iod->iod_muxcnt++;
- TAILQ_INSERT_TAIL(&iod->iod_rqlist, rqp, sr_link);
- SMB_IOD_RQUNLOCK(iod);
- smb_iod_wakeup(iod);
- return 0;
- }
- int
- smb_iod_removerq(struct smb_rq *rqp)
- {
- struct smb_vc *vcp = rqp->sr_vc;
- struct smbiod *iod = vcp->vc_iod;
- SMBIODEBUG("\n");
- if (rqp->sr_flags & SMBR_INTERNAL) {
- SMB_IOD_RQLOCK(iod);
- TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
- SMB_IOD_RQUNLOCK(iod);
- return 0;
- }
- SMB_IOD_RQLOCK(iod);
- while (rqp->sr_flags & SMBR_XLOCK) {
- rqp->sr_flags |= SMBR_XLOCKWANT;
- msleep(rqp, SMB_IOD_RQLOCKPTR(iod), PWAIT, "90xrm", 0);
- }
- TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
- iod->iod_muxcnt--;
- if (iod->iod_muxwant) {
- iod->iod_muxwant--;
- wakeup(&iod->iod_muxwant);
- }
- SMB_IOD_RQUNLOCK(iod);
- return 0;
- }
- int
- smb_iod_waitrq(struct smb_rq *rqp)
- {
- struct smbiod *iod = rqp->sr_vc->vc_iod;
- int error;
- SMBIODEBUG("\n");
- if (rqp->sr_flags & SMBR_INTERNAL) {
- for (;;) {
- smb_iod_sendall(iod);
- smb_iod_recvall(iod);
- if (rqp->sr_rpgen != rqp->sr_rplast)
- break;
- tsleep(&iod->iod_flags, PWAIT, "90irq", hz);
- }
- smb_iod_removerq(rqp);
- return rqp->sr_lerror;
- }
- SMBRQ_SLOCK(rqp);
- if (rqp->sr_rpgen == rqp->sr_rplast)
- msleep(&rqp->sr_state, SMBRQ_SLOCKPTR(rqp), PWAIT, "90wrq", 0);
- rqp->sr_rplast++;
- SMBRQ_SUNLOCK(rqp);
- error = rqp->sr_lerror;
- if (rqp->sr_flags & SMBR_MULTIPACKET) {
- /*
- * If request should stay in the list, then reinsert it
- * at the end of queue so other waiters have chance to concur
- */
- SMB_IOD_RQLOCK(iod);
- TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
- TAILQ_INSERT_TAIL(&iod->iod_rqlist, rqp, sr_link);
- SMB_IOD_RQUNLOCK(iod);
- } else
- smb_iod_removerq(rqp);
- return error;
- }
- static int
- smb_iod_sendall(struct smbiod *iod)
- {
- struct smb_vc *vcp = iod->iod_vc;
- struct smb_rq *rqp;
- struct timespec ts, tstimeout;
- int herror;
- herror = 0;
- /*
- * Loop through the list of requests and send them if possible
- */
- SMB_IOD_RQLOCK(iod);
- TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
- switch (rqp->sr_state) {
- case SMBRQ_NOTSENT:
- rqp->sr_flags |= SMBR_XLOCK;
- SMB_IOD_RQUNLOCK(iod);
- herror = smb_iod_sendrq(iod, rqp);
- SMB_IOD_RQLOCK(iod);
- rqp->sr_flags &= ~SMBR_XLOCK;
- if (rqp->sr_flags & SMBR_XLOCKWANT) {
- rqp->sr_flags &= ~SMBR_XLOCKWANT;
- wakeup(rqp);
- }
- break;
- case SMBRQ_SENT:
- SMB_TRAN_GETPARAM(vcp, SMBTP_TIMEOUT, &tstimeout);
- timespecadd(&tstimeout, &tstimeout, &tstimeout);
- getnanotime(&ts);
- timespecsub(&ts, &tstimeout, &ts);
- if (timespeccmp(&ts, &rqp->sr_timesent, >)) {
- smb_iod_rqprocessed(rqp, ETIMEDOUT);
- }
- break;
- default:
- break;
- }
- if (herror)
- break;
- }
- SMB_IOD_RQUNLOCK(iod);
- if (herror == ENOTCONN)
- smb_iod_dead(iod);
- return 0;
- }
- /*
- * "main" function for smbiod daemon
- */
- static __inline void
- smb_iod_main(struct smbiod *iod)
- {
- /* struct smb_vc *vcp = iod->iod_vc;*/
- struct smbiod_event *evp;
- /* struct timespec tsnow;*/
- int error;
- SMBIODEBUG("\n");
- error = 0;
- /*
- * Check all interesting events
- */
- for (;;) {
- SMB_IOD_EVLOCK(iod);
- evp = STAILQ_FIRST(&iod->iod_evlist);
- if (evp == NULL) {
- SMB_IOD_EVUNLOCK(iod);
- break;
- }
- STAILQ_REMOVE_HEAD(&iod->iod_evlist, ev_link);
- evp->ev_type |= SMBIOD_EV_PROCESSING;
- SMB_IOD_EVUNLOCK(iod);
- switch (evp->ev_type & SMBIOD_EV_MASK) {
- case SMBIOD_EV_CONNECT:
- iod->iod_state = SMBIOD_ST_RECONNECT;
- evp->ev_error = smb_iod_connect(iod);
- break;
- case SMBIOD_EV_DISCONNECT:
- evp->ev_error = smb_iod_disconnect(iod);
- break;
- case SMBIOD_EV_TREECONNECT:
- evp->ev_error = smb_iod_treeconnect(iod, evp->ev_ident);
- break;
- case SMBIOD_EV_SHUTDOWN:
- iod->iod_flags |= SMBIOD_SHUTDOWN;
- break;
- case SMBIOD_EV_NEWRQ:
- break;
- }
- if (evp->ev_type & SMBIOD_EV_SYNC) {
- SMB_IOD_EVLOCK(iod);
- wakeup(evp);
- SMB_IOD_EVUNLOCK(iod);
- } else
- free(evp, M_SMBIOD);
- }
- #if 0
- if (iod->iod_state == SMBIOD_ST_VCACTIVE) {
- getnanotime(&tsnow);
- timespecsub(&tsnow, &iod->iod_pingtimo, &tsnow);
- if (timespeccmp(&tsnow, &iod->iod_lastrqsent, >)) {
- smb_smb_echo(vcp, &iod->iod_scred);
- }
- }
- #endif
- smb_iod_sendall(iod);
- smb_iod_recvall(iod);
- return;
- }
- void
- smb_iod_thread(void *arg)
- {
- struct smbiod *iod = arg;
- mtx_lock(&Giant);
- /*
- * Here we assume that the thread structure will be the same
- * for an entire kthread (kproc, to be more precise) life.
- */
- iod->iod_td = curthread;
- smb_makescred(&iod->iod_scred, iod->iod_td, NULL);
- while ((iod->iod_flags & SMBIOD_SHUTDOWN) == 0) {
- smb_iod_main(iod);
- SMBIODEBUG("going to sleep for %d ticks\n", iod->iod_sleeptimo);
- if (iod->iod_flags & SMBIOD_SHUTDOWN)
- break;
- tsleep(&iod->iod_flags, PWAIT, "90idle", iod->iod_sleeptimo);
- }
- /* We can now safely destroy the mutexes and free the iod structure. */
- smb_sl_destroy(&iod->iod_rqlock);
- smb_sl_destroy(&iod->iod_evlock);
- free(iod, M_SMBIOD);
- mtx_unlock(&Giant);
- kproc_exit(0);
- }
- int
- smb_iod_create(struct smb_vc *vcp)
- {
- struct smbiod *iod;
- int error;
- iod = smb_zmalloc(sizeof(*iod), M_SMBIOD, M_WAITOK);
- iod->iod_id = smb_iod_next++;
- iod->iod_state = SMBIOD_ST_NOTCONN;
- iod->iod_vc = vcp;
- iod->iod_sleeptimo = hz * SMBIOD_SLEEP_TIMO;
- iod->iod_pingtimo.tv_sec = SMBIOD_PING_TIMO;
- getnanotime(&iod->iod_lastrqsent);
- vcp->vc_iod = iod;
- smb_sl_init(&iod->iod_rqlock, "90rql");
- TAILQ_INIT(&iod->iod_rqlist);
- smb_sl_init(&iod->iod_evlock, "90evl");
- STAILQ_INIT(&iod->iod_evlist);
- error = kproc_create(smb_iod_thread, iod, &iod->iod_p,
- RFNOWAIT, 0, "smbiod%d", iod->iod_id);
- if (error) {
- SMBERROR("can't start smbiod: %d", error);
- vcp->vc_iod = NULL;
- smb_sl_destroy(&iod->iod_rqlock);
- smb_sl_destroy(&iod->iod_evlock);
- free(iod, M_SMBIOD);
- return error;
- }
- return 0;
- }
- int
- smb_iod_destroy(struct smbiod *iod)
- {
- smb_iod_request(iod, SMBIOD_EV_SHUTDOWN | SMBIOD_EV_SYNC, NULL);
- return 0;
- }
- int
- smb_iod_init(void)
- {
- return 0;
- }
- int
- smb_iod_done(void)
- {
- return 0;
- }
|