2a069fdaa61854d64e694d91794fdbb522063188
[dragonfly.git] / sys / kern / kern_udev.c
1 /*
2  * Copyright (c) 2010,2018 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Alex Hornung <ahornung@gmail.com>
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  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/proc.h>
38 #include <sys/buf.h>
39 #include <sys/conf.h>
40 #include <sys/event.h>
41 #include <sys/vnode.h>
42 #include <sys/malloc.h>
43 #include <sys/objcache.h>
44 #include <sys/ctype.h>
45 #include <sys/syslog.h>
46 #include <sys/udev.h>
47 #include <sys/devfs.h>
48 #include <libprop/proplib.h>
49
50 MALLOC_DEFINE(M_UDEV, "udev", "udev allocs");
51 static struct objcache *udev_event_kernel_cache;
52
53 /* XXX: use UUIDs for identification; would need help from devfs */
54
55 static cdev_t           udev_dev;
56 static d_open_t         udev_dev_open;
57 static d_close_t        udev_dev_close;
58 static d_read_t         udev_dev_read;
59 static d_kqfilter_t     udev_dev_kqfilter;
60 static d_ioctl_t        udev_dev_ioctl;
61 static d_clone_t        udev_dev_clone;
62
63 struct udev_prop_ctx {
64         prop_array_t cdevs;
65         int error;
66 };
67
68 struct udev_event_kernel {
69         struct udev_event ev;
70         TAILQ_ENTRY(udev_event_kernel)  link;
71 };
72
73 struct udev_softc {
74         TAILQ_ENTRY(udev_softc) entry;
75         int opened;
76         int initiated;
77         int unit;
78         cdev_t dev;
79
80         struct udev_event_kernel marker;        /* udev_evq marker */
81 };
82
83 struct cmd_function {
84         const char *cmd;
85         int  (*fn)(struct udev_softc *, struct plistref *,
86                    u_long, prop_dictionary_t);
87 };
88
89 static int _udev_dict_set_cstr(prop_dictionary_t, const char *, char *);
90 static int _udev_dict_set_int(prop_dictionary_t, const char *, int64_t);
91 static int _udev_dict_set_uint(prop_dictionary_t, const char *, uint64_t);
92 static int _udev_dict_delete_key(prop_dictionary_t, const char *);
93 static prop_dictionary_t udev_init_dict_event(cdev_t, const char *);
94 static int udev_init_dict(cdev_t);
95 static int udev_destroy_dict(cdev_t);
96 static void udev_event_insert(int, prop_dictionary_t);
97 static void udev_clean_events_locked(void);
98 static char *udev_event_externalize(struct udev_event_kernel *);
99 static void udev_getdevs_scan_callback(char *, cdev_t, bool, void *);
100 static int udev_getdevs_ioctl(struct udev_softc *, struct plistref *,
101                                         u_long, prop_dictionary_t);
102 static void udev_dev_filter_detach(struct knote *);
103 static int udev_dev_filter_read(struct knote *, long);
104
105 static struct dev_ops udev_dev_ops = {
106         { "udev", 0, 0 },
107         .d_open = udev_dev_open,
108         .d_close = udev_dev_close,
109         .d_read = udev_dev_read,
110         .d_kqfilter = udev_dev_kqfilter,
111         .d_ioctl = udev_dev_ioctl
112 };
113
114 static struct cmd_function cmd_fn[] = {
115                 { .cmd = "getdevs", .fn = udev_getdevs_ioctl},
116                 {NULL, NULL}
117 };
118
119 DEVFS_DEFINE_CLONE_BITMAP(udev);
120
121 static TAILQ_HEAD(, udev_softc) udevq;
122 static TAILQ_HEAD(, udev_event_kernel) udev_evq;
123 static struct kqinfo udev_kq;
124 static struct lock udev_lk;
125 static int udev_evqlen;
126 static int udev_initiated_count;
127 static int udev_open_count;
128 static int udev_seqwait;
129 static int udev_seq;
130 static struct lock udev_dict_lk = LOCK_INITIALIZER("dict", 0, 0);
131
132 /*
133  * Acquire the device's si_dict and lock the device's si_dict field.
134  * If the device does not have an attached dictionary, NULL is returned.
135  *
136  * This function must be matched by a udev_put_dict() call regardless of
137  * the return value.  The device field is STILL LOCKED even when NULL is
138  * returned.
139  *
140  * Currently a single global lock is implemented.
141  */
142 static prop_dictionary_t
143 udev_get_dict(cdev_t dev)
144 {
145         prop_dictionary_t udict;
146
147         lockmgr(&udev_dict_lk, LK_EXCLUSIVE|LK_CANRECURSE);
148         udict = dev->si_dict;
149         if (udict)
150                 prop_object_retain(udict);
151         return udict;
152 }
153
154 /*
155  * Release the dictionary previously returned by udev_get_dict() and unlock
156  * the device's si_dict field.  udict may be NULL.
157  */
158 static void
159 udev_put_dict(cdev_t dev, prop_dictionary_t udict)
160 {
161         if (udict)
162                 prop_object_release(udict);
163         lockmgr(&udev_dict_lk, LK_RELEASE);
164 }
165
166 static int
167 _udev_dict_set_cstr(prop_dictionary_t dict, const char *key, char *str)
168 {
169         prop_string_t   ps;
170
171         KKASSERT(dict != NULL);
172
173         ps = prop_string_create_cstring(str);
174         if (ps == NULL) {
175                 return ENOMEM;
176         }
177
178         if (prop_dictionary_set(dict, key, ps) == false) {
179                 prop_object_release(ps);
180                 return ENOMEM;
181         }
182
183         prop_object_release(ps);
184         return 0;
185 }
186
187 static int
188 _udev_dict_set_int(prop_dictionary_t dict, const char *key, int64_t val)
189 {
190         prop_number_t   pn;
191
192         KKASSERT(dict != NULL);
193
194         pn = prop_number_create_integer(val);
195         if (pn == NULL)
196                 return ENOMEM;
197
198         if (prop_dictionary_set(dict, key, pn) == false) {
199                 prop_object_release(pn);
200                 return ENOMEM;
201         }
202
203         prop_object_release(pn);
204         return 0;
205 }
206
207 static int
208 _udev_dict_set_uint(prop_dictionary_t dict, const char *key, uint64_t val)
209 {
210         prop_number_t   pn;
211
212         KKASSERT(dict != NULL);
213
214         pn = prop_number_create_unsigned_integer(val);
215         if (pn == NULL)
216                 return ENOMEM;
217
218         if (prop_dictionary_set(dict, key, pn) == false) {
219                 prop_object_release(pn);
220                 return ENOMEM;
221         }
222
223         prop_object_release(pn);
224         return 0;
225 }
226
227 static int
228 _udev_dict_delete_key(prop_dictionary_t dict, const char *key)
229 {
230         KKASSERT(dict != NULL);
231
232         prop_dictionary_remove(dict, key);
233
234         return 0;
235 }
236
237 /*
238  * Initialize an event dictionary, which contains three parameters to
239  * identify the device referred to (name, devnum, kptr) and the affected key.
240  */
241 static prop_dictionary_t
242 udev_init_dict_event(cdev_t dev, const char *key)
243 {
244         prop_dictionary_t       dict;
245         uint64_t        kptr;
246         int error;
247
248         kptr = (uint64_t)(uintptr_t)dev;
249         KKASSERT(dev != NULL);
250
251         dict = prop_dictionary_create();
252         if (dict == NULL) {
253                 log(LOG_DEBUG, "udev_init_dict_event: prop_dictionary_create() failed\n");
254                 return NULL;
255         }
256
257         if ((error = _udev_dict_set_cstr(dict, "name", dev->si_name)))
258                 goto error_out;
259         if ((error = _udev_dict_set_uint(dict, "devnum", dev->si_inode)))
260                 goto error_out;
261         if ((error = _udev_dict_set_uint(dict, "devtype", (dev_dflags(dev) & D_TYPEMASK))))
262                 goto error_out;
263         if ((error = _udev_dict_set_uint(dict, "kptr", kptr)))
264                 goto error_out;
265         if ((error = _udev_dict_set_cstr(dict, "key", __DECONST(char *, key))))
266                 goto error_out;
267
268         return dict;
269
270 error_out:
271         prop_object_release(dict);
272         return NULL;
273 }
274
275 int
276 udev_dict_set_cstr(cdev_t dev, const char *key, char *str)
277 {
278         prop_dictionary_t dict;
279         prop_dictionary_t udict;
280         int error;
281
282         KKASSERT(dev != NULL);
283
284         while ((udict = udev_get_dict(dev)) == NULL) {
285                 error = udev_init_dict(dev);
286                 udev_put_dict(dev, udict);
287                 if (error)
288                         return -1;
289         }
290
291         /* Queue a key update event */
292         dict = udev_init_dict_event(dev, key);
293         if (dict == NULL) {
294                 error = ENOMEM;
295                 goto errout;
296         }
297
298         if ((error = _udev_dict_set_cstr(dict, "value", str))) {
299                 prop_object_release(dict);
300                 goto errout;
301         }
302         udev_event_insert(UDEV_EV_KEY_UPDATE, dict);
303         prop_object_release(dict);
304         error = _udev_dict_set_cstr(udict, key, str);
305
306 errout:
307         udev_put_dict(dev, udict);
308
309         return error;
310 }
311
312 int
313 udev_dict_set_int(cdev_t dev, const char *key, int64_t val)
314 {
315         prop_dictionary_t dict;
316         prop_dictionary_t udict;
317         int error;
318
319         KKASSERT(dev != NULL);
320
321         while ((udict = udev_get_dict(dev)) == NULL) {
322                 error = udev_init_dict(dev);
323                 udev_put_dict(dev, udict);
324                 if (error)
325                         return -1;
326         }
327
328         /* Queue a key update event */
329         dict = udev_init_dict_event(dev, key);
330         if (dict == NULL) {
331                 error = ENOMEM;
332                 goto errout;
333         }
334         if ((error = _udev_dict_set_int(dict, "value", val))) {
335                 prop_object_release(dict);
336                 goto errout;
337         }
338         udev_event_insert(UDEV_EV_KEY_UPDATE, dict);
339         prop_object_release(dict);
340         error = _udev_dict_set_int(udict, key, val);
341 errout:
342         udev_put_dict(dev, udict);
343
344         return error;
345 }
346
347 int
348 udev_dict_set_uint(cdev_t dev, const char *key, uint64_t val)
349 {
350         prop_dictionary_t dict;
351         prop_dictionary_t udict;
352         int error;
353
354         KKASSERT(dev != NULL);
355
356         while ((udict = udev_get_dict(dev)) == NULL) {
357                 error = udev_init_dict(dev);
358                 udev_put_dict(dev, udict);
359                 if (error)
360                         return -1;
361         }
362
363         /* Queue a key update event */
364         dict = udev_init_dict_event(dev, key);
365         if (dict == NULL) {
366                 error = ENOMEM;
367                 goto errout;
368         }
369         if ((error = _udev_dict_set_uint(dict, "value", val))) {
370                 prop_object_release(dict);
371                 goto errout;
372         }
373         udev_event_insert(UDEV_EV_KEY_UPDATE, dict);
374         prop_object_release(dict);
375         error = _udev_dict_set_uint(udict, key, val);
376 errout:
377         udev_put_dict(dev, udict);
378
379         return error;
380 }
381
382 int
383 udev_dict_delete_key(cdev_t dev, const char *key)
384 {
385         prop_dictionary_t dict;
386         prop_dictionary_t udict;
387         int error;
388
389         KKASSERT(dev != NULL);
390         udict = udev_get_dict(dev);
391         if (udict == NULL) {
392                 error = ENOMEM;
393                 goto errout;
394         }
395
396         /* Queue a key removal event */
397         dict = udev_init_dict_event(dev, key);
398         if (dict == NULL) {
399                 error = ENOMEM;
400                 goto errout;
401         }
402         udev_event_insert(UDEV_EV_KEY_REMOVE, dict);
403         prop_object_release(dict);
404         error = _udev_dict_delete_key(udict, key);
405 errout:
406         udev_put_dict(dev, udict);
407
408         return error;
409 }
410
411 /*
412  * device dictionary access already locked
413  */
414 static int
415 udev_init_dict(cdev_t dev)
416 {
417         prop_dictionary_t dict;
418         uint64_t        kptr;
419         int error;
420
421         kptr = (uint64_t)(uintptr_t)dev;
422
423         KKASSERT(dev != NULL);
424
425         if (dev->si_dict != NULL) {
426                 log(LOG_DEBUG,
427                     "udev_init_dict: new dict for %s, but has "
428                     "dict already (%p)!\n",
429                     dev->si_name, dev->si_dict);
430                 return 0;
431         }
432
433         dict = prop_dictionary_create();
434         if (dict == NULL) {
435                 log(LOG_DEBUG,
436                     "udev_init_dict: prop_dictionary_create() failed\n");
437                 return ENOMEM;
438         }
439
440         if ((error = _udev_dict_set_cstr(dict, "name", dev->si_name)))
441                 goto error_out;
442         if ((error = _udev_dict_set_uint(dict, "devnum", dev->si_inode)))
443                 goto error_out;
444         if ((error = _udev_dict_set_uint(dict, "kptr", kptr)))
445                 goto error_out;
446         if ((error = _udev_dict_set_uint(dict, "devtype",
447                                          (dev_dflags(dev) & D_TYPEMASK)))) {
448                 goto error_out;
449         }
450
451         /* XXX: The next 3 are marginallly useful, if at all */
452         if ((error = _udev_dict_set_uint(dict, "uid", dev->si_uid)))
453                 goto error_out;
454         if ((error = _udev_dict_set_uint(dict, "gid", dev->si_gid)))
455                 goto error_out;
456         if ((error = _udev_dict_set_int(dict, "mode", dev->si_perms)))
457                 goto error_out;
458
459         if ((error = _udev_dict_set_int(dict, "major", dev->si_umajor)))
460                 goto error_out;
461         if ((error = _udev_dict_set_int(dict, "minor", dev->si_uminor)))
462                 goto error_out;
463         if (dev->si_ops->head.name != NULL) {
464                 if ((error = _udev_dict_set_cstr(dict, "driver",
465                     __DECONST(char *, dev->si_ops->head.name))))
466                         goto error_out;
467         }
468
469         dev->si_dict = dict;
470         return 0;
471
472 error_out:
473         dev->si_dict = NULL;
474         prop_object_release(dict);
475         return error;
476 }
477
478 /*
479  * device dictionary access already locked
480  */
481 static int
482 udev_destroy_dict(cdev_t dev)
483 {
484         prop_dictionary_t udict;
485
486         KKASSERT(dev != NULL);
487         udict = udev_get_dict(dev);
488
489         /* field is now locked, use directly to handle races */
490         if (dev->si_dict) {
491                 prop_object_release(dev->si_dict);
492                 dev->si_dict = NULL;
493         }
494         udev_put_dict(dev, udict);
495
496         return 0;
497 }
498
499 static void
500 udev_event_insert(int ev_type, prop_dictionary_t dict)
501 {
502         struct udev_event_kernel *ev;
503         prop_dictionary_t dict_copy;
504
505         /* Only start queing events after client has initiated properly */
506         if (udev_initiated_count) {
507                 dict_copy = prop_dictionary_copy(dict);
508                 if (dict_copy == NULL)
509                         return;
510                 ev = objcache_get(udev_event_kernel_cache, M_WAITOK);
511                 ev->ev.ev_dict = dict_copy;
512                 ev->ev.ev_type = ev_type;
513
514                 lockmgr(&udev_lk, LK_EXCLUSIVE);
515                 TAILQ_INSERT_TAIL(&udev_evq, ev, link);
516                 ++udev_evqlen;
517                 ++udev_seq;
518                 if (udev_seqwait)
519                         wakeup(&udev_seqwait);
520                 lockmgr(&udev_lk, LK_RELEASE);
521                 wakeup(&udev_evq);
522                 KNOTE(&udev_kq.ki_note, 0);
523         } else if (udev_open_count) {
524                 lockmgr(&udev_lk, LK_EXCLUSIVE);
525                 ++udev_seq;
526                 if (udev_seqwait)
527                         wakeup(&udev_seqwait);
528                 lockmgr(&udev_lk, LK_RELEASE);
529                 KNOTE(&udev_kq.ki_note, 0);
530         }
531 }
532
533 static void
534 udev_clean_events_locked(void)
535 {
536         struct udev_event_kernel *ev;
537
538         while ((ev = TAILQ_FIRST(&udev_evq)) &&
539                ev->ev.ev_dict != NULL) {
540                 TAILQ_REMOVE(&udev_evq, ev, link);
541                 objcache_put(udev_event_kernel_cache, ev);
542                 --udev_evqlen;
543         }
544 }
545
546 static char *
547 udev_event_externalize(struct udev_event_kernel *ev)
548 {
549         prop_dictionary_t       dict;
550         char *xml;
551         int error;
552
553         dict = prop_dictionary_create();
554         if (dict == NULL) {
555                 log(LOG_DEBUG,
556                     "udev_event_externalize: prop_dictionary_create() failed\n");
557                 return NULL;
558         }
559
560         if ((error = _udev_dict_set_int(dict, "evtype", ev->ev.ev_type))) {
561                 prop_object_release(dict);
562                 return NULL;
563         }
564
565         if (prop_dictionary_set(dict, "evdict", ev->ev.ev_dict) == false) {
566                 prop_object_release(dict);
567                 return NULL;
568         }
569
570         prop_object_release(ev->ev.ev_dict);
571
572         xml = prop_dictionary_externalize(dict);
573
574         prop_object_release(dict);
575
576         return xml;
577 }
578
579 int
580 udev_event_attach(cdev_t dev, char *name, int alias)
581 {
582         prop_dictionary_t dict;
583         prop_dictionary_t udict;
584         int error;
585
586         KKASSERT(dev != NULL);
587
588         error = ENOMEM;
589
590         udict = udev_get_dict(dev);
591         if (alias) {
592                 if (udict == NULL)
593                         goto error_out;
594                 dict = prop_dictionary_copy(udict);
595                 if (dict == NULL)
596                         goto error_out;
597
598                 if ((error = _udev_dict_set_cstr(dict, "name", name))) {
599                         prop_object_release(dict);
600                         goto error_out;
601                 }
602
603                 _udev_dict_set_int(dict, "alias", 1);
604
605                 udev_event_insert(UDEV_EVENT_ATTACH, dict);
606                 prop_object_release(dict);
607         } else {
608                 while (udict == NULL) {
609                         error = udev_init_dict(dev);
610                         if (error)
611                                 goto error_out;
612                         udev_put_dict(dev, udict);
613                         udict = udev_get_dict(dev);
614                 }
615                 _udev_dict_set_int(udict, "alias", 0);
616                 udev_event_insert(UDEV_EVENT_ATTACH, udict);
617         }
618 error_out:
619         udev_put_dict(dev, udict);
620
621         return error;
622 }
623
624 int
625 udev_event_detach(cdev_t dev, char *name, int alias)
626 {
627         prop_dictionary_t dict;
628         prop_dictionary_t udict;
629
630         KKASSERT(dev != NULL);
631
632         udict = udev_get_dict(dev);
633         if (alias) {
634                 dict = prop_dictionary_copy(udict);
635                 if (dict == NULL)
636                         goto error_out;
637
638                 if (_udev_dict_set_cstr(dict, "name", name)) {
639                         prop_object_release(dict);
640                         goto error_out;
641                 }
642
643                 _udev_dict_set_int(dict, "alias", 1);
644
645                 udev_event_insert(UDEV_EVENT_DETACH, dict);
646                 prop_object_release(dict);
647         } else {
648                 if (udict)
649                         udev_event_insert(UDEV_EVENT_DETACH, udict);
650         }
651
652 error_out:
653         udev_destroy_dict(dev);
654         udev_put_dict(dev, udict);
655
656         return 0;
657 }
658
659 /*
660  * Allow multiple opens.  Each opener gets a different device.
661  * Messages are replicated to all devices using a marker system.
662  */
663 static int
664 udev_dev_clone(struct dev_clone_args *ap)
665 {
666         struct udev_softc *softc;
667         int unit;
668
669         unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(udev), 1000);
670         if (unit < 0) {
671                 ap->a_dev = NULL;
672                 return 1;
673         }
674
675         softc = kmalloc(sizeof(*softc), M_UDEV, M_WAITOK | M_ZERO);
676         softc->unit = unit;
677         lockmgr(&udev_lk, LK_EXCLUSIVE);
678         TAILQ_INSERT_TAIL(&udevq, softc, entry);
679         lockmgr(&udev_lk, LK_RELEASE);
680
681         softc->dev = make_only_dev(&udev_dev_ops, unit, ap->a_cred->cr_ruid,
682                                    0, 0600, "udevs/%d", unit);
683         softc->dev->si_drv1 = softc;
684         ap->a_dev = softc->dev;
685         return 0;
686 }
687
688 /*
689  * dev stuff
690  */
691 static int
692 udev_dev_open(struct dev_open_args *ap)
693 {
694         struct udev_softc *softc = ap->a_head.a_dev->si_drv1;
695
696         lockmgr(&udev_lk, LK_EXCLUSIVE);
697         if (softc == NULL || softc->opened) {
698                 lockmgr(&udev_lk, LK_RELEASE);
699                 return EBUSY;
700         }
701         softc->opened = 1;
702         ++udev_open_count;
703         lockmgr(&udev_lk, LK_RELEASE);
704
705         return 0;
706 }
707
708 static int
709 udev_dev_close(struct dev_close_args *ap)
710 {
711         struct udev_softc *softc = ap->a_head.a_dev->si_drv1;
712
713         KKASSERT(softc->dev == ap->a_head.a_dev);
714         KKASSERT(softc->opened == 1);
715
716         destroy_dev(ap->a_head.a_dev);
717         lockmgr(&udev_lk, LK_EXCLUSIVE);
718         TAILQ_REMOVE(&udevq, softc, entry);
719
720         if (softc->initiated) {
721                 TAILQ_REMOVE(&udev_evq, &softc->marker, link);
722                 softc->initiated = 0;
723                 --udev_initiated_count;
724                 udev_clean_events_locked();
725         }
726         softc->opened = 0;
727         softc->dev = NULL;
728         ap->a_head.a_dev->si_drv1 = NULL;
729         --udev_open_count;
730         lockmgr(&udev_lk, LK_RELEASE);
731
732         /*
733          * WARNING! devfs_clone_bitmap_put() interacts with the devfs
734          *          thread, avoid deadlocks by ensuring we are unlocked
735          *          before calling.
736          */
737         devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(udev), softc->unit);
738         wakeup(&udev_evq);
739
740         kfree(softc, M_UDEV);
741
742         return 0;
743 }
744
745 static struct filterops udev_dev_read_filtops =
746         { FILTEROP_ISFD | FILTEROP_MPSAFE, NULL,
747           udev_dev_filter_detach, udev_dev_filter_read };
748
749 static int
750 udev_dev_kqfilter(struct dev_kqfilter_args *ap)
751 {
752         struct udev_softc *softc = ap->a_head.a_dev->si_drv1;
753         struct knote *kn = ap->a_kn;
754         struct klist *klist;
755
756         ap->a_result = 0;
757         lockmgr(&udev_lk, LK_EXCLUSIVE);
758
759         switch (kn->kn_filter) {
760         case EVFILT_READ:
761                 kn->kn_fop = &udev_dev_read_filtops;
762                 kn->kn_hook = (caddr_t)softc;
763                 break;
764         default:
765                 ap->a_result = EOPNOTSUPP;
766                 lockmgr(&udev_lk, LK_RELEASE);
767                 return (0);
768         }
769
770         klist = &udev_kq.ki_note;
771         knote_insert(klist, kn);
772
773         lockmgr(&udev_lk, LK_RELEASE);
774
775         return (0);
776 }
777
778 static void
779 udev_dev_filter_detach(struct knote *kn)
780 {
781         struct klist *klist;
782
783         lockmgr(&udev_lk, LK_EXCLUSIVE);
784         klist = &udev_kq.ki_note;
785         knote_remove(klist, kn);
786         lockmgr(&udev_lk, LK_RELEASE);
787 }
788
789 static int
790 udev_dev_filter_read(struct knote *kn, long hint)
791 {
792         struct udev_softc *softc = (void *)kn->kn_hook;
793         struct udev_event_kernel *ev;
794         int ready = 0;
795
796         lockmgr(&udev_lk, LK_EXCLUSIVE);
797         if (softc->initiated) {
798                 ev = TAILQ_NEXT(&softc->marker, link);
799                 while (ev && ev->ev.ev_dict == NULL)
800                         ev = TAILQ_NEXT(ev, link);
801                 if (ev)
802                         ready = 1;
803         }
804         lockmgr(&udev_lk, LK_RELEASE);
805
806         return (ready);
807 }
808
809 static int
810 udev_dev_read(struct dev_read_args *ap)
811 {
812         struct udev_softc *softc = ap->a_head.a_dev->si_drv1;
813         struct udev_event_kernel *ev;
814         struct uio *uio = ap->a_uio;
815         char    *xml;
816         size_t  len;
817         int     error;
818
819         lockmgr(&udev_lk, LK_EXCLUSIVE);
820
821         /*
822          * Automatically enable message collection if it has not already
823          * been enabled.
824          */
825         if (softc->initiated == 0) {
826                 softc->initiated = 1;
827                 ++udev_initiated_count;
828                 TAILQ_INSERT_HEAD(&udev_evq, &softc->marker, link);
829         }
830
831         /*
832          * Loop, sleep interruptably until we get an event or signal.
833          */
834         error = 0;
835         for (;;) {
836                 if (softc->initiated) {
837                         ev = TAILQ_NEXT(&softc->marker, link);
838                         while (ev && ev->ev.ev_dict == NULL)
839                                 ev = TAILQ_NEXT(ev, link);
840                         if (ev) {
841                                 if ((xml = udev_event_externalize(ev)) == NULL) {
842                                         error = ENOMEM;
843                                         break;
844                                 }
845                                 len = strlen(xml) + 1; /* include terminator */
846                                 if (uio->uio_resid < len)
847                                         error = ENOMEM;
848                                 else
849                                         error = uiomove((caddr_t)xml, len, uio);
850                                 kfree(xml, M_TEMP);
851
852                                 /*
853                                  * Move the marker
854                                  */
855                                 TAILQ_REMOVE(&udev_evq, &softc->marker, link);
856                                 TAILQ_INSERT_AFTER(&udev_evq,
857                                                    ev, &softc->marker, link);
858                                 udev_clean_events_locked();
859                                 break;
860                         }
861                 }
862                 if (ap->a_ioflag & IO_NDELAY) {
863                         error = EWOULDBLOCK;
864                         break;
865                 }
866                 if ((error = lksleep(&udev_evq, &udev_lk, PCATCH, "udevq", 0)))
867                         break;
868         }
869
870         lockmgr(&udev_lk, LK_RELEASE);
871         return error;
872 }
873
874 static int
875 udev_dev_ioctl(struct dev_ioctl_args *ap)
876 {
877         struct udev_softc *softc = ap->a_head.a_dev->si_drv1;
878         prop_dictionary_t dict;
879         prop_object_t   po;
880         prop_string_t   ps;
881         struct plistref *pref;
882         int i, error;
883         int seq;
884
885         error = 0;
886
887         switch(ap->a_cmd) {
888         case UDEVPROP:
889                 /* Use proplib(3) for userspace/kernel communication */
890                 pref = (struct plistref *)ap->a_data;
891                 error = prop_dictionary_copyin_ioctl(pref, ap->a_cmd, &dict);
892                 if (error)
893                         return error;
894
895                 po = prop_dictionary_get(dict, "command");
896                 if (po == NULL || prop_object_type(po) != PROP_TYPE_STRING) {
897                         log(LOG_DEBUG, "udev: prop_dictionary_get() failed\n");
898                         prop_object_release(dict);
899                         return EINVAL;
900                 }
901
902                 ps = po;
903                 /* Handle cmd */
904                 for(i = 0; cmd_fn[i].cmd != NULL; i++) {
905                         if (prop_string_equals_cstring(ps, cmd_fn[i].cmd))
906                                 break;
907                 }
908
909                 if (cmd_fn[i].cmd != NULL) {
910                         error = cmd_fn[i].fn(softc, pref, ap->a_cmd, dict);
911                 } else {
912                         error = EINVAL;
913                 }
914
915                 //prop_object_release(po);
916                 prop_object_release(dict);
917                 break;
918         case UDEVWAIT:
919                 /*
920                  * Wait for events based on sequence number.  Updates
921                  * sequence number for loop.
922                  */
923                 lockmgr(&udev_lk, LK_EXCLUSIVE);
924                 seq = *(int *)ap->a_data;
925                 ++udev_seqwait;
926                 while (seq == udev_seq) {
927                         error = lksleep(&udev_seqwait, &udev_lk,
928                                         PCATCH, "udevw", 0);
929                         if (error)
930                                 break;
931                 }
932                 --udev_seqwait;
933                 *(int *)ap->a_data = udev_seq;
934                 lockmgr(&udev_lk, LK_RELEASE);
935                 break;
936         default:
937                 error = ENOTTY; /* Inappropriate ioctl for device */
938                 break;
939         }
940
941         return(error);
942 }
943
944 static void
945 udev_getdevs_scan_callback(char *name, cdev_t cdev, bool is_alias, void *arg)
946 {
947         struct udev_prop_ctx *ctx = arg;
948
949         KKASSERT(arg != NULL);
950
951         if (cdev->si_dict == NULL)
952                 return;
953
954         if (prop_array_add(ctx->cdevs, cdev->si_dict) == false) {
955                 ctx->error = EINVAL;
956                 return;
957         }
958 }
959
960 static int
961 udev_getdevs_ioctl(struct udev_softc *softc, struct plistref *pref,
962                    u_long cmd, prop_dictionary_t dict)
963 {
964         prop_dictionary_t odict;
965         struct udev_prop_ctx ctx;
966         int error;
967
968         /*
969          * Ensure event notification is enabled before doing the devfs
970          * scan so nothing gets missed.
971          */
972         lockmgr(&udev_lk, LK_EXCLUSIVE);
973         if (softc->initiated == 0) {
974                 softc->initiated = 1;
975                 ++udev_initiated_count;
976                 TAILQ_INSERT_HEAD(&udev_evq, &softc->marker, link);
977         }
978         lockmgr(&udev_lk, LK_RELEASE);
979
980         /*
981          * Devfs scan to build full dictionary.
982          */
983         ctx.error = 0;
984         ctx.cdevs = prop_array_create();
985         if (ctx.cdevs == NULL) {
986                 log(LOG_DEBUG,
987                     "udev_getdevs_ioctl: prop_array_create() failed\n");
988                 return EINVAL;
989         }
990
991         devfs_scan_callback(udev_getdevs_scan_callback, &ctx);
992
993         if (ctx.error != 0) {
994                 prop_object_release(ctx.cdevs);
995                 return (ctx.error);
996         }
997
998         odict = prop_dictionary_create();
999         if (odict == NULL) {
1000                 return ENOMEM;
1001         }
1002
1003         if ((prop_dictionary_set(odict, "array", ctx.cdevs)) == 0) {
1004                 log(LOG_DEBUG,
1005                     "udev_getdevs_ioctl: prop_dictionary_set failed\n");
1006                 prop_object_release(odict);
1007                 return ENOMEM;
1008         }
1009
1010         error = prop_dictionary_copyout_ioctl(pref, cmd, odict);
1011
1012         prop_object_release(odict);
1013         return error;
1014 }
1015
1016
1017 /*
1018  * SYSINIT stuff
1019  */
1020 static void
1021 udev_init(void)
1022 {
1023         lockinit(&udev_lk, "udevlk", 0, LK_CANRECURSE);
1024         TAILQ_INIT(&udevq);
1025         TAILQ_INIT(&udev_evq);
1026         udev_event_kernel_cache = objcache_create_simple(M_UDEV, sizeof(struct udev_event_kernel));
1027 }
1028
1029 static void
1030 udev_uninit(void)
1031 {
1032         objcache_destroy(udev_event_kernel_cache);
1033 }
1034
1035 static void
1036 udev_dev_init(void)
1037 {
1038         udev_dev = make_autoclone_dev(&udev_dev_ops, &DEVFS_CLONE_BITMAP(udev),
1039                                       udev_dev_clone,
1040                                       UID_ROOT, GID_WHEEL, 0600, "udev");
1041 }
1042
1043 static void
1044 udev_dev_uninit(void)
1045 {
1046         destroy_dev(udev_dev);
1047 }
1048
1049 SYSINIT(subr_udev_register, SI_SUB_CREATE_INIT, SI_ORDER_ANY,
1050         udev_init, NULL);
1051 SYSUNINIT(subr_udev_register, SI_SUB_CREATE_INIT, SI_ORDER_ANY,
1052         udev_uninit, NULL);
1053 SYSINIT(subr_udev_dev_register, SI_SUB_DRIVERS, SI_ORDER_ANY,
1054         udev_dev_init, NULL);
1055 SYSUNINIT(subr_udev_dev_register, SI_SUB_DRIVERS, SI_ORDER_ANY,
1056         udev_dev_uninit, NULL);