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