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