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