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