xref: /freebsd/sys/netsmb/smb_iod.c (revision fce6fbfa4df708f2cd50c5eeb1c00d30c63a0f4d)
1681a5bbeSBoris Popov /*
2681a5bbeSBoris Popov  * Copyright (c) 2000-2001 Boris Popov
3681a5bbeSBoris Popov  * All rights reserved.
4681a5bbeSBoris Popov  *
5681a5bbeSBoris Popov  * Redistribution and use in source and binary forms, with or without
6681a5bbeSBoris Popov  * modification, are permitted provided that the following conditions
7681a5bbeSBoris Popov  * are met:
8681a5bbeSBoris Popov  * 1. Redistributions of source code must retain the above copyright
9681a5bbeSBoris Popov  *    notice, this list of conditions and the following disclaimer.
10681a5bbeSBoris Popov  * 2. Redistributions in binary form must reproduce the above copyright
11681a5bbeSBoris Popov  *    notice, this list of conditions and the following disclaimer in the
12681a5bbeSBoris Popov  *    documentation and/or other materials provided with the distribution.
13681a5bbeSBoris Popov  * 3. All advertising materials mentioning features or use of this software
14681a5bbeSBoris Popov  *    must display the following acknowledgement:
15681a5bbeSBoris Popov  *    This product includes software developed by Boris Popov.
16681a5bbeSBoris Popov  * 4. Neither the name of the author nor the names of any co-contributors
17681a5bbeSBoris Popov  *    may be used to endorse or promote products derived from this software
18681a5bbeSBoris Popov  *    without specific prior written permission.
19681a5bbeSBoris Popov  *
20681a5bbeSBoris Popov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21681a5bbeSBoris Popov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22681a5bbeSBoris Popov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23681a5bbeSBoris Popov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24681a5bbeSBoris Popov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25681a5bbeSBoris Popov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26681a5bbeSBoris Popov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27681a5bbeSBoris Popov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28681a5bbeSBoris Popov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29681a5bbeSBoris Popov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30681a5bbeSBoris Popov  * SUCH DAMAGE.
31681a5bbeSBoris Popov  *
32681a5bbeSBoris Popov  * $FreeBSD$
33681a5bbeSBoris Popov  */
34681a5bbeSBoris Popov 
35681a5bbeSBoris Popov #include <sys/param.h>
36681a5bbeSBoris Popov #include <sys/systm.h>
37681a5bbeSBoris Popov #include <sys/proc.h>
38681a5bbeSBoris Popov #include <sys/kernel.h>
39681a5bbeSBoris Popov #include <sys/kthread.h>
40681a5bbeSBoris Popov #include <sys/malloc.h>
41681a5bbeSBoris Popov #include <sys/mbuf.h>
42681a5bbeSBoris Popov #include <sys/unistd.h>
43681a5bbeSBoris Popov 
44681a5bbeSBoris Popov #include <netsmb/smb.h>
45681a5bbeSBoris Popov #include <netsmb/smb_conn.h>
46681a5bbeSBoris Popov #include <netsmb/smb_rq.h>
47681a5bbeSBoris Popov #include <netsmb/smb_tran.h>
48681a5bbeSBoris Popov #include <netsmb/smb_trantcp.h>
49681a5bbeSBoris Popov 
50681a5bbeSBoris Popov 
51681a5bbeSBoris Popov #define SMBIOD_SLEEP_TIMO	2
52681a5bbeSBoris Popov #define	SMBIOD_PING_TIMO	60	/* seconds */
53681a5bbeSBoris Popov 
54681a5bbeSBoris Popov #define	SMB_IOD_EVLOCKPTR(iod)	(&((iod)->iod_evlock))
55681a5bbeSBoris Popov #define	SMB_IOD_EVLOCK(iod)	smb_sl_lock(&((iod)->iod_evlock))
56681a5bbeSBoris Popov #define	SMB_IOD_EVUNLOCK(iod)	smb_sl_unlock(&((iod)->iod_evlock))
57681a5bbeSBoris Popov 
58681a5bbeSBoris Popov #define	SMB_IOD_RQLOCKPTR(iod)	(&((iod)->iod_rqlock))
59681a5bbeSBoris Popov #define	SMB_IOD_RQLOCK(iod)	smb_sl_lock(&((iod)->iod_rqlock))
60681a5bbeSBoris Popov #define	SMB_IOD_RQUNLOCK(iod)	smb_sl_unlock(&((iod)->iod_rqlock))
61681a5bbeSBoris Popov 
62681a5bbeSBoris Popov #define	smb_iod_wakeup(iod)	wakeup(&(iod)->iod_flags)
63681a5bbeSBoris Popov 
64681a5bbeSBoris Popov 
65681a5bbeSBoris Popov static MALLOC_DEFINE(M_SMBIOD, "SMBIOD", "SMB network io daemon");
66681a5bbeSBoris Popov 
67681a5bbeSBoris Popov static int smb_iod_next;
68681a5bbeSBoris Popov 
69681a5bbeSBoris Popov static int  smb_iod_sendall(struct smbiod *iod);
70681a5bbeSBoris Popov static int  smb_iod_disconnect(struct smbiod *iod);
71681a5bbeSBoris Popov static void smb_iod_thread(void *);
72681a5bbeSBoris Popov 
73681a5bbeSBoris Popov static __inline void
74681a5bbeSBoris Popov smb_iod_rqprocessed(struct smb_rq *rqp, int error)
75681a5bbeSBoris Popov {
76681a5bbeSBoris Popov 	SMBRQ_SLOCK(rqp);
77681a5bbeSBoris Popov 	rqp->sr_lerror = error;
78681a5bbeSBoris Popov 	rqp->sr_rpgen++;
79681a5bbeSBoris Popov 	rqp->sr_state = SMBRQ_NOTIFIED;
80681a5bbeSBoris Popov 	wakeup(&rqp->sr_state);
81681a5bbeSBoris Popov 	SMBRQ_SUNLOCK(rqp);
82681a5bbeSBoris Popov }
83681a5bbeSBoris Popov 
84681a5bbeSBoris Popov static void
85681a5bbeSBoris Popov smb_iod_invrq(struct smbiod *iod)
86681a5bbeSBoris Popov {
87681a5bbeSBoris Popov 	struct smb_rq *rqp;
88681a5bbeSBoris Popov 
89681a5bbeSBoris Popov 	/*
90681a5bbeSBoris Popov 	 * Invalidate all outstanding requests for this connection
91681a5bbeSBoris Popov 	 */
92681a5bbeSBoris Popov 	SMB_IOD_RQLOCK(iod);
93681a5bbeSBoris Popov 	TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
94681a5bbeSBoris Popov 		if (rqp->sr_flags & SMBR_INTERNAL)
95681a5bbeSBoris Popov 			SMBRQ_SUNLOCK(rqp);
96681a5bbeSBoris Popov 		rqp->sr_flags |= SMBR_RESTART;
97681a5bbeSBoris Popov 		smb_iod_rqprocessed(rqp, ENOTCONN);
98681a5bbeSBoris Popov 	}
99681a5bbeSBoris Popov 	SMB_IOD_RQUNLOCK(iod);
100681a5bbeSBoris Popov }
101681a5bbeSBoris Popov 
102681a5bbeSBoris Popov static void
103681a5bbeSBoris Popov smb_iod_closetran(struct smbiod *iod)
104681a5bbeSBoris Popov {
105681a5bbeSBoris Popov 	struct smb_vc *vcp = iod->iod_vc;
106fce6fbfaSBoris Popov 	struct thread *td = iod->iod_td;
107681a5bbeSBoris Popov 
108681a5bbeSBoris Popov 	if (vcp->vc_tdata == NULL)
109681a5bbeSBoris Popov 		return;
110fce6fbfaSBoris Popov 	SMB_TRAN_DISCONNECT(vcp, td);
111fce6fbfaSBoris Popov 	SMB_TRAN_DONE(vcp, td);
112681a5bbeSBoris Popov 	vcp->vc_tdata = NULL;
113681a5bbeSBoris Popov }
114681a5bbeSBoris Popov 
115681a5bbeSBoris Popov static void
116681a5bbeSBoris Popov smb_iod_dead(struct smbiod *iod)
117681a5bbeSBoris Popov {
118681a5bbeSBoris Popov 	iod->iod_state = SMBIOD_ST_DEAD;
119681a5bbeSBoris Popov 	smb_iod_closetran(iod);
120681a5bbeSBoris Popov 	smb_iod_invrq(iod);
121681a5bbeSBoris Popov }
122681a5bbeSBoris Popov 
123681a5bbeSBoris Popov static int
124681a5bbeSBoris Popov smb_iod_connect(struct smbiod *iod)
125681a5bbeSBoris Popov {
126681a5bbeSBoris Popov 	struct smb_vc *vcp = iod->iod_vc;
127fce6fbfaSBoris Popov 	struct thread *td = iod->iod_td;
128681a5bbeSBoris Popov 	int error;
129681a5bbeSBoris Popov 
130681a5bbeSBoris Popov 	SMBIODEBUG("%d\n", iod->iod_state);
131681a5bbeSBoris Popov 	switch(iod->iod_state) {
132681a5bbeSBoris Popov 	    case SMBIOD_ST_VCACTIVE:
133681a5bbeSBoris Popov 		SMBERROR("called for already opened connection\n");
134681a5bbeSBoris Popov 		return EISCONN;
135681a5bbeSBoris Popov 	    case SMBIOD_ST_DEAD:
136681a5bbeSBoris Popov 		return ENOTCONN;	/* XXX: last error code ? */
137681a5bbeSBoris Popov 	    default:
138681a5bbeSBoris Popov 		break;
139681a5bbeSBoris Popov 	}
140681a5bbeSBoris Popov 	vcp->vc_genid++;
141681a5bbeSBoris Popov 	error = 0;
142681a5bbeSBoris Popov 	itry {
143fce6fbfaSBoris Popov 		ithrow(SMB_TRAN_CREATE(vcp, td));
144681a5bbeSBoris Popov 		SMBIODEBUG("tcreate\n");
145681a5bbeSBoris Popov 		if (vcp->vc_laddr) {
146fce6fbfaSBoris Popov 			ithrow(SMB_TRAN_BIND(vcp, vcp->vc_laddr, td));
147681a5bbeSBoris Popov 		}
148681a5bbeSBoris Popov 		SMBIODEBUG("tbind\n");
149fce6fbfaSBoris Popov 		ithrow(SMB_TRAN_CONNECT(vcp, vcp->vc_paddr, td));
150681a5bbeSBoris Popov 		SMB_TRAN_SETPARAM(vcp, SMBTP_SELECTID, &iod->iod_flags);
151681a5bbeSBoris Popov 		iod->iod_state = SMBIOD_ST_TRANACTIVE;
152681a5bbeSBoris Popov 		SMBIODEBUG("tconnect\n");
153681a5bbeSBoris Popov /*		vcp->vc_mid = 0;*/
154681a5bbeSBoris Popov 		ithrow(smb_smb_negotiate(vcp, &iod->iod_scred));
155681a5bbeSBoris Popov 		SMBIODEBUG("snegotiate\n");
156681a5bbeSBoris Popov 		ithrow(smb_smb_ssnsetup(vcp, &iod->iod_scred));
157681a5bbeSBoris Popov 		iod->iod_state = SMBIOD_ST_VCACTIVE;
158681a5bbeSBoris Popov 		SMBIODEBUG("completed\n");
159681a5bbeSBoris Popov 		smb_iod_invrq(iod);
160681a5bbeSBoris Popov 	} icatch(error) {
161681a5bbeSBoris Popov 		smb_iod_dead(iod);
162681a5bbeSBoris Popov 	} ifinally {
163681a5bbeSBoris Popov 	} iendtry;
164681a5bbeSBoris Popov 	return error;
165681a5bbeSBoris Popov }
166681a5bbeSBoris Popov 
167681a5bbeSBoris Popov static int
168681a5bbeSBoris Popov smb_iod_disconnect(struct smbiod *iod)
169681a5bbeSBoris Popov {
170681a5bbeSBoris Popov 	struct smb_vc *vcp = iod->iod_vc;
171681a5bbeSBoris Popov 
172681a5bbeSBoris Popov 	SMBIODEBUG("\n");
173681a5bbeSBoris Popov 	if (iod->iod_state == SMBIOD_ST_VCACTIVE) {
174681a5bbeSBoris Popov 		smb_smb_ssnclose(vcp, &iod->iod_scred);
175681a5bbeSBoris Popov 		iod->iod_state = SMBIOD_ST_TRANACTIVE;
176681a5bbeSBoris Popov 	}
177681a5bbeSBoris Popov 	vcp->vc_smbuid = SMB_UID_UNKNOWN;
178681a5bbeSBoris Popov 	smb_iod_closetran(iod);
179681a5bbeSBoris Popov 	iod->iod_state = SMBIOD_ST_NOTCONN;
180681a5bbeSBoris Popov 	return 0;
181681a5bbeSBoris Popov }
182681a5bbeSBoris Popov 
183681a5bbeSBoris Popov static int
184681a5bbeSBoris Popov smb_iod_treeconnect(struct smbiod *iod, struct smb_share *ssp)
185681a5bbeSBoris Popov {
186681a5bbeSBoris Popov 	int error;
187681a5bbeSBoris Popov 
188681a5bbeSBoris Popov 	if (iod->iod_state != SMBIOD_ST_VCACTIVE) {
189681a5bbeSBoris Popov 		if (iod->iod_state != SMBIOD_ST_DEAD)
190681a5bbeSBoris Popov 			return ENOTCONN;
191681a5bbeSBoris Popov 		iod->iod_state = SMBIOD_ST_RECONNECT;
192681a5bbeSBoris Popov 		error = smb_iod_connect(iod);
193681a5bbeSBoris Popov 		if (error)
194681a5bbeSBoris Popov 			return error;
195681a5bbeSBoris Popov 	}
196681a5bbeSBoris Popov 	SMBIODEBUG("tree reconnect\n");
197681a5bbeSBoris Popov 	SMBS_ST_LOCK(ssp);
198681a5bbeSBoris Popov 	ssp->ss_flags |= SMBS_RECONNECTING;
199681a5bbeSBoris Popov 	SMBS_ST_UNLOCK(ssp);
200681a5bbeSBoris Popov 	error = smb_smb_treeconnect(ssp, &iod->iod_scred);
201681a5bbeSBoris Popov 	SMBS_ST_LOCK(ssp);
202681a5bbeSBoris Popov 	ssp->ss_flags &= ~SMBS_RECONNECTING;
203681a5bbeSBoris Popov 	SMBS_ST_UNLOCK(ssp);
204681a5bbeSBoris Popov 	wakeup(&ssp->ss_vcgenid);
205681a5bbeSBoris Popov 	return error;
206681a5bbeSBoris Popov }
207681a5bbeSBoris Popov 
208681a5bbeSBoris Popov static int
209681a5bbeSBoris Popov smb_iod_sendrq(struct smbiod *iod, struct smb_rq *rqp)
210681a5bbeSBoris Popov {
211fce6fbfaSBoris Popov 	struct thread *td = iod->iod_td;
212681a5bbeSBoris Popov 	struct smb_vc *vcp = iod->iod_vc;
213681a5bbeSBoris Popov 	struct smb_share *ssp = rqp->sr_share;
214681a5bbeSBoris Popov 	struct mbuf *m;
215681a5bbeSBoris Popov 	int error;
216681a5bbeSBoris Popov 
217681a5bbeSBoris Popov 	SMBIODEBUG("iod_state = %d\n", iod->iod_state);
218681a5bbeSBoris Popov 	switch (iod->iod_state) {
219681a5bbeSBoris Popov 	    case SMBIOD_ST_NOTCONN:
220681a5bbeSBoris Popov 		smb_iod_rqprocessed(rqp, ENOTCONN);
221681a5bbeSBoris Popov 		return 0;
222681a5bbeSBoris Popov 	    case SMBIOD_ST_DEAD:
223681a5bbeSBoris Popov 		iod->iod_state = SMBIOD_ST_RECONNECT;
224681a5bbeSBoris Popov 		return 0;
225681a5bbeSBoris Popov 	    case SMBIOD_ST_RECONNECT:
226681a5bbeSBoris Popov 		return 0;
227681a5bbeSBoris Popov 	    default:
228681a5bbeSBoris Popov 		break;
229681a5bbeSBoris Popov 	}
230681a5bbeSBoris Popov 	if (rqp->sr_sendcnt == 0) {
231681a5bbeSBoris Popov #ifdef movedtoanotherplace
232681a5bbeSBoris Popov 		if (vcp->vc_maxmux != 0 && iod->iod_muxcnt >= vcp->vc_maxmux)
233681a5bbeSBoris Popov 			return 0;
234681a5bbeSBoris Popov #endif
235681a5bbeSBoris Popov 		*rqp->sr_rqtid = htoles(ssp ? ssp->ss_tid : SMB_TID_UNKNOWN);
236681a5bbeSBoris Popov 		*rqp->sr_rquid = htoles(vcp ? vcp->vc_smbuid : 0);
237681a5bbeSBoris Popov 		mb_fixhdr(&rqp->sr_rq);
238681a5bbeSBoris Popov 	}
239681a5bbeSBoris Popov 	if (rqp->sr_sendcnt++ > 5) {
240681a5bbeSBoris Popov 		rqp->sr_flags |= SMBR_RESTART;
241681a5bbeSBoris Popov 		smb_iod_rqprocessed(rqp, rqp->sr_lerror);
242681a5bbeSBoris Popov 		/*
243681a5bbeSBoris Popov 		 * If all attempts to send a request failed, then
244681a5bbeSBoris Popov 		 * something is seriously hosed.
245681a5bbeSBoris Popov 		 */
246681a5bbeSBoris Popov 		return ENOTCONN;
247681a5bbeSBoris Popov 	}
248681a5bbeSBoris Popov 	SMBSDEBUG("M:%04x, P:%04x, U:%04x, T:%04x\n", rqp->sr_mid, 0, 0, 0);
249681a5bbeSBoris Popov 	m_dumpm(rqp->sr_rq.mb_top);
250681a5bbeSBoris Popov 	m = m_copym(rqp->sr_rq.mb_top, 0, M_COPYALL, M_WAIT);
251fce6fbfaSBoris Popov 	error = rqp->sr_lerror = m ? SMB_TRAN_SEND(vcp, m, td) : ENOBUFS;
252681a5bbeSBoris Popov 	if (error == 0) {
253681a5bbeSBoris Popov 		getnanotime(&rqp->sr_timesent);
254681a5bbeSBoris Popov 		iod->iod_lastrqsent = rqp->sr_timesent;
255681a5bbeSBoris Popov 		rqp->sr_flags |= SMBR_SENT;
256681a5bbeSBoris Popov 		rqp->sr_state = SMBRQ_SENT;
257681a5bbeSBoris Popov 		return 0;
258681a5bbeSBoris Popov 	}
259681a5bbeSBoris Popov 	/*
260681a5bbeSBoris Popov 	 * Check for fatal errors
261681a5bbeSBoris Popov 	 */
262681a5bbeSBoris Popov 	if (SMB_TRAN_FATAL(vcp, error)) {
263681a5bbeSBoris Popov 		/*
264681a5bbeSBoris Popov 		 * No further attempts should be made
265681a5bbeSBoris Popov 		 */
266681a5bbeSBoris Popov 		return ENOTCONN;
267681a5bbeSBoris Popov 	}
268681a5bbeSBoris Popov 	if (smb_rq_intr(rqp))
269681a5bbeSBoris Popov 		smb_iod_rqprocessed(rqp, EINTR);
270681a5bbeSBoris Popov 	return 0;
271681a5bbeSBoris Popov }
272681a5bbeSBoris Popov 
273681a5bbeSBoris Popov /*
274681a5bbeSBoris Popov  * Process incoming packets
275681a5bbeSBoris Popov  */
276681a5bbeSBoris Popov static int
277681a5bbeSBoris Popov smb_iod_recvall(struct smbiod *iod)
278681a5bbeSBoris Popov {
279681a5bbeSBoris Popov 	struct smb_vc *vcp = iod->iod_vc;
280fce6fbfaSBoris Popov 	struct thread *td = iod->iod_td;
281681a5bbeSBoris Popov 	struct smb_rq *rqp;
282681a5bbeSBoris Popov 	struct mbuf *m;
283681a5bbeSBoris Popov 	u_char *hp;
284681a5bbeSBoris Popov 	u_short mid;
285681a5bbeSBoris Popov 	int error;
286681a5bbeSBoris Popov 
287681a5bbeSBoris Popov 	switch (iod->iod_state) {
288681a5bbeSBoris Popov 	    case SMBIOD_ST_NOTCONN:
289681a5bbeSBoris Popov 	    case SMBIOD_ST_DEAD:
290681a5bbeSBoris Popov 	    case SMBIOD_ST_RECONNECT:
291681a5bbeSBoris Popov 		return 0;
292681a5bbeSBoris Popov 	    default:
293681a5bbeSBoris Popov 		break;
294681a5bbeSBoris Popov 	}
295681a5bbeSBoris Popov 	for (;;) {
296681a5bbeSBoris Popov 		m = NULL;
297fce6fbfaSBoris Popov 		error = SMB_TRAN_RECV(vcp, &m, td);
298681a5bbeSBoris Popov 		if (error == EWOULDBLOCK)
299681a5bbeSBoris Popov 			break;
300681a5bbeSBoris Popov 		if (SMB_TRAN_FATAL(vcp, error)) {
301681a5bbeSBoris Popov 			smb_iod_dead(iod);
302681a5bbeSBoris Popov 			break;
303681a5bbeSBoris Popov 		}
304681a5bbeSBoris Popov 		if (error)
305681a5bbeSBoris Popov 			break;
306681a5bbeSBoris Popov 		if (m == NULL) {
307681a5bbeSBoris Popov 			SMBERROR("tran return NULL without error\n");
308681a5bbeSBoris Popov 			error = EPIPE;
309681a5bbeSBoris Popov 			continue;
310681a5bbeSBoris Popov 		}
311681a5bbeSBoris Popov 		m = m_pullup(m, SMB_HDRLEN);
312681a5bbeSBoris Popov 		if (m == NULL)
313681a5bbeSBoris Popov 			continue;	/* wait for a good packet */
314681a5bbeSBoris Popov 		/*
315681a5bbeSBoris Popov 		 * Now we got an entire and possibly invalid SMB packet.
316681a5bbeSBoris Popov 		 * Be careful while parsing it.
317681a5bbeSBoris Popov 		 */
318681a5bbeSBoris Popov 		m_dumpm(m);
319681a5bbeSBoris Popov 		hp = mtod(m, u_char*);
320681a5bbeSBoris Popov 		if (bcmp(hp, SMB_SIGNATURE, SMB_SIGLEN) != 0) {
321681a5bbeSBoris Popov 			m_freem(m);
322681a5bbeSBoris Popov 			continue;
323681a5bbeSBoris Popov 		}
324681a5bbeSBoris Popov 		mid = SMB_HDRMID(hp);
325681a5bbeSBoris Popov 		SMBSDEBUG("mid %04x\n", (u_int)mid);
326681a5bbeSBoris Popov 		SMB_IOD_RQLOCK(iod);
327681a5bbeSBoris Popov 		TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
328681a5bbeSBoris Popov 			if (rqp->sr_mid != mid)
329681a5bbeSBoris Popov 				continue;
330681a5bbeSBoris Popov 			SMBRQ_SLOCK(rqp);
331681a5bbeSBoris Popov 			if (rqp->sr_rp.md_top == NULL) {
332681a5bbeSBoris Popov 				md_initm(&rqp->sr_rp, m);
333681a5bbeSBoris Popov 			} else {
334681a5bbeSBoris Popov 				if (rqp->sr_flags & SMBR_MULTIPACKET) {
335681a5bbeSBoris Popov 					md_append_record(&rqp->sr_rp, m);
336681a5bbeSBoris Popov 				} else {
337681a5bbeSBoris Popov 					SMBRQ_SUNLOCK(rqp);
338681a5bbeSBoris Popov 					SMBERROR("duplicate response %d (ignored)\n", mid);
339681a5bbeSBoris Popov 					break;
340681a5bbeSBoris Popov 				}
341681a5bbeSBoris Popov 			}
342681a5bbeSBoris Popov 			SMBRQ_SUNLOCK(rqp);
343681a5bbeSBoris Popov 			smb_iod_rqprocessed(rqp, 0);
344681a5bbeSBoris Popov 			break;
345681a5bbeSBoris Popov 		}
346681a5bbeSBoris Popov 		SMB_IOD_RQUNLOCK(iod);
347681a5bbeSBoris Popov 		if (rqp == NULL) {
348681a5bbeSBoris Popov 			SMBERROR("drop resp with mid %d\n", (u_int)mid);
349681a5bbeSBoris Popov /*			smb_printrqlist(vcp);*/
350681a5bbeSBoris Popov 			m_freem(m);
351681a5bbeSBoris Popov 		}
352681a5bbeSBoris Popov 	}
353681a5bbeSBoris Popov 	/*
354681a5bbeSBoris Popov 	 * check for interrupts
355681a5bbeSBoris Popov 	 */
356681a5bbeSBoris Popov 	SMB_IOD_RQLOCK(iod);
357681a5bbeSBoris Popov 	TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
358fce6fbfaSBoris Popov 		if (smb_proc_intr(rqp->sr_cred->scr_td->td_proc)) {
359681a5bbeSBoris Popov 			smb_iod_rqprocessed(rqp, EINTR);
360681a5bbeSBoris Popov 		}
361681a5bbeSBoris Popov 	}
362681a5bbeSBoris Popov 	SMB_IOD_RQUNLOCK(iod);
363681a5bbeSBoris Popov 	return 0;
364681a5bbeSBoris Popov }
365681a5bbeSBoris Popov 
366681a5bbeSBoris Popov int
367681a5bbeSBoris Popov smb_iod_request(struct smbiod *iod, int event, void *ident)
368681a5bbeSBoris Popov {
369681a5bbeSBoris Popov 	struct smbiod_event *evp;
370681a5bbeSBoris Popov 	int error;
371681a5bbeSBoris Popov 
372681a5bbeSBoris Popov 	SMBIODEBUG("\n");
373681a5bbeSBoris Popov 	evp = smb_zmalloc(sizeof(*evp), M_SMBIOD, M_WAITOK);
374681a5bbeSBoris Popov 	evp->ev_type = event;
375681a5bbeSBoris Popov 	evp->ev_ident = ident;
376681a5bbeSBoris Popov 	SMB_IOD_EVLOCK(iod);
377681a5bbeSBoris Popov 	STAILQ_INSERT_TAIL(&iod->iod_evlist, evp, ev_link);
378681a5bbeSBoris Popov 	if ((event & SMBIOD_EV_SYNC) == 0) {
379681a5bbeSBoris Popov 		SMB_IOD_EVUNLOCK(iod);
380681a5bbeSBoris Popov 		smb_iod_wakeup(iod);
381681a5bbeSBoris Popov 		return 0;
382681a5bbeSBoris Popov 	}
383681a5bbeSBoris Popov 	smb_iod_wakeup(iod);
384681a5bbeSBoris Popov 	msleep(evp, SMB_IOD_EVLOCKPTR(iod), PWAIT | PDROP, "90evw", 0);
385681a5bbeSBoris Popov 	error = evp->ev_error;
386681a5bbeSBoris Popov 	free(evp, M_SMBIOD);
387681a5bbeSBoris Popov 	return error;
388681a5bbeSBoris Popov }
389681a5bbeSBoris Popov 
390681a5bbeSBoris Popov /*
391681a5bbeSBoris Popov  * Place request in the queue.
392681a5bbeSBoris Popov  * Request from smbiod have a high priority.
393681a5bbeSBoris Popov  */
394681a5bbeSBoris Popov int
395681a5bbeSBoris Popov smb_iod_addrq(struct smb_rq *rqp)
396681a5bbeSBoris Popov {
397681a5bbeSBoris Popov 	struct smb_vc *vcp = rqp->sr_vc;
398681a5bbeSBoris Popov 	struct smbiod *iod = vcp->vc_iod;
399681a5bbeSBoris Popov 	int error;
400681a5bbeSBoris Popov 
401681a5bbeSBoris Popov 	SMBIODEBUG("\n");
402fce6fbfaSBoris Popov 	if (rqp->sr_cred->scr_td->td_proc == iod->iod_p) {
403681a5bbeSBoris Popov 		rqp->sr_flags |= SMBR_INTERNAL;
404681a5bbeSBoris Popov 		SMB_IOD_RQLOCK(iod);
405681a5bbeSBoris Popov 		TAILQ_INSERT_HEAD(&iod->iod_rqlist, rqp, sr_link);
406681a5bbeSBoris Popov 		SMB_IOD_RQUNLOCK(iod);
407681a5bbeSBoris Popov 		for (;;) {
408681a5bbeSBoris Popov 			if (smb_iod_sendrq(iod, rqp) != 0) {
409681a5bbeSBoris Popov 				smb_iod_dead(iod);
410681a5bbeSBoris Popov 				break;
411681a5bbeSBoris Popov 			}
412681a5bbeSBoris Popov 			/*
413681a5bbeSBoris Popov 			 * we don't need to lock state field here
414681a5bbeSBoris Popov 			 */
415681a5bbeSBoris Popov 			if (rqp->sr_state != SMBRQ_NOTSENT)
416681a5bbeSBoris Popov 				break;
417681a5bbeSBoris Popov 			tsleep(&iod->iod_flags, PWAIT, "90sndw", hz);
418681a5bbeSBoris Popov 		}
419681a5bbeSBoris Popov 		if (rqp->sr_lerror)
420681a5bbeSBoris Popov 			smb_iod_removerq(rqp);
421681a5bbeSBoris Popov 		return rqp->sr_lerror;
422681a5bbeSBoris Popov 	}
423681a5bbeSBoris Popov 
424681a5bbeSBoris Popov 	switch (iod->iod_state) {
425681a5bbeSBoris Popov 	    case SMBIOD_ST_NOTCONN:
426681a5bbeSBoris Popov 		return ENOTCONN;
427681a5bbeSBoris Popov 	    case SMBIOD_ST_DEAD:
428681a5bbeSBoris Popov 		error = smb_iod_request(vcp->vc_iod, SMBIOD_EV_CONNECT | SMBIOD_EV_SYNC, NULL);
429681a5bbeSBoris Popov 		if (error)
430681a5bbeSBoris Popov 			return error;
431681a5bbeSBoris Popov 		return EXDEV;
432681a5bbeSBoris Popov 	    default:
433681a5bbeSBoris Popov 		break;
434681a5bbeSBoris Popov 	}
435681a5bbeSBoris Popov 
436681a5bbeSBoris Popov 	SMB_IOD_RQLOCK(iod);
437681a5bbeSBoris Popov 	for (;;) {
438681a5bbeSBoris Popov 		if (vcp->vc_maxmux == 0) {
439681a5bbeSBoris Popov 			SMBERROR("maxmux == 0\n");
440681a5bbeSBoris Popov 			break;
441681a5bbeSBoris Popov 		}
442681a5bbeSBoris Popov 		if (iod->iod_muxcnt < vcp->vc_maxmux)
443681a5bbeSBoris Popov 			break;
444681a5bbeSBoris Popov 		iod->iod_muxwant++;
445681a5bbeSBoris Popov 		msleep(&iod->iod_muxwant, SMB_IOD_RQLOCKPTR(iod),
446681a5bbeSBoris Popov 		    PWAIT, "90mux", 0);
447681a5bbeSBoris Popov 	}
448681a5bbeSBoris Popov 	iod->iod_muxcnt++;
449681a5bbeSBoris Popov 	TAILQ_INSERT_TAIL(&iod->iod_rqlist, rqp, sr_link);
450681a5bbeSBoris Popov 	SMB_IOD_RQUNLOCK(iod);
451681a5bbeSBoris Popov 	smb_iod_wakeup(iod);
452681a5bbeSBoris Popov 	return 0;
453681a5bbeSBoris Popov }
454681a5bbeSBoris Popov 
455681a5bbeSBoris Popov int
456681a5bbeSBoris Popov smb_iod_removerq(struct smb_rq *rqp)
457681a5bbeSBoris Popov {
458681a5bbeSBoris Popov 	struct smb_vc *vcp = rqp->sr_vc;
459681a5bbeSBoris Popov 	struct smbiod *iod = vcp->vc_iod;
460681a5bbeSBoris Popov 
461681a5bbeSBoris Popov 	SMBIODEBUG("\n");
462681a5bbeSBoris Popov 	if (rqp->sr_flags & SMBR_INTERNAL) {
463681a5bbeSBoris Popov 		SMB_IOD_RQLOCK(iod);
464681a5bbeSBoris Popov 		TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
465681a5bbeSBoris Popov 		SMB_IOD_RQUNLOCK(iod);
466681a5bbeSBoris Popov 		return 0;
467681a5bbeSBoris Popov 	}
468681a5bbeSBoris Popov 	SMB_IOD_RQLOCK(iod);
469681a5bbeSBoris Popov 	while (rqp->sr_flags & SMBR_XLOCK) {
470681a5bbeSBoris Popov 		rqp->sr_flags |= SMBR_XLOCKWANT;
471681a5bbeSBoris Popov 		msleep(rqp, SMB_IOD_RQLOCKPTR(iod), PWAIT, "90xrm", 0);
472681a5bbeSBoris Popov 	}
473681a5bbeSBoris Popov 	TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
474681a5bbeSBoris Popov 	iod->iod_muxcnt--;
475681a5bbeSBoris Popov 	if (iod->iod_muxwant) {
476681a5bbeSBoris Popov 		iod->iod_muxwant--;
477681a5bbeSBoris Popov 		wakeup(&iod->iod_muxwant);
478681a5bbeSBoris Popov 	}
479681a5bbeSBoris Popov 	SMB_IOD_RQUNLOCK(iod);
480681a5bbeSBoris Popov 	return 0;
481681a5bbeSBoris Popov }
482681a5bbeSBoris Popov 
483681a5bbeSBoris Popov int
484681a5bbeSBoris Popov smb_iod_waitrq(struct smb_rq *rqp)
485681a5bbeSBoris Popov {
486681a5bbeSBoris Popov 	struct smbiod *iod = rqp->sr_vc->vc_iod;
487681a5bbeSBoris Popov 	int error;
488681a5bbeSBoris Popov 
489681a5bbeSBoris Popov 	SMBIODEBUG("\n");
490681a5bbeSBoris Popov 	if (rqp->sr_flags & SMBR_INTERNAL) {
491681a5bbeSBoris Popov 		for (;;) {
492681a5bbeSBoris Popov 			smb_iod_sendall(iod);
493681a5bbeSBoris Popov 			smb_iod_recvall(iod);
494681a5bbeSBoris Popov 			if (rqp->sr_rpgen != rqp->sr_rplast)
495681a5bbeSBoris Popov 				break;
496681a5bbeSBoris Popov 			tsleep(&iod->iod_flags, PWAIT, "90irq", hz);
497681a5bbeSBoris Popov 		}
498681a5bbeSBoris Popov 		smb_iod_removerq(rqp);
499681a5bbeSBoris Popov 		return rqp->sr_lerror;
500681a5bbeSBoris Popov 
501681a5bbeSBoris Popov 	}
502681a5bbeSBoris Popov 	SMBRQ_SLOCK(rqp);
503681a5bbeSBoris Popov 	if (rqp->sr_rpgen == rqp->sr_rplast)
504681a5bbeSBoris Popov 		msleep(&rqp->sr_state, SMBRQ_SLOCKPTR(rqp), PWAIT, "90wrq", 0);
505681a5bbeSBoris Popov 	rqp->sr_rplast++;
506681a5bbeSBoris Popov 	SMBRQ_SUNLOCK(rqp);
507681a5bbeSBoris Popov 	error = rqp->sr_lerror;
508681a5bbeSBoris Popov 	if (rqp->sr_flags & SMBR_MULTIPACKET) {
509681a5bbeSBoris Popov 		/*
510681a5bbeSBoris Popov 		 * If request should stay in the list, then reinsert it
511681a5bbeSBoris Popov 		 * at the end of queue so other waiters have chance to concur
512681a5bbeSBoris Popov 		 */
513681a5bbeSBoris Popov 		SMB_IOD_RQLOCK(iod);
514681a5bbeSBoris Popov 		TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
515681a5bbeSBoris Popov 		TAILQ_INSERT_TAIL(&iod->iod_rqlist, rqp, sr_link);
516681a5bbeSBoris Popov 		SMB_IOD_RQUNLOCK(iod);
517681a5bbeSBoris Popov 	} else
518681a5bbeSBoris Popov 		smb_iod_removerq(rqp);
519681a5bbeSBoris Popov 	return error;
520681a5bbeSBoris Popov }
521681a5bbeSBoris Popov 
522681a5bbeSBoris Popov 
523681a5bbeSBoris Popov static int
524681a5bbeSBoris Popov smb_iod_sendall(struct smbiod *iod)
525681a5bbeSBoris Popov {
526681a5bbeSBoris Popov 	struct smb_vc *vcp = iod->iod_vc;
527681a5bbeSBoris Popov 	struct smb_rq *rqp;
528681a5bbeSBoris Popov 	struct timespec ts, tstimeout;
529681a5bbeSBoris Popov 	int herror;
530681a5bbeSBoris Popov 
531681a5bbeSBoris Popov 	herror = 0;
532681a5bbeSBoris Popov 	/*
533681a5bbeSBoris Popov 	 * Loop through the list of requests and send them if possible
534681a5bbeSBoris Popov 	 */
535681a5bbeSBoris Popov 	SMB_IOD_RQLOCK(iod);
536681a5bbeSBoris Popov 	TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
537681a5bbeSBoris Popov 		switch (rqp->sr_state) {
538681a5bbeSBoris Popov 		    case SMBRQ_NOTSENT:
539681a5bbeSBoris Popov 			rqp->sr_flags |= SMBR_XLOCK;
540681a5bbeSBoris Popov 			SMB_IOD_RQUNLOCK(iod);
541681a5bbeSBoris Popov 			herror = smb_iod_sendrq(iod, rqp);
542681a5bbeSBoris Popov 			SMB_IOD_RQLOCK(iod);
543681a5bbeSBoris Popov 			rqp->sr_flags &= ~SMBR_XLOCK;
544681a5bbeSBoris Popov 			if (rqp->sr_flags & SMBR_XLOCKWANT) {
545681a5bbeSBoris Popov 				rqp->sr_flags &= ~SMBR_XLOCKWANT;
546681a5bbeSBoris Popov 				wakeup(rqp);
547681a5bbeSBoris Popov 			}
548681a5bbeSBoris Popov 			break;
549681a5bbeSBoris Popov 		    case SMBRQ_SENT:
550681a5bbeSBoris Popov 			SMB_TRAN_GETPARAM(vcp, SMBTP_TIMEOUT, &tstimeout);
551681a5bbeSBoris Popov 			timespecadd(&tstimeout, &tstimeout);
552681a5bbeSBoris Popov 			getnanotime(&ts);
553681a5bbeSBoris Popov 			timespecsub(&ts, &tstimeout);
554681a5bbeSBoris Popov 			if (timespeccmp(&ts, &rqp->sr_timesent, >)) {
555681a5bbeSBoris Popov 				smb_iod_rqprocessed(rqp, ETIMEDOUT);
556681a5bbeSBoris Popov 			}
557681a5bbeSBoris Popov 			break;
558681a5bbeSBoris Popov 		    default:
559681a5bbeSBoris Popov 		}
560681a5bbeSBoris Popov 		if (herror)
561681a5bbeSBoris Popov 			break;
562681a5bbeSBoris Popov 	}
563681a5bbeSBoris Popov 	SMB_IOD_RQUNLOCK(iod);
564681a5bbeSBoris Popov 	if (herror == ENOTCONN)
565681a5bbeSBoris Popov 		smb_iod_dead(iod);
566681a5bbeSBoris Popov 	return 0;
567681a5bbeSBoris Popov }
568681a5bbeSBoris Popov 
569681a5bbeSBoris Popov /*
570681a5bbeSBoris Popov  * "main" function for smbiod daemon
571681a5bbeSBoris Popov  */
572681a5bbeSBoris Popov static __inline void
573681a5bbeSBoris Popov smb_iod_main(struct smbiod *iod)
574681a5bbeSBoris Popov {
575681a5bbeSBoris Popov /*	struct smb_vc *vcp = iod->iod_vc;*/
576681a5bbeSBoris Popov 	struct smbiod_event *evp;
577681a5bbeSBoris Popov /*	struct timespec tsnow;*/
578681a5bbeSBoris Popov 	int error;
579681a5bbeSBoris Popov 
580681a5bbeSBoris Popov 	SMBIODEBUG("\n");
581681a5bbeSBoris Popov 	error = 0;
582681a5bbeSBoris Popov 
583681a5bbeSBoris Popov 	/*
584681a5bbeSBoris Popov 	 * Check all interesting events
585681a5bbeSBoris Popov 	 */
586681a5bbeSBoris Popov 	for (;;) {
587681a5bbeSBoris Popov 		SMB_IOD_EVLOCK(iod);
588681a5bbeSBoris Popov 		evp = STAILQ_FIRST(&iod->iod_evlist);
589681a5bbeSBoris Popov 		if (evp == NULL) {
590681a5bbeSBoris Popov 			SMB_IOD_EVUNLOCK(iod);
591681a5bbeSBoris Popov 			break;
592681a5bbeSBoris Popov 		}
593681a5bbeSBoris Popov 		STAILQ_REMOVE_HEAD(&iod->iod_evlist, ev_link);
594681a5bbeSBoris Popov 		evp->ev_type |= SMBIOD_EV_PROCESSING;
595681a5bbeSBoris Popov 		SMB_IOD_EVUNLOCK(iod);
596681a5bbeSBoris Popov 		switch (evp->ev_type & SMBIOD_EV_MASK) {
597681a5bbeSBoris Popov 		    case SMBIOD_EV_CONNECT:
598681a5bbeSBoris Popov 			iod->iod_state = SMBIOD_ST_RECONNECT;
599681a5bbeSBoris Popov 			evp->ev_error = smb_iod_connect(iod);
600681a5bbeSBoris Popov 			break;
601681a5bbeSBoris Popov 		    case SMBIOD_EV_DISCONNECT:
602681a5bbeSBoris Popov 			evp->ev_error = smb_iod_disconnect(iod);
603681a5bbeSBoris Popov 			break;
604681a5bbeSBoris Popov 		    case SMBIOD_EV_TREECONNECT:
605681a5bbeSBoris Popov 			evp->ev_error = smb_iod_treeconnect(iod, evp->ev_ident);
606681a5bbeSBoris Popov 			break;
607681a5bbeSBoris Popov 		    case SMBIOD_EV_SHUTDOWN:
608681a5bbeSBoris Popov 			iod->iod_flags |= SMBIOD_SHUTDOWN;
609681a5bbeSBoris Popov 			break;
610681a5bbeSBoris Popov 		    case SMBIOD_EV_NEWRQ:
611681a5bbeSBoris Popov 			break;
612681a5bbeSBoris Popov 		}
613681a5bbeSBoris Popov 		if (evp->ev_type & SMBIOD_EV_SYNC) {
614681a5bbeSBoris Popov 			SMB_IOD_EVLOCK(iod);
615681a5bbeSBoris Popov 			wakeup(evp);
616681a5bbeSBoris Popov 			SMB_IOD_EVUNLOCK(iod);
617681a5bbeSBoris Popov 		} else
618681a5bbeSBoris Popov 			free(evp, M_SMBIOD);
619681a5bbeSBoris Popov 	}
620681a5bbeSBoris Popov #if 0
621681a5bbeSBoris Popov 	if (iod->iod_state == SMBIOD_ST_VCACTIVE) {
622681a5bbeSBoris Popov 		getnanotime(&tsnow);
623681a5bbeSBoris Popov 		timespecsub(&tsnow, &iod->iod_pingtimo);
624681a5bbeSBoris Popov 		if (timespeccmp(&tsnow, &iod->iod_lastrqsent, >)) {
625681a5bbeSBoris Popov 			smb_smb_echo(vcp, &iod->iod_scred);
626681a5bbeSBoris Popov 		}
627681a5bbeSBoris Popov 	}
628681a5bbeSBoris Popov #endif
629681a5bbeSBoris Popov 	smb_iod_sendall(iod);
630681a5bbeSBoris Popov 	smb_iod_recvall(iod);
631681a5bbeSBoris Popov 	return;
632681a5bbeSBoris Popov }
633681a5bbeSBoris Popov 
634681a5bbeSBoris Popov void
635681a5bbeSBoris Popov smb_iod_thread(void *arg)
636681a5bbeSBoris Popov {
637681a5bbeSBoris Popov 	struct smbiod *iod = arg;
638681a5bbeSBoris Popov 
639681a5bbeSBoris Popov 	mtx_lock(&Giant);
640fce6fbfaSBoris Popov 	/*
641fce6fbfaSBoris Popov 	 * Here we assume that the thread structure will be the same
642fce6fbfaSBoris Popov 	 * for an entire kthread (kproc, to be more precise) life.
643fce6fbfaSBoris Popov 	 */
644fce6fbfaSBoris Popov 	iod->iod_td = curthread;
645fce6fbfaSBoris Popov 	smb_makescred(&iod->iod_scred, iod->iod_td, NULL);
646681a5bbeSBoris Popov 	while ((iod->iod_flags & SMBIOD_SHUTDOWN) == 0) {
647681a5bbeSBoris Popov 		smb_iod_main(iod);
648681a5bbeSBoris Popov 		SMBIODEBUG("going to sleep for %d ticks\n", iod->iod_sleeptimo);
649681a5bbeSBoris Popov /*		mtx_unlock(&Giant, MTX_DEF);*/
650681a5bbeSBoris Popov 		if (iod->iod_flags & SMBIOD_SHUTDOWN)
651681a5bbeSBoris Popov 			break;
652681a5bbeSBoris Popov 		tsleep(&iod->iod_flags, PWAIT, "90idle", iod->iod_sleeptimo);
653681a5bbeSBoris Popov 	}
654681a5bbeSBoris Popov /*	mtx_lock(&Giant, MTX_DEF);*/
655681a5bbeSBoris Popov 	kthread_exit(0);
656681a5bbeSBoris Popov }
657681a5bbeSBoris Popov 
658681a5bbeSBoris Popov int
659681a5bbeSBoris Popov smb_iod_create(struct smb_vc *vcp)
660681a5bbeSBoris Popov {
661681a5bbeSBoris Popov 	struct smbiod *iod;
662681a5bbeSBoris Popov 	int error;
663681a5bbeSBoris Popov 
664681a5bbeSBoris Popov 	iod = smb_zmalloc(sizeof(*iod), M_SMBIOD, M_WAITOK);
665681a5bbeSBoris Popov 	iod->iod_id = smb_iod_next++;
666681a5bbeSBoris Popov 	iod->iod_state = SMBIOD_ST_NOTCONN;
667681a5bbeSBoris Popov 	iod->iod_vc = vcp;
668681a5bbeSBoris Popov 	iod->iod_sleeptimo = hz * SMBIOD_SLEEP_TIMO;
669681a5bbeSBoris Popov 	iod->iod_pingtimo.tv_sec = SMBIOD_PING_TIMO;
670681a5bbeSBoris Popov 	getnanotime(&iod->iod_lastrqsent);
671681a5bbeSBoris Popov 	vcp->vc_iod = iod;
672681a5bbeSBoris Popov 	smb_sl_init(&iod->iod_rqlock, "90rql");
673681a5bbeSBoris Popov 	TAILQ_INIT(&iod->iod_rqlist);
674681a5bbeSBoris Popov 	smb_sl_init(&iod->iod_evlock, "90evl");
675681a5bbeSBoris Popov 	STAILQ_INIT(&iod->iod_evlist);
676fce6fbfaSBoris Popov 	error = kthread_create(smb_iod_thread, iod, &iod->iod_p,
677681a5bbeSBoris Popov 	    RFNOWAIT, "smbiod%d", iod->iod_id);
678681a5bbeSBoris Popov 	if (error) {
679681a5bbeSBoris Popov 		SMBERROR("can't start smbiod: %d", error);
680681a5bbeSBoris Popov 		free(iod, M_SMBIOD);
681681a5bbeSBoris Popov 		return error;
682681a5bbeSBoris Popov 	}
683681a5bbeSBoris Popov 	return 0;
684681a5bbeSBoris Popov }
685681a5bbeSBoris Popov 
686681a5bbeSBoris Popov int
687681a5bbeSBoris Popov smb_iod_destroy(struct smbiod *iod)
688681a5bbeSBoris Popov {
689681a5bbeSBoris Popov 	smb_iod_request(iod, SMBIOD_EV_SHUTDOWN | SMBIOD_EV_SYNC, NULL);
690e7681448SBoris Popov 	smb_sl_destroy(&iod->iod_rqlock);
691e7681448SBoris Popov 	smb_sl_destroy(&iod->iod_evlock);
692681a5bbeSBoris Popov 	free(iod, M_SMBIOD);
693681a5bbeSBoris Popov 	return 0;
694681a5bbeSBoris Popov }
695681a5bbeSBoris Popov 
696681a5bbeSBoris Popov int
697681a5bbeSBoris Popov smb_iod_init(void)
698681a5bbeSBoris Popov {
699681a5bbeSBoris Popov 	return 0;
700681a5bbeSBoris Popov }
701681a5bbeSBoris Popov 
702681a5bbeSBoris Popov int
703681a5bbeSBoris Popov smb_iod_done(void)
704681a5bbeSBoris Popov {
705681a5bbeSBoris Popov 	return 0;
706681a5bbeSBoris Popov }
707681a5bbeSBoris Popov 
708