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