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