kgdb - Add -D_KERNEL_STRUCTURES to access kernel structures properly.
[dragonfly.git] / sys / vfs / devfs / devfs_core.c
CommitLineData
21864bc5
MD
1/*
2 * Copyright (c) 2009 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/mount.h>
38#include <sys/vnode.h>
39#include <sys/types.h>
40#include <sys/lock.h>
41#include <sys/msgport.h>
42#include <sys/msgport2.h>
43#include <sys/spinlock2.h>
44#include <sys/sysctl.h>
45#include <sys/ucred.h>
46#include <sys/param.h>
47#include <sys/sysref2.h>
7cbab9da 48#include <sys/systm.h>
2c1e28dd
AH
49#include <sys/devfs.h>
50#include <sys/devfs_rules.h>
21864bc5
MD
51
52MALLOC_DEFINE(M_DEVFS, "devfs", "Device File System (devfs) allocations");
7cbab9da 53DEVFS_DECLARE_CLONE_BITMAP(ops_id);
21864bc5
MD
54/*
55 * SYSREF Integration - reference counting, allocation,
56 * sysid and syslink integration.
57 */
58static void devfs_cdev_terminate(cdev_t dev);
59static struct sysref_class cdev_sysref_class = {
60 .name = "cdev",
61 .mtype = M_DEVFS,
62 .proto = SYSREF_PROTO_DEV,
63 .offset = offsetof(struct cdev, si_sysref),
64 .objsize = sizeof(struct cdev),
65 .mag_capacity = 32,
66 .flags = 0,
67 .ops = {
68 .terminate = (sysref_terminate_func_t)devfs_cdev_terminate
69 }
70};
71
72static struct objcache *devfs_node_cache;
73static struct objcache *devfs_msg_cache;
74static struct objcache *devfs_dev_cache;
75
76static struct objcache_malloc_args devfs_node_malloc_args = {
77 sizeof(struct devfs_node), M_DEVFS };
78struct objcache_malloc_args devfs_msg_malloc_args = {
79 sizeof(struct devfs_msg), M_DEVFS };
80struct objcache_malloc_args devfs_dev_malloc_args = {
81 sizeof(struct cdev), M_DEVFS };
82
bc185c5a
AH
83static struct devfs_dev_head devfs_dev_list =
84 TAILQ_HEAD_INITIALIZER(devfs_dev_list);
85static struct devfs_mnt_head devfs_mnt_list =
86 TAILQ_HEAD_INITIALIZER(devfs_mnt_list);
87static struct devfs_chandler_head devfs_chandler_list =
88 TAILQ_HEAD_INITIALIZER(devfs_chandler_list);
89static struct devfs_alias_head devfs_alias_list =
90 TAILQ_HEAD_INITIALIZER(devfs_alias_list);
176de024
AH
91static struct devfs_dev_ops_head devfs_dev_ops_list =
92 TAILQ_HEAD_INITIALIZER(devfs_dev_ops_list);
21864bc5
MD
93
94struct lock devfs_lock;
95static struct lwkt_port devfs_dispose_port;
96static struct lwkt_port devfs_msg_port;
97static struct thread *td_core;
21864bc5 98
21864bc5 99static struct spinlock ino_lock;
d0fe8596
MD
100static ino_t d_ino;
101static int devfs_debug_enable;
102static int devfs_run;
21864bc5
MD
103
104static ino_t devfs_fetch_ino(void);
21864bc5
MD
105static int devfs_create_all_dev_worker(struct devfs_node *);
106static int devfs_create_dev_worker(cdev_t, uid_t, gid_t, int);
107static int devfs_destroy_dev_worker(cdev_t);
108static int devfs_destroy_subnames_worker(char *);
109static int devfs_destroy_dev_by_ops_worker(struct dev_ops *, int);
110static int devfs_propagate_dev(cdev_t, int);
ca8d7677 111static int devfs_unlink_dev(cdev_t dev);
d0fe8596 112static void devfs_msg_exec(devfs_msg_t msg);
21864bc5 113
07dfa375
AH
114static int devfs_chandler_add_worker(const char *, d_clone_t *);
115static int devfs_chandler_del_worker(const char *);
21864bc5
MD
116
117static void devfs_msg_autofree_reply(lwkt_port_t, lwkt_msg_t);
118static void devfs_msg_core(void *);
119
120static int devfs_find_device_by_name_worker(devfs_msg_t);
121static int devfs_find_device_by_udev_worker(devfs_msg_t);
122
123static int devfs_apply_reset_rules_caller(char *, int);
21864bc5
MD
124
125static int devfs_scan_callback_worker(devfs_scan_t *);
126
bc185c5a
AH
127static struct devfs_node *devfs_resolve_or_create_dir(struct devfs_node *,
128 char *, size_t, int);
21864bc5
MD
129
130static int devfs_make_alias_worker(struct devfs_alias *);
131static int devfs_alias_remove(cdev_t);
132static int devfs_alias_reap(void);
133static int devfs_alias_propagate(struct devfs_alias *);
134static int devfs_alias_apply(struct devfs_node *, struct devfs_alias *);
135static int devfs_alias_check_create(struct devfs_node *);
136
ca8d7677
MD
137static int devfs_clr_subnames_flag_worker(char *, uint32_t);
138static int devfs_destroy_subnames_without_flag_worker(char *, uint32_t);
139
66abefa5
AH
140static void *devfs_reaperp_callback(struct devfs_node *, void *);
141static void *devfs_gc_dirs_callback(struct devfs_node *, void *);
142static void *devfs_gc_links_callback(struct devfs_node *, struct devfs_node *);
143static void *
144devfs_inode_to_vnode_worker_callback(struct devfs_node *, ino_t *);
145
21864bc5 146/*
bc185c5a
AH
147 * devfs_debug() is a SYSCTL and TUNABLE controlled debug output function
148 * using kvprintf
21864bc5
MD
149 */
150int
151devfs_debug(int level, char *fmt, ...)
152{
153 __va_list ap;
154
155 __va_start(ap, fmt);
156 if (level <= devfs_debug_enable)
157 kvprintf(fmt, ap);
158 __va_end(ap);
159
160 return 0;
161}
162
163/*
ca8d7677
MD
164 * devfs_allocp() Allocates a new devfs node with the specified
165 * parameters. The node is also automatically linked into the topology
166 * if a parent is specified. It also calls the rule and alias stuff to
167 * be applied on the new node
21864bc5
MD
168 */
169struct devfs_node *
ca8d7677
MD
170devfs_allocp(devfs_nodetype devfsnodetype, char *name,
171 struct devfs_node *parent, struct mount *mp, cdev_t dev)
21864bc5
MD
172{
173 struct devfs_node *node = NULL;
174 size_t namlen = strlen(name);
21864bc5
MD
175
176 node = objcache_get(devfs_node_cache, M_WAITOK);
ca8d7677
MD
177 bzero(node, sizeof(*node));
178
71f27d2d 179 atomic_add_long(&(DEVFS_MNTDATA(mp)->leak_count), 1);
21864bc5 180
ca8d7677 181 node->d_dev = NULL;
21864bc5
MD
182 node->nchildren = 1;
183 node->mp = mp;
184 node->d_dir.d_ino = devfs_fetch_ino();
21864bc5 185
bc185c5a
AH
186 /*
187 * Cookie jar for children. Leave 0 and 1 for '.' and '..' entries
188 * respectively.
189 */
190 node->cookie_jar = 2;
191
192 /*
193 * Access Control members
194 */
195 node->mode = DEVFS_DEFAULT_MODE;
196 node->uid = DEVFS_DEFAULT_UID;
197 node->gid = DEVFS_DEFAULT_GID;
21864bc5 198
21864bc5
MD
199 switch (devfsnodetype) {
200 case Proot:
bc185c5a
AH
201 /*
202 * Ensure that we don't recycle the root vnode by marking it as
203 * linked into the topology.
204 */
894bbb25 205 node->flags |= DEVFS_NODE_LINKED;
21864bc5
MD
206 case Pdir:
207 TAILQ_INIT(DEVFS_DENODE_HEAD(node));
208 node->d_dir.d_type = DT_DIR;
209 node->nchildren = 2;
210 break;
211
212 case Plink:
213 node->d_dir.d_type = DT_LNK;
214 break;
215
216 case Preg:
217 node->d_dir.d_type = DT_REG;
218 break;
219
220 case Pdev:
221 if (dev != NULL) {
222 node->d_dir.d_type = DT_CHR;
223 node->d_dev = dev;
21864bc5 224
bc185c5a
AH
225 node->mode = dev->si_perms;
226 node->uid = dev->si_uid;
227 node->gid = dev->si_gid;
21864bc5
MD
228
229 devfs_alias_check_create(node);
230 }
231 break;
232
233 default:
234 panic("devfs_allocp: unknown node type");
235 }
236
237 node->v_node = NULL;
238 node->node_type = devfsnodetype;
239
bc185c5a 240 /* Initialize the dirent structure of each devfs vnode */
ca8d7677 241 KKASSERT(namlen < 256);
21864bc5 242 node->d_dir.d_namlen = namlen;
ca8d7677 243 node->d_dir.d_name = kmalloc(namlen+1, M_DEVFS, M_WAITOK);
21864bc5
MD
244 memcpy(node->d_dir.d_name, name, namlen);
245 node->d_dir.d_name[namlen] = '\0';
246
247 /* Initialize the parent node element */
248 node->parent = parent;
249
250 /* Apply rules */
66abefa5 251 devfs_rule_check_apply(node, NULL);
21864bc5 252
bc185c5a 253 /* Initialize *time members */
ca8d7677
MD
254 nanotime(&node->atime);
255 node->mtime = node->ctime = node->atime;
256
257 /*
258 * Associate with parent as last step, clean out namecache
259 * reference.
260 */
21864bc5 261 if ((parent != NULL) &&
ca8d7677 262 ((parent->node_type == Proot) || (parent->node_type == Pdir))) {
21864bc5
MD
263 parent->nchildren++;
264 node->cookie = parent->cookie_jar++;
265 node->flags |= DEVFS_NODE_LINKED;
ca8d7677 266 TAILQ_INSERT_TAIL(DEVFS_DENODE_HEAD(parent), node, link);
21864bc5 267
ca8d7677
MD
268 /* This forces negative namecache lookups to clear */
269 ++mp->mnt_namecache_gen;
270 }
21864bc5 271
21864bc5
MD
272 return node;
273}
274
275/*
276 * devfs_allocv() allocates a new vnode based on a devfs node.
277 */
278int
279devfs_allocv(struct vnode **vpp, struct devfs_node *node)
280{
281 struct vnode *vp;
282 int error = 0;
283
284 KKASSERT(node);
285
21864bc5
MD
286try_again:
287 while ((vp = node->v_node) != NULL) {
288 error = vget(vp, LK_EXCLUSIVE);
289 if (error != ENOENT) {
290 *vpp = vp;
21864bc5
MD
291 goto out;
292 }
293 }
21864bc5 294
21864bc5
MD
295 if ((error = getnewvnode(VT_DEVFS, node->mp, vpp, 0, 0)) != 0)
296 goto out;
297
298 vp = *vpp;
299
21864bc5
MD
300 if (node->v_node != NULL) {
301 vp->v_type = VBAD;
302 vx_put(vp);
303 goto try_again;
304 }
305
306 vp->v_data = node;
307 node->v_node = vp;
21864bc5
MD
308
309 switch (node->node_type) {
310 case Proot:
311 vp->v_flag |= VROOT;
312 case Pdir:
313 vp->v_type = VDIR;
314 break;
315
316 case Plink:
317 vp->v_type = VLNK;
318 break;
319
320 case Preg:
321 vp->v_type = VREG;
322 break;
323
324 case Pdev:
325 vp->v_type = VCHR;
21864bc5
MD
326 KKASSERT(node->d_dev);
327
bc185c5a
AH
328 vp->v_uminor = node->d_dev->si_uminor;
329 vp->v_umajor = 0;
330
331 v_associate_rdev(vp, node->d_dev);
332 vp->v_ops = &node->mp->mnt_vn_spec_ops;
21864bc5
MD
333 break;
334
335 default:
336 panic("devfs_allocv: unknown node type");
337 }
338
339out:
21864bc5
MD
340 return error;
341}
342
343/*
344 * devfs_allocvp allocates both a devfs node (with the given settings) and a vnode
345 * based on the newly created devfs node.
346 */
347int
348devfs_allocvp(struct mount *mp, struct vnode **vpp, devfs_nodetype devfsnodetype,
bc185c5a 349 char *name, struct devfs_node *parent, cdev_t dev)
21864bc5
MD
350{
351 struct devfs_node *node;
352
21864bc5 353 node = devfs_allocp(devfsnodetype, name, parent, mp, dev);
bc185c5a 354
21864bc5
MD
355 if (node != NULL)
356 devfs_allocv(vpp, node);
357 else
358 *vpp = NULL;
359
21864bc5
MD
360 return 0;
361}
362
363/*
ca8d7677
MD
364 * Destroy the devfs_node. The node must be unlinked from the topology.
365 *
366 * This function will also destroy any vnode association with the node
367 * and device.
368 *
369 * The cdev_t itself remains intact.
21864bc5
MD
370 */
371int
372devfs_freep(struct devfs_node *node)
373{
ca8d7677
MD
374 struct vnode *vp;
375
21864bc5 376 KKASSERT(node);
ca8d7677
MD
377 KKASSERT(((node->flags & DEVFS_NODE_LINKED) == 0) ||
378 (node->node_type == Proot));
379 KKASSERT((node->flags & DEVFS_DESTROYED) == 0);
21864bc5 380
71f27d2d 381 atomic_subtract_long(&(DEVFS_MNTDATA(node->mp)->leak_count), 1);
21864bc5
MD
382 if (node->symlink_name) {
383 kfree(node->symlink_name, M_DEVFS);
384 node->symlink_name = NULL;
385 }
386
ca8d7677
MD
387 /*
388 * Remove the node from the orphan list if it is still on it.
389 */
390 if (node->flags & DEVFS_ORPHANED)
21864bc5
MD
391 devfs_tracer_del_orphan(node);
392
ca8d7677
MD
393 /*
394 * Disassociate the vnode from the node. This also prevents the
395 * vnode's reclaim code from double-freeing the node.
e23485a5
MD
396 *
397 * The vget is needed to safely modify the vp. It also serves
398 * to cycle the refs and terminate the vnode if it happens to
399 * be inactive, otherwise namecache references may not get cleared.
ca8d7677 400 */
e23485a5
MD
401 while ((vp = node->v_node) != NULL) {
402 if (vget(vp, LK_EXCLUSIVE | LK_RETRY) != 0)
403 break;
9b823501 404 v_release_rdev(vp);
ca8d7677
MD
405 vp->v_data = NULL;
406 node->v_node = NULL;
71f27d2d 407 cache_inval_vp(vp, CINV_DESTROY);
e23485a5 408 vput(vp);
ca8d7677 409 }
4062d050 410 if (node->d_dir.d_name) {
ca8d7677 411 kfree(node->d_dir.d_name, M_DEVFS);
4062d050
MD
412 node->d_dir.d_name = NULL;
413 }
ca8d7677
MD
414 node->flags |= DEVFS_DESTROYED;
415
21864bc5
MD
416 objcache_put(devfs_node_cache, node);
417
418 return 0;
419}
420
421/*
ca8d7677
MD
422 * Unlink the devfs node from the topology and add it to the orphan list.
423 * The node will later be destroyed by freep.
424 *
425 * Any vnode association, including the v_rdev and v_data, remains intact
426 * until the freep.
21864bc5
MD
427 */
428int
429devfs_unlinkp(struct devfs_node *node)
430{
431 struct devfs_node *parent;
432 KKASSERT(node);
433
bc185c5a
AH
434 /*
435 * Add the node to the orphan list, so it is referenced somewhere, to
436 * so we don't leak it.
437 */
21864bc5 438 devfs_tracer_add_orphan(node);
bc185c5a 439
21864bc5
MD
440 parent = node->parent;
441
ca8d7677
MD
442 /*
443 * If the parent is known we can unlink the node out of the topology
444 */
21864bc5
MD
445 if (parent) {
446 TAILQ_REMOVE(DEVFS_DENODE_HEAD(parent), node, link);
447 parent->nchildren--;
448 KKASSERT((parent->nchildren >= 0));
449 node->flags &= ~DEVFS_NODE_LINKED;
450 }
451 node->parent = NULL;
21864bc5
MD
452 return 0;
453}
454
66abefa5
AH
455void *
456devfs_iterate_topology(struct devfs_node *node,
457 devfs_iterate_callback_t *callback, void *arg1)
21864bc5
MD
458{
459 struct devfs_node *node1, *node2;
66abefa5 460 void *ret = NULL;
21864bc5 461
21864bc5 462 if ((node->node_type == Proot) || (node->node_type == Pdir)) {
21864bc5 463 if (node->nchildren > 2) {
ca8d7677 464 TAILQ_FOREACH_MUTABLE(node1, DEVFS_DENODE_HEAD(node),
bc185c5a 465 link, node2) {
66abefa5
AH
466 if ((ret = devfs_iterate_topology(node1, callback, arg1)))
467 return ret;
21864bc5
MD
468 }
469 }
470 }
21864bc5 471
66abefa5
AH
472 ret = callback(node, arg1);
473 return ret;
21864bc5
MD
474}
475
476/*
66abefa5
AH
477 * devfs_reaperp() is a recursive function that iterates through all the
478 * topology, unlinking and freeing all devfs nodes.
21864bc5 479 */
66abefa5
AH
480static void *
481devfs_reaperp_callback(struct devfs_node *node, void *unused)
21864bc5 482{
21864bc5 483 devfs_unlinkp(node);
21864bc5
MD
484 devfs_freep(node);
485
66abefa5 486 return NULL;
21864bc5
MD
487}
488
66abefa5
AH
489static void *
490devfs_gc_dirs_callback(struct devfs_node *node, void *unused)
21864bc5 491{
66abefa5 492 if (node->node_type == Pdir) {
21864bc5 493 if (node->nchildren == 2) {
21864bc5
MD
494 devfs_unlinkp(node);
495 devfs_freep(node);
496 }
497 }
498
66abefa5
AH
499 return NULL;
500}
501
502static void *
503devfs_gc_links_callback(struct devfs_node *node, struct devfs_node *target)
504{
505 if ((node->node_type == Plink) && (node->link_target == target)) {
506 devfs_unlinkp(node);
507 devfs_freep(node);
508 }
509
510 return NULL;
21864bc5
MD
511}
512
513/*
66abefa5
AH
514 * devfs_gc() is devfs garbage collector. It takes care of unlinking and
515 * freeing a node, but also removes empty directories and links that link
516 * via devfs auto-link mechanism to the node being deleted.
21864bc5 517 */
66abefa5
AH
518int
519devfs_gc(struct devfs_node *node)
21864bc5 520{
66abefa5 521 struct devfs_node *root_node = DEVFS_MNTDATA(node->mp)->root_node;
21864bc5 522
66abefa5
AH
523 if (node->nlinks > 0)
524 devfs_iterate_topology(root_node,
525 (devfs_iterate_callback_t *)devfs_gc_links_callback, node);
21864bc5 526
66abefa5
AH
527 devfs_unlinkp(node);
528 devfs_iterate_topology(root_node,
529 (devfs_iterate_callback_t *)devfs_gc_dirs_callback, NULL);
530
531 devfs_freep(node);
21864bc5 532
66abefa5 533 return 0;
21864bc5
MD
534}
535
536/*
ca8d7677
MD
537 * devfs_create_dev() is the asynchronous entry point for device creation.
538 * It just sends a message with the relevant details to the devfs core.
539 *
540 * This function will reference the passed device. The reference is owned
541 * by devfs and represents all of the device's node associations.
21864bc5
MD
542 */
543int
544devfs_create_dev(cdev_t dev, uid_t uid, gid_t gid, int perms)
545{
ca8d7677 546 reference_dev(dev);
bc185c5a
AH
547 devfs_msg_send_dev(DEVFS_DEVICE_CREATE, dev, uid, gid, perms);
548
21864bc5
MD
549 return 0;
550}
551
552/*
ca8d7677
MD
553 * devfs_destroy_dev() is the asynchronous entry point for device destruction.
554 * It just sends a message with the relevant details to the devfs core.
21864bc5
MD
555 */
556int
557devfs_destroy_dev(cdev_t dev)
558{
559 devfs_msg_send_dev(DEVFS_DEVICE_DESTROY, dev, 0, 0, 0);
560 return 0;
561}
562
563/*
ca8d7677
MD
564 * devfs_mount_add() is the synchronous entry point for adding a new devfs
565 * mount. It sends a synchronous message with the relevant details to the
566 * devfs core.
21864bc5
MD
567 */
568int
569devfs_mount_add(struct devfs_mnt_data *mnt)
570{
571 devfs_msg_t msg;
572
573 msg = devfs_msg_get();
ca8d7677 574 msg->mdv_mnt = mnt;
21864bc5
MD
575 msg = devfs_msg_send_sync(DEVFS_MOUNT_ADD, msg);
576 devfs_msg_put(msg);
577
578 return 0;
579}
580
581/*
582 * devfs_mount_del() is the synchronous entry point for removing a devfs mount.
583 * It sends a synchronous message with the relevant details to the devfs core.
584 */
585int
586devfs_mount_del(struct devfs_mnt_data *mnt)
587{
588 devfs_msg_t msg;
589
590 msg = devfs_msg_get();
ca8d7677 591 msg->mdv_mnt = mnt;
21864bc5
MD
592 msg = devfs_msg_send_sync(DEVFS_MOUNT_DEL, msg);
593 devfs_msg_put(msg);
594
595 return 0;
596}
597
598/*
bc185c5a
AH
599 * devfs_destroy_subnames() is the synchronous entry point for device
600 * destruction by subname. It just sends a message with the relevant details to
601 * the devfs core.
21864bc5
MD
602 */
603int
604devfs_destroy_subnames(char *name)
605{
ca8d7677
MD
606 devfs_msg_t msg;
607
608 msg = devfs_msg_get();
609 msg->mdv_load = name;
610 msg = devfs_msg_send_sync(DEVFS_DESTROY_SUBNAMES, msg);
611 devfs_msg_put(msg);
612 return 0;
613}
614
615int
616devfs_clr_subnames_flag(char *name, uint32_t flag)
617{
618 devfs_msg_t msg;
619
620 msg = devfs_msg_get();
621 msg->mdv_flags.name = name;
622 msg->mdv_flags.flag = flag;
623 msg = devfs_msg_send_sync(DEVFS_CLR_SUBNAMES_FLAG, msg);
624 devfs_msg_put(msg);
625
626 return 0;
627}
628
629int
630devfs_destroy_subnames_without_flag(char *name, uint32_t flag)
631{
632 devfs_msg_t msg;
633
634 msg = devfs_msg_get();
635 msg->mdv_flags.name = name;
636 msg->mdv_flags.flag = flag;
637 msg = devfs_msg_send_sync(DEVFS_DESTROY_SUBNAMES_WO_FLAG, msg);
638 devfs_msg_put(msg);
639
21864bc5
MD
640 return 0;
641}
642
643/*
ca8d7677
MD
644 * devfs_create_all_dev is the asynchronous entry point to trigger device
645 * node creation. It just sends a message with the relevant details to
646 * the devfs core.
21864bc5
MD
647 */
648int
649devfs_create_all_dev(struct devfs_node *root)
650{
651 devfs_msg_send_generic(DEVFS_CREATE_ALL_DEV, root);
652 return 0;
653}
654
655/*
ca8d7677
MD
656 * devfs_destroy_dev_by_ops is the asynchronous entry point to destroy all
657 * devices with a specific set of dev_ops and minor. It just sends a
658 * message with the relevant details to the devfs core.
21864bc5
MD
659 */
660int
661devfs_destroy_dev_by_ops(struct dev_ops *ops, int minor)
662{
663 devfs_msg_send_ops(DEVFS_DESTROY_DEV_BY_OPS, ops, minor);
664 return 0;
665}
666
667/*
ca8d7677
MD
668 * devfs_clone_handler_add is the synchronous entry point to add a new
669 * clone handler. It just sends a message with the relevant details to
670 * the devfs core.
21864bc5
MD
671 */
672int
07dfa375 673devfs_clone_handler_add(const char *name, d_clone_t *nhandler)
21864bc5 674{
ca8d7677
MD
675 devfs_msg_t msg;
676
677 msg = devfs_msg_get();
d0fe8596 678 msg->mdv_chandler.name = name;
ca8d7677
MD
679 msg->mdv_chandler.nhandler = nhandler;
680 msg = devfs_msg_send_sync(DEVFS_CHANDLER_ADD, msg);
681 devfs_msg_put(msg);
21864bc5
MD
682 return 0;
683}
684
685/*
ca8d7677
MD
686 * devfs_clone_handler_del is the synchronous entry point to remove a
687 * clone handler. It just sends a message with the relevant details to
688 * the devfs core.
21864bc5
MD
689 */
690int
07dfa375 691devfs_clone_handler_del(const char *name)
21864bc5 692{
ca8d7677
MD
693 devfs_msg_t msg;
694
695 msg = devfs_msg_get();
d0fe8596 696 msg->mdv_chandler.name = name;
ca8d7677
MD
697 msg->mdv_chandler.nhandler = NULL;
698 msg = devfs_msg_send_sync(DEVFS_CHANDLER_DEL, msg);
699 devfs_msg_put(msg);
21864bc5
MD
700 return 0;
701}
702
703/*
ca8d7677
MD
704 * devfs_find_device_by_name is the synchronous entry point to find a
705 * device given its name. It sends a synchronous message with the
706 * relevant details to the devfs core and returns the answer.
21864bc5
MD
707 */
708cdev_t
709devfs_find_device_by_name(const char *fmt, ...)
710{
711 cdev_t found = NULL;
712 devfs_msg_t msg;
da655383 713 char *target;
21864bc5 714 __va_list ap;
21864bc5
MD
715
716 if (fmt == NULL)
717 return NULL;
718
21864bc5 719 __va_start(ap, fmt);
da655383 720 kvasnrprintf(&target, PATH_MAX, 10, fmt, ap);
21864bc5
MD
721 __va_end(ap);
722
21864bc5 723 msg = devfs_msg_get();
ca8d7677 724 msg->mdv_name = target;
21864bc5 725 msg = devfs_msg_send_sync(DEVFS_FIND_DEVICE_BY_NAME, msg);
ca8d7677 726 found = msg->mdv_cdev;
21864bc5 727 devfs_msg_put(msg);
da655383 728 kvasfree(&target);
21864bc5 729
21864bc5
MD
730 return found;
731}
732
733/*
ca8d7677
MD
734 * devfs_find_device_by_udev is the synchronous entry point to find a
735 * device given its udev number. It sends a synchronous message with
736 * the relevant details to the devfs core and returns the answer.
21864bc5
MD
737 */
738cdev_t
739devfs_find_device_by_udev(udev_t udev)
740{
741 cdev_t found = NULL;
742 devfs_msg_t msg;
743
744 msg = devfs_msg_get();
ca8d7677 745 msg->mdv_udev = udev;
21864bc5 746 msg = devfs_msg_send_sync(DEVFS_FIND_DEVICE_BY_UDEV, msg);
ca8d7677 747 found = msg->mdv_cdev;
21864bc5
MD
748 devfs_msg_put(msg);
749
ca8d7677
MD
750 devfs_debug(DEVFS_DEBUG_DEBUG,
751 "devfs_find_device_by_udev found? %s -end:3-\n",
752 ((found) ? found->si_name:"NO"));
21864bc5
MD
753 return found;
754}
755
fa7e6f37
AH
756struct vnode *
757devfs_inode_to_vnode(struct mount *mp, ino_t target)
758{
759 struct vnode *vp = NULL;
760 devfs_msg_t msg;
761
762 if (mp == NULL)
763 return NULL;
764
765 msg = devfs_msg_get();
766 msg->mdv_ino.mp = mp;
767 msg->mdv_ino.ino = target;
768 msg = devfs_msg_send_sync(DEVFS_INODE_TO_VNODE, msg);
769 vp = msg->mdv_ino.vp;
770 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
771 devfs_msg_put(msg);
772
773 return vp;
774}
775
21864bc5 776/*
ca8d7677
MD
777 * devfs_make_alias is the asynchronous entry point to register an alias
778 * for a device. It just sends a message with the relevant details to the
779 * devfs core.
21864bc5
MD
780 */
781int
07dfa375 782devfs_make_alias(const char *name, cdev_t dev_target)
21864bc5 783{
ca8d7677 784 struct devfs_alias *alias;
5298e788
AH
785 size_t len;
786
787 len = strlen(name);
ca8d7677
MD
788
789 alias = kmalloc(sizeof(struct devfs_alias), M_DEVFS, M_WAITOK);
07dfa375 790 alias->name = kstrdup(name, M_DEVFS);
5298e788 791 alias->namlen = len;
21864bc5
MD
792 alias->dev_target = dev_target;
793
794 devfs_msg_send_generic(DEVFS_MAKE_ALIAS, alias);
795 return 0;
796}
797
798/*
ca8d7677
MD
799 * devfs_apply_rules is the asynchronous entry point to trigger application
800 * of all rules. It just sends a message with the relevant details to the
801 * devfs core.
21864bc5
MD
802 */
803int
804devfs_apply_rules(char *mntto)
805{
806 char *new_name;
21864bc5 807
07dfa375 808 new_name = kstrdup(mntto, M_DEVFS);
21864bc5 809 devfs_msg_send_name(DEVFS_APPLY_RULES, new_name);
bc185c5a 810
21864bc5
MD
811 return 0;
812}
813
814/*
bc185c5a
AH
815 * devfs_reset_rules is the asynchronous entry point to trigger reset of all
816 * rules. It just sends a message with the relevant details to the devfs core.
21864bc5
MD
817 */
818int
819devfs_reset_rules(char *mntto)
820{
821 char *new_name;
21864bc5 822
07dfa375 823 new_name = kstrdup(mntto, M_DEVFS);
21864bc5 824 devfs_msg_send_name(DEVFS_RESET_RULES, new_name);
bc185c5a 825
21864bc5
MD
826 return 0;
827}
828
829
830/*
831 * devfs_scan_callback is the asynchronous entry point to call a callback
832 * on all cdevs.
833 * It just sends a message with the relevant details to the devfs core.
834 */
835int
836devfs_scan_callback(devfs_scan_t *callback)
837{
838 devfs_msg_t msg;
839
21864bc5
MD
840 KKASSERT(sizeof(callback) == sizeof(void *));
841
842 msg = devfs_msg_get();
ca8d7677 843 msg->mdv_load = callback;
21864bc5
MD
844 msg = devfs_msg_send_sync(DEVFS_SCAN_CALLBACK, msg);
845 devfs_msg_put(msg);
846
847 return 0;
848}
849
850
851/*
bc185c5a
AH
852 * Acts as a message drain. Any message that is replied to here gets destroyed
853 * and the memory freed.
21864bc5
MD
854 */
855static void
856devfs_msg_autofree_reply(lwkt_port_t port, lwkt_msg_t msg)
857{
858 devfs_msg_put((devfs_msg_t)msg);
859}
860
861/*
862 * devfs_msg_get allocates a new devfs msg and returns it.
863 */
864devfs_msg_t
865devfs_msg_get()
866{
867 return objcache_get(devfs_msg_cache, M_WAITOK);
868}
869
870/*
871 * devfs_msg_put deallocates a given devfs msg.
872 */
873int
874devfs_msg_put(devfs_msg_t msg)
875{
876 objcache_put(devfs_msg_cache, msg);
877 return 0;
878}
879
880/*
881 * devfs_msg_send is the generic asynchronous message sending facility
882 * for devfs. By default the reply port is the automatic disposal port.
d0fe8596
MD
883 *
884 * If the current thread is the devfs_msg_port thread we execute the
885 * operation synchronously.
21864bc5 886 */
d0fe8596 887void
21864bc5
MD
888devfs_msg_send(uint32_t cmd, devfs_msg_t devfs_msg)
889{
890 lwkt_port_t port = &devfs_msg_port;
891
d0fe8596 892 lwkt_initmsg(&devfs_msg->hdr, &devfs_dispose_port, 0);
21864bc5 893
d0fe8596 894 devfs_msg->hdr.u.ms_result = cmd;
21864bc5 895
d0fe8596
MD
896 if (port->mpu_td == curthread) {
897 devfs_msg_exec(devfs_msg);
898 lwkt_replymsg(&devfs_msg->hdr, 0);
899 } else {
900 lwkt_sendmsg(port, (lwkt_msg_t)devfs_msg);
901 }
21864bc5
MD
902}
903
904/*
905 * devfs_msg_send_sync is the generic synchronous message sending
906 * facility for devfs. It initializes a local reply port and waits
907 * for the core's answer. This answer is then returned.
908 */
909devfs_msg_t
910devfs_msg_send_sync(uint32_t cmd, devfs_msg_t devfs_msg)
911{
912 struct lwkt_port rep_port;
913 devfs_msg_t msg_incoming;
914 lwkt_port_t port = &devfs_msg_port;
915
916 lwkt_initport_thread(&rep_port, curthread);
d0fe8596 917 lwkt_initmsg(&devfs_msg->hdr, &rep_port, 0);
21864bc5 918
d0fe8596 919 devfs_msg->hdr.u.ms_result = cmd;
21864bc5 920
d0fe8596 921 lwkt_sendmsg(port, (lwkt_msg_t)devfs_msg);
21864bc5
MD
922 msg_incoming = lwkt_waitport(&rep_port, 0);
923
924 return msg_incoming;
925}
926
927/*
928 * sends a message with a generic argument.
929 */
d0fe8596 930void
21864bc5
MD
931devfs_msg_send_generic(uint32_t cmd, void *load)
932{
d0fe8596 933 devfs_msg_t devfs_msg = devfs_msg_get();
21864bc5 934
d0fe8596
MD
935 devfs_msg->mdv_load = load;
936 devfs_msg_send(cmd, devfs_msg);
21864bc5
MD
937}
938
939/*
940 * sends a message with a name argument.
941 */
d0fe8596 942void
21864bc5
MD
943devfs_msg_send_name(uint32_t cmd, char *name)
944{
d0fe8596 945 devfs_msg_t devfs_msg = devfs_msg_get();
21864bc5 946
d0fe8596
MD
947 devfs_msg->mdv_name = name;
948 devfs_msg_send(cmd, devfs_msg);
21864bc5
MD
949}
950
951/*
952 * sends a message with a mount argument.
953 */
d0fe8596 954void
21864bc5
MD
955devfs_msg_send_mount(uint32_t cmd, struct devfs_mnt_data *mnt)
956{
d0fe8596 957 devfs_msg_t devfs_msg = devfs_msg_get();
21864bc5 958
d0fe8596
MD
959 devfs_msg->mdv_mnt = mnt;
960 devfs_msg_send(cmd, devfs_msg);
21864bc5
MD
961}
962
963/*
964 * sends a message with an ops argument.
965 */
d0fe8596 966void
21864bc5
MD
967devfs_msg_send_ops(uint32_t cmd, struct dev_ops *ops, int minor)
968{
d0fe8596 969 devfs_msg_t devfs_msg = devfs_msg_get();
21864bc5 970
d0fe8596
MD
971 devfs_msg->mdv_ops.ops = ops;
972 devfs_msg->mdv_ops.minor = minor;
973 devfs_msg_send(cmd, devfs_msg);
21864bc5
MD
974}
975
976/*
977 * sends a message with a clone handler argument.
978 */
d0fe8596 979void
21864bc5
MD
980devfs_msg_send_chandler(uint32_t cmd, char *name, d_clone_t handler)
981{
d0fe8596 982 devfs_msg_t devfs_msg = devfs_msg_get();
21864bc5 983
d0fe8596
MD
984 devfs_msg->mdv_chandler.name = name;
985 devfs_msg->mdv_chandler.nhandler = handler;
986 devfs_msg_send(cmd, devfs_msg);
21864bc5
MD
987}
988
989/*
990 * sends a message with a device argument.
991 */
d0fe8596 992void
21864bc5
MD
993devfs_msg_send_dev(uint32_t cmd, cdev_t dev, uid_t uid, gid_t gid, int perms)
994{
d0fe8596
MD
995 devfs_msg_t devfs_msg = devfs_msg_get();
996
997 devfs_msg->mdv_dev.dev = dev;
ca8d7677
MD
998 devfs_msg->mdv_dev.uid = uid;
999 devfs_msg->mdv_dev.gid = gid;
1000 devfs_msg->mdv_dev.perms = perms;
21864bc5 1001
d0fe8596 1002 devfs_msg_send(cmd, devfs_msg);
21864bc5
MD
1003}
1004
1005/*
1006 * sends a message with a link argument.
1007 */
d0fe8596 1008void
21864bc5
MD
1009devfs_msg_send_link(uint32_t cmd, char *name, char *target, struct mount *mp)
1010{
d0fe8596
MD
1011 devfs_msg_t devfs_msg = devfs_msg_get();
1012
1013 devfs_msg->mdv_link.name = name;
ca8d7677
MD
1014 devfs_msg->mdv_link.target = target;
1015 devfs_msg->mdv_link.mp = mp;
d0fe8596 1016 devfs_msg_send(cmd, devfs_msg);
21864bc5
MD
1017}
1018
1019/*
1020 * devfs_msg_core is the main devfs thread. It handles all incoming messages
1021 * and calls the relevant worker functions. By using messages it's assured
1022 * that events occur in the correct order.
1023 */
1024static void
1025devfs_msg_core(void *arg)
1026{
ca8d7677 1027 devfs_msg_t msg;
21864bc5 1028
d0fe8596 1029 devfs_run = 1;
21864bc5 1030 lwkt_initport_thread(&devfs_msg_port, curthread);
bc185c5a 1031 wakeup(td_core);
21864bc5 1032
d0fe8596 1033 while (devfs_run) {
ca8d7677 1034 msg = (devfs_msg_t)lwkt_waitport(&devfs_msg_port, 0);
bc185c5a 1035 devfs_debug(DEVFS_DEBUG_DEBUG,
d0fe8596
MD
1036 "devfs_msg_core, new msg: %x\n",
1037 (unsigned int)msg->hdr.u.ms_result);
1038 devfs_msg_exec(msg);
1039 lwkt_replymsg(&msg->hdr, 0);
1040 }
1041 wakeup(td_core);
1042 lwkt_exit();
1043}
21864bc5 1044
d0fe8596
MD
1045static void
1046devfs_msg_exec(devfs_msg_t msg)
1047{
1048 struct devfs_mnt_data *mnt;
1049 struct devfs_node *node;
1050 cdev_t dev;
fa7e6f37 1051
d0fe8596
MD
1052 /*
1053 * Acquire the devfs lock to ensure safety of all called functions
1054 */
1055 lockmgr(&devfs_lock, LK_EXCLUSIVE);
1056
1057 switch (msg->hdr.u.ms_result) {
1058 case DEVFS_DEVICE_CREATE:
1059 dev = msg->mdv_dev.dev;
1060 devfs_create_dev_worker(dev,
1061 msg->mdv_dev.uid,
1062 msg->mdv_dev.gid,
1063 msg->mdv_dev.perms);
1064 break;
1065 case DEVFS_DEVICE_DESTROY:
1066 dev = msg->mdv_dev.dev;
1067 devfs_destroy_dev_worker(dev);
1068 break;
1069 case DEVFS_DESTROY_SUBNAMES:
1070 devfs_destroy_subnames_worker(msg->mdv_load);
1071 break;
1072 case DEVFS_DESTROY_DEV_BY_OPS:
1073 devfs_destroy_dev_by_ops_worker(msg->mdv_ops.ops,
1074 msg->mdv_ops.minor);
1075 break;
1076 case DEVFS_CREATE_ALL_DEV:
1077 node = (struct devfs_node *)msg->mdv_load;
1078 devfs_create_all_dev_worker(node);
1079 break;
1080 case DEVFS_MOUNT_ADD:
1081 mnt = msg->mdv_mnt;
1082 TAILQ_INSERT_TAIL(&devfs_mnt_list, mnt, link);
1083 devfs_create_all_dev_worker(mnt->root_node);
1084 break;
1085 case DEVFS_MOUNT_DEL:
1086 mnt = msg->mdv_mnt;
1087 TAILQ_REMOVE(&devfs_mnt_list, mnt, link);
66abefa5
AH
1088 devfs_iterate_topology(mnt->root_node, devfs_reaperp_callback,
1089 NULL);
d0fe8596
MD
1090 if (mnt->leak_count) {
1091 devfs_debug(DEVFS_DEBUG_SHOW,
71f27d2d 1092 "Leaked %ld devfs_node elements!\n",
d0fe8596 1093 mnt->leak_count);
ca8d7677 1094 }
d0fe8596
MD
1095 break;
1096 case DEVFS_CHANDLER_ADD:
1097 devfs_chandler_add_worker(msg->mdv_chandler.name,
1098 msg->mdv_chandler.nhandler);
1099 break;
1100 case DEVFS_CHANDLER_DEL:
1101 devfs_chandler_del_worker(msg->mdv_chandler.name);
1102 break;
1103 case DEVFS_FIND_DEVICE_BY_NAME:
1104 devfs_find_device_by_name_worker(msg);
1105 break;
1106 case DEVFS_FIND_DEVICE_BY_UDEV:
1107 devfs_find_device_by_udev_worker(msg);
1108 break;
1109 case DEVFS_MAKE_ALIAS:
1110 devfs_make_alias_worker((struct devfs_alias *)msg->mdv_load);
1111 break;
1112 case DEVFS_APPLY_RULES:
1113 devfs_apply_reset_rules_caller(msg->mdv_name, 1);
1114 break;
1115 case DEVFS_RESET_RULES:
1116 devfs_apply_reset_rules_caller(msg->mdv_name, 0);
1117 break;
1118 case DEVFS_SCAN_CALLBACK:
1119 devfs_scan_callback_worker((devfs_scan_t *)msg->mdv_load);
1120 break;
1121 case DEVFS_CLR_SUBNAMES_FLAG:
1122 devfs_clr_subnames_flag_worker(msg->mdv_flags.name,
1123 msg->mdv_flags.flag);
1124 break;
1125 case DEVFS_DESTROY_SUBNAMES_WO_FLAG:
1126 devfs_destroy_subnames_without_flag_worker(msg->mdv_flags.name,
1127 msg->mdv_flags.flag);
1128 break;
1129 case DEVFS_INODE_TO_VNODE:
66abefa5
AH
1130 msg->mdv_ino.vp = devfs_iterate_topology(
1131 DEVFS_MNTDATA(msg->mdv_ino.mp)->root_node,
1132 (devfs_iterate_callback_t *)devfs_inode_to_vnode_worker_callback,
1133 &msg->mdv_ino.ino);
d0fe8596
MD
1134 break;
1135 case DEVFS_TERMINATE_CORE:
1136 devfs_run = 0;
1137 break;
1138 case DEVFS_SYNC:
1139 break;
1140 default:
1141 devfs_debug(DEVFS_DEBUG_WARNING,
1142 "devfs_msg_core: unknown message "
1143 "received at core\n");
1144 break;
ca8d7677 1145 }
d0fe8596 1146 lockmgr(&devfs_lock, LK_RELEASE);
21864bc5
MD
1147}
1148
1149/*
1150 * Worker function to insert a new dev into the dev list and initialize its
1151 * permissions. It also calls devfs_propagate_dev which in turn propagates
1152 * the change to all mount points.
ca8d7677
MD
1153 *
1154 * The passed dev is already referenced. This reference is eaten by this
1155 * function and represents the dev's linkage into devfs_dev_list.
21864bc5
MD
1156 */
1157static int
1158devfs_create_dev_worker(cdev_t dev, uid_t uid, gid_t gid, int perms)
1159{
1160 KKASSERT(dev);
21864bc5
MD
1161
1162 dev->si_uid = uid;
1163 dev->si_gid = gid;
1164 dev->si_perms = perms;
1165
1166 devfs_link_dev(dev);
21864bc5
MD
1167 devfs_propagate_dev(dev, 1);
1168
21864bc5
MD
1169 return 0;
1170}
1171
1172/*
1173 * Worker function to delete a dev from the dev list and free the cdev.
1174 * It also calls devfs_propagate_dev which in turn propagates the change
1175 * to all mount points.
1176 */
1177static int
1178devfs_destroy_dev_worker(cdev_t dev)
1179{
ca8d7677
MD
1180 int error;
1181
21864bc5
MD
1182 KKASSERT(dev);
1183 KKASSERT((lockstatus(&devfs_lock, curthread)) == LK_EXCLUSIVE);
1184
ca8d7677 1185 error = devfs_unlink_dev(dev);
21864bc5 1186 devfs_propagate_dev(dev, 0);
ca8d7677
MD
1187 if (error == 0)
1188 release_dev(dev); /* link ref */
21864bc5
MD
1189 release_dev(dev);
1190 release_dev(dev);
21864bc5 1191
21864bc5
MD
1192 return 0;
1193}
1194
1195/*
1196 * Worker function to destroy all devices with a certain basename.
1197 * Calls devfs_destroy_dev_worker for the actual destruction.
1198 */
1199static int
1200devfs_destroy_subnames_worker(char *name)
1201{
1202 cdev_t dev, dev1;
21864bc5
MD
1203 size_t len = strlen(name);
1204
ca8d7677 1205 TAILQ_FOREACH_MUTABLE(dev, &devfs_dev_list, link, dev1) {
bc185c5a
AH
1206 if ((!strncmp(dev->si_name, name, len)) &&
1207 (dev->si_name[len] != '\0')) {
1208 devfs_destroy_dev_worker(dev);
21864bc5 1209 }
ca8d7677
MD
1210 }
1211 return 0;
1212}
1213
1214static int
1215devfs_clr_subnames_flag_worker(char *name, uint32_t flag)
1216{
1217 cdev_t dev, dev1;
1218 size_t len = strlen(name);
1219
1220 TAILQ_FOREACH_MUTABLE(dev, &devfs_dev_list, link, dev1) {
bc185c5a
AH
1221 if ((!strncmp(dev->si_name, name, len)) &&
1222 (dev->si_name[len] != '\0')) {
1223 dev->si_flags &= ~flag;
ca8d7677
MD
1224 }
1225 }
1226
1227 return 0;
1228}
1229
1230static int
1231devfs_destroy_subnames_without_flag_worker(char *name, uint32_t flag)
1232{
1233 cdev_t dev, dev1;
1234 size_t len = strlen(name);
1235
1236 TAILQ_FOREACH_MUTABLE(dev, &devfs_dev_list, link, dev1) {
bc185c5a
AH
1237 if ((!strncmp(dev->si_name, name, len)) &&
1238 (dev->si_name[len] != '\0')) {
1239 if (!(dev->si_flags & flag)) {
1240 devfs_destroy_dev_worker(dev);
ca8d7677
MD
1241 }
1242 }
1243 }
21864bc5
MD
1244
1245 return 0;
1246}
1247
1248/*
1249 * Worker function that creates all device nodes on top of a devfs
1250 * root node.
1251 */
1252static int
1253devfs_create_all_dev_worker(struct devfs_node *root)
1254{
1255 cdev_t dev;
1256
1257 KKASSERT(root);
21864bc5 1258
d0fe8596 1259 TAILQ_FOREACH(dev, &devfs_dev_list, link) {
21864bc5 1260 devfs_create_device_node(root, dev, NULL, NULL);
d0fe8596 1261 }
bc185c5a 1262
21864bc5
MD
1263 return 0;
1264}
1265
1266/*
1267 * Worker function that destroys all devices that match a specific
1268 * dev_ops and/or minor. If minor is less than 0, it is not matched
1269 * against. It also propagates all changes.
1270 */
1271static int
1272devfs_destroy_dev_by_ops_worker(struct dev_ops *ops, int minor)
1273{
1274 cdev_t dev, dev1;
1275
1276 KKASSERT(ops);
ca8d7677
MD
1277
1278 TAILQ_FOREACH_MUTABLE(dev, &devfs_dev_list, link, dev1) {
1279 if (dev->si_ops != ops)
1280 continue;
1281 if ((minor < 0) || (dev->si_uminor == minor)) {
ca8d7677 1282 devfs_destroy_dev_worker(dev);
21864bc5 1283 }
ca8d7677 1284 }
bc185c5a 1285
21864bc5
MD
1286 return 0;
1287}
1288
1289/*
1290 * Worker function that registers a new clone handler in devfs.
1291 */
1292static int
07dfa375 1293devfs_chandler_add_worker(const char *name, d_clone_t *nhandler)
21864bc5
MD
1294{
1295 struct devfs_clone_handler *chandler = NULL;
1296 u_char len = strlen(name);
1297
ca8d7677 1298 if (len == 0)
21864bc5
MD
1299 return 1;
1300
ca8d7677 1301 TAILQ_FOREACH(chandler, &devfs_chandler_list, link) {
bc185c5a
AH
1302 if (chandler->namlen != len)
1303 continue;
1304
1305 if (!memcmp(chandler->name, name, len)) {
1306 /* Clonable basename already exists */
1307 return 1;
21864bc5
MD
1308 }
1309 }
1310
ca8d7677 1311 chandler = kmalloc(sizeof(*chandler), M_DEVFS, M_WAITOK | M_ZERO);
07dfa375 1312 chandler->name = kstrdup(name, M_DEVFS);
21864bc5
MD
1313 chandler->namlen = len;
1314 chandler->nhandler = nhandler;
1315
1316 TAILQ_INSERT_TAIL(&devfs_chandler_list, chandler, link);
1317 return 0;
1318}
1319
1320/*
1321 * Worker function that removes a given clone handler from the
1322 * clone handler list.
1323 */
1324static int
07dfa375 1325devfs_chandler_del_worker(const char *name)
21864bc5
MD
1326{
1327 struct devfs_clone_handler *chandler, *chandler2;
1328 u_char len = strlen(name);
1329
ca8d7677 1330 if (len == 0)
21864bc5
MD
1331 return 1;
1332
ca8d7677
MD
1333 TAILQ_FOREACH_MUTABLE(chandler, &devfs_chandler_list, link, chandler2) {
1334 if (chandler->namlen != len)
1335 continue;
1336 if (memcmp(chandler->name, name, len))
1337 continue;
bc185c5a 1338
ca8d7677 1339 TAILQ_REMOVE(&devfs_chandler_list, chandler, link);
5298e788 1340 kfree(chandler->name, M_DEVFS);
ca8d7677 1341 kfree(chandler, M_DEVFS);
5298e788 1342 break;
21864bc5
MD
1343 }
1344
1345 return 0;
1346}
1347
1348/*
1349 * Worker function that finds a given device name and changes
1350 * the message received accordingly so that when replied to,
1351 * the answer is returned to the caller.
1352 */
1353static int
1354devfs_find_device_by_name_worker(devfs_msg_t devfs_msg)
1355{
6507240b
MD
1356 struct devfs_alias *alias;
1357 cdev_t dev;
21864bc5 1358 cdev_t found = NULL;
21864bc5 1359
6507240b
MD
1360 TAILQ_FOREACH(dev, &devfs_dev_list, link) {
1361 if (strcmp(devfs_msg->mdv_name, dev->si_name) == 0) {
21864bc5
MD
1362 found = dev;
1363 break;
1364 }
ca8d7677 1365 }
6507240b
MD
1366 if (found == NULL) {
1367 TAILQ_FOREACH(alias, &devfs_alias_list, link) {
1368 if (strcmp(devfs_msg->mdv_name, alias->name) == 0) {
1369 found = alias->dev_target;
1370 break;
1371 }
1372 }
1373 }
ca8d7677 1374 devfs_msg->mdv_cdev = found;
21864bc5
MD
1375
1376 return 0;
1377}
1378
1379/*
1380 * Worker function that finds a given device udev and changes
1381 * the message received accordingly so that when replied to,
1382 * the answer is returned to the caller.
1383 */
1384static int
1385devfs_find_device_by_udev_worker(devfs_msg_t devfs_msg)
1386{
1387 cdev_t dev, dev1;
1388 cdev_t found = NULL;
21864bc5 1389
ca8d7677
MD
1390 TAILQ_FOREACH_MUTABLE(dev, &devfs_dev_list, link, dev1) {
1391 if (((udev_t)dev->si_inode) == devfs_msg->mdv_udev) {
21864bc5
MD
1392 found = dev;
1393 break;
1394 }
ca8d7677
MD
1395 }
1396 devfs_msg->mdv_cdev = found;
21864bc5
MD
1397
1398 return 0;
1399}
1400
1401/*
1402 * Worker function that inserts a given alias into the
1403 * alias list, and propagates the alias to all mount
1404 * points.
1405 */
1406static int
1407devfs_make_alias_worker(struct devfs_alias *alias)
1408{
1409 struct devfs_alias *alias2;
1410 size_t len = strlen(alias->name);
1411 int found = 0;
1412
1413 TAILQ_FOREACH(alias2, &devfs_alias_list, link) {
bc185c5a
AH
1414 if (len != alias2->namlen)
1415 continue;
1416
1417 if (!memcmp(alias->name, alias2->name, len)) {
1418 found = 1;
1419 break;
21864bc5
MD
1420 }
1421 }
1422
1423 if (!found) {
bc185c5a
AH
1424 /*
1425 * The alias doesn't exist yet, so we add it to the alias list
1426 */
21864bc5
MD
1427 TAILQ_INSERT_TAIL(&devfs_alias_list, alias, link);
1428 devfs_alias_propagate(alias);
1429 } else {
5298e788 1430 devfs_debug(DEVFS_DEBUG_WARNING,
ca8d7677
MD
1431 "Warning: duplicate devfs_make_alias for %s\n",
1432 alias->name);
5298e788 1433 kfree(alias->name, M_DEVFS);
21864bc5
MD
1434 kfree(alias, M_DEVFS);
1435 }
1436
1437 return 0;
1438}
1439
1440/*
1441 * Function that removes and frees all aliases.
1442 */
1443static int
1444devfs_alias_reap(void)
1445{
1446 struct devfs_alias *alias, *alias2;
1447
1448 TAILQ_FOREACH_MUTABLE(alias, &devfs_alias_list, link, alias2) {
1449 TAILQ_REMOVE(&devfs_alias_list, alias, link);
1450 kfree(alias, M_DEVFS);
1451 }
1452 return 0;
1453}
1454
1455/*
1456 * Function that removes an alias matching a specific cdev and frees
1457 * it accordingly.
1458 */
1459static int
1460devfs_alias_remove(cdev_t dev)
1461{
1462 struct devfs_alias *alias, *alias2;
1463
1464 TAILQ_FOREACH_MUTABLE(alias, &devfs_alias_list, link, alias2) {
1465 if (alias->dev_target == dev) {
1466 TAILQ_REMOVE(&devfs_alias_list, alias, link);
1467 kfree(alias, M_DEVFS);
1468 }
1469 }
1470 return 0;
1471}
1472
1473/*
1474 * This function propagates a new alias to all mount points.
1475 */
1476static int
1477devfs_alias_propagate(struct devfs_alias *alias)
1478{
1479 struct devfs_mnt_data *mnt;
1480
1481 TAILQ_FOREACH(mnt, &devfs_mnt_list, link) {
1482 devfs_alias_apply(mnt->root_node, alias);
1483 }
1484 return 0;
1485}
1486
1487/*
1488 * This function is a recursive function iterating through
1489 * all device nodes in the topology and, if applicable,
1490 * creating the relevant alias for a device node.
1491 */
1492static int
1493devfs_alias_apply(struct devfs_node *node, struct devfs_alias *alias)
1494{
1495 struct devfs_node *node1, *node2;
1496
1497 KKASSERT(alias != NULL);
1498
1499 if ((node->node_type == Proot) || (node->node_type == Pdir)) {
21864bc5 1500 if (node->nchildren > 2) {
ca8d7677 1501 TAILQ_FOREACH_MUTABLE(node1, DEVFS_DENODE_HEAD(node), link, node2) {
21864bc5
MD
1502 devfs_alias_apply(node1, alias);
1503 }
1504 }
1505 } else {
1506 if (node->d_dev == alias->dev_target)
1cb12919 1507 devfs_alias_create(alias->name, node, 0);
21864bc5
MD
1508 }
1509 return 0;
1510}
1511
1512/*
1513 * This function checks if any alias possibly is applicable
1514 * to the given node. If so, the alias is created.
1515 */
1516static int
1517devfs_alias_check_create(struct devfs_node *node)
1518{
1519 struct devfs_alias *alias;
1520
1521 TAILQ_FOREACH(alias, &devfs_alias_list, link) {
1522 if (node->d_dev == alias->dev_target)
1cb12919 1523 devfs_alias_create(alias->name, node, 0);
21864bc5
MD
1524 }
1525 return 0;
1526}
1527
1528/*
1529 * This function creates an alias with a given name
1530 * linking to a given devfs node. It also increments
1531 * the link count on the target node.
1532 */
1533int
1cb12919 1534devfs_alias_create(char *name_orig, struct devfs_node *target, int rule_based)
21864bc5
MD
1535{
1536 struct mount *mp = target->mp;
1537 struct devfs_node *parent = DEVFS_MNTDATA(mp)->root_node;
1538 struct devfs_node *linknode;
21864bc5 1539 char *create_path = NULL;
da655383
MD
1540 char *name;
1541 char *name_buf;
1542 int result = 0;
21864bc5 1543
21864bc5
MD
1544 KKASSERT((lockstatus(&devfs_lock, curthread)) == LK_EXCLUSIVE);
1545
da655383 1546 name_buf = kmalloc(PATH_MAX, M_TEMP, M_WAITOK);
21864bc5
MD
1547 devfs_resolve_name_path(name_orig, name_buf, &create_path, &name);
1548
1549 if (create_path)
1550 parent = devfs_resolve_or_create_path(parent, create_path, 1);
1551
1552
1553 if (devfs_find_device_node_by_name(parent, name)) {
bc185c5a 1554 devfs_debug(DEVFS_DEBUG_WARNING,
ca8d7677
MD
1555 "Node already exists: %s "
1556 "(devfs_make_alias_worker)!\n",
1557 name);
da655383
MD
1558 result = 1;
1559 goto done;
21864bc5
MD
1560 }
1561
21864bc5 1562 linknode = devfs_allocp(Plink, name, parent, mp, NULL);
da655383
MD
1563 if (linknode == NULL) {
1564 result = 1;
1565 goto done;
1566 }
21864bc5
MD
1567
1568 linknode->link_target = target;
1569 target->nlinks++;
21864bc5 1570
1cb12919
AH
1571 if (rule_based)
1572 linknode->flags |= DEVFS_RULE_CREATED;
1573
da655383
MD
1574done:
1575 kfree(name_buf, M_TEMP);
1576 return (result);
21864bc5
MD
1577}
1578
1579/*
1580 * This function is called by the core and handles mount point
1581 * strings. It either calls the relevant worker (devfs_apply_
1582 * reset_rules_worker) on all mountpoints or only a specific
1583 * one.
1584 */
1585static int
1586devfs_apply_reset_rules_caller(char *mountto, int apply)
1587{
21864bc5 1588 struct devfs_mnt_data *mnt;
21864bc5 1589
bc185c5a 1590 if (mountto[0] == '*') {
21864bc5 1591 TAILQ_FOREACH(mnt, &devfs_mnt_list, link) {
66abefa5
AH
1592 devfs_iterate_topology(mnt->root_node,
1593 (apply)?(devfs_rule_check_apply):(devfs_rule_reset_node),
1594 NULL);
21864bc5
MD
1595 }
1596 } else {
1597 TAILQ_FOREACH(mnt, &devfs_mnt_list, link) {
9cf39e57 1598 if (!strcmp(mnt->mp->mnt_stat.f_mntonname, mountto)) {
66abefa5
AH
1599 devfs_iterate_topology(mnt->root_node,
1600 (apply)?(devfs_rule_check_apply):(devfs_rule_reset_node),
1601 NULL);
bc185c5a
AH
1602 break;
1603 }
21864bc5
MD
1604 }
1605 }
1606
1607 kfree(mountto, M_DEVFS);
1608 return 0;
1609}
1610
21864bc5
MD
1611/*
1612 * This function calls a given callback function for
1613 * every dev node in the devfs dev list.
1614 */
1615static int
1616devfs_scan_callback_worker(devfs_scan_t *callback)
1617{
1618 cdev_t dev, dev1;
1619
d0fe8596 1620 TAILQ_FOREACH_MUTABLE(dev, &devfs_dev_list, link, dev1) {
21864bc5 1621 callback(dev);
d0fe8596 1622 }
21864bc5 1623
21864bc5
MD
1624 return 0;
1625}
1626
21864bc5
MD
1627/*
1628 * This function tries to resolve a given directory, or if not
1629 * found and creation requested, creates the given directory.
1630 */
1631static struct devfs_node *
ca8d7677
MD
1632devfs_resolve_or_create_dir(struct devfs_node *parent, char *dir_name,
1633 size_t name_len, int create)
21864bc5
MD
1634{
1635 struct devfs_node *node, *found = NULL;
1636
1637 TAILQ_FOREACH(node, DEVFS_DENODE_HEAD(parent), link) {
bc185c5a
AH
1638 if (name_len != node->d_dir.d_namlen)
1639 continue;
1640
1641 if (!memcmp(dir_name, node->d_dir.d_name, name_len)) {
1642 found = node;
1643 break;
21864bc5
MD
1644 }
1645 }
1646
1647 if ((found == NULL) && (create)) {
1648 found = devfs_allocp(Pdir, dir_name, parent, parent->mp, NULL);
1649 }
1650
1651 return found;
1652}
1653
1654/*
1655 * This function tries to resolve a complete path. If creation is requested,
1656 * if a given part of the path cannot be resolved (because it doesn't exist),
1657 * it is created.
1658 */
1659struct devfs_node *
1660devfs_resolve_or_create_path(struct devfs_node *parent, char *path, int create)
1661{
1662 struct devfs_node *node = parent;
da655383 1663 char *buf;
21864bc5
MD
1664 size_t idx = 0;
1665
21864bc5
MD
1666 if (path == NULL)
1667 return parent;
1668
da655383 1669 buf = kmalloc(PATH_MAX, M_TEMP, M_WAITOK);
21864bc5 1670
da655383 1671 while (*path && idx < PATH_MAX - 1) {
21864bc5
MD
1672 if (*path != '/') {
1673 buf[idx++] = *path;
1674 } else {
1675 buf[idx] = '\0';
1676 node = devfs_resolve_or_create_dir(node, buf, idx, create);
da655383
MD
1677 if (node == NULL) {
1678 kfree(buf, M_TEMP);
21864bc5 1679 return NULL;
da655383 1680 }
21864bc5
MD
1681 idx = 0;
1682 }
da655383 1683 ++path;
21864bc5
MD
1684 }
1685 buf[idx] = '\0';
da655383
MD
1686 node = devfs_resolve_or_create_dir(node, buf, idx, create);
1687 kfree (buf, M_TEMP);
1688 return (node);
21864bc5
MD
1689}
1690
1691/*
1692 * Takes a full path and strips it into a directory path and a name.
1693 * For a/b/c/foo, it returns foo in namep and a/b/c in pathp. It
1694 * requires a working buffer with enough size to keep the whole
1695 * fullpath.
1696 */
1697int
1698devfs_resolve_name_path(char *fullpath, char *buf, char **pathp, char **namep)
1699{
1700 char *name = NULL;
1701 char *path = NULL;
1702 size_t len = strlen(fullpath) + 1;
1703 int i;
1704
bc185c5a
AH
1705 KKASSERT((fullpath != NULL) && (buf != NULL));
1706 KKASSERT((pathp != NULL) && (namep != NULL));
21864bc5
MD
1707
1708 memcpy(buf, fullpath, len);
1709
1710 for (i = len-1; i>= 0; i--) {
1711 if (buf[i] == '/') {
1712 buf[i] = '\0';
1713 name = &(buf[i+1]);
1714 path = buf;
1715 break;
1716 }
1717 }
1718
1719 *pathp = path;
1720
1721 if (name) {
1722 *namep = name;
1723 } else {
1724 *namep = buf;
1725 }
1726
1727 return 0;
1728}
1729
1730/*
ca8d7677 1731 * This function creates a new devfs node for a given device. It can
21864bc5
MD
1732 * handle a complete path as device name, and accordingly creates
1733 * the path and the final device node.
ca8d7677
MD
1734 *
1735 * The reference count on the passed dev remains unchanged.
21864bc5
MD
1736 */
1737struct devfs_node *
ca8d7677
MD
1738devfs_create_device_node(struct devfs_node *root, cdev_t dev,
1739 char *dev_name, char *path_fmt, ...)
21864bc5
MD
1740{
1741 struct devfs_node *parent, *node = NULL;
1742 char *path = NULL;
da655383
MD
1743 char *name;
1744 char *name_buf;
21864bc5
MD
1745 __va_list ap;
1746 int i, found;
21864bc5
MD
1747 char *create_path = NULL;
1748 char *names = "pqrsPQRS";
1749
da655383 1750 name_buf = kmalloc(PATH_MAX, M_TEMP, M_WAITOK);
21864bc5 1751
da655383 1752 if (path_fmt != NULL) {
21864bc5 1753 __va_start(ap, path_fmt);
da655383 1754 kvasnrprintf(&path, PATH_MAX, 10, path_fmt, ap);
21864bc5
MD
1755 __va_end(ap);
1756 }
1757
1758 parent = devfs_resolve_or_create_path(root, path, 1);
1759 KKASSERT(parent);
1760
bc185c5a
AH
1761 devfs_resolve_name_path(
1762 ((dev_name == NULL) && (dev))?(dev->si_name):(dev_name),
1763 name_buf, &create_path, &name);
21864bc5
MD
1764
1765 if (create_path)
1766 parent = devfs_resolve_or_create_path(parent, create_path, 1);
1767
1768
1769 if (devfs_find_device_node_by_name(parent, name)) {
bc185c5a 1770 devfs_debug(DEVFS_DEBUG_WARNING, "devfs_create_device_node: "
894bbb25 1771 "DEVICE %s ALREADY EXISTS!!! Ignoring creation request.\n", name);
21864bc5
MD
1772 goto out;
1773 }
bc185c5a 1774
21864bc5 1775 node = devfs_allocp(Pdev, name, parent, parent->mp, dev);
07dfa375 1776 nanotime(&parent->mtime);
0182b316 1777
bc185c5a
AH
1778 /*
1779 * Ugly unix98 pty magic, to hide pty master (ptm) devices and their
1780 * directory
1781 */
1782 if ((dev) && (strlen(dev->si_name) >= 4) &&
1783 (!memcmp(dev->si_name, "ptm/", 4))) {
894bbb25
AH
1784 node->parent->flags |= DEVFS_HIDDEN;
1785 node->flags |= DEVFS_HIDDEN;
21864bc5 1786 }
bc185c5a
AH
1787
1788 /*
1789 * Ugly pty magic, to tag pty devices as such and hide them if needed.
1790 */
21864bc5
MD
1791 if ((strlen(name) >= 3) && (!memcmp(name, "pty", 3)))
1792 node->flags |= (DEVFS_PTY | DEVFS_INVISIBLE);
1793
21864bc5
MD
1794 if ((strlen(name) >= 3) && (!memcmp(name, "tty", 3))) {
1795 found = 0;
1796 for (i = 0; i < strlen(names); i++) {
1797 if (name[3] == names[i]) {
1798 found = 1;
1799 break;
1800 }
1801 }
1802 if (found)
1803 node->flags |= (DEVFS_PTY | DEVFS_INVISIBLE);
1804 }
21864bc5
MD
1805
1806out:
da655383
MD
1807 kfree(name_buf, M_TEMP);
1808 kvasfree(&path);
21864bc5
MD
1809 return node;
1810}
1811
1812/*
1813 * This function finds a given device node in the topology with a given
1814 * cdev.
1815 */
66abefa5
AH
1816void *
1817devfs_find_device_node_callback(struct devfs_node *node, cdev_t target)
21864bc5 1818{
66abefa5
AH
1819 if ((node->node_type == Pdev) && (node->d_dev == target)) {
1820 return node;
21864bc5 1821 }
21864bc5
MD
1822
1823 return NULL;
1824}
1825
1826/*
66abefa5 1827 * This function finds a device node in the given parent directory by its
21864bc5
MD
1828 * name and returns it.
1829 */
1830struct devfs_node *
1831devfs_find_device_node_by_name(struct devfs_node *parent, char *target)
1832{
1833 struct devfs_node *node, *found = NULL;
1834 size_t len = strlen(target);
1835
1836 TAILQ_FOREACH(node, DEVFS_DENODE_HEAD(parent), link) {
bc185c5a
AH
1837 if (len != node->d_dir.d_namlen)
1838 continue;
1839
1840 if (!memcmp(node->d_dir.d_name, target, len)) {
21864bc5
MD
1841 found = node;
1842 break;
1843 }
1844 }
1845
1846 return found;
1847}
1848
66abefa5
AH
1849static void *
1850devfs_inode_to_vnode_worker_callback(struct devfs_node *node, ino_t *inop)
fa7e6f37 1851{
66abefa5
AH
1852 struct vnode *vp = NULL;
1853 ino_t target = *inop;
bc185c5a 1854
fa7e6f37
AH
1855 if (node->d_dir.d_ino == target) {
1856 if (node->v_node) {
1857 vp = node->v_node;
1858 vget(vp, LK_EXCLUSIVE | LK_RETRY);
1859 vn_unlock(vp);
1860 } else {
1861 devfs_allocv(&vp, node);
1862 vn_unlock(vp);
1863 }
fa7e6f37
AH
1864 }
1865
66abefa5 1866 return vp;
fa7e6f37
AH
1867}
1868
21864bc5 1869/*
ca8d7677
MD
1870 * This function takes a cdev and removes its devfs node in the
1871 * given topology. The cdev remains intact.
21864bc5
MD
1872 */
1873int
1874devfs_destroy_device_node(struct devfs_node *root, cdev_t target)
1875{
1876 struct devfs_node *node, *parent;
da655383
MD
1877 char *name;
1878 char *name_buf;
21864bc5
MD
1879 char *create_path = NULL;
1880
1881 KKASSERT(target);
1882
da655383
MD
1883 name_buf = kmalloc(PATH_MAX, M_TEMP, M_WAITOK);
1884 ksnprintf(name_buf, PATH_MAX, "%s", target->si_name);
21864bc5
MD
1885
1886 devfs_resolve_name_path(target->si_name, name_buf, &create_path, &name);
21864bc5
MD
1887
1888 if (create_path)
1889 parent = devfs_resolve_or_create_path(root, create_path, 0);
1890 else
1891 parent = root;
bc185c5a 1892
21864bc5
MD
1893 if (parent == NULL)
1894 return 1;
bc185c5a 1895
21864bc5 1896 node = devfs_find_device_node_by_name(parent, name);
bc185c5a 1897
07dfa375
AH
1898 if (node) {
1899 nanotime(&node->parent->mtime);
21864bc5 1900 devfs_gc(node);
07dfa375 1901 }
da655383 1902 kfree(name_buf, M_TEMP);
21864bc5
MD
1903
1904 return 0;
1905}
1906
1907/*
1908 * Just set perms and ownership for given node.
1909 */
1910int
bc185c5a
AH
1911devfs_set_perms(struct devfs_node *node, uid_t uid, gid_t gid,
1912 u_short mode, u_long flags)
21864bc5 1913{
bc185c5a
AH
1914 node->mode = mode;
1915 node->uid = uid;
1916 node->gid = gid;
21864bc5
MD
1917
1918 return 0;
1919}
1920
1921/*
1922 * Propagates a device attach/detach to all mount
1923 * points. Also takes care of automatic alias removal
1924 * for a deleted cdev.
1925 */
1926static int
1927devfs_propagate_dev(cdev_t dev, int attach)
1928{
1929 struct devfs_mnt_data *mnt;
1930
21864bc5 1931 TAILQ_FOREACH(mnt, &devfs_mnt_list, link) {
21864bc5
MD
1932 if (attach) {
1933 /* Device is being attached */
ca8d7677
MD
1934 devfs_create_device_node(mnt->root_node, dev,
1935 NULL, NULL );
21864bc5
MD
1936 } else {
1937 /* Device is being detached */
21864bc5
MD
1938 devfs_alias_remove(dev);
1939 devfs_destroy_device_node(mnt->root_node, dev);
1940 }
1941 }
21864bc5
MD
1942 return 0;
1943}
1944
21864bc5
MD
1945/*
1946 * devfs_clone either returns a basename from a complete name by
1947 * returning the length of the name without trailing digits, or,
1948 * if clone != 0, calls the device's clone handler to get a new
1949 * device, which in turn is returned in devp.
1950 */
07dfa375
AH
1951cdev_t
1952devfs_clone(cdev_t dev, const char *name, size_t len, int mode,
bc185c5a 1953 struct ucred *cred)
21864bc5 1954{
07dfa375 1955 int error;
21864bc5
MD
1956 struct devfs_clone_handler *chandler;
1957 struct dev_clone_args ap;
1958
d0fe8596 1959 TAILQ_FOREACH(chandler, &devfs_chandler_list, link) {
07dfa375
AH
1960 if (chandler->namlen != len)
1961 continue;
1962 if ((!memcmp(chandler->name, name, len)) && (chandler->nhandler)) {
1963 lockmgr(&devfs_lock, LK_RELEASE);
1964 devfs_config();
1965 lockmgr(&devfs_lock, LK_EXCLUSIVE);
1966
1967 ap.a_head.a_dev = dev;
1968 ap.a_dev = NULL;
1969 ap.a_name = name;
1970 ap.a_namelen = len;
1971 ap.a_mode = mode;
1972 ap.a_cred = cred;
1973 error = (chandler->nhandler)(&ap);
1974 if (error)
1975 continue;
21864bc5 1976
07dfa375 1977 return ap.a_dev;
21864bc5
MD
1978 }
1979 }
1980
07dfa375 1981 return NULL;
21864bc5
MD
1982}
1983
1984
1985/*
1986 * Registers a new orphan in the orphan list.
1987 */
1988void
1989devfs_tracer_add_orphan(struct devfs_node *node)
1990{
1991 struct devfs_orphan *orphan;
1992
1993 KKASSERT(node);
1994 orphan = kmalloc(sizeof(struct devfs_orphan), M_DEVFS, M_WAITOK);
1995 orphan->node = node;
1996
ca8d7677
MD
1997 KKASSERT((node->flags & DEVFS_ORPHANED) == 0);
1998 node->flags |= DEVFS_ORPHANED;
21864bc5
MD
1999 TAILQ_INSERT_TAIL(DEVFS_ORPHANLIST(node->mp), orphan, link);
2000}
2001
2002/*
2003 * Removes an orphan from the orphan list.
2004 */
2005void
2006devfs_tracer_del_orphan(struct devfs_node *node)
2007{
2008 struct devfs_orphan *orphan;
2009
2010 KKASSERT(node);
2011
2012 TAILQ_FOREACH(orphan, DEVFS_ORPHANLIST(node->mp), link) {
2013 if (orphan->node == node) {
ca8d7677 2014 node->flags &= ~DEVFS_ORPHANED;
21864bc5
MD
2015 TAILQ_REMOVE(DEVFS_ORPHANLIST(node->mp), orphan, link);
2016 kfree(orphan, M_DEVFS);
2017 break;
2018 }
2019 }
2020}
2021
2022/*
2023 * Counts the orphans in the orphan list, and if cleanup
2024 * is specified, also frees the orphan and removes it from
2025 * the list.
2026 */
2027size_t
2028devfs_tracer_orphan_count(struct mount *mp, int cleanup)
2029{
2030 struct devfs_orphan *orphan, *orphan2;
2031 size_t count = 0;
2032
2033 TAILQ_FOREACH_MUTABLE(orphan, DEVFS_ORPHANLIST(mp), link, orphan2) {
2034 count++;
bc185c5a
AH
2035 /*
2036 * If we are instructed to clean up, we do so.
2037 */
21864bc5 2038 if (cleanup) {
21864bc5 2039 TAILQ_REMOVE(DEVFS_ORPHANLIST(mp), orphan, link);
ca8d7677
MD
2040 orphan->node->flags &= ~DEVFS_ORPHANED;
2041 devfs_freep(orphan->node);
21864bc5
MD
2042 kfree(orphan, M_DEVFS);
2043 }
2044 }
2045
2046 return count;
2047}
2048
2049/*
2050 * Fetch an ino_t from the global d_ino by increasing it
2051 * while spinlocked.
2052 */
2053static ino_t
2054devfs_fetch_ino(void)
2055{
2056 ino_t ret;
2057
2058 spin_lock_wr(&ino_lock);
2059 ret = d_ino++;
2060 spin_unlock_wr(&ino_lock);
2061
2062 return ret;
2063}
2064
2065/*
2066 * Allocates a new cdev and initializes it's most basic
2067 * fields.
2068 */
2069cdev_t
2070devfs_new_cdev(struct dev_ops *ops, int minor)
2071{
21864bc5 2072 cdev_t dev = sysref_alloc(&cdev_sysref_class);
da655383 2073
21864bc5
MD
2074 sysref_activate(&dev->si_sysref);
2075 reference_dev(dev);
da655383 2076 bzero(dev, offsetof(struct cdev, si_sysref));
21864bc5
MD
2077
2078 dev->si_uid = 0;
2079 dev->si_gid = 0;
2080 dev->si_perms = 0;
2081 dev->si_drv1 = NULL;
2082 dev->si_drv2 = NULL;
2083 dev->si_lastread = 0; /* time_second */
2084 dev->si_lastwrite = 0; /* time_second */
2085
2086 dev->si_ops = ops;
894bbb25 2087 dev->si_flags = 0;
21864bc5
MD
2088 dev->si_umajor = 0;
2089 dev->si_uminor = minor;
7cbab9da 2090 dev->si_inode = makeudev(devfs_reference_ops(ops), minor);
21864bc5
MD
2091
2092 return dev;
2093}
2094
ca8d7677
MD
2095static void
2096devfs_cdev_terminate(cdev_t dev)
21864bc5
MD
2097{
2098 int locked = 0;
2099
2100 /* Check if it is locked already. if not, we acquire the devfs lock */
2101 if (!(lockstatus(&devfs_lock, curthread)) == LK_EXCLUSIVE) {
2102 lockmgr(&devfs_lock, LK_EXCLUSIVE);
2103 locked = 1;
2104 }
2105
21864bc5
MD
2106 /* Propagate destruction, just in case */
2107 devfs_propagate_dev(dev, 0);
2108
2109 /* If we acquired the lock, we also get rid of it */
2110 if (locked)
2111 lockmgr(&devfs_lock, LK_RELEASE);
2112
7cbab9da
AH
2113 devfs_release_ops(dev->si_ops);
2114
21864bc5
MD
2115 /* Finally destroy the device */
2116 sysref_put(&dev->si_sysref);
2117}
2118
21864bc5
MD
2119/*
2120 * Links a given cdev into the dev list.
2121 */
2122int
2123devfs_link_dev(cdev_t dev)
2124{
ca8d7677 2125 KKASSERT((dev->si_flags & SI_DEVFS_LINKED) == 0);
21864bc5
MD
2126 dev->si_flags |= SI_DEVFS_LINKED;
2127 TAILQ_INSERT_TAIL(&devfs_dev_list, dev, link);
2128
2129 return 0;
2130}
2131
2132/*
ca8d7677
MD
2133 * Removes a given cdev from the dev list. The caller is responsible for
2134 * releasing the reference on the device associated with the linkage.
2135 *
2136 * Returns EALREADY if the dev has already been unlinked.
21864bc5 2137 */
ca8d7677 2138static int
21864bc5
MD
2139devfs_unlink_dev(cdev_t dev)
2140{
2141 if ((dev->si_flags & SI_DEVFS_LINKED)) {
2142 TAILQ_REMOVE(&devfs_dev_list, dev, link);
2143 dev->si_flags &= ~SI_DEVFS_LINKED;
ca8d7677 2144 return (0);
21864bc5 2145 }
ca8d7677 2146 return (EALREADY);
21864bc5
MD
2147}
2148
894bbb25
AH
2149int
2150devfs_node_is_accessible(struct devfs_node *node)
2151{
2152 if ((node) && (!(node->flags & DEVFS_HIDDEN)))
2153 return 1;
2154 else
2155 return 0;
2156}
2157
7cbab9da
AH
2158int
2159devfs_reference_ops(struct dev_ops *ops)
2160{
2161 int unit;
176de024
AH
2162 struct devfs_dev_ops *found = NULL;
2163 struct devfs_dev_ops *devops;
7cbab9da 2164
176de024
AH
2165 TAILQ_FOREACH(devops, &devfs_dev_ops_list, link) {
2166 if (devops->ops == ops) {
2167 found = devops;
2168 break;
2169 }
2170 }
2171
2172 if (!found) {
2173 found = kmalloc(sizeof(struct devfs_dev_ops), M_DEVFS, M_WAITOK);
2174 found->ops = ops;
2175 found->ref_count = 0;
2176 TAILQ_INSERT_TAIL(&devfs_dev_ops_list, found, link);
2177 }
2178
2179 KKASSERT(found);
2180
2181 if (found->ref_count == 0) {
2182 found->id = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(ops_id), 255);
2183 if (found->id == -1) {
7cbab9da 2184 /* Ran out of unique ids */
bc185c5a
AH
2185 devfs_debug(DEVFS_DEBUG_WARNING,
2186 "devfs_reference_ops: WARNING: ran out of unique ids\n");
7cbab9da
AH
2187 }
2188 }
176de024
AH
2189 unit = found->id;
2190 ++found->ref_count;
7cbab9da
AH
2191
2192 return unit;
2193}
2194
2195void
2196devfs_release_ops(struct dev_ops *ops)
2197{
176de024
AH
2198 struct devfs_dev_ops *found = NULL;
2199 struct devfs_dev_ops *devops;
2200
2201 TAILQ_FOREACH(devops, &devfs_dev_ops_list, link) {
2202 if (devops->ops == ops) {
2203 found = devops;
2204 break;
2205 }
2206 }
2207
2208 KKASSERT(found);
2209
2210 --found->ref_count;
7cbab9da 2211
176de024
AH
2212 if (found->ref_count == 0) {
2213 TAILQ_REMOVE(&devfs_dev_ops_list, found, link);
2214 devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(ops_id), found->id);
2215 kfree(found, M_DEVFS);
7cbab9da
AH
2216 }
2217}
2218
21864bc5 2219void
d0fe8596 2220devfs_config(void)
21864bc5
MD
2221{
2222 devfs_msg_t msg;
2223
2224 msg = devfs_msg_get();
21864bc5
MD
2225 msg = devfs_msg_send_sync(DEVFS_SYNC, msg);
2226 devfs_msg_put(msg);
2227}
2228
2229/*
2230 * Called on init of devfs; creates the objcaches and
2231 * spawns off the devfs core thread. Also initializes
2232 * locks.
2233 */
2234static void
2235devfs_init(void)
2236{
2237 devfs_debug(DEVFS_DEBUG_DEBUG, "devfs_init() called\n");
2238 /* Create objcaches for nodes, msgs and devs */
d0fe8596
MD
2239 devfs_node_cache = objcache_create("devfs-node-cache", 0, 0,
2240 NULL, NULL, NULL,
2241 objcache_malloc_alloc,
2242 objcache_malloc_free,
2243 &devfs_node_malloc_args );
2244
2245 devfs_msg_cache = objcache_create("devfs-msg-cache", 0, 0,
2246 NULL, NULL, NULL,
2247 objcache_malloc_alloc,
2248 objcache_malloc_free,
2249 &devfs_msg_malloc_args );
2250
2251 devfs_dev_cache = objcache_create("devfs-dev-cache", 0, 0,
2252 NULL, NULL, NULL,
2253 objcache_malloc_alloc,
2254 objcache_malloc_free,
2255 &devfs_dev_malloc_args );
21864bc5 2256
7cbab9da 2257 devfs_clone_bitmap_init(&DEVFS_CLONE_BITMAP(ops_id));
7cbab9da 2258
21864bc5
MD
2259 /* Initialize the reply-only port which acts as a message drain */
2260 lwkt_initport_replyonly(&devfs_dispose_port, devfs_msg_autofree_reply);
2261
2262 /* Initialize *THE* devfs lock */
2263 lockinit(&devfs_lock, "devfs_core lock", 0, 0);
2264
2265
2266 lwkt_create(devfs_msg_core, /*args*/NULL, &td_core, NULL,
2267 0, 0, "devfs_msg_core");
2268
2269 tsleep(td_core/*devfs_id*/, 0, "devfsc", 0);
2270
2271 devfs_debug(DEVFS_DEBUG_DEBUG, "devfs_init finished\n");
2272}
2273
2274/*
2275 * Called on unload of devfs; takes care of destroying the core
2276 * and the objcaches. Also removes aliases that are no longer needed.
2277 */
2278static void
2279devfs_uninit(void)
2280{
2281 devfs_debug(DEVFS_DEBUG_DEBUG, "devfs_uninit() called\n");
2282
2283 devfs_msg_send(DEVFS_TERMINATE_CORE, NULL);
2284
2285 tsleep(td_core/*devfs_id*/, 0, "devfsc", 0);
2286 tsleep(td_core/*devfs_id*/, 0, "devfsc", 10000);
2287
7cbab9da
AH
2288 devfs_clone_bitmap_uninit(&DEVFS_CLONE_BITMAP(ops_id));
2289
21864bc5
MD
2290 /* Destroy the objcaches */
2291 objcache_destroy(devfs_msg_cache);
2292 objcache_destroy(devfs_node_cache);
2293 objcache_destroy(devfs_dev_cache);
2294
2295 devfs_alias_reap();
2296}
2297
2298/*
2299 * This is a sysctl handler to assist userland devname(3) to
2300 * find the device name for a given udev.
2301 */
2302static int
2303devfs_sysctl_devname_helper(SYSCTL_HANDLER_ARGS)
2304{
2305 udev_t udev;
2306 cdev_t found;
2307 int error;
2308
2309
2310 if ((error = SYSCTL_IN(req, &udev, sizeof(udev_t))))
2311 return (error);
2312
2313 devfs_debug(DEVFS_DEBUG_DEBUG, "devfs sysctl, received udev: %d\n", udev);
2314
2315 if (udev == NOUDEV)
2316 return(EINVAL);
2317
2318 if ((found = devfs_find_device_by_udev(udev)) == NULL)
2319 return(ENOENT);
2320
2321 return(SYSCTL_OUT(req, found->si_name, strlen(found->si_name) + 1));
2322}
2323
2324
2325SYSCTL_PROC(_kern, OID_AUTO, devname, CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_ANYBODY,
2326 NULL, 0, devfs_sysctl_devname_helper, "", "helper for devname(3)");
2327
2328static SYSCTL_NODE(_vfs, OID_AUTO, devfs, CTLFLAG_RW, 0, "devfs");
2329TUNABLE_INT("vfs.devfs.debug", &devfs_debug_enable);
bc185c5a
AH
2330SYSCTL_INT(_vfs_devfs, OID_AUTO, debug, CTLFLAG_RW, &devfs_debug_enable,
2331 0, "Enable DevFS debugging");
21864bc5 2332
bc185c5a
AH
2333SYSINIT(vfs_devfs_register, SI_SUB_PRE_DRIVERS, SI_ORDER_FIRST,
2334 devfs_init, NULL);
2335SYSUNINIT(vfs_devfs_register, SI_SUB_PRE_DRIVERS, SI_ORDER_ANY,
2336 devfs_uninit, NULL);