Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/vscan/vscan_drv.c
+++ new/usr/src/uts/common/io/vscan/vscan_drv.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 #include <sys/stat.h>
28 28 #include <sys/ddi.h>
29 29 #include <sys/sunddi.h>
30 30 #include <sys/time.h>
31 31 #include <sys/varargs.h>
32 32 #include <sys/conf.h>
33 33 #include <sys/modctl.h>
34 34 #include <sys/vnode.h>
35 35 #include <fs/fs_subr.h>
36 36 #include <sys/types.h>
37 37 #include <sys/file.h>
38 38 #include <sys/disp.h>
39 39 #include <sys/vscan.h>
40 40 #include <sys/policy.h>
41 41 #include <sys/sdt.h>
42 42
43 43
44 44 /* seconds to wait for daemon to reconnect before disabling */
45 45 #define VS_DAEMON_WAIT_SEC 60
46 46
47 47 /* length of minor node name - vscan%d */
48 48 #define VS_NODENAME_LEN 16
49 49
50 50 /* global variables - tunable via /etc/system */
51 51 uint32_t vs_reconnect_timeout = VS_DAEMON_WAIT_SEC;
52 52 extern uint32_t vs_nodes_max; /* max in-progress scan requests */
53 53
54 54 /*
55 55 * vscan_drv_state
56 56 *
57 57 * Operations on instance 0 represent vscand initiated state
58 58 * transition events:
59 59 * open(0) - vscand connect
60 60 * close(0) - vscan disconnect
61 61 * enable(0) - vscand enable (ready to hand requests)
62 62 * disable(0) - vscand disable (shutting down)
63 63 *
64 64 * +------------------------+
65 65 * | VS_DRV_UNCONFIG |
66 66 * +------------------------+
67 67 * | ^
68 68 * | attach | detach
69 69 * v |
70 70 * +------------------------+
71 71 * | VS_DRV_IDLE |<------|
72 72 * +------------------------+ |
73 73 * | ^ |
74 74 * | open(0) | close(0) |
75 75 * v | |
76 76 * +------------------------+ |
77 77 * | VS_DRV_CONNECTED |<-| |
78 78 * +------------------------+ | |
79 79 * | ^ | |
80 80 * | enable(0) | disable(0) | |
81 81 * v | | |
82 82 * +------------------------+ | |
83 83 * | VS_DRV_ENABLED | | |
84 84 * +------------------------+ | |
85 85 * | | |
86 86 * | close(0) open(0) |
87 87 * v | |
88 88 * +------------------------+ | | timeout
89 89 * | VS_DRV_DELAYED_DISABLE | -- |
90 90 * +------------------------+ ------|
91 91 *
92 92 */
93 93 typedef enum {
94 94 VS_DRV_UNCONFIG,
95 95 VS_DRV_IDLE,
96 96 VS_DRV_CONNECTED,
97 97 VS_DRV_ENABLED,
98 98 VS_DRV_DELAYED_DISABLE
99 99 } vscan_drv_state_t;
100 100 static vscan_drv_state_t vscan_drv_state = VS_DRV_UNCONFIG;
101 101
102 102
103 103 /*
104 104 * vscan_drv_inst_state
105 105 *
106 106 * Instance 0 controls the state of the driver: vscan_drv_state.
107 107 * vscan_drv_inst_state[0] should NOT be used.
108 108 *
109 109 * vscan_drv_inst_state[n] represents the state of driver
110 110 * instance n, used by vscand to access file data for the
111 111 * scan request with index n in vscan_svc_reqs.
112 112 * Minor nodes are created as required then all are destroyed
113 113 * during driver detach.
114 114 *
115 115 * +------------------------+
116 116 * | VS_DRV_INST_UNCONFIG |
117 117 * +------------------------+
118 118 * | ^
119 119 * | create_node(n) | detach
120 120 * v |
121 121 * +------------------------+
122 122 * | VS_DRV_INST_INIT |<-|
123 123 * +------------------------+ |
124 124 * | |
125 125 * | open(n) |
126 126 * v |
127 127 * +------------------------+ |
128 128 * | VS_DRV_INST_OPEN |--|
129 129 * +------------------------+ |
130 130 * | |
131 131 * | read(n) |
132 132 * v | close(n)
133 133 * +------------------------+ |
134 134 * | VS_DRV_INST_READING |--|
135 135 * +------------------------+
136 136 */
137 137 typedef enum {
138 138 VS_DRV_INST_UNCONFIG = 0, /* minor node not created */
139 139 VS_DRV_INST_INIT,
140 140 VS_DRV_INST_OPEN,
141 141 VS_DRV_INST_READING
142 142 } vscan_drv_inst_state_t;
143 143
144 144 static vscan_drv_inst_state_t *vscan_drv_inst_state;
145 145 static int vscan_drv_inst_state_sz;
146 146
147 147 static dev_info_t *vscan_drv_dip;
148 148 static kmutex_t vscan_drv_mutex;
149 149 static kcondvar_t vscan_drv_cv; /* wait for daemon reconnect */
150 150
151 151 /*
152 152 * DDI entry points.
153 153 */
154 154 static int vscan_drv_attach(dev_info_t *, ddi_attach_cmd_t);
155 155 static int vscan_drv_detach(dev_info_t *, ddi_detach_cmd_t);
156 156 static int vscan_drv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
157 157 static int vscan_drv_open(dev_t *, int, int, cred_t *);
158 158 static int vscan_drv_close(dev_t, int, int, cred_t *);
159 159 static int vscan_drv_read(dev_t, struct uio *, cred_t *);
160 160 static int vscan_drv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
161 161
162 162 static boolean_t vscan_drv_in_use(void);
163 163 static void vscan_drv_delayed_disable(void);
164 164
165 165
166 166 /*
167 167 * module linkage info for the kernel
168 168 */
169 169 static struct cb_ops cbops = {
170 170 vscan_drv_open, /* cb_open */
171 171 vscan_drv_close, /* cb_close */
172 172 nodev, /* cb_strategy */
173 173 nodev, /* cb_print */
174 174 nodev, /* cb_dump */
175 175 vscan_drv_read, /* cb_read */
176 176 nodev, /* cb_write */
177 177 vscan_drv_ioctl, /* cb_ioctl */
178 178 nodev, /* cb_devmap */
179 179 nodev, /* cb_mmap */
180 180 nodev, /* cb_segmap */
181 181 nochpoll, /* cb_chpoll */
182 182 ddi_prop_op, /* cb_prop_op */
183 183 NULL, /* cb_streamtab */
184 184 D_MP, /* cb_flag */
185 185 CB_REV, /* cb_rev */
186 186 nodev, /* cb_aread */
187 187 nodev, /* cb_awrite */
188 188 };
189 189
190 190 static struct dev_ops devops = {
191 191 DEVO_REV, /* devo_rev */
192 192 0, /* devo_refcnt */
193 193 vscan_drv_getinfo, /* devo_getinfo */
194 194 nulldev, /* devo_identify */
195 195 nulldev, /* devo_probe */
196 196 vscan_drv_attach, /* devo_attach */
197 197 vscan_drv_detach, /* devo_detach */
198 198 nodev, /* devo_reset */
199 199 &cbops, /* devo_cb_ops */
200 200 NULL, /* devo_bus_ops */
201 201 NULL, /* devo_power */
202 202 ddi_quiesce_not_needed, /* devo_quiesce */
203 203 };
↓ open down ↓ |
203 lines elided |
↑ open up ↑ |
204 204
205 205 static struct modldrv modldrv = {
206 206 &mod_driverops, /* drv_modops */
207 207 "virus scanning", /* drv_linkinfo */
208 208 &devops,
209 209 };
210 210
211 211 static struct modlinkage modlinkage = {
212 212
213 213 MODREV_1, /* revision of the module, must be: MODREV_1 */
214 - &modldrv, /* ptr to linkage structures */
215 - NULL,
214 + { &modldrv, NULL } /* ptr to linkage structures */
216 215 };
217 216
218 217
219 218 /*
220 219 * _init
221 220 */
222 221 int
223 222 _init(void)
224 223 {
225 224 int rc;
226 225
227 226 vscan_drv_inst_state_sz =
228 227 sizeof (vscan_drv_inst_state_t) * (vs_nodes_max + 1);
229 228
230 229 if (vscan_door_init() != 0)
231 230 return (DDI_FAILURE);
232 231
233 232 if (vscan_svc_init() != 0) {
234 233 vscan_door_fini();
235 234 return (DDI_FAILURE);
236 235 }
237 236
238 237 mutex_init(&vscan_drv_mutex, NULL, MUTEX_DRIVER, NULL);
239 238 vscan_drv_inst_state = kmem_zalloc(vscan_drv_inst_state_sz, KM_SLEEP);
240 239
241 240 cv_init(&vscan_drv_cv, NULL, CV_DEFAULT, NULL);
242 241
243 242 if ((rc = mod_install(&modlinkage)) != 0) {
244 243 vscan_door_fini();
245 244 vscan_svc_fini();
246 245 kmem_free(vscan_drv_inst_state, vscan_drv_inst_state_sz);
247 246 cv_destroy(&vscan_drv_cv);
248 247 mutex_destroy(&vscan_drv_mutex);
249 248 }
250 249
251 250 return (rc);
252 251 }
253 252
254 253
255 254 /*
256 255 * _info
257 256 */
258 257 int
259 258 _info(struct modinfo *modinfop)
260 259 {
261 260 return (mod_info(&modlinkage, modinfop));
262 261 }
263 262
264 263
265 264 /*
266 265 * _fini
267 266 */
268 267 int
269 268 _fini(void)
270 269 {
271 270 int rc;
272 271
273 272 if (vscan_drv_in_use())
274 273 return (EBUSY);
275 274
276 275 if ((rc = mod_remove(&modlinkage)) == 0) {
277 276 vscan_door_fini();
278 277 vscan_svc_fini();
279 278 kmem_free(vscan_drv_inst_state, vscan_drv_inst_state_sz);
280 279 cv_destroy(&vscan_drv_cv);
281 280 mutex_destroy(&vscan_drv_mutex);
282 281 }
283 282
284 283 return (rc);
285 284 }
286 285
287 286
288 287 /*
289 288 * DDI entry points.
290 289 */
291 290
292 291 /*
293 292 * vscan_drv_getinfo
294 293 */
295 294 /* ARGSUSED */
296 295 static int
297 296 vscan_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
298 297 {
299 298 ulong_t inst = getminor((dev_t)arg);
300 299
301 300 switch (cmd) {
302 301 case DDI_INFO_DEVT2DEVINFO:
303 302 *result = vscan_drv_dip;
304 303 return (DDI_SUCCESS);
305 304 case DDI_INFO_DEVT2INSTANCE:
306 305 *result = (void *)inst;
307 306 return (DDI_SUCCESS);
308 307 }
309 308 return (DDI_FAILURE);
310 309 }
311 310
312 311
313 312 /*
314 313 * vscan_drv_attach
315 314 */
316 315 static int
317 316 vscan_drv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
318 317 {
319 318 if (cmd != DDI_ATTACH)
320 319 return (DDI_FAILURE);
321 320
322 321 if (ddi_get_instance(dip) != 0)
323 322 return (DDI_FAILURE);
324 323
325 324 vscan_drv_dip = dip;
326 325
327 326 /* create minor node 0 for daemon-driver synchronization */
328 327 if (vscan_drv_create_node(0) == B_FALSE)
329 328 return (DDI_FAILURE);
330 329
331 330 vscan_drv_state = VS_DRV_IDLE;
332 331 return (DDI_SUCCESS);
333 332 }
334 333
335 334
336 335 /*
337 336 * vscan_drv_detach
338 337 */
339 338 static int
340 339 vscan_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
341 340 {
342 341 int i;
343 342
344 343 if (cmd != DDI_DETACH)
345 344 return (DDI_FAILURE);
346 345
347 346 if (ddi_get_instance(dip) != 0)
348 347 return (DDI_FAILURE);
349 348
350 349 if (vscan_drv_in_use())
351 350 return (DDI_FAILURE);
352 351
353 352 /* remove all minor nodes */
354 353 vscan_drv_dip = NULL;
355 354 ddi_remove_minor_node(dip, NULL);
356 355 for (i = 0; i <= vs_nodes_max; i++)
357 356 vscan_drv_inst_state[i] = VS_DRV_INST_UNCONFIG;
358 357
359 358 vscan_drv_state = VS_DRV_UNCONFIG;
360 359 return (DDI_SUCCESS);
361 360 }
362 361
363 362
364 363 /*
365 364 * vscan_drv_in_use
366 365 *
367 366 * If the driver state is not IDLE or UNCONFIG then the
368 367 * driver is in use. Otherwise, check the service interface
369 368 * (vscan_svc) to see if it is still in use - for example
370 369 * there there may be requests still in progress.
371 370 */
372 371 static boolean_t
373 372 vscan_drv_in_use()
374 373 {
375 374 boolean_t in_use = B_FALSE;
376 375
377 376 mutex_enter(&vscan_drv_mutex);
378 377 if ((vscan_drv_state != VS_DRV_IDLE) &&
379 378 (vscan_drv_state != VS_DRV_UNCONFIG)) {
380 379 in_use = B_TRUE;
381 380 }
382 381 mutex_exit(&vscan_drv_mutex);
383 382
384 383 if (in_use)
385 384 return (B_TRUE);
386 385 else
387 386 return (vscan_svc_in_use());
388 387 }
389 388
390 389
391 390 /*
392 391 * vscan_drv_open
393 392 *
394 393 * If inst == 0, this is vscand initializing.
395 394 * If the driver is in DELAYED_DISABLE, ie vscand previously
396 395 * disconnected without a clean shutdown and the driver is
397 396 * waiting for a period to allow vscand to reconnect, signal
398 397 * vscan_drv_cv to cancel the delayed disable.
399 398 *
400 399 * If inst != 0, open the file associated with inst.
401 400 */
402 401 /* ARGSUSED */
403 402 static int
404 403 vscan_drv_open(dev_t *devp, int flag, int otyp, cred_t *credp)
405 404 {
406 405 int rc;
407 406 int inst = getminor(*devp);
408 407
409 408 if ((inst < 0) || (inst > vs_nodes_max))
410 409 return (EINVAL);
411 410
412 411 /* check if caller has privilege for virus scanning */
413 412 if ((rc = secpolicy_vscan(credp)) != 0) {
414 413 DTRACE_PROBE1(vscan__priv, int, rc);
415 414 return (EPERM);
416 415 }
417 416
418 417 mutex_enter(&vscan_drv_mutex);
419 418 if (inst == 0) {
420 419 switch (vscan_drv_state) {
421 420 case VS_DRV_IDLE:
422 421 vscan_drv_state = VS_DRV_CONNECTED;
423 422 break;
424 423 case VS_DRV_DELAYED_DISABLE:
425 424 cv_signal(&vscan_drv_cv);
426 425 vscan_drv_state = VS_DRV_CONNECTED;
427 426 break;
428 427 default:
429 428 DTRACE_PROBE1(vscan__drv__state__violation,
430 429 int, vscan_drv_state);
431 430 mutex_exit(&vscan_drv_mutex);
432 431 return (EINVAL);
433 432 }
434 433 } else {
435 434 if ((vscan_drv_state != VS_DRV_ENABLED) ||
436 435 (vscan_drv_inst_state[inst] != VS_DRV_INST_INIT)) {
437 436 mutex_exit(&vscan_drv_mutex);
438 437 return (EINVAL);
439 438 }
440 439 vscan_drv_inst_state[inst] = VS_DRV_INST_OPEN;
441 440 }
442 441 mutex_exit(&vscan_drv_mutex);
443 442
444 443 return (0);
445 444 }
446 445
447 446
448 447 /*
449 448 * vscan_drv_close
450 449 *
451 450 * If inst == 0, this is vscand detaching.
452 451 * If the driver is in ENABLED state vscand has terminated without
453 452 * a clean shutdown (nod DISABLE received). Enter DELAYED_DISABLE
454 453 * state and initiate a delayed disable to allow vscand time to
455 454 * reconnect.
456 455 *
457 456 * If inst != 0, close the file associated with inst
458 457 */
459 458 /* ARGSUSED */
460 459 static int
461 460 vscan_drv_close(dev_t dev, int flag, int otyp, cred_t *credp)
462 461 {
463 462 int i, inst = getminor(dev);
464 463
465 464 if ((inst < 0) || (inst > vs_nodes_max))
466 465 return (EINVAL);
467 466
468 467 mutex_enter(&vscan_drv_mutex);
469 468 if (inst != 0) {
470 469 vscan_drv_inst_state[inst] = VS_DRV_INST_INIT;
471 470 mutex_exit(&vscan_drv_mutex);
472 471 return (0);
473 472 }
474 473
475 474 /* instance 0 - daemon disconnect */
476 475 if ((vscan_drv_state != VS_DRV_CONNECTED) &&
477 476 (vscan_drv_state != VS_DRV_ENABLED)) {
478 477 DTRACE_PROBE1(vscan__drv__state__violation,
479 478 int, vscan_drv_state);
480 479 mutex_exit(&vscan_drv_mutex);
481 480 return (EINVAL);
482 481 }
483 482
484 483 for (i = 1; i <= vs_nodes_max; i++) {
485 484 if (vscan_drv_inst_state[i] != VS_DRV_INST_UNCONFIG)
486 485 vscan_drv_inst_state[i] = VS_DRV_INST_INIT;
487 486 }
488 487
489 488 if (vscan_drv_state == VS_DRV_CONNECTED) {
490 489 vscan_drv_state = VS_DRV_IDLE;
491 490 } else { /* VS_DRV_ENABLED */
492 491 cmn_err(CE_WARN, "Detected vscand exit without clean shutdown");
493 492 if (thread_create(NULL, 0, vscan_drv_delayed_disable,
494 493 0, 0, &p0, TS_RUN, minclsyspri) == NULL) {
495 494 vscan_svc_disable();
496 495 vscan_drv_state = VS_DRV_IDLE;
497 496 } else {
498 497 vscan_drv_state = VS_DRV_DELAYED_DISABLE;
499 498 }
500 499 }
501 500 mutex_exit(&vscan_drv_mutex);
502 501
503 502 vscan_svc_scan_abort();
504 503 vscan_door_close();
505 504 return (0);
506 505 }
507 506
508 507
509 508 /*
510 509 * vscan_drv_delayed_disable
511 510 *
512 511 * Invoked from vscan_drv_close if the daemon disconnects
513 512 * without first sending disable (e.g. daemon crashed).
514 513 * Delays for vs_reconnect_timeout before disabling, to allow
515 514 * the daemon to reconnect. During this time, scan requests
516 515 * will be processed locally (see vscan_svc.c)
517 516 */
518 517 static void
519 518 vscan_drv_delayed_disable(void)
520 519 {
521 520 mutex_enter(&vscan_drv_mutex);
522 521 (void) cv_reltimedwait(&vscan_drv_cv, &vscan_drv_mutex,
523 522 SEC_TO_TICK(vs_reconnect_timeout), TR_CLOCK_TICK);
524 523
525 524 if (vscan_drv_state == VS_DRV_DELAYED_DISABLE) {
526 525 vscan_svc_disable();
527 526 vscan_drv_state = VS_DRV_IDLE;
528 527 } else {
529 528 DTRACE_PROBE(vscan__reconnect);
530 529 }
531 530 mutex_exit(&vscan_drv_mutex);
532 531 }
533 532
534 533
535 534 /*
536 535 * vscan_drv_read
537 536 */
538 537 /* ARGSUSED */
539 538 static int
540 539 vscan_drv_read(dev_t dev, struct uio *uiop, cred_t *credp)
541 540 {
542 541 int rc;
543 542 int inst = getminor(dev);
544 543 vnode_t *vp;
545 544
546 545 if ((inst <= 0) || (inst > vs_nodes_max))
547 546 return (EINVAL);
548 547
549 548 mutex_enter(&vscan_drv_mutex);
550 549 if ((vscan_drv_state != VS_DRV_ENABLED) ||
551 550 (vscan_drv_inst_state[inst] != VS_DRV_INST_OPEN)) {
552 551 mutex_exit(&vscan_drv_mutex);
553 552 return (EINVAL);
554 553 }
555 554 vscan_drv_inst_state[inst] = VS_DRV_INST_READING;
556 555 mutex_exit(&vscan_drv_mutex);
557 556
558 557 if ((vp = vscan_svc_get_vnode(inst)) == NULL)
559 558 return (EINVAL);
560 559
561 560 (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
562 561 rc = VOP_READ(vp, uiop, 0, kcred, NULL);
563 562 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
564 563
565 564 mutex_enter(&vscan_drv_mutex);
566 565 if (vscan_drv_inst_state[inst] == VS_DRV_INST_READING)
567 566 vscan_drv_inst_state[inst] = VS_DRV_INST_OPEN;
568 567 mutex_exit(&vscan_drv_mutex);
569 568
570 569 return (rc);
571 570 }
572 571
573 572
574 573 /*
575 574 * vscan_drv_ioctl
576 575 *
577 576 * Process ioctls from vscand:
578 577 * VS_IOCTL_ENABLE - vscand is ready to handle scan requests,
579 578 * enable VFS interface.
580 579 * VS_IOCTL_DISABLE - vscand is shutting down, disable VFS interface
581 580 * VS_IOCTL_RESULT - scan response data
582 581 * VS_IOCTL_CONFIG - configuration data from vscand
583 582 * VS_IOCTL_MAX_REQ - provide the max request idx to vscand,
584 583 * to allow vscand to set appropriate resource allocation limits
585 584 */
586 585 /* ARGSUSED */
587 586 static int
588 587 vscan_drv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
589 588 cred_t *credp, int *rvalp)
590 589 {
591 590 int inst = getminor(dev);
592 591 vs_config_t conf;
593 592 vs_scan_rsp_t rsp;
594 593
595 594 if (inst != 0)
596 595 return (EINVAL);
597 596
598 597 switch (cmd) {
599 598 case VS_IOCTL_ENABLE:
600 599 mutex_enter(&vscan_drv_mutex);
601 600 if (vscan_drv_state != VS_DRV_CONNECTED) {
602 601 DTRACE_PROBE1(vscan__drv__state__violation,
603 602 int, vscan_drv_state);
604 603 mutex_exit(&vscan_drv_mutex);
605 604 return (EINVAL);
606 605 }
607 606 if ((vscan_door_open((int)arg) != 0) ||
608 607 (vscan_svc_enable() != 0)) {
609 608 mutex_exit(&vscan_drv_mutex);
610 609 return (EINVAL);
611 610 }
612 611 vscan_drv_state = VS_DRV_ENABLED;
613 612 mutex_exit(&vscan_drv_mutex);
614 613 break;
615 614
616 615 case VS_IOCTL_DISABLE:
617 616 mutex_enter(&vscan_drv_mutex);
618 617 if (vscan_drv_state != VS_DRV_ENABLED) {
619 618 DTRACE_PROBE1(vscan__drv__state__violation,
620 619 int, vscan_drv_state);
621 620 mutex_exit(&vscan_drv_mutex);
622 621 return (EINVAL);
623 622 }
624 623 vscan_svc_disable();
625 624 vscan_drv_state = VS_DRV_CONNECTED;
626 625 mutex_exit(&vscan_drv_mutex);
627 626 break;
628 627
629 628 case VS_IOCTL_RESULT:
630 629 if (ddi_copyin((void *)arg, &rsp,
631 630 sizeof (vs_scan_rsp_t), 0) == -1)
632 631 return (EFAULT);
633 632 else
634 633 vscan_svc_scan_result(&rsp);
635 634 break;
636 635
637 636 case VS_IOCTL_CONFIG:
638 637 if (ddi_copyin((void *)arg, &conf,
639 638 sizeof (vs_config_t), 0) == -1)
640 639 return (EFAULT);
641 640 if (vscan_svc_configure(&conf) == -1)
642 641 return (EINVAL);
643 642 break;
644 643
645 644 case VS_IOCTL_MAX_REQ:
646 645 if (ddi_copyout(&vs_nodes_max, (void *)arg,
647 646 sizeof (uint32_t), 0) == -1)
648 647 return (EFAULT);
649 648 break;
650 649
651 650 default:
652 651 return (ENOTTY);
653 652 }
654 653
655 654 return (0);
656 655 }
657 656
658 657
659 658 /*
660 659 * vscan_drv_create_node
661 660 *
662 661 * Create minor node with which vscan daemon will communicate
663 662 * to access a file. Invoked from vscan_svc before scan request
664 663 * sent up to daemon.
665 664 * Minor node 0 is reserved for daemon-driver synchronization
666 665 * and is created during attach.
667 666 * All minor nodes are removed during detach.
668 667 */
669 668 boolean_t
670 669 vscan_drv_create_node(int idx)
671 670 {
672 671 char name[VS_NODENAME_LEN];
673 672 boolean_t rc = B_TRUE;
674 673
675 674 mutex_enter(&vscan_drv_mutex);
676 675
677 676 if (vscan_drv_inst_state[idx] == VS_DRV_INST_UNCONFIG) {
678 677 (void) snprintf(name, VS_NODENAME_LEN, "vscan%d", idx);
679 678 if (ddi_create_minor_node(vscan_drv_dip, name,
680 679 S_IFCHR, idx, DDI_PSEUDO, 0) == DDI_SUCCESS) {
681 680 vscan_drv_inst_state[idx] = VS_DRV_INST_INIT;
682 681 } else {
683 682 rc = B_FALSE;
684 683 }
685 684 DTRACE_PROBE2(vscan__minor__node, int, idx, int, rc);
686 685 }
687 686
688 687 mutex_exit(&vscan_drv_mutex);
689 688
690 689 return (rc);
691 690 }
↓ open down ↓ |
466 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX