1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * routines to invoke user level name lookup services 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 <sys/disp.h> 56 #include <sys/door.h> 57 #include <fs/fs_subr.h> 58 #include <sys/mount.h> 59 #include <sys/fs/snode.h> 60 #include <sys/fs/dv_node.h> 61 #include <sys/fs/sdev_impl.h> 62 #include <sys/fs/sdev_node.h> 63 #include <sys/sunndi.h> 64 #include <sys/sunddi.h> 65 #include <sys/sunmdi.h> 66 #include <sys/conf.h> 67 #include <sys/modctl.h> 68 #include <sys/ddi.h> 69 70 /* default timeout to wait for devfsadm response in seconds */ 71 #define DEV_DEVFSADM_STARTUP (1 * 60) 72 #define DEV_NODE_WAIT_TIMEOUT (5 * 60) 73 74 /* atomic bitset for devfsadm status */ 75 volatile uint_t devfsadm_state; 76 77 static kmutex_t devfsadm_lock; 78 static kcondvar_t devfsadm_cv; 79 80 int devname_nsmaps_loaded = 0; 81 static int dev_node_wait_timeout = DEV_NODE_WAIT_TIMEOUT; 82 static int dev_devfsadm_startup = DEV_DEVFSADM_STARTUP; 83 84 /* 85 * Door used to communicate with devfsadmd 86 */ 87 static door_handle_t sdev_upcall_door = NULL; /* Door for upcalls */ 88 static char *sdev_door_upcall_filename = NULL; 89 static int sdev_upcall_door_revoked = 0; 90 static int sdev_door_upcall_filename_size; 91 92 static void sdev_devfsadmd_nsrdr(sdev_nsrdr_work_t *); 93 static int sdev_devfsadm_revoked(void); 94 static int sdev_ki_call_devfsadmd(sdev_door_arg_t *, sdev_door_res_t *); 95 96 /* 97 * nsmap_readdir processing thread 98 */ 99 static uint_t sdev_nsrdr_thread_created = 0; 100 static kmutex_t sdev_nsrdr_thread_lock; 101 static kcondvar_t sdev_nsrdr_thread_cv; 102 static sdev_nsrdr_work_t *sdev_nsrdr_thread_workq = NULL; 103 static sdev_nsrdr_work_t *sdev_nsrdr_thread_tail = NULL; 104 105 void 106 sdev_devfsadm_lockinit(void) 107 { 108 mutex_init(&devfsadm_lock, NULL, MUTEX_DEFAULT, NULL); 109 cv_init(&devfsadm_cv, NULL, CV_DEFAULT, NULL); 110 } 111 112 void 113 sdev_devfsadm_lockdestroy(void) 114 { 115 mutex_destroy(&devfsadm_lock); 116 cv_destroy(&devfsadm_cv); 117 } 118 119 /* 120 * Wait for node to be created 121 */ 122 int 123 sdev_wait4lookup(struct sdev_node *dv, int cmd) 124 { 125 clock_t expire; 126 clock_t rv; 127 int rval = ENOENT; 128 int is_lookup = (cmd == SDEV_LOOKUP); 129 130 ASSERT(cmd == SDEV_LOOKUP || cmd == SDEV_READDIR); 131 ASSERT(MUTEX_HELD(&dv->sdev_lookup_lock)); 132 133 /* tick value at which wait expires */ 134 expire = ddi_get_lbolt() + 135 drv_usectohz(dev_node_wait_timeout * 1000000); 136 137 sdcmn_err6(("wait4lookup %s %s, %ld %d\n", 138 is_lookup ? "lookup" : "readdir", 139 dv->sdev_name, expire - ddi_get_lbolt(), dv->sdev_state)); 140 141 if (SDEV_IS_LGWAITING(dv)) { 142 /* devfsadm nodes */ 143 while (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state) && 144 !sdev_devfsadm_revoked()) { 145 /* wait 2 sec and check devfsadm completion */ 146 rv = cv_timedwait_sig(&dv->sdev_lookup_cv, 147 &dv->sdev_lookup_lock, ddi_get_lbolt() + 148 drv_usectohz(2 * 1000000)); 149 150 if (is_lookup && (rv > 0)) { 151 /* was this node constructed ? */ 152 if (dv->sdev_state == SDEV_READY) { 153 rval = 0; 154 } 155 sdcmn_err6(("%s: wait done, %screated %d\n", 156 dv->sdev_name, rval ? "not " : "", 157 dv->sdev_state)); 158 break; 159 } else if (rv == 0) { 160 /* interrupted */ 161 sdcmn_err6(("%s: wait interrupted\n", 162 dv->sdev_name)); 163 break; 164 } else if ((rv == -1) && 165 (ddi_get_lbolt() >= expire)) { 166 sdcmn_err6(("%s: wait time is up\n", 167 dv->sdev_name)); 168 break; 169 } 170 sdcmn_err6(("%s: wait " 171 "rv %ld state 0x%x expire %ld\n", 172 dv->sdev_name, rv, devfsadm_state, 173 expire - ddi_get_lbolt())); 174 } 175 } else { 176 /* 177 * for the nodes created by 178 * devname_lookup_func callback 179 * or plug-in modules 180 */ 181 while (SDEV_IS_LOOKUP(dv) || SDEV_IS_READDIR(dv)) { 182 cv_wait(&dv->sdev_lookup_cv, &dv->sdev_lookup_lock); 183 } 184 rval = 0; 185 } 186 187 sdcmn_err6(("wait4lookup unblocking %s state 0x%x %d\n", 188 dv->sdev_name, devfsadm_state, dv->sdev_state)); 189 190 if (is_lookup) { 191 SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP); 192 } else { 193 SDEV_UNBLOCK_OTHERS(dv, SDEV_READDIR); 194 } 195 196 return (rval); 197 } 198 199 void 200 sdev_unblock_others(struct sdev_node *dv, uint_t cmd) 201 { 202 ASSERT(MUTEX_HELD(&dv->sdev_lookup_lock)); 203 204 SDEV_CLEAR_LOOKUP_FLAGS(dv, cmd); 205 if (SDEV_IS_LGWAITING(dv)) { 206 SDEV_CLEAR_LOOKUP_FLAGS(dv, SDEV_LGWAITING); 207 } 208 cv_broadcast(&dv->sdev_lookup_cv); 209 } 210 211 /* 212 * In the case devfsadmd is down, it is re-started by syseventd 213 * upon receiving an event subscribed to by devfsadmd. 214 */ 215 static int 216 sdev_start_devfsadmd() 217 { 218 int se_err = 0; 219 sysevent_t *ev; 220 sysevent_id_t eid; 221 222 ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_START, EP_DDI, SE_SLEEP); 223 ASSERT(ev); 224 if ((se_err = log_sysevent(ev, SE_SLEEP, &eid)) != 0) { 225 switch (se_err) { 226 case SE_NO_TRANSPORT: 227 cmn_err(CE_WARN, "unable to start devfsadm - " 228 "syseventd may not be responding\n"); 229 break; 230 default: 231 cmn_err(CE_WARN, "unable to start devfsadm - " 232 "sysevent error %d\n", se_err); 233 break; 234 } 235 } 236 237 sysevent_free(ev); 238 return (se_err); 239 } 240 241 static int 242 sdev_open_upcall_door() 243 { 244 int error; 245 clock_t rv; 246 clock_t expire; 247 248 ASSERT(sdev_upcall_door == NULL); 249 250 /* tick value at which wait expires */ 251 expire = ddi_get_lbolt() + 252 drv_usectohz(dev_devfsadm_startup * 1000000); 253 254 if (sdev_door_upcall_filename == NULL) { 255 if ((error = sdev_start_devfsadmd()) != 0) { 256 return (error); 257 } 258 259 /* wait for devfsadmd start */ 260 mutex_enter(&devfsadm_lock); 261 while (sdev_door_upcall_filename == NULL) { 262 sdcmn_err6(("waiting for dev_door creation, %ld\n", 263 expire - ddi_get_lbolt())); 264 rv = cv_timedwait_sig(&devfsadm_cv, &devfsadm_lock, 265 expire); 266 sdcmn_err6(("dev_door wait rv %ld\n", rv)); 267 if (rv <= 0) { 268 sdcmn_err6(("devfsadmd startup error\n")); 269 mutex_exit(&devfsadm_lock); 270 return (EBADF); 271 } 272 } 273 sdcmn_err6(("devfsadmd is ready\n")); 274 mutex_exit(&devfsadm_lock); 275 } 276 277 if ((error = door_ki_open(sdev_door_upcall_filename, 278 &sdev_upcall_door)) != 0) { 279 sdcmn_err6(("upcall_lookup: door open error %d\n", 280 error)); 281 return (error); 282 } 283 284 return (0); 285 } 286 287 static void 288 sdev_release_door() 289 { 290 if (sdev_upcall_door) { 291 door_ki_rele(sdev_upcall_door); 292 sdev_upcall_door = NULL; 293 } 294 if (sdev_door_upcall_filename) { 295 kmem_free(sdev_door_upcall_filename, 296 sdev_door_upcall_filename_size); 297 sdev_door_upcall_filename = NULL; 298 } 299 } 300 301 static int 302 sdev_ki_call_devfsadmd(sdev_door_arg_t *argp, sdev_door_res_t *resultp) 303 { 304 door_arg_t darg, save_arg; 305 int error; 306 int retry; 307 308 if (((sdev_upcall_door == NULL) && 309 ((error = sdev_open_upcall_door()) != 0)) || 310 sdev_devfsadm_revoked()) { 311 sdcmn_err6(("call_devfsadm: upcall lookup error\n")); 312 return (error); 313 } 314 315 ASSERT(argp); 316 darg.data_ptr = (char *)argp; 317 darg.data_size = sizeof (struct sdev_door_arg); 318 darg.desc_ptr = NULL; 319 darg.desc_num = 0; 320 darg.rbuf = (char *)(resultp); 321 darg.rsize = sizeof (struct sdev_door_res); 322 323 ASSERT(sdev_upcall_door); 324 save_arg = darg; 325 for (retry = 0; ; retry++) { 326 sdcmn_err6(("call devfsadm: upcall lookup, retry %d\n", retry)); 327 if ((error = door_ki_upcall(sdev_upcall_door, &darg)) == 0) { 328 sdcmn_err6(("call devfsadm: upcall lookup ok\n")); 329 break; 330 } 331 332 /* 333 * handle door call errors 334 */ 335 if (sdev_devfsadm_revoked()) { 336 sdcmn_err6(("upcall lookup door revoked, " 337 "error %d\n", error)); 338 return (error); 339 } 340 341 switch (error) { 342 case EINTR: 343 /* return error here? */ 344 sdcmn_err6(("sdev_ki_call_devfsadm: EINTR\n")); 345 delay(hz); 346 break; 347 case EAGAIN: 348 sdcmn_err6(("sdev_ki_call_devfsadm: EAGAIN\n")); 349 delay(2 * hz); 350 break; 351 case EBADF: 352 if (retry > 4) { 353 sdcmn_err6(("sdev_ki_call_devfsadm: EBADF\n")); 354 return (EBADF); 355 } 356 sdcmn_err6(( 357 "sdev_ki_call_devfsadm: EBADF, re-binding\n")); 358 sdev_release_door(); 359 delay(retry * hz); 360 error = sdev_open_upcall_door(); 361 if (error != 0) { 362 sdcmn_err6(("sdev_ki_call_devfsadm: " 363 "EBADF lookup error %d\n", error)); 364 if (!sdev_devfsadm_revoked()) 365 cmn_err(CE_NOTE, 366 "?unable to invoke devfsadm - " 367 "please run manually\n"); 368 return (EBADF); 369 } 370 break; 371 case EINVAL: 372 default: 373 cmn_err(CE_CONT, 374 "?sdev: door_ki_upcall unexpected result %d\n", 375 error); 376 return (error); 377 } 378 379 darg = save_arg; 380 } 381 382 if (!error) { 383 ASSERT((struct sdev_door_res *)darg.rbuf == resultp); 384 if (resultp->devfsadm_error != 0) { 385 sdcmn_err6(("sdev_ki_call_devfsadmd: result %d\n", 386 resultp->devfsadm_error)); 387 error = resultp->devfsadm_error; 388 } 389 } else { 390 sdcmn_err6(("sdev_ki_call_devfsadmd with error %d\n", error)); 391 } 392 393 return (error); 394 } 395 396 static int 397 sdev_devfsadm_revoked(void) 398 { 399 struct door_info info; 400 int rv; 401 extern int sys_shutdown; 402 403 if (sys_shutdown) { 404 sdcmn_err6(("dev: shutdown observed\n")); 405 return (1); 406 } 407 408 if (sdev_upcall_door && !sdev_upcall_door_revoked) { 409 rv = door_ki_info(sdev_upcall_door, &info); 410 if ((rv == 0) && info.di_attributes & DOOR_REVOKED) { 411 sdcmn_err6(("lookup door: revoked\n")); 412 sdev_upcall_door_revoked = 1; 413 } 414 } 415 416 return (sdev_upcall_door_revoked); 417 } 418 419 /*ARGSUSED*/ 420 static void 421 sdev_config_all_thread(struct sdev_node *dv) 422 { 423 int32_t error = 0; 424 sdev_door_arg_t *argp; 425 sdev_door_res_t result; 426 427 argp = kmem_zalloc(sizeof (sdev_door_arg_t), KM_SLEEP); 428 argp->devfsadm_cmd = DEVFSADMD_RUN_ALL; 429 430 error = sdev_ki_call_devfsadmd(argp, &result); 431 if (!error) { 432 sdcmn_err6(("devfsadm result error: %d\n", 433 result.devfsadm_error)); 434 if (!result.devfsadm_error) { 435 DEVNAME_DEVFSADM_SET_RUN(devfsadm_state); 436 } else { 437 DEVNAME_DEVFSADM_SET_STOP(devfsadm_state); 438 } 439 } else { 440 DEVNAME_DEVFSADM_SET_STOP(devfsadm_state); 441 } 442 443 kmem_free(argp, sizeof (sdev_door_arg_t)); 444 done: 445 sdcmn_err6(("sdev_config_all_thread: stopping, devfsadm state 0x%x\n", 446 devfsadm_state)); 447 thread_exit(); 448 } 449 450 /* 451 * launch an asynchronous thread to do the devfsadm dev_config_all 452 */ 453 /*ARGSUSED*/ 454 void 455 sdev_devfsadmd_thread(struct sdev_node *ddv, struct sdev_node *dv, 456 struct cred *cred) 457 { 458 ASSERT(i_ddi_io_initialized()); 459 DEVNAME_DEVFSADM_SET_RUNNING(devfsadm_state); 460 (void) thread_create(NULL, 0, sdev_config_all_thread, dv, 0, 461 &p0, TS_RUN, MINCLSYSPRI); 462 } 463 464 int 465 devname_filename_register(int cmd, char *name) 466 { 467 int error = 0; 468 char *strbuf; 469 char *namep; 470 int n; 471 472 ASSERT(cmd == MODDEVNAME_LOOKUPDOOR || 473 cmd == MODDEVNAME_DEVFSADMNODE); 474 475 strbuf = kmem_zalloc(MOD_MAXPATH, KM_SLEEP); 476 477 if (copyinstr(name, strbuf, MOD_MAXPATH, 0)) { 478 sdcmn_err6(("error copyin \n")); 479 error = EFAULT; 480 } else { 481 sdcmn_err6(("file %s is registering\n", strbuf)); 482 switch (cmd) { 483 case MODDEVNAME_LOOKUPDOOR: 484 /* handling the daemon re-start situations */ 485 n = strlen(strbuf) + 1; 486 namep = i_ddi_strdup(strbuf, KM_SLEEP); 487 mutex_enter(&devfsadm_lock); 488 sdev_release_door(); 489 sdev_door_upcall_filename_size = n; 490 sdev_door_upcall_filename = namep; 491 sdcmn_err6(("size %d file name %s\n", 492 sdev_door_upcall_filename_size, 493 sdev_door_upcall_filename)); 494 cv_broadcast(&devfsadm_cv); 495 mutex_exit(&devfsadm_lock); 496 break; 497 case MODDEVNAME_DEVFSADMNODE: 498 break; 499 } 500 } 501 502 kmem_free(strbuf, MOD_MAXPATH); 503 return (error); 504 } 505 static void 506 sdev_nsrdr_thread(void) 507 { 508 sdev_nsrdr_work_t *work; 509 510 for (;;) { 511 mutex_enter(&sdev_nsrdr_thread_lock); 512 if (sdev_nsrdr_thread_workq == NULL) { 513 cv_wait(&sdev_nsrdr_thread_cv, &sdev_nsrdr_thread_lock); 514 } 515 work = sdev_nsrdr_thread_workq; 516 sdev_nsrdr_thread_workq = work->next; 517 if (sdev_nsrdr_thread_tail == work) 518 sdev_nsrdr_thread_tail = work->next; 519 mutex_exit(&sdev_nsrdr_thread_lock); 520 sdev_devfsadmd_nsrdr(work); 521 } 522 /*NOTREACHED*/ 523 } 524 525 int 526 devname_nsmaps_register(char *nvlbuf, size_t nvlsize) 527 { 528 int error = 0; 529 nvlist_t *nvl, *attrs; 530 nvpair_t *nvp = NULL; 531 nvpair_t *kvp = NULL; 532 char *buf; 533 char *key; 534 char *dirname = NULL; 535 char *dirmodule = NULL; 536 char *dirmap = NULL; 537 char *orig_module; 538 char *orig_map; 539 int len = 0; 540 char *tmpmap; 541 int mapcount = 0; 542 543 buf = kmem_zalloc(nvlsize, KM_SLEEP); 544 if ((error = ddi_copyin(nvlbuf, buf, nvlsize, 0)) != 0) { 545 kmem_free(buf, nvlsize); 546 return (error); 547 } 548 549 ASSERT(buf); 550 sdcmn_err6(("devname_nsmaps_register: nsmap buf %p\n", (void *)buf)); 551 nvl = NULL; 552 error = nvlist_unpack(buf, nvlsize, &nvl, KM_SLEEP); 553 kmem_free(buf, nvlsize); 554 if (error || (nvl == NULL)) 555 return (error); 556 557 /* invalidate all the nsmaps */ 558 mutex_enter(&devname_nsmaps_lock); 559 sdev_invalidate_nsmaps(); 560 for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL; 561 nvp = nvlist_next_nvpair(nvl, nvp)) { 562 dirname = nvpair_name(nvp); 563 if (dirname == NULL) { 564 nvlist_free(nvl); 565 mutex_exit(&devname_nsmaps_lock); 566 return (-1); 567 } 568 569 sdcmn_err6(("dirname %s\n", dirname)); 570 (void) nvpair_value_nvlist(nvp, &attrs); 571 for (kvp = nvlist_next_nvpair(attrs, NULL); kvp; 572 kvp = nvlist_next_nvpair(attrs, kvp)) { 573 key = nvpair_name(kvp); 574 sdcmn_err6(("key %s\n", key)); 575 if (strcmp(key, "module") == 0) { 576 (void) nvpair_value_string(kvp, &orig_module); 577 sdcmn_err6(("module %s\n", orig_module)); 578 dirmodule = i_ddi_strdup(orig_module, KM_SLEEP); 579 if (strcmp(dirmodule, "devname_null") == 0) 580 dirmodule = NULL; 581 } 582 583 if (strcmp(key, "nsconfig") == 0) { 584 (void) nvpair_value_string(kvp, &orig_map); 585 sdcmn_err6(("dirmap %s\n", orig_map)); 586 dirmap = i_ddi_strdup(orig_map, KM_SLEEP); 587 if (strcmp(dirmap, "devname_null") == 0) 588 dirmap = NULL; 589 else if (dirmap[0] != '/') { 590 len = strlen(dirmap) + 591 strlen(ETC_DEV_DIR) + 2; 592 tmpmap = i_ddi_strdup(dirmap, KM_SLEEP); 593 (void) snprintf(dirmap, len, "%s/%s", 594 ETC_DEV_DIR, tmpmap); 595 kmem_free(tmpmap, strlen(tmpmap) + 1); 596 } 597 } 598 } 599 600 if (dirmodule == NULL && dirmap == NULL) { 601 nvlist_free(nvl); 602 mutex_exit(&devname_nsmaps_lock); 603 return (-1); 604 } 605 606 sdcmn_err6(("sdev_nsmaps_register: dir %s module %s map %s\n", 607 dirname, dirmodule, dirmap)); 608 sdev_insert_nsmap(dirname, dirmodule, dirmap); 609 mapcount++; 610 } 611 612 if (mapcount > 0) 613 devname_nsmaps_loaded = 1; 614 615 /* clean up obsolete nsmaps */ 616 sdev_validate_nsmaps(); 617 mutex_exit(&devname_nsmaps_lock); 618 if (nvl) 619 nvlist_free(nvl); 620 621 if (sdev_nsrdr_thread_created) { 622 return (0); 623 } 624 625 mutex_init(&sdev_nsrdr_thread_lock, NULL, MUTEX_DEFAULT, NULL); 626 cv_init(&sdev_nsrdr_thread_cv, NULL, CV_DEFAULT, NULL); 627 (void) thread_create(NULL, 0, (void (*)())sdev_nsrdr_thread, NULL, 0, 628 &p0, TS_RUN, minclsyspri); 629 sdev_nsrdr_thread_created = 1; 630 631 return (0); 632 } 633 634 void 635 sdev_dispatch_to_nsrdr_thread(struct sdev_node *ddv, char *dir_map, 636 devname_rdr_result_t *result) 637 { 638 sdev_nsrdr_work_t *new_work; 639 640 new_work = kmem_zalloc(sizeof (sdev_nsrdr_work_t), KM_SLEEP); 641 new_work->dir_name = i_ddi_strdup(ddv->sdev_name, KM_SLEEP); 642 new_work->dir_map = i_ddi_strdup(dir_map, KM_SLEEP); 643 new_work->dir_dv = ddv; 644 new_work->result = &result; 645 mutex_enter(&sdev_nsrdr_thread_lock); 646 if (sdev_nsrdr_thread_workq == NULL) { 647 sdev_nsrdr_thread_workq = new_work; 648 sdev_nsrdr_thread_tail = new_work; 649 new_work->next = NULL; 650 } else { 651 sdev_nsrdr_thread_tail->next = new_work; 652 sdev_nsrdr_thread_tail = new_work; 653 new_work->next = NULL; 654 } 655 cv_signal(&sdev_nsrdr_thread_cv); 656 mutex_exit(&sdev_nsrdr_thread_lock); 657 } 658 659 static void 660 sdev_devfsadmd_nsrdr(sdev_nsrdr_work_t *work) 661 { 662 int32_t error; 663 struct sdev_door_arg *argp; 664 struct sdev_door_res res; 665 struct sdev_node *ddv = work->dir_dv; 666 uint32_t mapcount; 667 668 argp = kmem_zalloc(sizeof (sdev_door_arg_t), KM_SLEEP); 669 argp->devfsadm_cmd = DEVFSADMD_NS_READDIR; 670 671 (void) snprintf(argp->ns_hdl.ns_name, 672 strlen(work->dir_dv->sdev_path) + 1, "%s", work->dir_dv->sdev_path); 673 (void) snprintf(argp->ns_hdl.ns_map, strlen(work->dir_map) + 1, "%s", 674 work->dir_map); 675 676 sdcmn_err6(("sdev_devfsadmd_nsrdr: ns_name %s, ns_map %s\n", 677 argp->ns_hdl.ns_name, argp->ns_hdl.ns_map)); 678 error = sdev_ki_call_devfsadmd(argp, &res); 679 sdcmn_err6(("sdev_devfsadmd_nsrdr error %d\n", error)); 680 if (error == 0) { 681 error = res.devfsadm_error; 682 if (error) { 683 goto out; 684 } 685 686 mapcount = (uint32_t)res.ns_rdr_hdl.ns_mapcount; 687 sdcmn_err6(("nsmapcount %d\n", mapcount)); 688 if (mapcount > 0) { 689 struct devname_nsmap *map = 690 ddv->sdev_mapinfo; 691 ASSERT(map && map->dir_map); 692 rw_enter(&map->dir_lock, RW_WRITER); 693 map->dir_maploaded = 1; 694 rw_exit(&map->dir_lock); 695 } 696 } 697 698 out: 699 mutex_enter(&ddv->sdev_lookup_lock); 700 SDEV_UNBLOCK_OTHERS(ddv, SDEV_READDIR); 701 mutex_exit(&ddv->sdev_lookup_lock); 702 703 kmem_free(argp, sizeof (sdev_door_arg_t)); 704 } 705 706 707 int 708 devname_nsmap_lookup(devname_lkp_arg_t *args, devname_lkp_result_t **result) 709 { 710 int32_t error = 0; 711 struct sdev_door_arg *argp; 712 struct sdev_door_res resp; 713 char *link; 714 uint8_t spec; 715 716 argp = kmem_zalloc(sizeof (sdev_door_arg_t), KM_SLEEP); 717 argp->devfsadm_cmd = DEVFSADMD_NS_LOOKUP; 718 719 (void) snprintf(argp->ns_hdl.ns_name, strlen(args->devname_name) + 1, 720 "%s", args->devname_name); 721 (void) snprintf(argp->ns_hdl.ns_map, strlen(args->devname_map) + 1, 722 "%s", args->devname_map); 723 724 error = sdev_ki_call_devfsadmd(argp, &resp); 725 if (error == 0) { 726 error = resp.devfsadm_error; 727 sdcmn_err6(("devfsadm: error %d\n", error)); 728 if (error) { 729 goto done; 730 } 731 link = resp.ns_lkp_hdl.devfsadm_link; 732 if (link == NULL) { 733 error = ENOENT; 734 goto done; 735 } 736 spec = resp.ns_lkp_hdl.devfsadm_spec; 737 sdcmn_err6(("devfsadm_link %s spec %d\n", link, spec)); 738 739 740 (*result)->devname_spec = (devname_spec_t)spec; 741 (*result)->devname_link = i_ddi_strdup(link, KM_SLEEP); 742 } else { 743 (*result)->devname_spec = DEVNAME_NS_NONE; 744 (*result)->devname_link = NULL; 745 } 746 done: 747 kmem_free(argp, sizeof (sdev_door_arg_t)); 748 return (error); 749 } 750