1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * utility routines for the /dev fs 28 */ 29 30 #include <sys/types.h> 31 #include <sys/param.h> 32 #include <sys/t_lock.h> 33 #include <sys/systm.h> 34 #include <sys/sysmacros.h> 35 #include <sys/user.h> 36 #include <sys/time.h> 37 #include <sys/vfs.h> 38 #include <sys/vnode.h> 39 #include <sys/file.h> 40 #include <sys/fcntl.h> 41 #include <sys/flock.h> 42 #include <sys/kmem.h> 43 #include <sys/uio.h> 44 #include <sys/errno.h> 45 #include <sys/stat.h> 46 #include <sys/cred.h> 47 #include <sys/dirent.h> 48 #include <sys/pathname.h> 49 #include <sys/cmn_err.h> 50 #include <sys/debug.h> 51 #include <sys/mode.h> 52 #include <sys/policy.h> 53 #include <fs/fs_subr.h> 54 #include <sys/mount.h> 55 #include <sys/fs/snode.h> 56 #include <sys/fs/dv_node.h> 57 #include <sys/fs/sdev_impl.h> 58 #include <sys/fs/sdev_node.h> 59 #include <sys/sunndi.h> 60 #include <sys/sunmdi.h> 61 #include <sys/conf.h> 62 #include <sys/proc.h> 63 #include <sys/user.h> 64 #include <sys/modctl.h> 65 66 #ifdef DEBUG 67 int sdev_debug = 0x00000001; 68 int sdev_debug_cache_flags = 0; 69 #endif 70 71 /* 72 * globals 73 */ 74 /* prototype memory vattrs */ 75 vattr_t sdev_vattr_dir = { 76 AT_TYPE|AT_MODE|AT_UID|AT_GID, /* va_mask */ 77 VDIR, /* va_type */ 78 SDEV_DIRMODE_DEFAULT, /* va_mode */ 79 SDEV_UID_DEFAULT, /* va_uid */ 80 SDEV_GID_DEFAULT, /* va_gid */ 81 0, /* va_fsid */ 82 0, /* va_nodeid */ 83 0, /* va_nlink */ 84 0, /* va_size */ 85 0, /* va_atime */ 86 0, /* va_mtime */ 87 0, /* va_ctime */ 88 0, /* va_rdev */ 89 0, /* va_blksize */ 90 0, /* va_nblocks */ 91 0 /* va_vcode */ 92 }; 93 94 vattr_t sdev_vattr_lnk = { 95 AT_TYPE|AT_MODE, /* va_mask */ 96 VLNK, /* va_type */ 97 SDEV_LNKMODE_DEFAULT, /* va_mode */ 98 SDEV_UID_DEFAULT, /* va_uid */ 99 SDEV_GID_DEFAULT, /* va_gid */ 100 0, /* va_fsid */ 101 0, /* va_nodeid */ 102 0, /* va_nlink */ 103 0, /* va_size */ 104 0, /* va_atime */ 105 0, /* va_mtime */ 106 0, /* va_ctime */ 107 0, /* va_rdev */ 108 0, /* va_blksize */ 109 0, /* va_nblocks */ 110 0 /* va_vcode */ 111 }; 112 113 vattr_t sdev_vattr_blk = { 114 AT_TYPE|AT_MODE|AT_UID|AT_GID, /* va_mask */ 115 VBLK, /* va_type */ 116 S_IFBLK | SDEV_DEVMODE_DEFAULT, /* va_mode */ 117 SDEV_UID_DEFAULT, /* va_uid */ 118 SDEV_GID_DEFAULT, /* va_gid */ 119 0, /* va_fsid */ 120 0, /* va_nodeid */ 121 0, /* va_nlink */ 122 0, /* va_size */ 123 0, /* va_atime */ 124 0, /* va_mtime */ 125 0, /* va_ctime */ 126 0, /* va_rdev */ 127 0, /* va_blksize */ 128 0, /* va_nblocks */ 129 0 /* va_vcode */ 130 }; 131 132 vattr_t sdev_vattr_chr = { 133 AT_TYPE|AT_MODE|AT_UID|AT_GID, /* va_mask */ 134 VCHR, /* va_type */ 135 S_IFCHR | SDEV_DEVMODE_DEFAULT, /* va_mode */ 136 SDEV_UID_DEFAULT, /* va_uid */ 137 SDEV_GID_DEFAULT, /* va_gid */ 138 0, /* va_fsid */ 139 0, /* va_nodeid */ 140 0, /* va_nlink */ 141 0, /* va_size */ 142 0, /* va_atime */ 143 0, /* va_mtime */ 144 0, /* va_ctime */ 145 0, /* va_rdev */ 146 0, /* va_blksize */ 147 0, /* va_nblocks */ 148 0 /* va_vcode */ 149 }; 150 151 kmem_cache_t *sdev_node_cache; /* sdev_node cache */ 152 int devtype; /* fstype */ 153 154 struct devname_ops *devname_ns_ops; /* default name service directory ops */ 155 kmutex_t devname_nsmaps_lock; /* protect devname_nsmaps */ 156 157 /* static */ 158 static struct devname_nsmap *devname_nsmaps = NULL; 159 /* contents from /etc/dev/devname_master */ 160 static int devname_nsmaps_invalidated = 0; /* "devfsadm -m" has run */ 161 162 static struct vnodeops *sdev_get_vop(struct sdev_node *); 163 static void sdev_set_no_nocache(struct sdev_node *); 164 static int sdev_get_moduleops(struct sdev_node *); 165 static fs_operation_def_t *sdev_merge_vtab(const fs_operation_def_t []); 166 static void sdev_free_vtab(fs_operation_def_t *); 167 168 static void 169 sdev_prof_free(struct sdev_node *dv) 170 { 171 ASSERT(!SDEV_IS_GLOBAL(dv)); 172 if (dv->sdev_prof.dev_name) 173 nvlist_free(dv->sdev_prof.dev_name); 174 if (dv->sdev_prof.dev_map) 175 nvlist_free(dv->sdev_prof.dev_map); 176 if (dv->sdev_prof.dev_symlink) 177 nvlist_free(dv->sdev_prof.dev_symlink); 178 if (dv->sdev_prof.dev_glob_incdir) 179 nvlist_free(dv->sdev_prof.dev_glob_incdir); 180 if (dv->sdev_prof.dev_glob_excdir) 181 nvlist_free(dv->sdev_prof.dev_glob_excdir); 182 bzero(&dv->sdev_prof, sizeof (dv->sdev_prof)); 183 } 184 185 /* sdev_node cache constructor */ 186 /*ARGSUSED1*/ 187 static int 188 i_sdev_node_ctor(void *buf, void *cfarg, int flag) 189 { 190 struct sdev_node *dv = (struct sdev_node *)buf; 191 struct vnode *vp; 192 193 bzero(buf, sizeof (struct sdev_node)); 194 vp = dv->sdev_vnode = vn_alloc(flag); 195 if (vp == NULL) { 196 return (-1); 197 } 198 vp->v_data = dv; 199 rw_init(&dv->sdev_contents, NULL, RW_DEFAULT, NULL); 200 return (0); 201 } 202 203 /* sdev_node cache destructor */ 204 /*ARGSUSED1*/ 205 static void 206 i_sdev_node_dtor(void *buf, void *arg) 207 { 208 struct sdev_node *dv = (struct sdev_node *)buf; 209 struct vnode *vp = SDEVTOV(dv); 210 211 rw_destroy(&dv->sdev_contents); 212 vn_free(vp); 213 } 214 215 /* initialize sdev_node cache */ 216 void 217 sdev_node_cache_init() 218 { 219 int flags = 0; 220 221 #ifdef DEBUG 222 flags = sdev_debug_cache_flags; 223 if (flags) 224 sdcmn_err(("cache debug flags 0x%x\n", flags)); 225 #endif /* DEBUG */ 226 227 ASSERT(sdev_node_cache == NULL); 228 sdev_node_cache = kmem_cache_create("sdev_node_cache", 229 sizeof (struct sdev_node), 0, i_sdev_node_ctor, i_sdev_node_dtor, 230 NULL, NULL, NULL, flags); 231 } 232 233 /* destroy sdev_node cache */ 234 void 235 sdev_node_cache_fini() 236 { 237 ASSERT(sdev_node_cache != NULL); 238 kmem_cache_destroy(sdev_node_cache); 239 sdev_node_cache = NULL; 240 } 241 242 /* 243 * Compare two nodes lexographically to balance avl tree 244 */ 245 static int 246 sdev_compare_nodes(const struct sdev_node *dv1, const struct sdev_node *dv2) 247 { 248 int rv; 249 if ((rv = strcmp(dv1->sdev_name, dv2->sdev_name)) == 0) 250 return (0); 251 return ((rv < 0) ? -1 : 1); 252 } 253 254 void 255 sdev_set_nodestate(struct sdev_node *dv, sdev_node_state_t state) 256 { 257 ASSERT(dv); 258 ASSERT(RW_WRITE_HELD(&dv->sdev_contents)); 259 dv->sdev_state = state; 260 } 261 262 static void 263 sdev_attrinit(struct sdev_node *dv, vattr_t *vap) 264 { 265 timestruc_t now; 266 267 ASSERT(vap); 268 269 dv->sdev_attr = kmem_zalloc(sizeof (struct vattr), KM_SLEEP); 270 *dv->sdev_attr = *vap; 271 272 dv->sdev_attr->va_mode = MAKEIMODE(vap->va_type, vap->va_mode); 273 274 gethrestime(&now); 275 dv->sdev_attr->va_atime = now; 276 dv->sdev_attr->va_mtime = now; 277 dv->sdev_attr->va_ctime = now; 278 } 279 280 /* alloc and initialize a sdev_node */ 281 int 282 sdev_nodeinit(struct sdev_node *ddv, char *nm, struct sdev_node **newdv, 283 vattr_t *vap) 284 { 285 struct sdev_node *dv = NULL; 286 struct vnode *vp; 287 size_t nmlen, len; 288 devname_handle_t *dhl; 289 290 nmlen = strlen(nm) + 1; 291 if (nmlen > MAXNAMELEN) { 292 sdcmn_err9(("sdev_nodeinit: node name %s" 293 " too long\n", nm)); 294 *newdv = NULL; 295 return (ENAMETOOLONG); 296 } 297 298 dv = kmem_cache_alloc(sdev_node_cache, KM_SLEEP); 299 300 dv->sdev_name = kmem_alloc(nmlen, KM_SLEEP); 301 bcopy(nm, dv->sdev_name, nmlen); 302 dv->sdev_namelen = nmlen - 1; /* '\0' not included */ 303 len = strlen(ddv->sdev_path) + strlen(nm) + 2; 304 dv->sdev_path = kmem_alloc(len, KM_SLEEP); 305 (void) snprintf(dv->sdev_path, len, "%s/%s", ddv->sdev_path, nm); 306 /* overwritten for VLNK nodes */ 307 dv->sdev_symlink = NULL; 308 309 vp = SDEVTOV(dv); 310 vn_reinit(vp); 311 vp->v_vfsp = SDEVTOV(ddv)->v_vfsp; 312 if (vap) 313 vp->v_type = vap->va_type; 314 315 /* 316 * initialized to the parent's vnodeops. 317 * maybe overwriten for a VDIR 318 */ 319 vn_setops(vp, vn_getops(SDEVTOV(ddv))); 320 vn_exists(vp); 321 322 dv->sdev_dotdot = NULL; 323 dv->sdev_attrvp = NULL; 324 if (vap) { 325 sdev_attrinit(dv, vap); 326 } else { 327 dv->sdev_attr = NULL; 328 } 329 330 dv->sdev_ino = sdev_mkino(dv); 331 dv->sdev_nlink = 0; /* updated on insert */ 332 dv->sdev_flags = ddv->sdev_flags; /* inherit from the parent first */ 333 dv->sdev_flags |= SDEV_BUILD; 334 mutex_init(&dv->sdev_lookup_lock, NULL, MUTEX_DEFAULT, NULL); 335 cv_init(&dv->sdev_lookup_cv, NULL, CV_DEFAULT, NULL); 336 if (SDEV_IS_GLOBAL(ddv)) { 337 dv->sdev_flags |= SDEV_GLOBAL; 338 dv->sdev_mapinfo = NULL; 339 dhl = &(dv->sdev_handle); 340 dhl->dh_data = dv; 341 dhl->dh_spec = DEVNAME_NS_NONE; 342 dhl->dh_args = NULL; 343 sdev_set_no_nocache(dv); 344 dv->sdev_gdir_gen = 0; 345 } else { 346 dv->sdev_flags &= ~SDEV_GLOBAL; 347 dv->sdev_origin = NULL; /* set later */ 348 bzero(&dv->sdev_prof, sizeof (dv->sdev_prof)); 349 dv->sdev_ldir_gen = 0; 350 dv->sdev_devtree_gen = 0; 351 } 352 353 rw_enter(&dv->sdev_contents, RW_WRITER); 354 sdev_set_nodestate(dv, SDEV_INIT); 355 rw_exit(&dv->sdev_contents); 356 *newdv = dv; 357 358 return (0); 359 } 360 361 /* 362 * transition a sdev_node into SDEV_READY state 363 */ 364 int 365 sdev_nodeready(struct sdev_node *dv, struct vattr *vap, struct vnode *avp, 366 void *args, struct cred *cred) 367 { 368 int error = 0; 369 struct vnode *vp = SDEVTOV(dv); 370 vtype_t type; 371 372 ASSERT(dv && (dv->sdev_state != SDEV_READY) && vap); 373 374 type = vap->va_type; 375 vp->v_type = type; 376 vp->v_rdev = vap->va_rdev; 377 rw_enter(&dv->sdev_contents, RW_WRITER); 378 if (type == VDIR) { 379 dv->sdev_nlink = 2; 380 dv->sdev_flags &= ~SDEV_PERSIST; 381 dv->sdev_flags &= ~SDEV_DYNAMIC; 382 vn_setops(vp, sdev_get_vop(dv)); /* from internal vtab */ 383 error = sdev_get_moduleops(dv); /* from plug-in module */ 384 ASSERT(dv->sdev_dotdot); 385 ASSERT(SDEVTOV(dv->sdev_dotdot)->v_type == VDIR); 386 vp->v_rdev = SDEVTOV(dv->sdev_dotdot)->v_rdev; 387 avl_create(&dv->sdev_entries, 388 (int (*)(const void *, const void *))sdev_compare_nodes, 389 sizeof (struct sdev_node), 390 offsetof(struct sdev_node, sdev_avllink)); 391 } else if (type == VLNK) { 392 ASSERT(args); 393 dv->sdev_nlink = 1; 394 dv->sdev_symlink = i_ddi_strdup((char *)args, KM_SLEEP); 395 } else { 396 dv->sdev_nlink = 1; 397 } 398 399 if (!(SDEV_IS_GLOBAL(dv))) { 400 dv->sdev_origin = (struct sdev_node *)args; 401 dv->sdev_flags &= ~SDEV_PERSIST; 402 } 403 404 /* 405 * shadow node is created here OR 406 * if failed (indicated by dv->sdev_attrvp == NULL), 407 * created later in sdev_setattr 408 */ 409 if (avp) { 410 dv->sdev_attrvp = avp; 411 } else { 412 if (dv->sdev_attr == NULL) 413 sdev_attrinit(dv, vap); 414 else 415 *dv->sdev_attr = *vap; 416 417 if ((SDEV_IS_PERSIST(dv) && (dv->sdev_attrvp == NULL)) || 418 ((SDEVTOV(dv)->v_type == VDIR) && 419 (dv->sdev_attrvp == NULL))) { 420 error = sdev_shadow_node(dv, cred); 421 } 422 } 423 424 if (error == 0) { 425 /* transition to READY state */ 426 sdev_set_nodestate(dv, SDEV_READY); 427 sdev_nc_node_exists(dv); 428 } else { 429 sdev_set_nodestate(dv, SDEV_ZOMBIE); 430 } 431 rw_exit(&dv->sdev_contents); 432 return (error); 433 } 434 435 /* 436 * setting ZOMBIE state 437 */ 438 static int 439 sdev_nodezombied(struct sdev_node *dv) 440 { 441 rw_enter(&dv->sdev_contents, RW_WRITER); 442 sdev_set_nodestate(dv, SDEV_ZOMBIE); 443 rw_exit(&dv->sdev_contents); 444 return (0); 445 } 446 447 /* 448 * Build the VROOT sdev_node. 449 */ 450 /*ARGSUSED*/ 451 struct sdev_node * 452 sdev_mkroot(struct vfs *vfsp, dev_t devdev, struct vnode *mvp, 453 struct vnode *avp, struct cred *cred) 454 { 455 struct sdev_node *dv; 456 struct vnode *vp; 457 char devdir[] = "/dev"; 458 459 ASSERT(sdev_node_cache != NULL); 460 ASSERT(avp); 461 dv = kmem_cache_alloc(sdev_node_cache, KM_SLEEP); 462 vp = SDEVTOV(dv); 463 vn_reinit(vp); 464 vp->v_flag |= VROOT; 465 vp->v_vfsp = vfsp; 466 vp->v_type = VDIR; 467 vp->v_rdev = devdev; 468 vn_setops(vp, sdev_vnodeops); /* apply the default vnodeops at /dev */ 469 vn_exists(vp); 470 471 if (vfsp->vfs_mntpt) 472 dv->sdev_name = i_ddi_strdup( 473 (char *)refstr_value(vfsp->vfs_mntpt), KM_SLEEP); 474 else 475 /* vfs_mountdev1 set mount point later */ 476 dv->sdev_name = i_ddi_strdup("/dev", KM_SLEEP); 477 dv->sdev_namelen = strlen(dv->sdev_name); /* '\0' not included */ 478 dv->sdev_path = i_ddi_strdup(devdir, KM_SLEEP); 479 dv->sdev_ino = SDEV_ROOTINO; 480 dv->sdev_nlink = 2; /* name + . (no sdev_insert) */ 481 dv->sdev_dotdot = dv; /* .. == self */ 482 dv->sdev_attrvp = avp; 483 dv->sdev_attr = NULL; 484 mutex_init(&dv->sdev_lookup_lock, NULL, MUTEX_DEFAULT, NULL); 485 cv_init(&dv->sdev_lookup_cv, NULL, CV_DEFAULT, NULL); 486 if (strcmp(dv->sdev_name, "/dev") == 0) { 487 mutex_init(&devname_nsmaps_lock, NULL, MUTEX_DEFAULT, NULL); 488 dv->sdev_mapinfo = NULL; 489 dv->sdev_flags = SDEV_BUILD|SDEV_GLOBAL|SDEV_PERSIST; 490 bzero(&dv->sdev_handle, sizeof (dv->sdev_handle)); 491 dv->sdev_gdir_gen = 0; 492 } else { 493 dv->sdev_flags = SDEV_BUILD; 494 dv->sdev_flags &= ~SDEV_PERSIST; 495 bzero(&dv->sdev_prof, sizeof (dv->sdev_prof)); 496 dv->sdev_ldir_gen = 0; 497 dv->sdev_devtree_gen = 0; 498 } 499 500 avl_create(&dv->sdev_entries, 501 (int (*)(const void *, const void *))sdev_compare_nodes, 502 sizeof (struct sdev_node), 503 offsetof(struct sdev_node, sdev_avllink)); 504 505 rw_enter(&dv->sdev_contents, RW_WRITER); 506 sdev_set_nodestate(dv, SDEV_READY); 507 rw_exit(&dv->sdev_contents); 508 sdev_nc_node_exists(dv); 509 return (dv); 510 } 511 512 /* 513 * 1. load the module 514 * 2. modload invokes sdev_module_register, which in turn sets 515 * the dv->sdev_mapinfo->dir_ops 516 * 517 * note: locking order: 518 * dv->sdev_contents -> map->dir_lock 519 */ 520 static int 521 sdev_get_moduleops(struct sdev_node *dv) 522 { 523 int error = 0; 524 struct devname_nsmap *map = NULL; 525 char *module; 526 char *path; 527 int load = 1; 528 529 ASSERT(SDEVTOV(dv)->v_type == VDIR); 530 531 if (devname_nsmaps == NULL) 532 return (0); 533 534 if (!sdev_nsmaps_loaded() && !sdev_nsmaps_reloaded()) 535 return (0); 536 537 538 path = dv->sdev_path; 539 if ((map = sdev_get_nsmap_by_dir(path, 0))) { 540 rw_enter(&map->dir_lock, RW_READER); 541 if (map->dir_invalid) { 542 if (map->dir_module && map->dir_newmodule && 543 (strcmp(map->dir_module, 544 map->dir_newmodule) == 0)) { 545 load = 0; 546 } 547 sdev_replace_nsmap(map, map->dir_newmodule, 548 map->dir_newmap); 549 } 550 551 module = map->dir_module; 552 if (module && load) { 553 sdcmn_err6(("sdev_get_moduleops: " 554 "load module %s", module)); 555 rw_exit(&map->dir_lock); 556 error = modload("devname", module); 557 sdcmn_err6(("sdev_get_moduleops: error %d\n", error)); 558 if (error < 0) { 559 return (-1); 560 } 561 } else if (module == NULL) { 562 /* 563 * loading the module ops for name services 564 */ 565 if (devname_ns_ops == NULL) { 566 sdcmn_err6(( 567 "sdev_get_moduleops: modload default\n")); 568 error = modload("devname", DEVNAME_NSCONFIG); 569 sdcmn_err6(( 570 "sdev_get_moduleops: error %d\n", error)); 571 if (error < 0) { 572 return (-1); 573 } 574 } 575 576 if (!rw_tryupgrade(&map->dir_lock)) { 577 rw_exit(&map->dir_lock); 578 rw_enter(&map->dir_lock, RW_WRITER); 579 } 580 ASSERT(devname_ns_ops); 581 map->dir_ops = devname_ns_ops; 582 rw_exit(&map->dir_lock); 583 } 584 } 585 586 dv->sdev_mapinfo = map; 587 return (0); 588 } 589 590 /* directory dependent vop table */ 591 struct sdev_vop_table { 592 char *vt_name; /* subdirectory name */ 593 const fs_operation_def_t *vt_service; /* vnodeops table */ 594 struct vnodeops *vt_vops; /* constructed vop */ 595 struct vnodeops **vt_global_vops; /* global container for vop */ 596 int (*vt_vtor)(struct sdev_node *); /* validate sdev_node */ 597 int vt_flags; 598 }; 599 600 /* 601 * A nice improvement would be to provide a plug-in mechanism 602 * for this table instead of a const table. 603 */ 604 static struct sdev_vop_table vtab[] = 605 { 606 { "pts", devpts_vnodeops_tbl, NULL, &devpts_vnodeops, devpts_validate, 607 SDEV_DYNAMIC | SDEV_VTOR }, 608 609 { "vt", devvt_vnodeops_tbl, NULL, &devvt_vnodeops, devvt_validate, 610 SDEV_DYNAMIC | SDEV_VTOR }, 611 612 { "zcons", NULL, NULL, NULL, NULL, SDEV_NO_NCACHE }, 613 614 { "net", devnet_vnodeops_tbl, NULL, &devnet_vnodeops, devnet_validate, 615 SDEV_DYNAMIC | SDEV_VTOR }, 616 617 { "ipnet", devipnet_vnodeops_tbl, NULL, &devipnet_vnodeops, 618 devipnet_validate, SDEV_DYNAMIC | SDEV_VTOR | SDEV_NO_NCACHE }, 619 620 { NULL, NULL, NULL, NULL, NULL, 0} 621 }; 622 623 624 /* 625 * sets a directory's vnodeops if the directory is in the vtab; 626 */ 627 static struct vnodeops * 628 sdev_get_vop(struct sdev_node *dv) 629 { 630 int i; 631 char *path; 632 633 path = dv->sdev_path; 634 ASSERT(path); 635 636 /* gets the relative path to /dev/ */ 637 path += 5; 638 639 /* gets the vtab entry if matches */ 640 for (i = 0; vtab[i].vt_name; i++) { 641 if (strcmp(vtab[i].vt_name, path) != 0) 642 continue; 643 dv->sdev_flags |= vtab[i].vt_flags; 644 645 if (vtab[i].vt_vops) { 646 if (vtab[i].vt_global_vops) 647 *(vtab[i].vt_global_vops) = vtab[i].vt_vops; 648 return (vtab[i].vt_vops); 649 } 650 651 if (vtab[i].vt_service) { 652 fs_operation_def_t *templ; 653 templ = sdev_merge_vtab(vtab[i].vt_service); 654 if (vn_make_ops(vtab[i].vt_name, 655 (const fs_operation_def_t *)templ, 656 &vtab[i].vt_vops) != 0) { 657 cmn_err(CE_PANIC, "%s: malformed vnode ops\n", 658 vtab[i].vt_name); 659 /*NOTREACHED*/ 660 } 661 if (vtab[i].vt_global_vops) { 662 *(vtab[i].vt_global_vops) = vtab[i].vt_vops; 663 } 664 sdev_free_vtab(templ); 665 return (vtab[i].vt_vops); 666 } 667 return (sdev_vnodeops); 668 } 669 670 /* child inherits the persistence of the parent */ 671 if (SDEV_IS_PERSIST(dv->sdev_dotdot)) 672 dv->sdev_flags |= SDEV_PERSIST; 673 674 return (sdev_vnodeops); 675 } 676 677 static void 678 sdev_set_no_nocache(struct sdev_node *dv) 679 { 680 int i; 681 char *path; 682 683 ASSERT(dv->sdev_path); 684 path = dv->sdev_path + strlen("/dev/"); 685 686 for (i = 0; vtab[i].vt_name; i++) { 687 if (strcmp(vtab[i].vt_name, path) == 0) { 688 if (vtab[i].vt_flags & SDEV_NO_NCACHE) 689 dv->sdev_flags |= SDEV_NO_NCACHE; 690 break; 691 } 692 } 693 } 694 695 void * 696 sdev_get_vtor(struct sdev_node *dv) 697 { 698 int i; 699 700 for (i = 0; vtab[i].vt_name; i++) { 701 if (strcmp(vtab[i].vt_name, dv->sdev_name) != 0) 702 continue; 703 return ((void *)vtab[i].vt_vtor); 704 } 705 return (NULL); 706 } 707 708 /* 709 * Build the base root inode 710 */ 711 ino_t 712 sdev_mkino(struct sdev_node *dv) 713 { 714 ino_t ino; 715 716 /* 717 * for now, follow the lead of tmpfs here 718 * need to someday understand the requirements here 719 */ 720 ino = (ino_t)(uint32_t)((uintptr_t)dv >> 3); 721 ino += SDEV_ROOTINO + 1; 722 723 return (ino); 724 } 725 726 static int 727 sdev_getlink(struct vnode *linkvp, char **link) 728 { 729 int err; 730 char *buf; 731 struct uio uio = {0}; 732 struct iovec iov = {0}; 733 734 if (linkvp == NULL) 735 return (ENOENT); 736 ASSERT(linkvp->v_type == VLNK); 737 738 buf = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 739 iov.iov_base = buf; 740 iov.iov_len = MAXPATHLEN; 741 uio.uio_iov = &iov; 742 uio.uio_iovcnt = 1; 743 uio.uio_resid = MAXPATHLEN; 744 uio.uio_segflg = UIO_SYSSPACE; 745 uio.uio_llimit = MAXOFFSET_T; 746 747 err = VOP_READLINK(linkvp, &uio, kcred, NULL); 748 if (err) { 749 cmn_err(CE_WARN, "readlink %s failed in dev\n", buf); 750 kmem_free(buf, MAXPATHLEN); 751 return (ENOENT); 752 } 753 754 /* mission complete */ 755 *link = i_ddi_strdup(buf, KM_SLEEP); 756 kmem_free(buf, MAXPATHLEN); 757 return (0); 758 } 759 760 /* 761 * A convenient wrapper to get the devfs node vnode for a device 762 * minor functionality: readlink() of a /dev symlink 763 * Place the link into dv->sdev_symlink 764 */ 765 static int 766 sdev_follow_link(struct sdev_node *dv) 767 { 768 int err; 769 struct vnode *linkvp; 770 char *link = NULL; 771 772 linkvp = SDEVTOV(dv); 773 if (linkvp == NULL) 774 return (ENOENT); 775 ASSERT(linkvp->v_type == VLNK); 776 err = sdev_getlink(linkvp, &link); 777 if (err) { 778 (void) sdev_nodezombied(dv); 779 dv->sdev_symlink = NULL; 780 return (ENOENT); 781 } 782 783 ASSERT(link != NULL); 784 dv->sdev_symlink = link; 785 return (0); 786 } 787 788 static int 789 sdev_node_check(struct sdev_node *dv, struct vattr *nvap, void *nargs) 790 { 791 vtype_t otype = SDEVTOV(dv)->v_type; 792 793 /* 794 * existing sdev_node has a different type. 795 */ 796 if (otype != nvap->va_type) { 797 sdcmn_err9(("sdev_node_check: existing node " 798 " %s type %d does not match new node type %d\n", 799 dv->sdev_name, otype, nvap->va_type)); 800 return (EEXIST); 801 } 802 803 /* 804 * For a symlink, the target should be the same. 805 */ 806 if (otype == VLNK) { 807 ASSERT(nargs != NULL); 808 ASSERT(dv->sdev_symlink != NULL); 809 if (strcmp(dv->sdev_symlink, (char *)nargs) != 0) { 810 sdcmn_err9(("sdev_node_check: existing node " 811 " %s has different symlink %s as new node " 812 " %s\n", dv->sdev_name, dv->sdev_symlink, 813 (char *)nargs)); 814 return (EEXIST); 815 } 816 } 817 818 return (0); 819 } 820 821 /* 822 * sdev_mknode - a wrapper for sdev_nodeinit(), sdev_nodeready() 823 * 824 * arguments: 825 * - ddv (parent) 826 * - nm (child name) 827 * - newdv (sdev_node for nm is returned here) 828 * - vap (vattr for the node to be created, va_type should be set. 829 * - avp (attribute vnode) 830 * the defaults should be used if unknown) 831 * - cred 832 * - args 833 * . tnm (for VLNK) 834 * . global sdev_node (for !SDEV_GLOBAL) 835 * - state: SDEV_INIT, SDEV_READY 836 * 837 * only ddv, nm, newddv, vap, cred are required for sdev_mknode(SDEV_INIT) 838 * 839 * NOTE: directory contents writers lock needs to be held before 840 * calling this routine. 841 */ 842 int 843 sdev_mknode(struct sdev_node *ddv, char *nm, struct sdev_node **newdv, 844 struct vattr *vap, struct vnode *avp, void *args, struct cred *cred, 845 sdev_node_state_t state) 846 { 847 int error = 0; 848 sdev_node_state_t node_state; 849 struct sdev_node *dv = NULL; 850 851 ASSERT(state != SDEV_ZOMBIE); 852 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents)); 853 854 if (*newdv) { 855 dv = *newdv; 856 } else { 857 /* allocate and initialize a sdev_node */ 858 if (ddv->sdev_state == SDEV_ZOMBIE) { 859 sdcmn_err9(("sdev_mknode: parent %s ZOMBIEd\n", 860 ddv->sdev_path)); 861 return (ENOENT); 862 } 863 864 error = sdev_nodeinit(ddv, nm, &dv, vap); 865 if (error != 0) { 866 sdcmn_err9(("sdev_mknode: error %d," 867 " name %s can not be initialized\n", 868 error, nm)); 869 return (error); 870 } 871 ASSERT(dv); 872 873 /* insert into the directory cache */ 874 error = sdev_cache_update(ddv, &dv, nm, SDEV_CACHE_ADD); 875 if (error) { 876 sdcmn_err9(("sdev_mknode: node %s can not" 877 " be added into directory cache\n", nm)); 878 return (ENOENT); 879 } 880 } 881 882 ASSERT(dv); 883 node_state = dv->sdev_state; 884 ASSERT(node_state != SDEV_ZOMBIE); 885 886 if (state == SDEV_READY) { 887 switch (node_state) { 888 case SDEV_INIT: 889 error = sdev_nodeready(dv, vap, avp, args, cred); 890 if (error) { 891 sdcmn_err9(("sdev_mknode: node %s can NOT" 892 " be transitioned into READY state, " 893 "error %d\n", nm, error)); 894 } 895 break; 896 case SDEV_READY: 897 /* 898 * Do some sanity checking to make sure 899 * the existing sdev_node is what has been 900 * asked for. 901 */ 902 error = sdev_node_check(dv, vap, args); 903 break; 904 default: 905 break; 906 } 907 } 908 909 if (!error) { 910 *newdv = dv; 911 ASSERT((*newdv)->sdev_state != SDEV_ZOMBIE); 912 } else { 913 SDEV_SIMPLE_RELE(dv); 914 *newdv = NULL; 915 } 916 917 return (error); 918 } 919 920 /* 921 * convenient wrapper to change vp's ATIME, CTIME and MTIME 922 */ 923 void 924 sdev_update_timestamps(struct vnode *vp, cred_t *cred, uint_t mask) 925 { 926 struct vattr attr; 927 timestruc_t now; 928 int err; 929 930 ASSERT(vp); 931 gethrestime(&now); 932 if (mask & AT_CTIME) 933 attr.va_ctime = now; 934 if (mask & AT_MTIME) 935 attr.va_mtime = now; 936 if (mask & AT_ATIME) 937 attr.va_atime = now; 938 939 attr.va_mask = (mask & AT_TIMES); 940 err = VOP_SETATTR(vp, &attr, 0, cred, NULL); 941 if (err && (err != EROFS)) { 942 sdcmn_err(("update timestamps error %d\n", err)); 943 } 944 } 945 946 /* 947 * the backing store vnode is released here 948 */ 949 /*ARGSUSED1*/ 950 void 951 sdev_nodedestroy(struct sdev_node *dv, uint_t flags) 952 { 953 /* no references */ 954 ASSERT(dv->sdev_nlink == 0); 955 956 if (dv->sdev_attrvp != NULLVP) { 957 VN_RELE(dv->sdev_attrvp); 958 /* 959 * reset the attrvp so that no more 960 * references can be made on this already 961 * vn_rele() vnode 962 */ 963 dv->sdev_attrvp = NULLVP; 964 } 965 966 if (dv->sdev_attr != NULL) { 967 kmem_free(dv->sdev_attr, sizeof (struct vattr)); 968 dv->sdev_attr = NULL; 969 } 970 971 if (dv->sdev_name != NULL) { 972 kmem_free(dv->sdev_name, dv->sdev_namelen + 1); 973 dv->sdev_name = NULL; 974 } 975 976 if (dv->sdev_symlink != NULL) { 977 kmem_free(dv->sdev_symlink, strlen(dv->sdev_symlink) + 1); 978 dv->sdev_symlink = NULL; 979 } 980 981 if (dv->sdev_path) { 982 kmem_free(dv->sdev_path, strlen(dv->sdev_path) + 1); 983 dv->sdev_path = NULL; 984 } 985 986 if (!SDEV_IS_GLOBAL(dv)) 987 sdev_prof_free(dv); 988 989 if (SDEVTOV(dv)->v_type == VDIR) { 990 ASSERT(SDEV_FIRST_ENTRY(dv) == NULL); 991 avl_destroy(&dv->sdev_entries); 992 } 993 994 mutex_destroy(&dv->sdev_lookup_lock); 995 cv_destroy(&dv->sdev_lookup_cv); 996 997 /* return node to initial state as per constructor */ 998 (void) memset((void *)&dv->sdev_instance_data, 0, 999 sizeof (dv->sdev_instance_data)); 1000 vn_invalid(SDEVTOV(dv)); 1001 kmem_cache_free(sdev_node_cache, dv); 1002 } 1003 1004 /* 1005 * DIRECTORY CACHE lookup 1006 */ 1007 struct sdev_node * 1008 sdev_findbyname(struct sdev_node *ddv, char *nm) 1009 { 1010 struct sdev_node *dv; 1011 struct sdev_node dvtmp; 1012 avl_index_t where; 1013 1014 ASSERT(RW_LOCK_HELD(&ddv->sdev_contents)); 1015 1016 dvtmp.sdev_name = nm; 1017 dv = avl_find(&ddv->sdev_entries, &dvtmp, &where); 1018 if (dv) { 1019 ASSERT(dv->sdev_dotdot == ddv); 1020 ASSERT(strcmp(dv->sdev_name, nm) == 0); 1021 SDEV_HOLD(dv); 1022 return (dv); 1023 } 1024 return (NULL); 1025 } 1026 1027 /* 1028 * Inserts a new sdev_node in a parent directory 1029 */ 1030 void 1031 sdev_direnter(struct sdev_node *ddv, struct sdev_node *dv) 1032 { 1033 avl_index_t where; 1034 1035 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents)); 1036 ASSERT(SDEVTOV(ddv)->v_type == VDIR); 1037 ASSERT(ddv->sdev_nlink >= 2); 1038 ASSERT(dv->sdev_nlink == 0); 1039 1040 dv->sdev_dotdot = ddv; 1041 VERIFY(avl_find(&ddv->sdev_entries, dv, &where) == NULL); 1042 avl_insert(&ddv->sdev_entries, dv, where); 1043 ddv->sdev_nlink++; 1044 } 1045 1046 /* 1047 * The following check is needed because while sdev_nodes are linked 1048 * in SDEV_INIT state, they have their link counts incremented only 1049 * in SDEV_READY state. 1050 */ 1051 static void 1052 decr_link(struct sdev_node *dv) 1053 { 1054 if (dv->sdev_state != SDEV_INIT) 1055 dv->sdev_nlink--; 1056 else 1057 ASSERT(dv->sdev_nlink == 0); 1058 } 1059 1060 /* 1061 * Delete an existing dv from directory cache 1062 * 1063 * In the case of a node is still held by non-zero reference count, 1064 * the node is put into ZOMBIE state. Once the reference count 1065 * reaches "0", the node is unlinked and destroyed, 1066 * in sdev_inactive(). 1067 */ 1068 static int 1069 sdev_dirdelete(struct sdev_node *ddv, struct sdev_node *dv) 1070 { 1071 struct vnode *vp; 1072 1073 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents)); 1074 1075 vp = SDEVTOV(dv); 1076 mutex_enter(&vp->v_lock); 1077 1078 /* dv is held still */ 1079 if (vp->v_count > 1) { 1080 rw_enter(&dv->sdev_contents, RW_WRITER); 1081 if (dv->sdev_state == SDEV_READY) { 1082 sdcmn_err9(( 1083 "sdev_delete: node %s busy with count %d\n", 1084 dv->sdev_name, vp->v_count)); 1085 dv->sdev_state = SDEV_ZOMBIE; 1086 } 1087 rw_exit(&dv->sdev_contents); 1088 --vp->v_count; 1089 mutex_exit(&vp->v_lock); 1090 return (EBUSY); 1091 } 1092 ASSERT(vp->v_count == 1); 1093 1094 /* unlink from the memory cache */ 1095 ddv->sdev_nlink--; /* .. to above */ 1096 if (vp->v_type == VDIR) { 1097 decr_link(dv); /* . to self */ 1098 } 1099 1100 avl_remove(&ddv->sdev_entries, dv); 1101 decr_link(dv); /* name, back to zero */ 1102 vp->v_count--; 1103 mutex_exit(&vp->v_lock); 1104 1105 /* destroy the node */ 1106 sdev_nodedestroy(dv, 0); 1107 return (0); 1108 } 1109 1110 /* 1111 * check if the source is in the path of the target 1112 * 1113 * source and target are different 1114 */ 1115 /*ARGSUSED2*/ 1116 static int 1117 sdev_checkpath(struct sdev_node *sdv, struct sdev_node *tdv, struct cred *cred) 1118 { 1119 int error = 0; 1120 struct sdev_node *dotdot, *dir; 1121 1122 dotdot = tdv->sdev_dotdot; 1123 ASSERT(dotdot); 1124 1125 /* fs root */ 1126 if (dotdot == tdv) { 1127 return (0); 1128 } 1129 1130 for (;;) { 1131 /* 1132 * avoid error cases like 1133 * mv a a/b 1134 * mv a a/b/c 1135 * etc. 1136 */ 1137 if (dotdot == sdv) { 1138 error = EINVAL; 1139 break; 1140 } 1141 1142 dir = dotdot; 1143 dotdot = dir->sdev_dotdot; 1144 1145 /* done checking because root is reached */ 1146 if (dir == dotdot) { 1147 break; 1148 } 1149 } 1150 return (error); 1151 } 1152 1153 int 1154 sdev_rnmnode(struct sdev_node *oddv, struct sdev_node *odv, 1155 struct sdev_node *nddv, struct sdev_node **ndvp, char *nnm, 1156 struct cred *cred) 1157 { 1158 int error = 0; 1159 struct vnode *ovp = SDEVTOV(odv); 1160 struct vnode *nvp; 1161 struct vattr vattr; 1162 int doingdir = (ovp->v_type == VDIR); 1163 char *link = NULL; 1164 int samedir = (oddv == nddv) ? 1 : 0; 1165 int bkstore = 0; 1166 struct sdev_node *idv = NULL; 1167 struct sdev_node *ndv = NULL; 1168 timestruc_t now; 1169 1170 vattr.va_mask = AT_MODE|AT_UID|AT_GID; 1171 error = VOP_GETATTR(ovp, &vattr, 0, cred, NULL); 1172 if (error) 1173 return (error); 1174 1175 if (!samedir) 1176 rw_enter(&oddv->sdev_contents, RW_WRITER); 1177 rw_enter(&nddv->sdev_contents, RW_WRITER); 1178 1179 /* 1180 * the source may have been deleted by another thread before 1181 * we gets here. 1182 */ 1183 if (odv->sdev_state != SDEV_READY) { 1184 error = ENOENT; 1185 goto err_out; 1186 } 1187 1188 if (doingdir && (odv == nddv)) { 1189 error = EINVAL; 1190 goto err_out; 1191 } 1192 1193 /* 1194 * If renaming a directory, and the parents are different (".." must be 1195 * changed) then the source dir must not be in the dir hierarchy above 1196 * the target since it would orphan everything below the source dir. 1197 */ 1198 if (doingdir && (oddv != nddv)) { 1199 error = sdev_checkpath(odv, nddv, cred); 1200 if (error) 1201 goto err_out; 1202 } 1203 1204 /* destination existing */ 1205 if (*ndvp) { 1206 nvp = SDEVTOV(*ndvp); 1207 ASSERT(nvp); 1208 1209 /* handling renaming to itself */ 1210 if (odv == *ndvp) { 1211 error = 0; 1212 goto err_out; 1213 } 1214 1215 if (nvp->v_type == VDIR) { 1216 if (!doingdir) { 1217 error = EISDIR; 1218 goto err_out; 1219 } 1220 1221 if (vn_vfswlock(nvp)) { 1222 error = EBUSY; 1223 goto err_out; 1224 } 1225 1226 if (vn_mountedvfs(nvp) != NULL) { 1227 vn_vfsunlock(nvp); 1228 error = EBUSY; 1229 goto err_out; 1230 } 1231 1232 /* in case dir1 exists in dir2 and "mv dir1 dir2" */ 1233 if ((*ndvp)->sdev_nlink > 2) { 1234 vn_vfsunlock(nvp); 1235 error = EEXIST; 1236 goto err_out; 1237 } 1238 vn_vfsunlock(nvp); 1239 1240 (void) sdev_dirdelete(nddv, *ndvp); 1241 *ndvp = NULL; 1242 ASSERT(nddv->sdev_attrvp); 1243 error = VOP_RMDIR(nddv->sdev_attrvp, nnm, 1244 nddv->sdev_attrvp, cred, NULL, 0); 1245 if (error) 1246 goto err_out; 1247 } else { 1248 if (doingdir) { 1249 error = ENOTDIR; 1250 goto err_out; 1251 } 1252 1253 if (SDEV_IS_PERSIST((*ndvp))) { 1254 bkstore = 1; 1255 } 1256 1257 /* 1258 * get rid of the node from the directory cache 1259 * note, in case EBUSY is returned, the ZOMBIE 1260 * node is taken care in sdev_mknode. 1261 */ 1262 (void) sdev_dirdelete(nddv, *ndvp); 1263 *ndvp = NULL; 1264 if (bkstore) { 1265 ASSERT(nddv->sdev_attrvp); 1266 error = VOP_REMOVE(nddv->sdev_attrvp, 1267 nnm, cred, NULL, 0); 1268 if (error) 1269 goto err_out; 1270 } 1271 } 1272 } 1273 1274 /* fix the source for a symlink */ 1275 if (vattr.va_type == VLNK) { 1276 if (odv->sdev_symlink == NULL) { 1277 error = sdev_follow_link(odv); 1278 if (error) { 1279 error = ENOENT; 1280 goto err_out; 1281 } 1282 } 1283 ASSERT(odv->sdev_symlink); 1284 link = i_ddi_strdup(odv->sdev_symlink, KM_SLEEP); 1285 } 1286 1287 /* 1288 * make a fresh node from the source attrs 1289 */ 1290 ASSERT(RW_WRITE_HELD(&nddv->sdev_contents)); 1291 error = sdev_mknode(nddv, nnm, ndvp, &vattr, 1292 NULL, (void *)link, cred, SDEV_READY); 1293 1294 if (link) 1295 kmem_free(link, strlen(link) + 1); 1296 1297 if (error) 1298 goto err_out; 1299 ASSERT(*ndvp); 1300 ASSERT((*ndvp)->sdev_state == SDEV_READY); 1301 1302 /* move dir contents */ 1303 if (doingdir) { 1304 for (idv = SDEV_FIRST_ENTRY(odv); idv; 1305 idv = SDEV_NEXT_ENTRY(odv, idv)) { 1306 error = sdev_rnmnode(odv, idv, 1307 (struct sdev_node *)(*ndvp), &ndv, 1308 idv->sdev_name, cred); 1309 if (error) 1310 goto err_out; 1311 ndv = NULL; 1312 } 1313 } 1314 1315 if ((*ndvp)->sdev_attrvp) { 1316 sdev_update_timestamps((*ndvp)->sdev_attrvp, kcred, 1317 AT_CTIME|AT_ATIME); 1318 } else { 1319 ASSERT((*ndvp)->sdev_attr); 1320 gethrestime(&now); 1321 (*ndvp)->sdev_attr->va_ctime = now; 1322 (*ndvp)->sdev_attr->va_atime = now; 1323 } 1324 1325 if (nddv->sdev_attrvp) { 1326 sdev_update_timestamps(nddv->sdev_attrvp, kcred, 1327 AT_MTIME|AT_ATIME); 1328 } else { 1329 ASSERT(nddv->sdev_attr); 1330 gethrestime(&now); 1331 nddv->sdev_attr->va_mtime = now; 1332 nddv->sdev_attr->va_atime = now; 1333 } 1334 rw_exit(&nddv->sdev_contents); 1335 if (!samedir) 1336 rw_exit(&oddv->sdev_contents); 1337 1338 SDEV_RELE(*ndvp); 1339 return (error); 1340 1341 err_out: 1342 rw_exit(&nddv->sdev_contents); 1343 if (!samedir) 1344 rw_exit(&oddv->sdev_contents); 1345 return (error); 1346 } 1347 1348 /* 1349 * Merge sdev_node specific information into an attribute structure. 1350 * 1351 * note: sdev_node is not locked here 1352 */ 1353 void 1354 sdev_vattr_merge(struct sdev_node *dv, struct vattr *vap) 1355 { 1356 struct vnode *vp = SDEVTOV(dv); 1357 1358 vap->va_nlink = dv->sdev_nlink; 1359 vap->va_nodeid = dv->sdev_ino; 1360 vap->va_fsid = SDEVTOV(dv->sdev_dotdot)->v_rdev; 1361 vap->va_type = vp->v_type; 1362 1363 if (vp->v_type == VDIR) { 1364 vap->va_rdev = 0; 1365 vap->va_fsid = vp->v_rdev; 1366 } else if (vp->v_type == VLNK) { 1367 vap->va_rdev = 0; 1368 vap->va_mode &= ~S_IFMT; 1369 vap->va_mode |= S_IFLNK; 1370 } else if ((vp->v_type == VCHR) || (vp->v_type == VBLK)) { 1371 vap->va_rdev = vp->v_rdev; 1372 vap->va_mode &= ~S_IFMT; 1373 if (vap->va_type == VCHR) 1374 vap->va_mode |= S_IFCHR; 1375 else 1376 vap->va_mode |= S_IFBLK; 1377 } else { 1378 vap->va_rdev = 0; 1379 } 1380 } 1381 1382 static struct vattr * 1383 sdev_getdefault_attr(enum vtype type) 1384 { 1385 if (type == VDIR) 1386 return (&sdev_vattr_dir); 1387 else if (type == VCHR) 1388 return (&sdev_vattr_chr); 1389 else if (type == VBLK) 1390 return (&sdev_vattr_blk); 1391 else if (type == VLNK) 1392 return (&sdev_vattr_lnk); 1393 else 1394 return (NULL); 1395 } 1396 int 1397 sdev_to_vp(struct sdev_node *dv, struct vnode **vpp) 1398 { 1399 int rv = 0; 1400 struct vnode *vp = SDEVTOV(dv); 1401 1402 switch (vp->v_type) { 1403 case VCHR: 1404 case VBLK: 1405 /* 1406 * If vnode is a device, return special vnode instead 1407 * (though it knows all about -us- via sp->s_realvp) 1408 */ 1409 *vpp = specvp(vp, vp->v_rdev, vp->v_type, kcred); 1410 VN_RELE(vp); 1411 if (*vpp == NULLVP) 1412 rv = ENOSYS; 1413 break; 1414 default: /* most types are returned as is */ 1415 *vpp = vp; 1416 break; 1417 } 1418 return (rv); 1419 } 1420 1421 /* 1422 * loopback into sdev_lookup() 1423 */ 1424 static struct vnode * 1425 devname_find_by_devpath(char *devpath, struct vattr *vattr) 1426 { 1427 int error = 0; 1428 struct vnode *vp; 1429 1430 error = lookupname(devpath, UIO_SYSSPACE, NO_FOLLOW, NULLVPP, &vp); 1431 if (error) { 1432 return (NULL); 1433 } 1434 1435 if (vattr) 1436 (void) VOP_GETATTR(vp, vattr, 0, kcred, NULL); 1437 return (vp); 1438 } 1439 1440 /* 1441 * the junction between devname and devfs 1442 */ 1443 static struct vnode * 1444 devname_configure_by_path(char *physpath, struct vattr *vattr) 1445 { 1446 int error = 0; 1447 struct vnode *vp; 1448 1449 ASSERT(strncmp(physpath, "/devices/", sizeof ("/devices/") - 1) 1450 == 0); 1451 1452 error = devfs_lookupname(physpath + sizeof ("/devices/") - 1, 1453 NULLVPP, &vp); 1454 if (error != 0) { 1455 if (error == ENODEV) { 1456 cmn_err(CE_CONT, "%s: not found (line %d)\n", 1457 physpath, __LINE__); 1458 } 1459 1460 return (NULL); 1461 } 1462 1463 if (vattr) 1464 (void) VOP_GETATTR(vp, vattr, 0, kcred, NULL); 1465 return (vp); 1466 } 1467 1468 /* 1469 * junction between devname and root file system, e.g. ufs 1470 */ 1471 int 1472 devname_backstore_lookup(struct sdev_node *ddv, char *nm, struct vnode **rvp) 1473 { 1474 struct vnode *rdvp = ddv->sdev_attrvp; 1475 int rval = 0; 1476 1477 ASSERT(rdvp); 1478 1479 rval = VOP_LOOKUP(rdvp, nm, rvp, NULL, 0, NULL, kcred, NULL, NULL, 1480 NULL); 1481 return (rval); 1482 } 1483 1484 static int 1485 sdev_filldir_from_store(struct sdev_node *ddv, int dlen, struct cred *cred) 1486 { 1487 struct sdev_node *dv = NULL; 1488 char *nm; 1489 struct vnode *dirvp; 1490 int error; 1491 vnode_t *vp; 1492 int eof; 1493 struct iovec iov; 1494 struct uio uio; 1495 struct dirent64 *dp; 1496 dirent64_t *dbuf; 1497 size_t dbuflen; 1498 struct vattr vattr; 1499 char *link = NULL; 1500 1501 if (ddv->sdev_attrvp == NULL) 1502 return (0); 1503 if (!(ddv->sdev_flags & SDEV_BUILD)) 1504 return (0); 1505 1506 dirvp = ddv->sdev_attrvp; 1507 VN_HOLD(dirvp); 1508 dbuf = kmem_zalloc(dlen, KM_SLEEP); 1509 1510 uio.uio_iov = &iov; 1511 uio.uio_iovcnt = 1; 1512 uio.uio_segflg = UIO_SYSSPACE; 1513 uio.uio_fmode = 0; 1514 uio.uio_extflg = UIO_COPY_CACHED; 1515 uio.uio_loffset = 0; 1516 uio.uio_llimit = MAXOFFSET_T; 1517 1518 eof = 0; 1519 error = 0; 1520 while (!error && !eof) { 1521 uio.uio_resid = dlen; 1522 iov.iov_base = (char *)dbuf; 1523 iov.iov_len = dlen; 1524 (void) VOP_RWLOCK(dirvp, V_WRITELOCK_FALSE, NULL); 1525 error = VOP_READDIR(dirvp, &uio, kcred, &eof, NULL, 0); 1526 VOP_RWUNLOCK(dirvp, V_WRITELOCK_FALSE, NULL); 1527 1528 dbuflen = dlen - uio.uio_resid; 1529 if (error || dbuflen == 0) 1530 break; 1531 1532 if (!(ddv->sdev_flags & SDEV_BUILD)) { 1533 error = 0; 1534 break; 1535 } 1536 1537 for (dp = dbuf; ((intptr_t)dp < 1538 (intptr_t)dbuf + dbuflen); 1539 dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen)) { 1540 nm = dp->d_name; 1541 1542 if (strcmp(nm, ".") == 0 || 1543 strcmp(nm, "..") == 0) 1544 continue; 1545 1546 vp = NULLVP; 1547 dv = sdev_cache_lookup(ddv, nm); 1548 if (dv) { 1549 if (dv->sdev_state != SDEV_ZOMBIE) { 1550 SDEV_SIMPLE_RELE(dv); 1551 } else { 1552 /* 1553 * A ZOMBIE node may not have been 1554 * cleaned up from the backing store, 1555 * bypass this entry in this case, 1556 * and clean it up from the directory 1557 * cache if this is the last call. 1558 */ 1559 (void) sdev_dirdelete(ddv, dv); 1560 } 1561 continue; 1562 } 1563 1564 /* refill the cache if not already */ 1565 error = devname_backstore_lookup(ddv, nm, &vp); 1566 if (error) 1567 continue; 1568 1569 vattr.va_mask = AT_MODE|AT_UID|AT_GID; 1570 error = VOP_GETATTR(vp, &vattr, 0, cred, NULL); 1571 if (error) 1572 continue; 1573 1574 if (vattr.va_type == VLNK) { 1575 error = sdev_getlink(vp, &link); 1576 if (error) { 1577 continue; 1578 } 1579 ASSERT(link != NULL); 1580 } 1581 1582 if (!rw_tryupgrade(&ddv->sdev_contents)) { 1583 rw_exit(&ddv->sdev_contents); 1584 rw_enter(&ddv->sdev_contents, RW_WRITER); 1585 } 1586 error = sdev_mknode(ddv, nm, &dv, &vattr, vp, link, 1587 cred, SDEV_READY); 1588 rw_downgrade(&ddv->sdev_contents); 1589 1590 if (link != NULL) { 1591 kmem_free(link, strlen(link) + 1); 1592 link = NULL; 1593 } 1594 1595 if (!error) { 1596 ASSERT(dv); 1597 ASSERT(dv->sdev_state != SDEV_ZOMBIE); 1598 SDEV_SIMPLE_RELE(dv); 1599 } 1600 vp = NULL; 1601 dv = NULL; 1602 } 1603 } 1604 1605 done: 1606 VN_RELE(dirvp); 1607 kmem_free(dbuf, dlen); 1608 1609 return (error); 1610 } 1611 1612 void 1613 sdev_filldir_dynamic(struct sdev_node *ddv) 1614 { 1615 int error; 1616 int i; 1617 struct vattr *vap; 1618 char *nm = NULL; 1619 struct sdev_node *dv = NULL; 1620 1621 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents)); 1622 ASSERT((ddv->sdev_flags & SDEV_BUILD)); 1623 1624 vap = sdev_getdefault_attr(VDIR); 1625 for (i = 0; vtab[i].vt_name != NULL; i++) { 1626 nm = vtab[i].vt_name; 1627 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents)); 1628 dv = NULL; 1629 error = sdev_mknode(ddv, nm, &dv, vap, NULL, 1630 NULL, kcred, SDEV_READY); 1631 if (error) { 1632 cmn_err(CE_WARN, "%s/%s: error %d\n", 1633 ddv->sdev_name, nm, error); 1634 } else { 1635 ASSERT(dv); 1636 ASSERT(dv->sdev_state != SDEV_ZOMBIE); 1637 SDEV_SIMPLE_RELE(dv); 1638 } 1639 } 1640 } 1641 1642 /* 1643 * Creating a backing store entry based on sdev_attr. 1644 * This is called either as part of node creation in a persistent directory 1645 * or from setattr/setsecattr to persist access attributes across reboot. 1646 */ 1647 int 1648 sdev_shadow_node(struct sdev_node *dv, struct cred *cred) 1649 { 1650 int error = 0; 1651 struct vnode *dvp = SDEVTOV(dv->sdev_dotdot); 1652 struct vnode *rdvp = VTOSDEV(dvp)->sdev_attrvp; 1653 struct vattr *vap = dv->sdev_attr; 1654 char *nm = dv->sdev_name; 1655 struct vnode *tmpvp, **rvp = &tmpvp, *rrvp = NULL; 1656 1657 ASSERT(dv && dv->sdev_name && rdvp); 1658 ASSERT(RW_WRITE_HELD(&dv->sdev_contents) && dv->sdev_attrvp == NULL); 1659 1660 lookup: 1661 /* try to find it in the backing store */ 1662 error = VOP_LOOKUP(rdvp, nm, rvp, NULL, 0, NULL, cred, NULL, NULL, 1663 NULL); 1664 if (error == 0) { 1665 if (VOP_REALVP(*rvp, &rrvp, NULL) == 0) { 1666 VN_HOLD(rrvp); 1667 VN_RELE(*rvp); 1668 *rvp = rrvp; 1669 } 1670 1671 kmem_free(dv->sdev_attr, sizeof (vattr_t)); 1672 dv->sdev_attr = NULL; 1673 dv->sdev_attrvp = *rvp; 1674 return (0); 1675 } 1676 1677 /* let's try to persist the node */ 1678 gethrestime(&vap->va_atime); 1679 vap->va_mtime = vap->va_atime; 1680 vap->va_ctime = vap->va_atime; 1681 vap->va_mask |= AT_TYPE|AT_MODE; 1682 switch (vap->va_type) { 1683 case VDIR: 1684 error = VOP_MKDIR(rdvp, nm, vap, rvp, cred, NULL, 0, NULL); 1685 sdcmn_err9(("sdev_shadow_node: mkdir vp %p error %d\n", 1686 (void *)(*rvp), error)); 1687 break; 1688 case VCHR: 1689 case VBLK: 1690 case VREG: 1691 case VDOOR: 1692 error = VOP_CREATE(rdvp, nm, vap, NONEXCL, VREAD|VWRITE, 1693 rvp, cred, 0, NULL, NULL); 1694 sdcmn_err9(("sdev_shadow_node: create vp %p, error %d\n", 1695 (void *)(*rvp), error)); 1696 if (!error) 1697 VN_RELE(*rvp); 1698 break; 1699 case VLNK: 1700 ASSERT(dv->sdev_symlink); 1701 error = VOP_SYMLINK(rdvp, nm, vap, dv->sdev_symlink, cred, 1702 NULL, 0); 1703 sdcmn_err9(("sdev_shadow_node: create symlink error %d\n", 1704 error)); 1705 break; 1706 default: 1707 cmn_err(CE_PANIC, "dev: %s: sdev_shadow_node " 1708 "create\n", nm); 1709 /*NOTREACHED*/ 1710 } 1711 1712 /* go back to lookup to factor out spec node and set attrvp */ 1713 if (error == 0) 1714 goto lookup; 1715 1716 sdcmn_err(("cannot persist %s - error %d\n", dv->sdev_path, error)); 1717 return (error); 1718 } 1719 1720 static int 1721 sdev_cache_add(struct sdev_node *ddv, struct sdev_node **dv, char *nm) 1722 { 1723 int error = 0; 1724 struct sdev_node *dup = NULL; 1725 1726 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents)); 1727 if ((dup = sdev_findbyname(ddv, nm)) == NULL) { 1728 sdev_direnter(ddv, *dv); 1729 } else { 1730 if (dup->sdev_state == SDEV_ZOMBIE) { 1731 error = sdev_dirdelete(ddv, dup); 1732 /* 1733 * The ZOMBIE node is still hanging 1734 * around with more than one reference counts. 1735 * Fail the new node creation so that 1736 * the directory cache won't have 1737 * duplicate entries for the same named node 1738 */ 1739 if (error == EBUSY) { 1740 SDEV_SIMPLE_RELE(*dv); 1741 sdev_nodedestroy(*dv, 0); 1742 *dv = NULL; 1743 return (error); 1744 } 1745 sdev_direnter(ddv, *dv); 1746 } else { 1747 ASSERT((*dv)->sdev_state != SDEV_ZOMBIE); 1748 SDEV_SIMPLE_RELE(*dv); 1749 sdev_nodedestroy(*dv, 0); 1750 *dv = dup; 1751 } 1752 } 1753 1754 return (0); 1755 } 1756 1757 static int 1758 sdev_cache_delete(struct sdev_node *ddv, struct sdev_node **dv) 1759 { 1760 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents)); 1761 return (sdev_dirdelete(ddv, *dv)); 1762 } 1763 1764 /* 1765 * update the in-core directory cache 1766 */ 1767 int 1768 sdev_cache_update(struct sdev_node *ddv, struct sdev_node **dv, char *nm, 1769 sdev_cache_ops_t ops) 1770 { 1771 int error = 0; 1772 1773 ASSERT((SDEV_HELD(*dv))); 1774 1775 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents)); 1776 switch (ops) { 1777 case SDEV_CACHE_ADD: 1778 error = sdev_cache_add(ddv, dv, nm); 1779 break; 1780 case SDEV_CACHE_DELETE: 1781 error = sdev_cache_delete(ddv, dv); 1782 break; 1783 default: 1784 break; 1785 } 1786 1787 return (error); 1788 } 1789 1790 /* 1791 * retrieve the named entry from the directory cache 1792 */ 1793 struct sdev_node * 1794 sdev_cache_lookup(struct sdev_node *ddv, char *nm) 1795 { 1796 struct sdev_node *dv = NULL; 1797 1798 ASSERT(RW_LOCK_HELD(&ddv->sdev_contents)); 1799 dv = sdev_findbyname(ddv, nm); 1800 1801 return (dv); 1802 } 1803 1804 /* 1805 * Implicit reconfig for nodes constructed by a link generator 1806 * Start devfsadm if needed, or if devfsadm is in progress, 1807 * prepare to block on devfsadm either completing or 1808 * constructing the desired node. As devfsadmd is global 1809 * in scope, constructing all necessary nodes, we only 1810 * need to initiate it once. 1811 */ 1812 static int 1813 sdev_call_devfsadmd(struct sdev_node *ddv, struct sdev_node *dv, char *nm) 1814 { 1815 int error = 0; 1816 1817 if (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state)) { 1818 sdcmn_err6(("lookup: waiting for %s/%s, 0x%x\n", 1819 ddv->sdev_name, nm, devfsadm_state)); 1820 mutex_enter(&dv->sdev_lookup_lock); 1821 SDEV_BLOCK_OTHERS(dv, (SDEV_LOOKUP | SDEV_LGWAITING)); 1822 mutex_exit(&dv->sdev_lookup_lock); 1823 error = 0; 1824 } else if (!DEVNAME_DEVFSADM_HAS_RUN(devfsadm_state)) { 1825 sdcmn_err6(("lookup %s/%s starting devfsadm, 0x%x\n", 1826 ddv->sdev_name, nm, devfsadm_state)); 1827 1828 sdev_devfsadmd_thread(ddv, dv, kcred); 1829 mutex_enter(&dv->sdev_lookup_lock); 1830 SDEV_BLOCK_OTHERS(dv, 1831 (SDEV_LOOKUP | SDEV_LGWAITING)); 1832 mutex_exit(&dv->sdev_lookup_lock); 1833 error = 0; 1834 } else { 1835 error = -1; 1836 } 1837 1838 return (error); 1839 } 1840 1841 static int 1842 sdev_call_modulelookup(struct sdev_node *ddv, struct sdev_node **dvp, char *nm, 1843 int (*fn)(char *, devname_handle_t *, struct cred *), struct cred *cred) 1844 { 1845 struct vnode *rvp = NULL; 1846 int error = 0; 1847 struct vattr *vap; 1848 devname_spec_t spec; 1849 devname_handle_t *hdl; 1850 void *args = NULL; 1851 struct sdev_node *dv = *dvp; 1852 1853 ASSERT(dv && ddv); 1854 hdl = &(dv->sdev_handle); 1855 ASSERT(hdl->dh_data == dv); 1856 mutex_enter(&dv->sdev_lookup_lock); 1857 SDEV_BLOCK_OTHERS(dv, SDEV_LOOKUP); 1858 mutex_exit(&dv->sdev_lookup_lock); 1859 error = (*fn)(nm, hdl, cred); 1860 if (error) { 1861 return (error); 1862 } 1863 1864 spec = hdl->dh_spec; 1865 args = hdl->dh_args; 1866 ASSERT(args); 1867 1868 switch (spec) { 1869 case DEVNAME_NS_PATH: 1870 /* 1871 * symlink of: 1872 * /dev/dir/nm -> /device/... 1873 */ 1874 rvp = devname_configure_by_path((char *)args, NULL); 1875 break; 1876 case DEVNAME_NS_DEV: 1877 /* 1878 * symlink of: 1879 * /dev/dir/nm -> /dev/... 1880 */ 1881 rvp = devname_find_by_devpath((char *)args, NULL); 1882 break; 1883 default: 1884 if (args) 1885 kmem_free((char *)args, strlen(args) + 1); 1886 return (ENOENT); 1887 1888 } 1889 1890 if (rvp == NULL) { 1891 if (args) 1892 kmem_free((char *)args, strlen(args) + 1); 1893 return (ENOENT); 1894 } else { 1895 vap = sdev_getdefault_attr(VLNK); 1896 ASSERT(RW_READ_HELD(&ddv->sdev_contents)); 1897 /* 1898 * Could sdev_mknode return a different dv_node 1899 * once the lock is dropped? 1900 */ 1901 if (!rw_tryupgrade(&ddv->sdev_contents)) { 1902 rw_exit(&ddv->sdev_contents); 1903 rw_enter(&ddv->sdev_contents, RW_WRITER); 1904 } 1905 error = sdev_mknode(ddv, nm, &dv, vap, NULL, args, cred, 1906 SDEV_READY); 1907 rw_downgrade(&ddv->sdev_contents); 1908 if (error) { 1909 if (args) 1910 kmem_free((char *)args, strlen(args) + 1); 1911 return (error); 1912 } else { 1913 mutex_enter(&dv->sdev_lookup_lock); 1914 SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP); 1915 mutex_exit(&dv->sdev_lookup_lock); 1916 error = 0; 1917 } 1918 } 1919 1920 if (args) 1921 kmem_free((char *)args, strlen(args) + 1); 1922 1923 *dvp = dv; 1924 return (0); 1925 } 1926 1927 /* 1928 * Support for specialized device naming construction mechanisms 1929 */ 1930 static int 1931 sdev_call_dircallback(struct sdev_node *ddv, struct sdev_node **dvp, char *nm, 1932 int (*callback)(struct sdev_node *, char *, void **, struct cred *, 1933 void *, char *), int flags, struct cred *cred) 1934 { 1935 int rv = 0; 1936 char *physpath = NULL; 1937 struct vnode *rvp = NULL; 1938 struct vattr vattr; 1939 struct vattr *vap; 1940 struct sdev_node *dv = *dvp; 1941 1942 mutex_enter(&dv->sdev_lookup_lock); 1943 SDEV_BLOCK_OTHERS(dv, SDEV_LOOKUP); 1944 mutex_exit(&dv->sdev_lookup_lock); 1945 1946 /* for non-devfsadm devices */ 1947 if (flags & SDEV_PATH) { 1948 physpath = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 1949 rv = callback(ddv, nm, (void *)&physpath, kcred, NULL, 1950 NULL); 1951 if (rv) { 1952 kmem_free(physpath, MAXPATHLEN); 1953 return (-1); 1954 } 1955 1956 rvp = devname_configure_by_path(physpath, NULL); 1957 if (rvp == NULL) { 1958 sdcmn_err3(("devname_configure_by_path: " 1959 "failed for /dev/%s/%s\n", 1960 ddv->sdev_name, nm)); 1961 kmem_free(physpath, MAXPATHLEN); 1962 rv = -1; 1963 } else { 1964 vap = sdev_getdefault_attr(VLNK); 1965 ASSERT(RW_READ_HELD(&ddv->sdev_contents)); 1966 1967 /* 1968 * Sdev_mknode may return back a different sdev_node 1969 * that was created by another thread that 1970 * raced to the directroy cache before this thread. 1971 * 1972 * With current directory cache mechanism 1973 * (linked list with the sdev_node name as 1974 * the entity key), this is a way to make sure 1975 * only one entry exists for the same name 1976 * in the same directory. The outcome is 1977 * the winner wins. 1978 */ 1979 if (!rw_tryupgrade(&ddv->sdev_contents)) { 1980 rw_exit(&ddv->sdev_contents); 1981 rw_enter(&ddv->sdev_contents, RW_WRITER); 1982 } 1983 rv = sdev_mknode(ddv, nm, &dv, vap, NULL, 1984 (void *)physpath, cred, SDEV_READY); 1985 rw_downgrade(&ddv->sdev_contents); 1986 kmem_free(physpath, MAXPATHLEN); 1987 if (rv) { 1988 return (rv); 1989 } else { 1990 mutex_enter(&dv->sdev_lookup_lock); 1991 SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP); 1992 mutex_exit(&dv->sdev_lookup_lock); 1993 return (0); 1994 } 1995 } 1996 } else if (flags & SDEV_VLINK) { 1997 physpath = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 1998 rv = callback(ddv, nm, (void *)&physpath, kcred, NULL, 1999 NULL); 2000 if (rv) { 2001 kmem_free(physpath, MAXPATHLEN); 2002 return (-1); 2003 } 2004 2005 vap = sdev_getdefault_attr(VLNK); 2006 vap->va_size = strlen(physpath); 2007 ASSERT(RW_READ_HELD(&ddv->sdev_contents)); 2008 2009 if (!rw_tryupgrade(&ddv->sdev_contents)) { 2010 rw_exit(&ddv->sdev_contents); 2011 rw_enter(&ddv->sdev_contents, RW_WRITER); 2012 } 2013 rv = sdev_mknode(ddv, nm, &dv, vap, NULL, 2014 (void *)physpath, cred, SDEV_READY); 2015 rw_downgrade(&ddv->sdev_contents); 2016 kmem_free(physpath, MAXPATHLEN); 2017 if (rv) 2018 return (rv); 2019 2020 mutex_enter(&dv->sdev_lookup_lock); 2021 SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP); 2022 mutex_exit(&dv->sdev_lookup_lock); 2023 return (0); 2024 } else if (flags & SDEV_VNODE) { 2025 /* 2026 * DBNR has its own way to create the device 2027 * and return a backing store vnode in rvp 2028 */ 2029 ASSERT(callback); 2030 rv = callback(ddv, nm, (void *)&rvp, kcred, NULL, NULL); 2031 if (rv || (rvp == NULL)) { 2032 sdcmn_err3(("devname_lookup_func: SDEV_VNODE " 2033 "callback failed \n")); 2034 return (-1); 2035 } 2036 vap = sdev_getdefault_attr(rvp->v_type); 2037 if (vap == NULL) 2038 return (-1); 2039 2040 ASSERT(RW_READ_HELD(&ddv->sdev_contents)); 2041 if (!rw_tryupgrade(&ddv->sdev_contents)) { 2042 rw_exit(&ddv->sdev_contents); 2043 rw_enter(&ddv->sdev_contents, RW_WRITER); 2044 } 2045 rv = sdev_mknode(ddv, nm, &dv, vap, rvp, NULL, 2046 cred, SDEV_READY); 2047 rw_downgrade(&ddv->sdev_contents); 2048 if (rv) 2049 return (rv); 2050 2051 mutex_enter(&dv->sdev_lookup_lock); 2052 SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP); 2053 mutex_exit(&dv->sdev_lookup_lock); 2054 return (0); 2055 } else if (flags & SDEV_VATTR) { 2056 /* 2057 * /dev/pts 2058 * 2059 * DBNR has its own way to create the device 2060 * "0" is returned upon success. 2061 * 2062 * callback is responsible to set the basic attributes, 2063 * e.g. va_type/va_uid/va_gid/ 2064 * dev_t if VCHR or VBLK/ 2065 */ 2066 ASSERT(callback); 2067 rv = callback(ddv, nm, (void *)&vattr, kcred, NULL, NULL); 2068 if (rv) { 2069 sdcmn_err3(("devname_lookup_func: SDEV_NONE " 2070 "callback failed \n")); 2071 return (-1); 2072 } 2073 2074 ASSERT(RW_READ_HELD(&ddv->sdev_contents)); 2075 if (!rw_tryupgrade(&ddv->sdev_contents)) { 2076 rw_exit(&ddv->sdev_contents); 2077 rw_enter(&ddv->sdev_contents, RW_WRITER); 2078 } 2079 rv = sdev_mknode(ddv, nm, &dv, &vattr, NULL, NULL, 2080 cred, SDEV_READY); 2081 rw_downgrade(&ddv->sdev_contents); 2082 2083 if (rv) 2084 return (rv); 2085 2086 mutex_enter(&dv->sdev_lookup_lock); 2087 SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP); 2088 mutex_exit(&dv->sdev_lookup_lock); 2089 return (0); 2090 } else { 2091 impossible(("lookup: %s/%s by %s not supported (%d)\n", 2092 SDEVTOV(ddv)->v_path, nm, curproc->p_user.u_comm, 2093 __LINE__)); 2094 rv = -1; 2095 } 2096 2097 *dvp = dv; 2098 return (rv); 2099 } 2100 2101 static int 2102 is_devfsadm_thread(char *exec_name) 2103 { 2104 /* 2105 * note: because devfsadmd -> /usr/sbin/devfsadm 2106 * it is safe to use "devfsadm" to capture the lookups 2107 * from devfsadm and its daemon version. 2108 */ 2109 if (strcmp(exec_name, "devfsadm") == 0) 2110 return (1); 2111 return (0); 2112 } 2113 2114 2115 /* 2116 * Lookup Order: 2117 * sdev_node cache; 2118 * backing store (SDEV_PERSIST); 2119 * DBNR: a. dir_ops implemented in the loadable modules; 2120 * b. vnode ops in vtab. 2121 */ 2122 int 2123 devname_lookup_func(struct sdev_node *ddv, char *nm, struct vnode **vpp, 2124 struct cred *cred, int (*callback)(struct sdev_node *, char *, void **, 2125 struct cred *, void *, char *), int flags) 2126 { 2127 int rv = 0, nmlen; 2128 struct vnode *rvp = NULL; 2129 struct sdev_node *dv = NULL; 2130 int retried = 0; 2131 int error = 0; 2132 struct devname_nsmap *map = NULL; 2133 struct devname_ops *dirops = NULL; 2134 int (*fn)(char *, devname_handle_t *, struct cred *) = NULL; 2135 struct vattr vattr; 2136 char *lookup_thread = curproc->p_user.u_comm; 2137 int failed_flags = 0; 2138 int (*vtor)(struct sdev_node *) = NULL; 2139 int state; 2140 int parent_state; 2141 char *link = NULL; 2142 2143 if (SDEVTOV(ddv)->v_type != VDIR) 2144 return (ENOTDIR); 2145 2146 /* 2147 * Empty name or ., return node itself. 2148 */ 2149 nmlen = strlen(nm); 2150 if ((nmlen == 0) || ((nmlen == 1) && (nm[0] == '.'))) { 2151 *vpp = SDEVTOV(ddv); 2152 VN_HOLD(*vpp); 2153 return (0); 2154 } 2155 2156 /* 2157 * .., return the parent directory 2158 */ 2159 if ((nmlen == 2) && (strcmp(nm, "..") == 0)) { 2160 *vpp = SDEVTOV(ddv->sdev_dotdot); 2161 VN_HOLD(*vpp); 2162 return (0); 2163 } 2164 2165 rw_enter(&ddv->sdev_contents, RW_READER); 2166 if (ddv->sdev_flags & SDEV_VTOR) { 2167 vtor = (int (*)(struct sdev_node *))sdev_get_vtor(ddv); 2168 ASSERT(vtor); 2169 } 2170 2171 tryagain: 2172 /* 2173 * (a) directory cache lookup: 2174 */ 2175 ASSERT(RW_READ_HELD(&ddv->sdev_contents)); 2176 parent_state = ddv->sdev_state; 2177 dv = sdev_cache_lookup(ddv, nm); 2178 if (dv) { 2179 state = dv->sdev_state; 2180 switch (state) { 2181 case SDEV_INIT: 2182 if (is_devfsadm_thread(lookup_thread)) 2183 break; 2184 2185 /* ZOMBIED parent won't allow node creation */ 2186 if (parent_state == SDEV_ZOMBIE) { 2187 SD_TRACE_FAILED_LOOKUP(ddv, nm, 2188 retried); 2189 goto nolock_notfound; 2190 } 2191 2192 mutex_enter(&dv->sdev_lookup_lock); 2193 /* compensate the threads started after devfsadm */ 2194 if (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state) && 2195 !(SDEV_IS_LOOKUP(dv))) 2196 SDEV_BLOCK_OTHERS(dv, 2197 (SDEV_LOOKUP | SDEV_LGWAITING)); 2198 2199 if (SDEV_IS_LOOKUP(dv)) { 2200 failed_flags |= SLF_REBUILT; 2201 rw_exit(&ddv->sdev_contents); 2202 error = sdev_wait4lookup(dv, SDEV_LOOKUP); 2203 mutex_exit(&dv->sdev_lookup_lock); 2204 rw_enter(&ddv->sdev_contents, RW_READER); 2205 2206 if (error != 0) { 2207 SD_TRACE_FAILED_LOOKUP(ddv, nm, 2208 retried); 2209 goto nolock_notfound; 2210 } 2211 2212 state = dv->sdev_state; 2213 if (state == SDEV_INIT) { 2214 SD_TRACE_FAILED_LOOKUP(ddv, nm, 2215 retried); 2216 goto nolock_notfound; 2217 } else if (state == SDEV_READY) { 2218 goto found; 2219 } else if (state == SDEV_ZOMBIE) { 2220 rw_exit(&ddv->sdev_contents); 2221 SD_TRACE_FAILED_LOOKUP(ddv, nm, 2222 retried); 2223 SDEV_RELE(dv); 2224 goto lookup_failed; 2225 } 2226 } else { 2227 mutex_exit(&dv->sdev_lookup_lock); 2228 } 2229 break; 2230 case SDEV_READY: 2231 goto found; 2232 case SDEV_ZOMBIE: 2233 rw_exit(&ddv->sdev_contents); 2234 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2235 SDEV_RELE(dv); 2236 goto lookup_failed; 2237 default: 2238 rw_exit(&ddv->sdev_contents); 2239 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2240 sdev_lookup_failed(ddv, nm, failed_flags); 2241 *vpp = NULLVP; 2242 return (ENOENT); 2243 } 2244 } 2245 ASSERT(RW_READ_HELD(&ddv->sdev_contents)); 2246 2247 /* 2248 * ZOMBIED parent does not allow new node creation. 2249 * bail out early 2250 */ 2251 if (parent_state == SDEV_ZOMBIE) { 2252 rw_exit(&ddv->sdev_contents); 2253 *vpp = NULL; 2254 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2255 return (ENOENT); 2256 } 2257 2258 /* 2259 * (b0): backing store lookup 2260 * SDEV_PERSIST is default except: 2261 * 1) pts nodes 2262 * 2) non-chmod'ed local nodes 2263 */ 2264 if (SDEV_IS_PERSIST(ddv)) { 2265 error = devname_backstore_lookup(ddv, nm, &rvp); 2266 2267 if (!error) { 2268 sdcmn_err3(("devname_backstore_lookup: " 2269 "found attrvp %p for %s\n", (void *)rvp, nm)); 2270 2271 vattr.va_mask = AT_MODE|AT_UID|AT_GID; 2272 error = VOP_GETATTR(rvp, &vattr, 0, cred, NULL); 2273 if (error) { 2274 rw_exit(&ddv->sdev_contents); 2275 if (dv) 2276 SDEV_RELE(dv); 2277 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2278 sdev_lookup_failed(ddv, nm, failed_flags); 2279 *vpp = NULLVP; 2280 return (ENOENT); 2281 } 2282 2283 if (vattr.va_type == VLNK) { 2284 error = sdev_getlink(rvp, &link); 2285 if (error) { 2286 rw_exit(&ddv->sdev_contents); 2287 if (dv) 2288 SDEV_RELE(dv); 2289 SD_TRACE_FAILED_LOOKUP(ddv, nm, 2290 retried); 2291 sdev_lookup_failed(ddv, nm, 2292 failed_flags); 2293 *vpp = NULLVP; 2294 return (ENOENT); 2295 } 2296 ASSERT(link != NULL); 2297 } 2298 2299 if (!rw_tryupgrade(&ddv->sdev_contents)) { 2300 rw_exit(&ddv->sdev_contents); 2301 rw_enter(&ddv->sdev_contents, RW_WRITER); 2302 } 2303 error = sdev_mknode(ddv, nm, &dv, &vattr, 2304 rvp, link, cred, SDEV_READY); 2305 rw_downgrade(&ddv->sdev_contents); 2306 2307 if (link != NULL) { 2308 kmem_free(link, strlen(link) + 1); 2309 link = NULL; 2310 } 2311 2312 if (error) { 2313 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2314 rw_exit(&ddv->sdev_contents); 2315 if (dv) 2316 SDEV_RELE(dv); 2317 goto lookup_failed; 2318 } else { 2319 goto found; 2320 } 2321 } else if (retried) { 2322 rw_exit(&ddv->sdev_contents); 2323 sdcmn_err3(("retry of lookup of %s/%s: failed\n", 2324 ddv->sdev_name, nm)); 2325 if (dv) 2326 SDEV_RELE(dv); 2327 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2328 sdev_lookup_failed(ddv, nm, failed_flags); 2329 *vpp = NULLVP; 2330 return (ENOENT); 2331 } 2332 } 2333 2334 lookup_create_node: 2335 /* first thread that is doing the lookup on this node */ 2336 if (!dv) { 2337 if (!rw_tryupgrade(&ddv->sdev_contents)) { 2338 rw_exit(&ddv->sdev_contents); 2339 rw_enter(&ddv->sdev_contents, RW_WRITER); 2340 } 2341 error = sdev_mknode(ddv, nm, &dv, NULL, NULL, NULL, 2342 cred, SDEV_INIT); 2343 if (!dv) { 2344 rw_exit(&ddv->sdev_contents); 2345 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2346 sdev_lookup_failed(ddv, nm, failed_flags); 2347 *vpp = NULLVP; 2348 return (ENOENT); 2349 } 2350 rw_downgrade(&ddv->sdev_contents); 2351 } 2352 ASSERT(dv); 2353 ASSERT(SDEV_HELD(dv)); 2354 2355 if (SDEV_IS_NO_NCACHE(dv)) { 2356 failed_flags |= SLF_NO_NCACHE; 2357 } 2358 2359 if (SDEV_IS_GLOBAL(ddv)) { 2360 map = sdev_get_map(ddv, 1); 2361 dirops = map ? map->dir_ops : NULL; 2362 fn = dirops ? dirops->devnops_lookup : NULL; 2363 } 2364 2365 /* 2366 * (b1) invoking devfsadm once per life time for devfsadm nodes 2367 */ 2368 if ((fn == NULL) && !callback) { 2369 2370 if (sdev_reconfig_boot || !i_ddi_io_initialized() || 2371 SDEV_IS_DYNAMIC(ddv) || SDEV_IS_NO_NCACHE(dv) || 2372 ((moddebug & MODDEBUG_FINI_EBUSY) != 0)) { 2373 ASSERT(SDEV_HELD(dv)); 2374 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2375 goto nolock_notfound; 2376 } 2377 2378 /* 2379 * filter out known non-existent devices recorded 2380 * during initial reconfiguration boot for which 2381 * reconfig should not be done and lookup may 2382 * be short-circuited now. 2383 */ 2384 if (sdev_lookup_filter(ddv, nm)) { 2385 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2386 goto nolock_notfound; 2387 } 2388 2389 /* bypassing devfsadm internal nodes */ 2390 if (is_devfsadm_thread(lookup_thread)) { 2391 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2392 goto nolock_notfound; 2393 } 2394 2395 if (sdev_reconfig_disable) { 2396 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2397 goto nolock_notfound; 2398 } 2399 2400 error = sdev_call_devfsadmd(ddv, dv, nm); 2401 if (error == 0) { 2402 sdcmn_err8(("lookup of %s/%s by %s: reconfig\n", 2403 ddv->sdev_name, nm, curproc->p_user.u_comm)); 2404 if (sdev_reconfig_verbose) { 2405 cmn_err(CE_CONT, 2406 "?lookup of %s/%s by %s: reconfig\n", 2407 ddv->sdev_name, nm, curproc->p_user.u_comm); 2408 } 2409 retried = 1; 2410 failed_flags |= SLF_REBUILT; 2411 ASSERT(dv->sdev_state != SDEV_ZOMBIE); 2412 SDEV_SIMPLE_RELE(dv); 2413 goto tryagain; 2414 } else { 2415 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2416 goto nolock_notfound; 2417 } 2418 } 2419 2420 /* 2421 * (b2) Directory Based Name Resolution (DBNR): 2422 * ddv - parent 2423 * nm - /dev/(ddv->sdev_name)/nm 2424 * 2425 * note: module vnode ops take precedence than the build-in ones 2426 */ 2427 if (fn) { 2428 error = sdev_call_modulelookup(ddv, &dv, nm, fn, cred); 2429 if (error) { 2430 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2431 goto notfound; 2432 } else { 2433 goto found; 2434 } 2435 } else if (callback) { 2436 error = sdev_call_dircallback(ddv, &dv, nm, callback, 2437 flags, cred); 2438 if (error == 0) { 2439 goto found; 2440 } else { 2441 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2442 goto notfound; 2443 } 2444 } 2445 ASSERT(rvp); 2446 2447 found: 2448 ASSERT(!(dv->sdev_flags & SDEV_STALE)); 2449 ASSERT(dv->sdev_state == SDEV_READY); 2450 if (vtor) { 2451 /* 2452 * Check validity of returned node 2453 */ 2454 switch (vtor(dv)) { 2455 case SDEV_VTOR_VALID: 2456 break; 2457 case SDEV_VTOR_STALE: 2458 /* 2459 * The name exists, but the cache entry is 2460 * stale and needs to be re-created. 2461 */ 2462 ASSERT(RW_READ_HELD(&ddv->sdev_contents)); 2463 if (rw_tryupgrade(&ddv->sdev_contents) == 0) { 2464 rw_exit(&ddv->sdev_contents); 2465 rw_enter(&ddv->sdev_contents, RW_WRITER); 2466 } 2467 error = sdev_cache_update(ddv, &dv, nm, 2468 SDEV_CACHE_DELETE); 2469 rw_downgrade(&ddv->sdev_contents); 2470 if (error == 0) { 2471 dv = NULL; 2472 goto lookup_create_node; 2473 } 2474 /* FALLTHRU */ 2475 case SDEV_VTOR_INVALID: 2476 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2477 sdcmn_err7(("lookup: destroy invalid " 2478 "node: %s(%p)\n", dv->sdev_name, (void *)dv)); 2479 goto nolock_notfound; 2480 case SDEV_VTOR_SKIP: 2481 sdcmn_err7(("lookup: node not applicable - " 2482 "skipping: %s(%p)\n", dv->sdev_name, (void *)dv)); 2483 rw_exit(&ddv->sdev_contents); 2484 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried); 2485 SDEV_RELE(dv); 2486 goto lookup_failed; 2487 default: 2488 cmn_err(CE_PANIC, 2489 "dev fs: validator failed: %s(%p)\n", 2490 dv->sdev_name, (void *)dv); 2491 break; 2492 /*NOTREACHED*/ 2493 } 2494 } 2495 2496 if ((SDEVTOV(dv)->v_type == VDIR) && SDEV_IS_GLOBAL(dv)) { 2497 rw_enter(&dv->sdev_contents, RW_READER); 2498 (void) sdev_get_map(dv, 1); 2499 rw_exit(&dv->sdev_contents); 2500 } 2501 rw_exit(&ddv->sdev_contents); 2502 rv = sdev_to_vp(dv, vpp); 2503 sdcmn_err3(("devname_lookup_func: returning vp %p v_count %d state %d " 2504 "for nm %s, error %d\n", (void *)*vpp, (*vpp)->v_count, 2505 dv->sdev_state, nm, rv)); 2506 return (rv); 2507 2508 notfound: 2509 mutex_enter(&dv->sdev_lookup_lock); 2510 SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP); 2511 mutex_exit(&dv->sdev_lookup_lock); 2512 nolock_notfound: 2513 /* 2514 * Destroy the node that is created for synchronization purposes. 2515 */ 2516 sdcmn_err3(("devname_lookup_func: %s with state %d\n", 2517 nm, dv->sdev_state)); 2518 ASSERT(RW_READ_HELD(&ddv->sdev_contents)); 2519 if (dv->sdev_state == SDEV_INIT) { 2520 if (!rw_tryupgrade(&ddv->sdev_contents)) { 2521 rw_exit(&ddv->sdev_contents); 2522 rw_enter(&ddv->sdev_contents, RW_WRITER); 2523 } 2524 2525 /* 2526 * Node state may have changed during the lock 2527 * changes. Re-check. 2528 */ 2529 if (dv->sdev_state == SDEV_INIT) { 2530 (void) sdev_dirdelete(ddv, dv); 2531 rw_exit(&ddv->sdev_contents); 2532 sdev_lookup_failed(ddv, nm, failed_flags); 2533 *vpp = NULL; 2534 return (ENOENT); 2535 } 2536 } 2537 2538 rw_exit(&ddv->sdev_contents); 2539 SDEV_RELE(dv); 2540 2541 lookup_failed: 2542 sdev_lookup_failed(ddv, nm, failed_flags); 2543 *vpp = NULL; 2544 return (ENOENT); 2545 } 2546 2547 /* 2548 * Given a directory node, mark all nodes beneath as 2549 * STALE, i.e. nodes that don't exist as far as new 2550 * consumers are concerned. Remove them from the 2551 * list of directory entries so that no lookup or 2552 * directory traversal will find them. The node 2553 * not deallocated so existing holds are not affected. 2554 */ 2555 void 2556 sdev_stale(struct sdev_node *ddv) 2557 { 2558 struct sdev_node *dv; 2559 struct vnode *vp; 2560 2561 ASSERT(SDEVTOV(ddv)->v_type == VDIR); 2562 2563 rw_enter(&ddv->sdev_contents, RW_WRITER); 2564 for (dv = SDEV_FIRST_ENTRY(ddv); dv; dv = SDEV_NEXT_ENTRY(ddv, dv)) { 2565 vp = SDEVTOV(dv); 2566 if (vp->v_type == VDIR) 2567 sdev_stale(dv); 2568 2569 sdcmn_err9(("sdev_stale: setting stale %s\n", 2570 dv->sdev_path)); 2571 dv->sdev_flags |= SDEV_STALE; 2572 avl_remove(&ddv->sdev_entries, dv); 2573 } 2574 ddv->sdev_flags |= SDEV_BUILD; 2575 rw_exit(&ddv->sdev_contents); 2576 } 2577 2578 /* 2579 * Given a directory node, clean out all the nodes beneath. 2580 * If expr is specified, clean node with names matching expr. 2581 * If SDEV_ENFORCE is specified in flags, busy nodes are made stale, 2582 * so they are excluded from future lookups. 2583 */ 2584 int 2585 sdev_cleandir(struct sdev_node *ddv, char *expr, uint_t flags) 2586 { 2587 int error = 0; 2588 int busy = 0; 2589 struct vnode *vp; 2590 struct sdev_node *dv, *next = NULL; 2591 int bkstore = 0; 2592 int len = 0; 2593 char *bks_name = NULL; 2594 2595 ASSERT(SDEVTOV(ddv)->v_type == VDIR); 2596 2597 /* 2598 * We try our best to destroy all unused sdev_node's 2599 */ 2600 rw_enter(&ddv->sdev_contents, RW_WRITER); 2601 for (dv = SDEV_FIRST_ENTRY(ddv); dv; dv = next) { 2602 next = SDEV_NEXT_ENTRY(ddv, dv); 2603 vp = SDEVTOV(dv); 2604 2605 if (expr && gmatch(dv->sdev_name, expr) == 0) 2606 continue; 2607 2608 if (vp->v_type == VDIR && 2609 sdev_cleandir(dv, NULL, flags) != 0) { 2610 sdcmn_err9(("sdev_cleandir: dir %s busy\n", 2611 dv->sdev_name)); 2612 busy++; 2613 continue; 2614 } 2615 2616 if (vp->v_count > 0 && (flags & SDEV_ENFORCE) == 0) { 2617 sdcmn_err9(("sdev_cleandir: dir %s busy\n", 2618 dv->sdev_name)); 2619 busy++; 2620 continue; 2621 } 2622 2623 /* 2624 * at this point, either dv is not held or SDEV_ENFORCE 2625 * is specified. In either case, dv needs to be deleted 2626 */ 2627 SDEV_HOLD(dv); 2628 2629 bkstore = SDEV_IS_PERSIST(dv) ? 1 : 0; 2630 if (bkstore && (vp->v_type == VDIR)) 2631 bkstore += 1; 2632 2633 if (bkstore) { 2634 len = strlen(dv->sdev_name) + 1; 2635 bks_name = kmem_alloc(len, KM_SLEEP); 2636 bcopy(dv->sdev_name, bks_name, len); 2637 } 2638 2639 error = sdev_dirdelete(ddv, dv); 2640 2641 if (error == EBUSY) { 2642 sdcmn_err9(("sdev_cleandir: dir busy\n")); 2643 busy++; 2644 } 2645 2646 /* take care the backing store clean up */ 2647 if (bkstore && (error == 0)) { 2648 ASSERT(bks_name); 2649 ASSERT(ddv->sdev_attrvp); 2650 2651 if (bkstore == 1) { 2652 error = VOP_REMOVE(ddv->sdev_attrvp, 2653 bks_name, kcred, NULL, 0); 2654 } else if (bkstore == 2) { 2655 error = VOP_RMDIR(ddv->sdev_attrvp, 2656 bks_name, ddv->sdev_attrvp, kcred, NULL, 0); 2657 } 2658 2659 /* do not propagate the backing store errors */ 2660 if (error) { 2661 sdcmn_err9(("sdev_cleandir: backing store" 2662 "not cleaned\n")); 2663 error = 0; 2664 } 2665 2666 bkstore = 0; 2667 kmem_free(bks_name, len); 2668 bks_name = NULL; 2669 len = 0; 2670 } 2671 } 2672 2673 ddv->sdev_flags |= SDEV_BUILD; 2674 rw_exit(&ddv->sdev_contents); 2675 2676 if (busy) { 2677 error = EBUSY; 2678 } 2679 2680 return (error); 2681 } 2682 2683 /* 2684 * a convenient wrapper for readdir() funcs 2685 */ 2686 size_t 2687 add_dir_entry(dirent64_t *de, char *nm, size_t size, ino_t ino, offset_t off) 2688 { 2689 size_t reclen = DIRENT64_RECLEN(strlen(nm)); 2690 if (reclen > size) 2691 return (0); 2692 2693 de->d_ino = (ino64_t)ino; 2694 de->d_off = (off64_t)off + 1; 2695 de->d_reclen = (ushort_t)reclen; 2696 (void) strncpy(de->d_name, nm, DIRENT64_NAMELEN(reclen)); 2697 return (reclen); 2698 } 2699 2700 /* 2701 * sdev_mount service routines 2702 */ 2703 int 2704 sdev_copyin_mountargs(struct mounta *uap, struct sdev_mountargs *args) 2705 { 2706 int error; 2707 2708 if (uap->datalen != sizeof (*args)) 2709 return (EINVAL); 2710 2711 if (error = copyin(uap->dataptr, args, sizeof (*args))) { 2712 cmn_err(CE_WARN, "sdev_copyin_mountargs: can not" 2713 "get user data. error %d\n", error); 2714 return (EFAULT); 2715 } 2716 2717 return (0); 2718 } 2719 2720 #ifdef nextdp 2721 #undef nextdp 2722 #endif 2723 #define nextdp(dp) ((struct dirent64 *) \ 2724 (intptr_t)((char *)(dp) + (dp)->d_reclen)) 2725 2726 /* 2727 * readdir helper func 2728 */ 2729 int 2730 devname_readdir_func(vnode_t *vp, uio_t *uiop, cred_t *cred, int *eofp, 2731 int flags) 2732 { 2733 struct sdev_node *ddv = VTOSDEV(vp); 2734 struct sdev_node *dv; 2735 dirent64_t *dp; 2736 ulong_t outcount = 0; 2737 size_t namelen; 2738 ulong_t alloc_count; 2739 void *outbuf; 2740 struct iovec *iovp; 2741 int error = 0; 2742 size_t reclen; 2743 offset_t diroff; 2744 offset_t soff; 2745 int this_reclen; 2746 struct devname_nsmap *map = NULL; 2747 struct devname_ops *dirops = NULL; 2748 int (*fn)(devname_handle_t *, struct cred *) = NULL; 2749 int (*vtor)(struct sdev_node *) = NULL; 2750 struct vattr attr; 2751 timestruc_t now; 2752 2753 ASSERT(ddv->sdev_attr || ddv->sdev_attrvp); 2754 ASSERT(RW_READ_HELD(&ddv->sdev_contents)); 2755 2756 if (uiop->uio_loffset >= MAXOFF_T) { 2757 if (eofp) 2758 *eofp = 1; 2759 return (0); 2760 } 2761 2762 if (uiop->uio_iovcnt != 1) 2763 return (EINVAL); 2764 2765 if (vp->v_type != VDIR) 2766 return (ENOTDIR); 2767 2768 if (ddv->sdev_flags & SDEV_VTOR) { 2769 vtor = (int (*)(struct sdev_node *))sdev_get_vtor(ddv); 2770 ASSERT(vtor); 2771 } 2772 2773 if (eofp != NULL) 2774 *eofp = 0; 2775 2776 soff = uiop->uio_loffset; 2777 iovp = uiop->uio_iov; 2778 alloc_count = iovp->iov_len; 2779 dp = outbuf = kmem_alloc(alloc_count, KM_SLEEP); 2780 outcount = 0; 2781 2782 if (ddv->sdev_state == SDEV_ZOMBIE) 2783 goto get_cache; 2784 2785 if (SDEV_IS_GLOBAL(ddv)) { 2786 map = sdev_get_map(ddv, 0); 2787 dirops = map ? map->dir_ops : NULL; 2788 fn = dirops ? dirops->devnops_readdir : NULL; 2789 2790 if (map && map->dir_map) { 2791 /* 2792 * load the name mapping rule database 2793 * through invoking devfsadm and symlink 2794 * all the entries in the map 2795 */ 2796 devname_rdr_result_t rdr_result; 2797 int do_thread = 0; 2798 2799 rw_enter(&map->dir_lock, RW_READER); 2800 do_thread = map->dir_maploaded ? 0 : 1; 2801 rw_exit(&map->dir_lock); 2802 2803 if (do_thread) { 2804 mutex_enter(&ddv->sdev_lookup_lock); 2805 SDEV_BLOCK_OTHERS(ddv, SDEV_READDIR); 2806 mutex_exit(&ddv->sdev_lookup_lock); 2807 2808 sdev_dispatch_to_nsrdr_thread(ddv, 2809 map->dir_map, &rdr_result); 2810 } 2811 } else if ((sdev_boot_state == SDEV_BOOT_STATE_COMPLETE) && 2812 !sdev_reconfig_boot && (flags & SDEV_BROWSE) && 2813 !SDEV_IS_DYNAMIC(ddv) && !SDEV_IS_NO_NCACHE(ddv) && 2814 ((moddebug & MODDEBUG_FINI_EBUSY) == 0) && 2815 !DEVNAME_DEVFSADM_HAS_RUN(devfsadm_state) && 2816 !DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state) && 2817 !sdev_reconfig_disable) { 2818 /* 2819 * invoking "devfsadm" to do system device reconfig 2820 */ 2821 mutex_enter(&ddv->sdev_lookup_lock); 2822 SDEV_BLOCK_OTHERS(ddv, 2823 (SDEV_READDIR|SDEV_LGWAITING)); 2824 mutex_exit(&ddv->sdev_lookup_lock); 2825 2826 sdcmn_err8(("readdir of %s by %s: reconfig\n", 2827 ddv->sdev_path, curproc->p_user.u_comm)); 2828 if (sdev_reconfig_verbose) { 2829 cmn_err(CE_CONT, 2830 "?readdir of %s by %s: reconfig\n", 2831 ddv->sdev_path, curproc->p_user.u_comm); 2832 } 2833 2834 sdev_devfsadmd_thread(ddv, NULL, kcred); 2835 } else if (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state)) { 2836 /* 2837 * compensate the "ls" started later than "devfsadm" 2838 */ 2839 mutex_enter(&ddv->sdev_lookup_lock); 2840 SDEV_BLOCK_OTHERS(ddv, (SDEV_READDIR|SDEV_LGWAITING)); 2841 mutex_exit(&ddv->sdev_lookup_lock); 2842 } 2843 2844 /* 2845 * release the contents lock so that 2846 * the cache may be updated by devfsadmd 2847 */ 2848 rw_exit(&ddv->sdev_contents); 2849 mutex_enter(&ddv->sdev_lookup_lock); 2850 if (SDEV_IS_READDIR(ddv)) 2851 (void) sdev_wait4lookup(ddv, SDEV_READDIR); 2852 mutex_exit(&ddv->sdev_lookup_lock); 2853 rw_enter(&ddv->sdev_contents, RW_READER); 2854 2855 sdcmn_err4(("readdir of directory %s by %s\n", 2856 ddv->sdev_name, curproc->p_user.u_comm)); 2857 if (ddv->sdev_flags & SDEV_BUILD) { 2858 if (SDEV_IS_PERSIST(ddv)) { 2859 error = sdev_filldir_from_store(ddv, 2860 alloc_count, cred); 2861 } 2862 ddv->sdev_flags &= ~SDEV_BUILD; 2863 } 2864 } 2865 2866 get_cache: 2867 /* handle "." and ".." */ 2868 diroff = 0; 2869 if (soff == 0) { 2870 /* first time */ 2871 this_reclen = DIRENT64_RECLEN(1); 2872 if (alloc_count < this_reclen) { 2873 error = EINVAL; 2874 goto done; 2875 } 2876 2877 dp->d_ino = (ino64_t)ddv->sdev_ino; 2878 dp->d_off = (off64_t)1; 2879 dp->d_reclen = (ushort_t)this_reclen; 2880 2881 (void) strncpy(dp->d_name, ".", 2882 DIRENT64_NAMELEN(this_reclen)); 2883 outcount += dp->d_reclen; 2884 dp = nextdp(dp); 2885 } 2886 2887 diroff++; 2888 if (soff <= 1) { 2889 this_reclen = DIRENT64_RECLEN(2); 2890 if (alloc_count < outcount + this_reclen) { 2891 error = EINVAL; 2892 goto done; 2893 } 2894 2895 dp->d_reclen = (ushort_t)this_reclen; 2896 dp->d_ino = (ino64_t)ddv->sdev_dotdot->sdev_ino; 2897 dp->d_off = (off64_t)2; 2898 2899 (void) strncpy(dp->d_name, "..", 2900 DIRENT64_NAMELEN(this_reclen)); 2901 outcount += dp->d_reclen; 2902 2903 dp = nextdp(dp); 2904 } 2905 2906 2907 /* gets the cache */ 2908 diroff++; 2909 for (dv = SDEV_FIRST_ENTRY(ddv); dv; 2910 dv = SDEV_NEXT_ENTRY(ddv, dv), diroff++) { 2911 sdcmn_err3(("sdev_readdir: diroff %lld soff %lld for '%s' \n", 2912 diroff, soff, dv->sdev_name)); 2913 2914 /* bypassing pre-matured nodes */ 2915 if (diroff < soff || (dv->sdev_state != SDEV_READY)) { 2916 sdcmn_err3(("sdev_readdir: pre-mature node " 2917 "%s\n", dv->sdev_name)); 2918 continue; 2919 } 2920 2921 /* 2922 * Check validity of node 2923 */ 2924 if (vtor) { 2925 switch (vtor(dv)) { 2926 case SDEV_VTOR_VALID: 2927 break; 2928 case SDEV_VTOR_INVALID: 2929 case SDEV_VTOR_SKIP: 2930 continue; 2931 default: 2932 cmn_err(CE_PANIC, 2933 "dev fs: validator failed: %s(%p)\n", 2934 dv->sdev_name, (void *)dv); 2935 break; 2936 /*NOTREACHED*/ 2937 } 2938 } 2939 2940 /* 2941 * call back into the module for the validity/bookkeeping 2942 * of this entry 2943 */ 2944 if (fn) { 2945 error = (*fn)(&(dv->sdev_handle), cred); 2946 if (error) { 2947 sdcmn_err4(("sdev_readdir: module did not " 2948 "validate %s\n", dv->sdev_name)); 2949 continue; 2950 } 2951 } 2952 2953 namelen = strlen(dv->sdev_name); 2954 reclen = DIRENT64_RECLEN(namelen); 2955 if (outcount + reclen > alloc_count) { 2956 goto full; 2957 } 2958 dp->d_reclen = (ushort_t)reclen; 2959 dp->d_ino = (ino64_t)dv->sdev_ino; 2960 dp->d_off = (off64_t)diroff + 1; 2961 (void) strncpy(dp->d_name, dv->sdev_name, 2962 DIRENT64_NAMELEN(reclen)); 2963 outcount += reclen; 2964 dp = nextdp(dp); 2965 } 2966 2967 full: 2968 sdcmn_err4(("sdev_readdir: moving %lu bytes: " 2969 "diroff %lld, soff %lld, dv %p\n", outcount, diroff, soff, 2970 (void *)dv)); 2971 2972 if (outcount) 2973 error = uiomove(outbuf, outcount, UIO_READ, uiop); 2974 2975 if (!error) { 2976 uiop->uio_loffset = diroff; 2977 if (eofp) 2978 *eofp = dv ? 0 : 1; 2979 } 2980 2981 2982 if (ddv->sdev_attrvp) { 2983 gethrestime(&now); 2984 attr.va_ctime = now; 2985 attr.va_atime = now; 2986 attr.va_mask = AT_CTIME|AT_ATIME; 2987 2988 (void) VOP_SETATTR(ddv->sdev_attrvp, &attr, 0, kcred, NULL); 2989 } 2990 done: 2991 kmem_free(outbuf, alloc_count); 2992 return (error); 2993 } 2994 2995 static int 2996 sdev_modctl_lookup(const char *path, vnode_t **r_vp) 2997 { 2998 vnode_t *vp; 2999 vnode_t *cvp; 3000 struct sdev_node *svp; 3001 char *nm; 3002 struct pathname pn; 3003 int error; 3004 int persisted = 0; 3005 3006 ASSERT(INGLOBALZONE(curproc)); 3007 3008 if (error = pn_get((char *)path, UIO_SYSSPACE, &pn)) 3009 return (error); 3010 nm = kmem_alloc(MAXNAMELEN, KM_SLEEP); 3011 3012 vp = rootdir; 3013 VN_HOLD(vp); 3014 3015 while (pn_pathleft(&pn)) { 3016 ASSERT(vp->v_type == VDIR || vp->v_type == VLNK); 3017 (void) pn_getcomponent(&pn, nm); 3018 3019 /* 3020 * Deal with the .. special case where we may be 3021 * traversing up across a mount point, to the 3022 * root of this filesystem or global root. 3023 */ 3024 if (nm[0] == '.' && nm[1] == '.' && nm[2] == 0) { 3025 checkforroot: 3026 if (VN_CMP(vp, rootdir)) { 3027 nm[1] = 0; 3028 } else if (vp->v_flag & VROOT) { 3029 vfs_t *vfsp; 3030 cvp = vp; 3031 vfsp = cvp->v_vfsp; 3032 vfs_rlock_wait(vfsp); 3033 vp = cvp->v_vfsp->vfs_vnodecovered; 3034 if (vp == NULL || 3035 (cvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)) { 3036 vfs_unlock(vfsp); 3037 VN_RELE(cvp); 3038 error = EIO; 3039 break; 3040 } 3041 VN_HOLD(vp); 3042 vfs_unlock(vfsp); 3043 VN_RELE(cvp); 3044 cvp = NULL; 3045 goto checkforroot; 3046 } 3047 } 3048 3049 error = VOP_LOOKUP(vp, nm, &cvp, NULL, 0, NULL, kcred, NULL, 3050 NULL, NULL); 3051 if (error) { 3052 VN_RELE(vp); 3053 break; 3054 } 3055 3056 /* traverse mount points encountered on our journey */ 3057 if (vn_ismntpt(cvp) && (error = traverse(&cvp)) != 0) { 3058 VN_RELE(vp); 3059 VN_RELE(cvp); 3060 break; 3061 } 3062 3063 /* 3064 * symbolic link, can be either relative and absolute 3065 */ 3066 if ((cvp->v_type == VLNK) && pn_pathleft(&pn)) { 3067 struct pathname linkpath; 3068 pn_alloc(&linkpath); 3069 if (error = pn_getsymlink(cvp, &linkpath, kcred)) { 3070 pn_free(&linkpath); 3071 break; 3072 } 3073 if (pn_pathleft(&linkpath) == 0) 3074 (void) pn_set(&linkpath, "."); 3075 error = pn_insert(&pn, &linkpath, strlen(nm)); 3076 pn_free(&linkpath); 3077 if (pn.pn_pathlen == 0) { 3078 VN_RELE(vp); 3079 return (ENOENT); 3080 } 3081 if (pn.pn_path[0] == '/') { 3082 pn_skipslash(&pn); 3083 VN_RELE(vp); 3084 VN_RELE(cvp); 3085 vp = rootdir; 3086 VN_HOLD(vp); 3087 } else { 3088 VN_RELE(cvp); 3089 } 3090 continue; 3091 } 3092 3093 VN_RELE(vp); 3094 3095 /* 3096 * Direct the operation to the persisting filesystem 3097 * underlying /dev. Bail if we encounter a 3098 * non-persistent dev entity here. 3099 */ 3100 if (cvp->v_vfsp->vfs_fstype == devtype) { 3101 3102 if ((VTOSDEV(cvp)->sdev_flags & SDEV_PERSIST) == 0) { 3103 error = ENOENT; 3104 VN_RELE(cvp); 3105 break; 3106 } 3107 3108 if (VTOSDEV(cvp) == NULL) { 3109 error = ENOENT; 3110 VN_RELE(cvp); 3111 break; 3112 } 3113 svp = VTOSDEV(cvp); 3114 if ((vp = svp->sdev_attrvp) == NULL) { 3115 error = ENOENT; 3116 VN_RELE(cvp); 3117 break; 3118 } 3119 persisted = 1; 3120 VN_HOLD(vp); 3121 VN_RELE(cvp); 3122 cvp = vp; 3123 } 3124 3125 vp = cvp; 3126 pn_skipslash(&pn); 3127 } 3128 3129 kmem_free(nm, MAXNAMELEN); 3130 pn_free(&pn); 3131 3132 if (error) 3133 return (error); 3134 3135 /* 3136 * Only return persisted nodes in the filesystem underlying /dev. 3137 */ 3138 if (!persisted) { 3139 VN_RELE(vp); 3140 return (ENOENT); 3141 } 3142 3143 *r_vp = vp; 3144 return (0); 3145 } 3146 3147 int 3148 sdev_modctl_readdir(const char *dir, char ***dirlistp, 3149 int *npathsp, int *npathsp_alloc, int checking_empty) 3150 { 3151 char **pathlist = NULL; 3152 char **newlist = NULL; 3153 int npaths = 0; 3154 int npaths_alloc = 0; 3155 dirent64_t *dbuf = NULL; 3156 int n; 3157 char *s; 3158 int error; 3159 vnode_t *vp; 3160 int eof; 3161 struct iovec iov; 3162 struct uio uio; 3163 struct dirent64 *dp; 3164 size_t dlen; 3165 size_t dbuflen; 3166 int ndirents = 64; 3167 char *nm; 3168 3169 error = sdev_modctl_lookup(dir, &vp); 3170 sdcmn_err11(("modctl readdir: %s by %s: %s\n", 3171 dir, curproc->p_user.u_comm, 3172 (error == 0) ? "ok" : "failed")); 3173 if (error) 3174 return (error); 3175 3176 dlen = ndirents * (sizeof (*dbuf)); 3177 dbuf = kmem_alloc(dlen, KM_SLEEP); 3178 3179 uio.uio_iov = &iov; 3180 uio.uio_iovcnt = 1; 3181 uio.uio_segflg = UIO_SYSSPACE; 3182 uio.uio_fmode = 0; 3183 uio.uio_extflg = UIO_COPY_CACHED; 3184 uio.uio_loffset = 0; 3185 uio.uio_llimit = MAXOFFSET_T; 3186 3187 eof = 0; 3188 error = 0; 3189 while (!error && !eof) { 3190 uio.uio_resid = dlen; 3191 iov.iov_base = (char *)dbuf; 3192 iov.iov_len = dlen; 3193 3194 (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL); 3195 error = VOP_READDIR(vp, &uio, kcred, &eof, NULL, 0); 3196 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); 3197 3198 dbuflen = dlen - uio.uio_resid; 3199 3200 if (error || dbuflen == 0) 3201 break; 3202 3203 for (dp = dbuf; ((intptr_t)dp < (intptr_t)dbuf + dbuflen); 3204 dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen)) { 3205 3206 nm = dp->d_name; 3207 3208 if (strcmp(nm, ".") == 0 || strcmp(nm, "..") == 0) 3209 continue; 3210 if (npaths == npaths_alloc) { 3211 npaths_alloc += 64; 3212 newlist = (char **) 3213 kmem_zalloc((npaths_alloc + 1) * 3214 sizeof (char *), KM_SLEEP); 3215 if (pathlist) { 3216 bcopy(pathlist, newlist, 3217 npaths * sizeof (char *)); 3218 kmem_free(pathlist, 3219 (npaths + 1) * sizeof (char *)); 3220 } 3221 pathlist = newlist; 3222 } 3223 n = strlen(nm) + 1; 3224 s = kmem_alloc(n, KM_SLEEP); 3225 bcopy(nm, s, n); 3226 pathlist[npaths++] = s; 3227 sdcmn_err11((" %s/%s\n", dir, s)); 3228 3229 /* if checking empty, one entry is as good as many */ 3230 if (checking_empty) { 3231 eof = 1; 3232 break; 3233 } 3234 } 3235 } 3236 3237 exit: 3238 VN_RELE(vp); 3239 3240 if (dbuf) 3241 kmem_free(dbuf, dlen); 3242 3243 if (error) 3244 return (error); 3245 3246 *dirlistp = pathlist; 3247 *npathsp = npaths; 3248 *npathsp_alloc = npaths_alloc; 3249 3250 return (0); 3251 } 3252 3253 void 3254 sdev_modctl_readdir_free(char **pathlist, int npaths, int npaths_alloc) 3255 { 3256 int i, n; 3257 3258 for (i = 0; i < npaths; i++) { 3259 n = strlen(pathlist[i]) + 1; 3260 kmem_free(pathlist[i], n); 3261 } 3262 3263 kmem_free(pathlist, (npaths_alloc + 1) * sizeof (char *)); 3264 } 3265 3266 int 3267 sdev_modctl_devexists(const char *path) 3268 { 3269 vnode_t *vp; 3270 int error; 3271 3272 error = sdev_modctl_lookup(path, &vp); 3273 sdcmn_err11(("modctl dev exists: %s by %s: %s\n", 3274 path, curproc->p_user.u_comm, 3275 (error == 0) ? "ok" : "failed")); 3276 if (error == 0) 3277 VN_RELE(vp); 3278 3279 return (error); 3280 } 3281 3282 void 3283 sdev_update_newnsmap(struct devname_nsmap *map, char *module, char *mapname) 3284 { 3285 rw_enter(&map->dir_lock, RW_WRITER); 3286 if (module) { 3287 ASSERT(map->dir_newmodule == NULL); 3288 map->dir_newmodule = i_ddi_strdup(module, KM_SLEEP); 3289 } 3290 if (mapname) { 3291 ASSERT(map->dir_newmap == NULL); 3292 map->dir_newmap = i_ddi_strdup(mapname, KM_SLEEP); 3293 } 3294 3295 map->dir_invalid = 1; 3296 rw_exit(&map->dir_lock); 3297 } 3298 3299 void 3300 sdev_replace_nsmap(struct devname_nsmap *map, char *module, char *mapname) 3301 { 3302 char *old_module = NULL; 3303 char *old_map = NULL; 3304 3305 ASSERT(RW_LOCK_HELD(&map->dir_lock)); 3306 if (!rw_tryupgrade(&map->dir_lock)) { 3307 rw_exit(&map->dir_lock); 3308 rw_enter(&map->dir_lock, RW_WRITER); 3309 } 3310 3311 old_module = map->dir_module; 3312 if (module) { 3313 if (old_module && strcmp(old_module, module) != 0) { 3314 kmem_free(old_module, strlen(old_module) + 1); 3315 } 3316 map->dir_module = module; 3317 map->dir_newmodule = NULL; 3318 } 3319 3320 old_map = map->dir_map; 3321 if (mapname) { 3322 if (old_map && strcmp(old_map, mapname) != 0) { 3323 kmem_free(old_map, strlen(old_map) + 1); 3324 } 3325 3326 map->dir_map = mapname; 3327 map->dir_newmap = NULL; 3328 } 3329 map->dir_maploaded = 0; 3330 map->dir_invalid = 0; 3331 rw_downgrade(&map->dir_lock); 3332 } 3333 3334 /* 3335 * dir_name should have at least one attribute, 3336 * dir_module 3337 * or dir_map 3338 * or both 3339 * caller holds the devname_nsmaps_lock 3340 */ 3341 void 3342 sdev_insert_nsmap(char *dir_name, char *dir_module, char *dir_map) 3343 { 3344 struct devname_nsmap *map; 3345 int len = 0; 3346 3347 ASSERT(dir_name); 3348 ASSERT(dir_module || dir_map); 3349 ASSERT(MUTEX_HELD(&devname_nsmaps_lock)); 3350 3351 if (map = sdev_get_nsmap_by_dir(dir_name, 1)) { 3352 sdev_update_newnsmap(map, dir_module, dir_map); 3353 return; 3354 } 3355 3356 map = (struct devname_nsmap *)kmem_zalloc(sizeof (*map), KM_SLEEP); 3357 map->dir_name = i_ddi_strdup(dir_name, KM_SLEEP); 3358 if (dir_module) { 3359 map->dir_module = i_ddi_strdup(dir_module, KM_SLEEP); 3360 } 3361 3362 if (dir_map) { 3363 if (dir_map[0] != '/') { 3364 len = strlen(ETC_DEV_DIR) + strlen(dir_map) + 2; 3365 map->dir_map = kmem_zalloc(len, KM_SLEEP); 3366 (void) snprintf(map->dir_map, len, "%s/%s", ETC_DEV_DIR, 3367 dir_map); 3368 } else { 3369 map->dir_map = i_ddi_strdup(dir_map, KM_SLEEP); 3370 } 3371 } 3372 3373 map->dir_ops = NULL; 3374 map->dir_maploaded = 0; 3375 map->dir_invalid = 0; 3376 rw_init(&map->dir_lock, NULL, RW_DEFAULT, NULL); 3377 3378 map->next = devname_nsmaps; 3379 map->prev = NULL; 3380 if (devname_nsmaps) { 3381 devname_nsmaps->prev = map; 3382 } 3383 devname_nsmaps = map; 3384 } 3385 3386 struct devname_nsmap * 3387 sdev_get_nsmap_by_dir(char *dir_path, int locked) 3388 { 3389 struct devname_nsmap *map = NULL; 3390 3391 if (!locked) 3392 mutex_enter(&devname_nsmaps_lock); 3393 for (map = devname_nsmaps; map; map = map->next) { 3394 sdcmn_err6(("sdev_get_nsmap_by_dir: dir %s\n", map->dir_name)); 3395 if (strcmp(map->dir_name, dir_path) == 0) { 3396 if (!locked) 3397 mutex_exit(&devname_nsmaps_lock); 3398 return (map); 3399 } 3400 } 3401 if (!locked) 3402 mutex_exit(&devname_nsmaps_lock); 3403 return (NULL); 3404 } 3405 3406 struct devname_nsmap * 3407 sdev_get_nsmap_by_module(char *mod_name) 3408 { 3409 struct devname_nsmap *map = NULL; 3410 3411 mutex_enter(&devname_nsmaps_lock); 3412 for (map = devname_nsmaps; map; map = map->next) { 3413 sdcmn_err7(("sdev_get_nsmap_by_module: module %s\n", 3414 map->dir_module)); 3415 if (map->dir_module && strcmp(map->dir_module, mod_name) == 0) { 3416 mutex_exit(&devname_nsmaps_lock); 3417 return (map); 3418 } 3419 } 3420 mutex_exit(&devname_nsmaps_lock); 3421 return (NULL); 3422 } 3423 3424 void 3425 sdev_invalidate_nsmaps() 3426 { 3427 struct devname_nsmap *map = NULL; 3428 3429 ASSERT(MUTEX_HELD(&devname_nsmaps_lock)); 3430 3431 if (devname_nsmaps == NULL) 3432 return; 3433 3434 for (map = devname_nsmaps; map; map = map->next) { 3435 rw_enter(&map->dir_lock, RW_WRITER); 3436 map->dir_invalid = 1; 3437 rw_exit(&map->dir_lock); 3438 } 3439 devname_nsmaps_invalidated = 1; 3440 } 3441 3442 3443 int 3444 sdev_nsmaps_loaded() 3445 { 3446 int ret = 0; 3447 3448 mutex_enter(&devname_nsmaps_lock); 3449 if (devname_nsmaps_loaded) 3450 ret = 1; 3451 3452 mutex_exit(&devname_nsmaps_lock); 3453 return (ret); 3454 } 3455 3456 int 3457 sdev_nsmaps_reloaded() 3458 { 3459 int ret = 0; 3460 3461 mutex_enter(&devname_nsmaps_lock); 3462 if (devname_nsmaps_invalidated) 3463 ret = 1; 3464 3465 mutex_exit(&devname_nsmaps_lock); 3466 return (ret); 3467 } 3468 3469 static void 3470 sdev_free_nsmap(struct devname_nsmap *map) 3471 { 3472 ASSERT(map); 3473 if (map->dir_name) 3474 kmem_free(map->dir_name, strlen(map->dir_name) + 1); 3475 if (map->dir_module) 3476 kmem_free(map->dir_module, strlen(map->dir_module) + 1); 3477 if (map->dir_map) 3478 kmem_free(map->dir_map, strlen(map->dir_map) + 1); 3479 rw_destroy(&map->dir_lock); 3480 kmem_free(map, sizeof (*map)); 3481 } 3482 3483 void 3484 sdev_validate_nsmaps() 3485 { 3486 struct devname_nsmap *map = NULL; 3487 struct devname_nsmap *oldmap = NULL; 3488 3489 ASSERT(MUTEX_HELD(&devname_nsmaps_lock)); 3490 map = devname_nsmaps; 3491 while (map) { 3492 rw_enter(&map->dir_lock, RW_READER); 3493 if ((map->dir_invalid == 1) && (map->dir_newmodule == NULL) && 3494 (map->dir_newmap == NULL)) { 3495 oldmap = map; 3496 rw_exit(&map->dir_lock); 3497 if (map->prev) 3498 map->prev->next = oldmap->next; 3499 if (map == devname_nsmaps) 3500 devname_nsmaps = oldmap->next; 3501 3502 map = oldmap->next; 3503 if (map) 3504 map->prev = oldmap->prev; 3505 sdev_free_nsmap(oldmap); 3506 oldmap = NULL; 3507 } else { 3508 rw_exit(&map->dir_lock); 3509 map = map->next; 3510 } 3511 } 3512 devname_nsmaps_invalidated = 0; 3513 } 3514 3515 static int 3516 sdev_map_is_invalid(struct devname_nsmap *map) 3517 { 3518 int ret = 0; 3519 3520 ASSERT(map); 3521 rw_enter(&map->dir_lock, RW_READER); 3522 if (map->dir_invalid) 3523 ret = 1; 3524 rw_exit(&map->dir_lock); 3525 return (ret); 3526 } 3527 3528 static int 3529 sdev_check_map(struct devname_nsmap *map) 3530 { 3531 struct devname_nsmap *mapp; 3532 3533 mutex_enter(&devname_nsmaps_lock); 3534 if (devname_nsmaps == NULL) { 3535 mutex_exit(&devname_nsmaps_lock); 3536 return (1); 3537 } 3538 3539 for (mapp = devname_nsmaps; mapp; mapp = mapp->next) { 3540 if (mapp == map) { 3541 mutex_exit(&devname_nsmaps_lock); 3542 return (0); 3543 } 3544 } 3545 3546 mutex_exit(&devname_nsmaps_lock); 3547 return (1); 3548 3549 } 3550 3551 struct devname_nsmap * 3552 sdev_get_map(struct sdev_node *dv, int validate) 3553 { 3554 struct devname_nsmap *map; 3555 int error; 3556 3557 ASSERT(RW_READ_HELD(&dv->sdev_contents)); 3558 map = dv->sdev_mapinfo; 3559 if (map && sdev_check_map(map)) { 3560 if (!rw_tryupgrade(&dv->sdev_contents)) { 3561 rw_exit(&dv->sdev_contents); 3562 rw_enter(&dv->sdev_contents, RW_WRITER); 3563 } 3564 dv->sdev_mapinfo = NULL; 3565 rw_downgrade(&dv->sdev_contents); 3566 return (NULL); 3567 } 3568 3569 if (validate && (!map || (map && sdev_map_is_invalid(map)))) { 3570 if (!rw_tryupgrade(&dv->sdev_contents)) { 3571 rw_exit(&dv->sdev_contents); 3572 rw_enter(&dv->sdev_contents, RW_WRITER); 3573 } 3574 error = sdev_get_moduleops(dv); 3575 if (!error) 3576 map = dv->sdev_mapinfo; 3577 rw_downgrade(&dv->sdev_contents); 3578 } 3579 return (map); 3580 } 3581 3582 extern int sdev_vnodeops_tbl_size; 3583 3584 /* 3585 * construct a new template with overrides from vtab 3586 */ 3587 static fs_operation_def_t * 3588 sdev_merge_vtab(const fs_operation_def_t tab[]) 3589 { 3590 fs_operation_def_t *new; 3591 const fs_operation_def_t *tab_entry; 3592 3593 /* make a copy of standard vnode ops table */ 3594 new = kmem_alloc(sdev_vnodeops_tbl_size, KM_SLEEP); 3595 bcopy((void *)sdev_vnodeops_tbl, new, sdev_vnodeops_tbl_size); 3596 3597 /* replace the overrides from tab */ 3598 for (tab_entry = tab; tab_entry->name != NULL; tab_entry++) { 3599 fs_operation_def_t *std_entry = new; 3600 while (std_entry->name) { 3601 if (strcmp(tab_entry->name, std_entry->name) == 0) { 3602 std_entry->func = tab_entry->func; 3603 break; 3604 } 3605 std_entry++; 3606 } 3607 if (std_entry->name == NULL) 3608 cmn_err(CE_NOTE, "sdev_merge_vtab: entry %s unused.", 3609 tab_entry->name); 3610 } 3611 3612 return (new); 3613 } 3614 3615 /* free memory allocated by sdev_merge_vtab */ 3616 static void 3617 sdev_free_vtab(fs_operation_def_t *new) 3618 { 3619 kmem_free(new, sdev_vnodeops_tbl_size); 3620 } 3621 3622 void 3623 devname_get_vnode(devname_handle_t *hdl, vnode_t **vpp) 3624 { 3625 struct sdev_node *dv = hdl->dh_data; 3626 3627 ASSERT(dv); 3628 3629 rw_enter(&dv->sdev_contents, RW_READER); 3630 *vpp = SDEVTOV(dv); 3631 rw_exit(&dv->sdev_contents); 3632 } 3633 3634 int 3635 devname_get_path(devname_handle_t *hdl, char **path) 3636 { 3637 struct sdev_node *dv = hdl->dh_data; 3638 3639 ASSERT(dv); 3640 3641 rw_enter(&dv->sdev_contents, RW_READER); 3642 *path = dv->sdev_path; 3643 rw_exit(&dv->sdev_contents); 3644 return (0); 3645 } 3646 3647 int 3648 devname_get_name(devname_handle_t *hdl, char **entry) 3649 { 3650 struct sdev_node *dv = hdl->dh_data; 3651 3652 ASSERT(dv); 3653 rw_enter(&dv->sdev_contents, RW_READER); 3654 *entry = dv->sdev_name; 3655 rw_exit(&dv->sdev_contents); 3656 return (0); 3657 } 3658 3659 void 3660 devname_get_dir_vnode(devname_handle_t *hdl, vnode_t **vpp) 3661 { 3662 struct sdev_node *dv = hdl->dh_data->sdev_dotdot; 3663 3664 ASSERT(dv); 3665 3666 rw_enter(&dv->sdev_contents, RW_READER); 3667 *vpp = SDEVTOV(dv); 3668 rw_exit(&dv->sdev_contents); 3669 } 3670 3671 int 3672 devname_get_dir_path(devname_handle_t *hdl, char **path) 3673 { 3674 struct sdev_node *dv = hdl->dh_data->sdev_dotdot; 3675 3676 ASSERT(dv); 3677 rw_enter(&dv->sdev_contents, RW_READER); 3678 *path = dv->sdev_path; 3679 rw_exit(&dv->sdev_contents); 3680 return (0); 3681 } 3682 3683 int 3684 devname_get_dir_name(devname_handle_t *hdl, char **entry) 3685 { 3686 struct sdev_node *dv = hdl->dh_data->sdev_dotdot; 3687 3688 ASSERT(dv); 3689 rw_enter(&dv->sdev_contents, RW_READER); 3690 *entry = dv->sdev_name; 3691 rw_exit(&dv->sdev_contents); 3692 return (0); 3693 } 3694 3695 int 3696 devname_get_dir_nsmap(devname_handle_t *hdl, struct devname_nsmap **map) 3697 { 3698 struct sdev_node *dv = hdl->dh_data->sdev_dotdot; 3699 3700 ASSERT(dv); 3701 rw_enter(&dv->sdev_contents, RW_READER); 3702 *map = dv->sdev_mapinfo; 3703 rw_exit(&dv->sdev_contents); 3704 return (0); 3705 } 3706 3707 int 3708 devname_get_dir_handle(devname_handle_t *hdl, devname_handle_t **dir_hdl) 3709 { 3710 struct sdev_node *dv = hdl->dh_data->sdev_dotdot; 3711 3712 ASSERT(dv); 3713 rw_enter(&dv->sdev_contents, RW_READER); 3714 *dir_hdl = &(dv->sdev_handle); 3715 rw_exit(&dv->sdev_contents); 3716 return (0); 3717 } 3718 3719 void 3720 devname_set_nodetype(devname_handle_t *hdl, void *args, int spec) 3721 { 3722 struct sdev_node *dv = hdl->dh_data; 3723 3724 ASSERT(dv); 3725 rw_enter(&dv->sdev_contents, RW_WRITER); 3726 hdl->dh_spec = (devname_spec_t)spec; 3727 hdl->dh_args = (void *)i_ddi_strdup((char *)args, KM_SLEEP); 3728 rw_exit(&dv->sdev_contents); 3729 } 3730 3731 /* 3732 * a generic setattr() function 3733 * 3734 * note: flags only supports AT_UID and AT_GID. 3735 * Future enhancements can be done for other types, e.g. AT_MODE 3736 */ 3737 int 3738 devname_setattr_func(struct vnode *vp, struct vattr *vap, int flags, 3739 struct cred *cred, int (*callback)(struct sdev_node *, struct vattr *, 3740 int), int protocol) 3741 { 3742 struct sdev_node *dv = VTOSDEV(vp); 3743 struct sdev_node *parent = dv->sdev_dotdot; 3744 struct vattr *get; 3745 uint_t mask = vap->va_mask; 3746 int error; 3747 3748 /* some sanity checks */ 3749 if (vap->va_mask & AT_NOSET) 3750 return (EINVAL); 3751 3752 if (vap->va_mask & AT_SIZE) { 3753 if (vp->v_type == VDIR) { 3754 return (EISDIR); 3755 } 3756 } 3757 3758 /* no need to set attribute, but do not fail either */ 3759 ASSERT(parent); 3760 rw_enter(&parent->sdev_contents, RW_READER); 3761 if (dv->sdev_state == SDEV_ZOMBIE) { 3762 rw_exit(&parent->sdev_contents); 3763 return (0); 3764 } 3765 3766 /* If backing store exists, just set it. */ 3767 if (dv->sdev_attrvp) { 3768 rw_exit(&parent->sdev_contents); 3769 return (VOP_SETATTR(dv->sdev_attrvp, vap, flags, cred, NULL)); 3770 } 3771 3772 /* 3773 * Otherwise, for nodes with the persistence attribute, create it. 3774 */ 3775 ASSERT(dv->sdev_attr); 3776 if (SDEV_IS_PERSIST(dv) || 3777 ((vap->va_mask & ~AT_TIMES) != 0 && !SDEV_IS_DYNAMIC(dv))) { 3778 sdev_vattr_merge(dv, vap); 3779 rw_enter(&dv->sdev_contents, RW_WRITER); 3780 error = sdev_shadow_node(dv, cred); 3781 rw_exit(&dv->sdev_contents); 3782 rw_exit(&parent->sdev_contents); 3783 3784 if (error) 3785 return (error); 3786 return (VOP_SETATTR(dv->sdev_attrvp, vap, flags, cred, NULL)); 3787 } 3788 3789 3790 /* 3791 * sdev_attr was allocated in sdev_mknode 3792 */ 3793 rw_enter(&dv->sdev_contents, RW_WRITER); 3794 error = secpolicy_vnode_setattr(cred, vp, vap, 3795 dv->sdev_attr, flags, sdev_unlocked_access, dv); 3796 if (error) { 3797 rw_exit(&dv->sdev_contents); 3798 rw_exit(&parent->sdev_contents); 3799 return (error); 3800 } 3801 3802 get = dv->sdev_attr; 3803 if (mask & AT_MODE) { 3804 get->va_mode &= S_IFMT; 3805 get->va_mode |= vap->va_mode & ~S_IFMT; 3806 } 3807 3808 if ((mask & AT_UID) || (mask & AT_GID)) { 3809 if (mask & AT_UID) 3810 get->va_uid = vap->va_uid; 3811 if (mask & AT_GID) 3812 get->va_gid = vap->va_gid; 3813 /* 3814 * a callback must be provided if the protocol is set 3815 */ 3816 if ((protocol & AT_UID) || (protocol & AT_GID)) { 3817 ASSERT(callback); 3818 error = callback(dv, get, protocol); 3819 if (error) { 3820 rw_exit(&dv->sdev_contents); 3821 rw_exit(&parent->sdev_contents); 3822 return (error); 3823 } 3824 } 3825 } 3826 3827 if (mask & AT_ATIME) 3828 get->va_atime = vap->va_atime; 3829 if (mask & AT_MTIME) 3830 get->va_mtime = vap->va_mtime; 3831 if (mask & (AT_MODE | AT_UID | AT_GID | AT_CTIME)) { 3832 gethrestime(&get->va_ctime); 3833 } 3834 3835 sdev_vattr_merge(dv, get); 3836 rw_exit(&dv->sdev_contents); 3837 rw_exit(&parent->sdev_contents); 3838 return (0); 3839 } 3840 3841 /* 3842 * a generic inactive() function 3843 */ 3844 void 3845 devname_inactive_func(struct vnode *vp, struct cred *cred, 3846 void (*callback)(struct vnode *)) 3847 { 3848 int clean; 3849 struct sdev_node *dv = VTOSDEV(vp); 3850 struct sdev_node *ddv = dv->sdev_dotdot; 3851 int state; 3852 struct devname_nsmap *map = NULL; 3853 struct devname_ops *dirops = NULL; 3854 void (*fn)(devname_handle_t *, struct cred *) = NULL; 3855 3856 rw_enter(&ddv->sdev_contents, RW_WRITER); 3857 state = dv->sdev_state; 3858 3859 mutex_enter(&vp->v_lock); 3860 ASSERT(vp->v_count >= 1); 3861 3862 if (vp->v_count == 1 && callback != NULL) 3863 callback(vp); 3864 3865 clean = (vp->v_count == 1) && (state == SDEV_ZOMBIE); 3866 3867 /* 3868 * last ref count on the ZOMBIE node is released. 3869 * clean up the sdev_node, and 3870 * release the hold on the backing store node so that 3871 * the ZOMBIE backing stores also cleaned out. 3872 */ 3873 if (clean) { 3874 ASSERT(ddv); 3875 if (SDEV_IS_GLOBAL(dv)) { 3876 map = ddv->sdev_mapinfo; 3877 dirops = map ? map->dir_ops : NULL; 3878 if (dirops && (fn = dirops->devnops_inactive)) 3879 (*fn)(&(dv->sdev_handle), cred); 3880 } 3881 3882 ddv->sdev_nlink--; 3883 if (vp->v_type == VDIR) { 3884 dv->sdev_nlink--; 3885 } 3886 if ((dv->sdev_flags & SDEV_STALE) == 0) 3887 avl_remove(&ddv->sdev_entries, dv); 3888 dv->sdev_nlink--; 3889 --vp->v_count; 3890 mutex_exit(&vp->v_lock); 3891 sdev_nodedestroy(dv, 0); 3892 } else { 3893 --vp->v_count; 3894 mutex_exit(&vp->v_lock); 3895 } 3896 rw_exit(&ddv->sdev_contents); 3897 } 3898