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