FreeBSD/Linux Kernel Cross Reference
sys/netsmb/smb_iod.c
1 /*
2 * Copyright (c) 2000-2001 Boris Popov
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/endian.h>
39 #include <sys/proc.h>
40 #include <sys/kernel.h>
41 #include <sys/kthread.h>
42 #include <sys/malloc.h>
43 #include <sys/mbuf.h>
44 #include <sys/unistd.h>
45
46 #include <netsmb/smb.h>
47 #include <netsmb/smb_conn.h>
48 #include <netsmb/smb_rq.h>
49 #include <netsmb/smb_tran.h>
50 #include <netsmb/smb_trantcp.h>
51
52
53 #define SMBIOD_SLEEP_TIMO 2
54 #define SMBIOD_PING_TIMO 60 /* seconds */
55
56 #define SMB_IOD_EVLOCKPTR(iod) (&((iod)->iod_evlock))
57 #define SMB_IOD_EVLOCK(iod) smb_sl_lock(&((iod)->iod_evlock))
58 #define SMB_IOD_EVUNLOCK(iod) smb_sl_unlock(&((iod)->iod_evlock))
59
60 #define SMB_IOD_RQLOCKPTR(iod) (&((iod)->iod_rqlock))
61 #define SMB_IOD_RQLOCK(iod) smb_sl_lock(&((iod)->iod_rqlock))
62 #define SMB_IOD_RQUNLOCK(iod) smb_sl_unlock(&((iod)->iod_rqlock))
63
64 #define smb_iod_wakeup(iod) wakeup(&(iod)->iod_flags)
65
66
67 static MALLOC_DEFINE(M_SMBIOD, "SMBIOD", "SMB network io daemon");
68
69 static int smb_iod_next;
70
71 static int smb_iod_sendall(struct smbiod *iod);
72 static int smb_iod_disconnect(struct smbiod *iod);
73 static void smb_iod_thread(void *);
74
75 static __inline void
76 smb_iod_rqprocessed(struct smb_rq *rqp, int error)
77 {
78 SMBRQ_SLOCK(rqp);
79 rqp->sr_lerror = error;
80 rqp->sr_rpgen++;
81 rqp->sr_state = SMBRQ_NOTIFIED;
82 wakeup(&rqp->sr_state);
83 SMBRQ_SUNLOCK(rqp);
84 }
85
86 static void
87 smb_iod_invrq(struct smbiod *iod)
88 {
89 struct smb_rq *rqp;
90
91 /*
92 * Invalidate all outstanding requests for this connection
93 */
94 SMB_IOD_RQLOCK(iod);
95 TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
96 if (rqp->sr_flags & SMBR_INTERNAL)
97 SMBRQ_SUNLOCK(rqp);
98 rqp->sr_flags |= SMBR_RESTART;
99 smb_iod_rqprocessed(rqp, ENOTCONN);
100 }
101 SMB_IOD_RQUNLOCK(iod);
102 }
103
104 static void
105 smb_iod_closetran(struct smbiod *iod)
106 {
107 struct smb_vc *vcp = iod->iod_vc;
108 struct proc *p = iod->iod_p;
109
110 if (vcp->vc_tdata == NULL)
111 return;
112 SMB_TRAN_DISCONNECT(vcp, p);
113 SMB_TRAN_DONE(vcp, p);
114 vcp->vc_tdata = NULL;
115 }
116
117 static void
118 smb_iod_dead(struct smbiod *iod)
119 {
120 iod->iod_state = SMBIOD_ST_DEAD;
121 smb_iod_closetran(iod);
122 smb_iod_invrq(iod);
123 }
124
125 static int
126 smb_iod_connect(struct smbiod *iod)
127 {
128 struct smb_vc *vcp = iod->iod_vc;
129 struct proc *p = iod->iod_p;
130 int error;
131
132 SMBIODEBUG("%d\n", iod->iod_state);
133 switch(iod->iod_state) {
134 case SMBIOD_ST_VCACTIVE:
135 SMBERROR("called for already opened connection\n");
136 return EISCONN;
137 case SMBIOD_ST_DEAD:
138 return ENOTCONN; /* XXX: last error code ? */
139 default:
140 break;
141 }
142 vcp->vc_genid++;
143 error = (int)SMB_TRAN_CREATE(vcp, p);
144 if (error)
145 goto fail;
146 SMBIODEBUG("tcreate\n");
147 if (vcp->vc_laddr) {
148 error = (int)SMB_TRAN_BIND(vcp, vcp->vc_laddr, p);
149 if (error)
150 goto fail;
151 }
152 SMBIODEBUG("tbind\n");
153 error = (int)SMB_TRAN_CONNECT(vcp, vcp->vc_paddr, p);
154 if (error)
155 goto fail;
156 SMB_TRAN_SETPARAM(vcp, SMBTP_SELECTID, &iod->iod_flags);
157 iod->iod_state = SMBIOD_ST_TRANACTIVE;
158 SMBIODEBUG("tconnect\n");
159 /* vcp->vc_mid = 0;*/
160 error = (int)smb_smb_negotiate(vcp, &iod->iod_scred);
161 if (error)
162 goto fail;
163 SMBIODEBUG("snegotiate\n");
164 error = (int)smb_smb_ssnsetup(vcp, &iod->iod_scred);
165 if (error)
166 goto fail;
167 iod->iod_state = SMBIOD_ST_VCACTIVE;
168 SMBIODEBUG("completed\n");
169 smb_iod_invrq(iod);
170 return (0);
171
172 fail:
173 smb_iod_dead(iod);
174 return (error);
175 }
176
177 static int
178 smb_iod_disconnect(struct smbiod *iod)
179 {
180 struct smb_vc *vcp = iod->iod_vc;
181
182 SMBIODEBUG("\n");
183 if (iod->iod_state == SMBIOD_ST_VCACTIVE) {
184 smb_smb_ssnclose(vcp, &iod->iod_scred);
185 iod->iod_state = SMBIOD_ST_TRANACTIVE;
186 }
187 vcp->vc_smbuid = SMB_UID_UNKNOWN;
188 smb_iod_closetran(iod);
189 iod->iod_state = SMBIOD_ST_NOTCONN;
190 return 0;
191 }
192
193 static int
194 smb_iod_treeconnect(struct smbiod *iod, struct smb_share *ssp)
195 {
196 int error;
197
198 if (iod->iod_state != SMBIOD_ST_VCACTIVE) {
199 if (iod->iod_state != SMBIOD_ST_DEAD)
200 return ENOTCONN;
201 iod->iod_state = SMBIOD_ST_RECONNECT;
202 error = smb_iod_connect(iod);
203 if (error)
204 return error;
205 }
206 SMBIODEBUG("tree reconnect\n");
207 SMBS_ST_LOCK(ssp);
208 ssp->ss_flags |= SMBS_RECONNECTING;
209 SMBS_ST_UNLOCK(ssp);
210 error = smb_smb_treeconnect(ssp, &iod->iod_scred);
211 SMBS_ST_LOCK(ssp);
212 ssp->ss_flags &= ~SMBS_RECONNECTING;
213 SMBS_ST_UNLOCK(ssp);
214 wakeup(&ssp->ss_vcgenid);
215 return error;
216 }
217
218 static int
219 smb_iod_sendrq(struct smbiod *iod, struct smb_rq *rqp)
220 {
221 struct proc *p = iod->iod_p;
222 struct smb_vc *vcp = iod->iod_vc;
223 struct smb_share *ssp = rqp->sr_share;
224 struct mbuf *m;
225 int error;
226
227 SMBIODEBUG("iod_state = %d\n", iod->iod_state);
228 switch (iod->iod_state) {
229 case SMBIOD_ST_NOTCONN:
230 smb_iod_rqprocessed(rqp, ENOTCONN);
231 return 0;
232 case SMBIOD_ST_DEAD:
233 iod->iod_state = SMBIOD_ST_RECONNECT;
234 return 0;
235 case SMBIOD_ST_RECONNECT:
236 return 0;
237 default:
238 break;
239 }
240 if (rqp->sr_sendcnt == 0) {
241 #ifdef movedtoanotherplace
242 if (vcp->vc_maxmux != 0 && iod->iod_muxcnt >= vcp->vc_maxmux)
243 return 0;
244 #endif
245 *rqp->sr_rqtid = htole16(ssp ? ssp->ss_tid : SMB_TID_UNKNOWN);
246 *rqp->sr_rquid = htole16(vcp ? vcp->vc_smbuid : 0);
247 mb_fixhdr(&rqp->sr_rq);
248 if (vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE)
249 smb_rq_sign(rqp);
250 }
251 if (rqp->sr_sendcnt++ > 5) {
252 rqp->sr_flags |= SMBR_RESTART;
253 smb_iod_rqprocessed(rqp, rqp->sr_lerror);
254 /*
255 * If all attempts to send a request failed, then
256 * something is seriously hosed.
257 */
258 return ENOTCONN;
259 }
260 SMBSDEBUG("M:%04x, P:%04x, U:%04x, T:%04x\n", rqp->sr_mid, 0, 0, 0);
261 m_dumpm(rqp->sr_rq.mb_top);
262 m = m_copym(rqp->sr_rq.mb_top, 0, M_COPYALL, M_WAITOK);
263 error = rqp->sr_lerror = m ? SMB_TRAN_SEND(vcp, m, p) : ENOBUFS;
264 if (error == 0) {
265 getnanotime(&rqp->sr_timesent);
266 iod->iod_lastrqsent = rqp->sr_timesent;
267 rqp->sr_flags |= SMBR_SENT;
268 rqp->sr_state = SMBRQ_SENT;
269 return 0;
270 }
271 /*
272 * Check for fatal errors
273 */
274 if (SMB_TRAN_FATAL(vcp, error)) {
275 /*
276 * No further attempts should be made
277 */
278 return ENOTCONN;
279 }
280 if (smb_rq_intr(rqp))
281 smb_iod_rqprocessed(rqp, EINTR);
282 return 0;
283 }
284
285 /*
286 * Process incoming packets
287 */
288 static int
289 smb_iod_recvall(struct smbiod *iod)
290 {
291 struct smb_vc *vcp = iod->iod_vc;
292 struct proc *p = iod->iod_p;
293 struct smb_rq *rqp;
294 struct mbuf *m;
295 u_char *hp;
296 u_short mid;
297 int error;
298
299 switch (iod->iod_state) {
300 case SMBIOD_ST_NOTCONN:
301 case SMBIOD_ST_DEAD:
302 case SMBIOD_ST_RECONNECT:
303 return 0;
304 default:
305 break;
306 }
307 for (;;) {
308 m = NULL;
309 error = SMB_TRAN_RECV(vcp, &m, p);
310 if (error == EWOULDBLOCK)
311 break;
312 if (SMB_TRAN_FATAL(vcp, error)) {
313 smb_iod_dead(iod);
314 break;
315 }
316 if (error)
317 break;
318 if (m == NULL) {
319 SMBERROR("tran return NULL without error\n");
320 error = EPIPE;
321 continue;
322 }
323 m = m_pullup(m, SMB_HDRLEN);
324 if (m == NULL)
325 continue; /* wait for a good packet */
326 /*
327 * Now we got an entire and possibly invalid SMB packet.
328 * Be careful while parsing it.
329 */
330 m_dumpm(m);
331 hp = mtod(m, u_char*);
332 if (bcmp(hp, SMB_SIGNATURE, SMB_SIGLEN) != 0) {
333 m_freem(m);
334 continue;
335 }
336 mid = SMB_HDRMID(hp);
337 SMBSDEBUG("mid %04x\n", (u_int)mid);
338 SMB_IOD_RQLOCK(iod);
339 TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
340 if (rqp->sr_mid != mid)
341 continue;
342 SMBRQ_SLOCK(rqp);
343 if (rqp->sr_rp.md_top == NULL) {
344 md_initm(&rqp->sr_rp, m);
345 } else {
346 if (rqp->sr_flags & SMBR_MULTIPACKET) {
347 md_append_record(&rqp->sr_rp, m);
348 } else {
349 SMBRQ_SUNLOCK(rqp);
350 SMBERROR("duplicate response %d (ignored)\n", mid);
351 break;
352 }
353 }
354 SMBRQ_SUNLOCK(rqp);
355 smb_iod_rqprocessed(rqp, 0);
356 break;
357 }
358 SMB_IOD_RQUNLOCK(iod);
359 if (rqp == NULL) {
360 SMBERROR("drop resp with mid %d\n", (u_int)mid);
361 /* smb_printrqlist(vcp);*/
362 m_freem(m);
363 }
364 }
365 /*
366 * check for interrupts
367 */
368 SMB_IOD_RQLOCK(iod);
369 TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
370 if (smb_proc_intr(rqp->sr_cred->scr_p)) {
371 smb_iod_rqprocessed(rqp, EINTR);
372 }
373 }
374 SMB_IOD_RQUNLOCK(iod);
375 return 0;
376 }
377
378 int
379 smb_iod_request(struct smbiod *iod, int event, void *ident)
380 {
381 struct smbiod_event *evp;
382 int error;
383
384 SMBIODEBUG("\n");
385 evp = smb_zmalloc(sizeof(*evp), M_SMBIOD, M_WAITOK);
386 evp->ev_type = event;
387 evp->ev_ident = ident;
388 SMB_IOD_EVLOCK(iod);
389 STAILQ_INSERT_TAIL(&iod->iod_evlist, evp, ev_link);
390 if ((event & SMBIOD_EV_SYNC) == 0) {
391 SMB_IOD_EVUNLOCK(iod);
392 smb_iod_wakeup(iod);
393 return 0;
394 }
395 smb_iod_wakeup(iod);
396 msleep(evp, SMB_IOD_EVLOCKPTR(iod), PWAIT | PDROP, "90evw", 0);
397 error = evp->ev_error;
398 free(evp, M_SMBIOD);
399 return error;
400 }
401
402 /*
403 * Place request in the queue.
404 * Request from smbiod have a high priority.
405 */
406 int
407 smb_iod_addrq(struct smb_rq *rqp)
408 {
409 struct smb_vc *vcp = rqp->sr_vc;
410 struct smbiod *iod = vcp->vc_iod;
411 int error;
412
413 SMBIODEBUG("\n");
414 if (rqp->sr_cred->scr_p == iod->iod_p) {
415 rqp->sr_flags |= SMBR_INTERNAL;
416 SMB_IOD_RQLOCK(iod);
417 TAILQ_INSERT_HEAD(&iod->iod_rqlist, rqp, sr_link);
418 SMB_IOD_RQUNLOCK(iod);
419 for (;;) {
420 if (smb_iod_sendrq(iod, rqp) != 0) {
421 smb_iod_dead(iod);
422 break;
423 }
424 /*
425 * we don't need to lock state field here
426 */
427 if (rqp->sr_state != SMBRQ_NOTSENT)
428 break;
429 tsleep(&iod->iod_flags, PWAIT, "90sndw", hz);
430 }
431 if (rqp->sr_lerror)
432 smb_iod_removerq(rqp);
433 return rqp->sr_lerror;
434 }
435
436 switch (iod->iod_state) {
437 case SMBIOD_ST_NOTCONN:
438 return ENOTCONN;
439 case SMBIOD_ST_DEAD:
440 error = smb_iod_request(vcp->vc_iod, SMBIOD_EV_CONNECT | SMBIOD_EV_SYNC, NULL);
441 if (error)
442 return error;
443 return EXDEV;
444 default:
445 break;
446 }
447
448 SMB_IOD_RQLOCK(iod);
449 for (;;) {
450 if (vcp->vc_maxmux == 0) {
451 SMBERROR("maxmux == 0\n");
452 break;
453 }
454 if (iod->iod_muxcnt < vcp->vc_maxmux)
455 break;
456 iod->iod_muxwant++;
457 msleep(&iod->iod_muxwant, SMB_IOD_RQLOCKPTR(iod),
458 PWAIT, "90mux", 0);
459 }
460 iod->iod_muxcnt++;
461 TAILQ_INSERT_TAIL(&iod->iod_rqlist, rqp, sr_link);
462 SMB_IOD_RQUNLOCK(iod);
463 smb_iod_wakeup(iod);
464 return 0;
465 }
466
467 int
468 smb_iod_removerq(struct smb_rq *rqp)
469 {
470 struct smb_vc *vcp = rqp->sr_vc;
471 struct smbiod *iod = vcp->vc_iod;
472
473 SMBIODEBUG("\n");
474 if (rqp->sr_flags & SMBR_INTERNAL) {
475 SMB_IOD_RQLOCK(iod);
476 TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
477 SMB_IOD_RQUNLOCK(iod);
478 return 0;
479 }
480 SMB_IOD_RQLOCK(iod);
481 while (rqp->sr_flags & SMBR_XLOCK) {
482 rqp->sr_flags |= SMBR_XLOCKWANT;
483 msleep(rqp, SMB_IOD_RQLOCKPTR(iod), PWAIT, "90xrm", 0);
484 }
485 TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
486 iod->iod_muxcnt--;
487 if (iod->iod_muxwant) {
488 iod->iod_muxwant--;
489 wakeup(&iod->iod_muxwant);
490 }
491 SMB_IOD_RQUNLOCK(iod);
492 return 0;
493 }
494
495 int
496 smb_iod_waitrq(struct smb_rq *rqp)
497 {
498 struct smbiod *iod = rqp->sr_vc->vc_iod;
499 int error;
500
501 SMBIODEBUG("\n");
502 if (rqp->sr_flags & SMBR_INTERNAL) {
503 for (;;) {
504 smb_iod_sendall(iod);
505 smb_iod_recvall(iod);
506 if (rqp->sr_rpgen != rqp->sr_rplast)
507 break;
508 tsleep(&iod->iod_flags, PWAIT, "90irq", hz);
509 }
510 smb_iod_removerq(rqp);
511 return rqp->sr_lerror;
512
513 }
514 SMBRQ_SLOCK(rqp);
515 if (rqp->sr_rpgen == rqp->sr_rplast)
516 msleep(&rqp->sr_state, SMBRQ_SLOCKPTR(rqp), PWAIT, "90wrq", 0);
517 rqp->sr_rplast++;
518 SMBRQ_SUNLOCK(rqp);
519 error = rqp->sr_lerror;
520 if (rqp->sr_flags & SMBR_MULTIPACKET) {
521 /*
522 * If request should stay in the list, then reinsert it
523 * at the end of queue so other waiters have chance to concur
524 */
525 SMB_IOD_RQLOCK(iod);
526 TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
527 TAILQ_INSERT_TAIL(&iod->iod_rqlist, rqp, sr_link);
528 SMB_IOD_RQUNLOCK(iod);
529 } else
530 smb_iod_removerq(rqp);
531 return error;
532 }
533
534
535 static int
536 smb_iod_sendall(struct smbiod *iod)
537 {
538 struct smb_vc *vcp = iod->iod_vc;
539 struct smb_rq *rqp;
540 struct timespec ts, tstimeout;
541 int herror;
542
543 herror = 0;
544 /*
545 * Loop through the list of requests and send them if possible
546 */
547 SMB_IOD_RQLOCK(iod);
548 TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
549 switch (rqp->sr_state) {
550 case SMBRQ_NOTSENT:
551 rqp->sr_flags |= SMBR_XLOCK;
552 SMB_IOD_RQUNLOCK(iod);
553 herror = smb_iod_sendrq(iod, rqp);
554 SMB_IOD_RQLOCK(iod);
555 rqp->sr_flags &= ~SMBR_XLOCK;
556 if (rqp->sr_flags & SMBR_XLOCKWANT) {
557 rqp->sr_flags &= ~SMBR_XLOCKWANT;
558 wakeup(rqp);
559 }
560 break;
561 case SMBRQ_SENT:
562 SMB_TRAN_GETPARAM(vcp, SMBTP_TIMEOUT, &tstimeout);
563 timespecadd(&tstimeout, &tstimeout);
564 getnanotime(&ts);
565 timespecsub(&ts, &tstimeout);
566 if (timespeccmp(&ts, &rqp->sr_timesent, >)) {
567 smb_iod_rqprocessed(rqp, ETIMEDOUT);
568 }
569 break;
570 default:
571 break;
572 }
573 if (herror)
574 break;
575 }
576 SMB_IOD_RQUNLOCK(iod);
577 if (herror == ENOTCONN)
578 smb_iod_dead(iod);
579 return 0;
580 }
581
582 /*
583 * "main" function for smbiod daemon
584 */
585 static __inline void
586 smb_iod_main(struct smbiod *iod)
587 {
588 /* struct smb_vc *vcp = iod->iod_vc;*/
589 struct smbiod_event *evp;
590 /* struct timespec tsnow;*/
591 int error;
592
593 SMBIODEBUG("\n");
594 error = 0;
595
596 /*
597 * Check all interesting events
598 */
599 for (;;) {
600 SMB_IOD_EVLOCK(iod);
601 evp = STAILQ_FIRST(&iod->iod_evlist);
602 if (evp == NULL) {
603 SMB_IOD_EVUNLOCK(iod);
604 break;
605 }
606 STAILQ_REMOVE_HEAD(&iod->iod_evlist, ev_link);
607 evp->ev_type |= SMBIOD_EV_PROCESSING;
608 SMB_IOD_EVUNLOCK(iod);
609 switch (evp->ev_type & SMBIOD_EV_MASK) {
610 case SMBIOD_EV_CONNECT:
611 iod->iod_state = SMBIOD_ST_RECONNECT;
612 evp->ev_error = smb_iod_connect(iod);
613 break;
614 case SMBIOD_EV_DISCONNECT:
615 evp->ev_error = smb_iod_disconnect(iod);
616 break;
617 case SMBIOD_EV_TREECONNECT:
618 evp->ev_error = smb_iod_treeconnect(iod, evp->ev_ident);
619 break;
620 case SMBIOD_EV_SHUTDOWN:
621 iod->iod_flags |= SMBIOD_SHUTDOWN;
622 break;
623 case SMBIOD_EV_NEWRQ:
624 break;
625 }
626 if (evp->ev_type & SMBIOD_EV_SYNC) {
627 SMB_IOD_EVLOCK(iod);
628 wakeup(evp);
629 SMB_IOD_EVUNLOCK(iod);
630 } else
631 free(evp, M_SMBIOD);
632 }
633 #if 0
634 if (iod->iod_state == SMBIOD_ST_VCACTIVE) {
635 getnanotime(&tsnow);
636 timespecsub(&tsnow, &iod->iod_pingtimo);
637 if (timespeccmp(&tsnow, &iod->iod_lastrqsent, >)) {
638 smb_smb_echo(vcp, &iod->iod_scred);
639 }
640 }
641 #endif
642 smb_iod_sendall(iod);
643 smb_iod_recvall(iod);
644 return;
645 }
646
647 #define kthread_create_compat kthread_create2
648
649
650 void
651 smb_iod_thread(void *arg)
652 {
653 struct smbiod *iod = arg;
654
655 smb_makescred(&iod->iod_scred, iod->iod_p, NULL);
656 while ((iod->iod_flags & SMBIOD_SHUTDOWN) == 0) {
657 smb_iod_main(iod);
658 SMBIODEBUG("going to sleep for %d ticks\n", iod->iod_sleeptimo);
659 if (iod->iod_flags & SMBIOD_SHUTDOWN)
660 break;
661 tsleep(&iod->iod_flags, PWAIT, "90idle", iod->iod_sleeptimo);
662 }
663 kthread_exit(0);
664 }
665
666 int
667 smb_iod_create(struct smb_vc *vcp)
668 {
669 struct smbiod *iod;
670 int error;
671
672 iod = smb_zmalloc(sizeof(*iod), M_SMBIOD, M_WAITOK);
673 iod->iod_id = smb_iod_next++;
674 iod->iod_state = SMBIOD_ST_NOTCONN;
675 iod->iod_vc = vcp;
676 iod->iod_sleeptimo = hz * SMBIOD_SLEEP_TIMO;
677 iod->iod_pingtimo.tv_sec = SMBIOD_PING_TIMO;
678 getnanotime(&iod->iod_lastrqsent);
679 vcp->vc_iod = iod;
680 smb_sl_init(&iod->iod_rqlock, "90rql");
681 TAILQ_INIT(&iod->iod_rqlist);
682 smb_sl_init(&iod->iod_evlock, "90evl");
683 STAILQ_INIT(&iod->iod_evlist);
684 error = kthread_create_compat(smb_iod_thread, iod, &iod->iod_p,
685 RFNOWAIT, "smbiod%d", iod->iod_id);
686 if (error) {
687 SMBERROR("can't start smbiod: %d", error);
688 free(iod, M_SMBIOD);
689 return error;
690 }
691 return 0;
692 }
693
694 int
695 smb_iod_destroy(struct smbiod *iod)
696 {
697 smb_iod_request(iod, SMBIOD_EV_SHUTDOWN | SMBIOD_EV_SYNC, NULL);
698 smb_sl_destroy(&iod->iod_rqlock);
699 smb_sl_destroy(&iod->iod_evlock);
700 free(iod, M_SMBIOD);
701 return 0;
702 }
703
704 int
705 smb_iod_init(void)
706 {
707 return 0;
708 }
709
710 int
711 smb_iod_done(void)
712 {
713 return 0;
714 }
715
Cache object: 88a31bc6a30fdfd0d572f894b53bfb21
|