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 * 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_limited(sdev_upcall_door, &darg, 328 NULL, SIZE_MAX, 0)) == 0) { 329 sdcmn_err6(("call devfsadm: upcall lookup ok\n")); 330 break; 331 } 332 333 /* 334 * handle door call errors 335 */ 336 if (sdev_devfsadm_revoked()) { 337 sdcmn_err6(("upcall lookup door revoked, " 338 "error %d\n", error)); 339 return (error); 340 } 341 342 switch (error) { 343 case EINTR: 344 /* return error here? */ 345 sdcmn_err6(("sdev_ki_call_devfsadm: EINTR\n")); 346 delay(hz); 347 break; 348 case EAGAIN: 349 sdcmn_err6(("sdev_ki_call_devfsadm: EAGAIN\n")); 350 delay(2 * hz); 351 break; 352 case EBADF: 353 if (retry > 4) { 354 sdcmn_err6(("sdev_ki_call_devfsadm: EBADF\n")); 355 return (EBADF); 356 } 357 sdcmn_err6(( 358 "sdev_ki_call_devfsadm: EBADF, re-binding\n")); 359 sdev_release_door(); 360 delay(retry * hz); 361 error = sdev_open_upcall_door(); 362 if (error != 0) { 363 sdcmn_err6(("sdev_ki_call_devfsadm: " 364 "EBADF lookup error %d\n", error)); 365 if (!sdev_devfsadm_revoked()) 366 cmn_err(CE_NOTE, 367 "?unable to invoke devfsadm - " 368 "please run manually\n"); 369 return (EBADF); 370 } 371 break; 372 case EINVAL: 373 default: 374 cmn_err(CE_CONT, 375 "?sdev: door_ki_upcall unexpected result %d\n", 376 error); 377 return (error); 378 } 379 380 darg = save_arg; 381 } 382 383 if (!error) { 384 ASSERT((struct sdev_door_res *)(intptr_t)darg.rbuf == resultp); 385 if (resultp->devfsadm_error != 0) { 386 sdcmn_err6(("sdev_ki_call_devfsadmd: result %d\n", 387 resultp->devfsadm_error)); 388 error = resultp->devfsadm_error; 389 } 390 } else { 391 sdcmn_err6(("sdev_ki_call_devfsadmd with error %d\n", error)); 392 } 393 394 return (error); 395 } 396 397 static int 398 sdev_devfsadm_revoked(void) 399 { 400 struct door_info info; 401 int rv; 402 extern int sys_shutdown; 403 404 if (sys_shutdown) { 405 sdcmn_err6(("dev: shutdown observed\n")); 406 return (1); 407 } 408 409 if (sdev_upcall_door && !sdev_upcall_door_revoked) { 410 rv = door_ki_info(sdev_upcall_door, &info); 411 if ((rv == 0) && info.di_attributes & DOOR_REVOKED) { 412 sdcmn_err6(("lookup door: revoked\n")); 413 sdev_upcall_door_revoked = 1; 414 } 415 } 416 417 return (sdev_upcall_door_revoked); 418 } 419 420 /*ARGSUSED*/ 421 static void 422 sdev_config_all_thread(struct sdev_node *dv) 423 { 424 int32_t error = 0; 425 sdev_door_arg_t *argp; 426 sdev_door_res_t result; 427 428 argp = kmem_zalloc(sizeof (sdev_door_arg_t), KM_SLEEP); 429 argp->devfsadm_cmd = DEVFSADMD_RUN_ALL; 430 431 error = sdev_ki_call_devfsadmd(argp, &result); 432 if (!error) { 433 sdcmn_err6(("devfsadm result error: %d\n", 434 result.devfsadm_error)); 435 if (!result.devfsadm_error) { 436 DEVNAME_DEVFSADM_SET_RUN(devfsadm_state); 437 } else { 438 DEVNAME_DEVFSADM_SET_STOP(devfsadm_state); 439 } 440 } else { 441 DEVNAME_DEVFSADM_SET_STOP(devfsadm_state); 442 } 443 444 kmem_free(argp, sizeof (sdev_door_arg_t)); 445 done: 446 sdcmn_err6(("sdev_config_all_thread: stopping, devfsadm state 0x%x\n", 447 devfsadm_state)); 448 thread_exit(); 449 } 450 451 /* 452 * launch an asynchronous thread to do the devfsadm dev_config_all 453 */ 454 /*ARGSUSED*/ 455 void 456 sdev_devfsadmd_thread(struct sdev_node *ddv, struct sdev_node *dv, 457 struct cred *cred) 458 { 459 ASSERT(i_ddi_io_initialized()); 460 DEVNAME_DEVFSADM_SET_RUNNING(devfsadm_state); 461 (void) thread_create(NULL, 0, sdev_config_all_thread, dv, 0, 462 &p0, TS_RUN, MINCLSYSPRI); 463 } 464 465 int 466 devname_filename_register(int cmd, char *name) 467 { 468 int error = 0; 469 char *strbuf; 470 char *namep; 471 int n; 472 473 ASSERT(cmd == MODDEVNAME_LOOKUPDOOR || 474 cmd == MODDEVNAME_DEVFSADMNODE); 475 476 strbuf = kmem_zalloc(MOD_MAXPATH, KM_SLEEP); 477 478 if (copyinstr(name, strbuf, MOD_MAXPATH, 0)) { 479 sdcmn_err6(("error copyin \n")); 480 error = EFAULT; 481 } else { 482 sdcmn_err6(("file %s is registering\n", strbuf)); 483 switch (cmd) { 484 case MODDEVNAME_LOOKUPDOOR: 485 /* handling the daemon re-start situations */ 486 n = strlen(strbuf) + 1; 487 namep = i_ddi_strdup(strbuf, KM_SLEEP); 488 mutex_enter(&devfsadm_lock); 489 sdev_release_door(); 490 sdev_door_upcall_filename_size = n; 491 sdev_door_upcall_filename = namep; 492 sdcmn_err6(("size %d file name %s\n", 493 sdev_door_upcall_filename_size, 494 sdev_door_upcall_filename)); 495 cv_broadcast(&devfsadm_cv); 496 mutex_exit(&devfsadm_lock); 497 break; 498 case MODDEVNAME_DEVFSADMNODE: 499 break; 500 } 501 } 502 503 kmem_free(strbuf, MOD_MAXPATH); 504 return (error); 505 } 506 static void 507 sdev_nsrdr_thread(void) 508 { 509 sdev_nsrdr_work_t *work; 510 511 for (;;) { 512 mutex_enter(&sdev_nsrdr_thread_lock); 513 if (sdev_nsrdr_thread_workq == NULL) { 514 cv_wait(&sdev_nsrdr_thread_cv, &sdev_nsrdr_thread_lock); 515 } 516 work = sdev_nsrdr_thread_workq; 517 sdev_nsrdr_thread_workq = work->next; 518 if (sdev_nsrdr_thread_tail == work) 519 sdev_nsrdr_thread_tail = work->next; 520 mutex_exit(&sdev_nsrdr_thread_lock); 521 sdev_devfsadmd_nsrdr(work); 522 } 523 /*NOTREACHED*/ 524 } 525 526 int 527 devname_nsmaps_register(char *nvlbuf, size_t nvlsize) 528 { 529 int error = 0; 530 nvlist_t *nvl, *attrs; 531 nvpair_t *nvp = NULL; 532 nvpair_t *kvp = NULL; 533 char *buf; 534 char *key; 535 char *dirname = NULL; 536 char *dirmodule = NULL; 537 char *dirmap = NULL; 538 char *orig_module; 539 char *orig_map; 540 int len = 0; 541 char *tmpmap; 542 int mapcount = 0; 543 544 buf = kmem_zalloc(nvlsize, KM_SLEEP); 545 if ((error = ddi_copyin(nvlbuf, buf, nvlsize, 0)) != 0) { 546 kmem_free(buf, nvlsize); 547 return (error); 548 } 549 550 ASSERT(buf); 551 sdcmn_err6(("devname_nsmaps_register: nsmap buf %p\n", (void *)buf)); 552 nvl = NULL; 553 error = nvlist_unpack(buf, nvlsize, &nvl, KM_SLEEP); 554 kmem_free(buf, nvlsize); 555 if (error || (nvl == NULL)) 556 return (error); 557 558 /* invalidate all the nsmaps */ 559 mutex_enter(&devname_nsmaps_lock); 560 sdev_invalidate_nsmaps(); 561 for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL; 562 nvp = nvlist_next_nvpair(nvl, nvp)) { 563 dirname = nvpair_name(nvp); 564 if (dirname == NULL) { 565 nvlist_free(nvl); 566 mutex_exit(&devname_nsmaps_lock); 567 return (-1); 568 } 569 570 sdcmn_err6(("dirname %s\n", dirname)); 571 (void) nvpair_value_nvlist(nvp, &attrs); 572 for (kvp = nvlist_next_nvpair(attrs, NULL); kvp; 573 kvp = nvlist_next_nvpair(attrs, kvp)) { 574 key = nvpair_name(kvp); 575 sdcmn_err6(("key %s\n", key)); 576 if (strcmp(key, "module") == 0) { 577 (void) nvpair_value_string(kvp, &orig_module); 578 sdcmn_err6(("module %s\n", orig_module)); 579 dirmodule = i_ddi_strdup(orig_module, KM_SLEEP); 580 if (strcmp(dirmodule, "devname_null") == 0) 581 dirmodule = NULL; 582 } 583 584 if (strcmp(key, "nsconfig") == 0) { 585 (void) nvpair_value_string(kvp, &orig_map); 586 sdcmn_err6(("dirmap %s\n", orig_map)); 587 dirmap = i_ddi_strdup(orig_map, KM_SLEEP); 588 if (strcmp(dirmap, "devname_null") == 0) 589 dirmap = NULL; 590 else if (dirmap[0] != '/') { 591 len = strlen(dirmap) + 592 strlen(ETC_DEV_DIR) + 2; 593 tmpmap = i_ddi_strdup(dirmap, KM_SLEEP); 594 (void) snprintf(dirmap, len, "%s/%s", 595 ETC_DEV_DIR, tmpmap); 596 kmem_free(tmpmap, strlen(tmpmap) + 1); 597 } 598 } 599 } 600 601 if (dirmodule == NULL && dirmap == NULL) { 602 nvlist_free(nvl); 603 mutex_exit(&devname_nsmaps_lock); 604 return (-1); 605 } 606 607 sdcmn_err6(("sdev_nsmaps_register: dir %s module %s map %s\n", 608 dirname, dirmodule, dirmap)); 609 sdev_insert_nsmap(dirname, dirmodule, dirmap); 610 mapcount++; 611 } 612 613 if (mapcount > 0) 614 devname_nsmaps_loaded = 1; 615 616 /* clean up obsolete nsmaps */ 617 sdev_validate_nsmaps(); 618 mutex_exit(&devname_nsmaps_lock); 619 if (nvl) 620 nvlist_free(nvl); 621 622 if (sdev_nsrdr_thread_created) { 623 return (0); 624 } 625 626 mutex_init(&sdev_nsrdr_thread_lock, NULL, MUTEX_DEFAULT, NULL); 627 cv_init(&sdev_nsrdr_thread_cv, NULL, CV_DEFAULT, NULL); 628 (void) thread_create(NULL, 0, (void (*)())sdev_nsrdr_thread, NULL, 0, 629 &p0, TS_RUN, minclsyspri); 630 sdev_nsrdr_thread_created = 1; 631 632 return (0); 633 } 634 635 void 636 sdev_dispatch_to_nsrdr_thread(struct sdev_node *ddv, char *dir_map, 637 devname_rdr_result_t *result) 638 { 639 sdev_nsrdr_work_t *new_work; 640 641 new_work = kmem_zalloc(sizeof (sdev_nsrdr_work_t), KM_SLEEP); 642 new_work->dir_name = i_ddi_strdup(ddv->sdev_name, KM_SLEEP); 643 new_work->dir_map = i_ddi_strdup(dir_map, KM_SLEEP); 644 new_work->dir_dv = ddv; 645 new_work->result = &result; 646 mutex_enter(&sdev_nsrdr_thread_lock); 647 if (sdev_nsrdr_thread_workq == NULL) { 648 sdev_nsrdr_thread_workq = new_work; 649 sdev_nsrdr_thread_tail = new_work; 650 new_work->next = NULL; 651 } else { 652 sdev_nsrdr_thread_tail->next = new_work; 653 sdev_nsrdr_thread_tail = new_work; 654 new_work->next = NULL; 655 } 656 cv_signal(&sdev_nsrdr_thread_cv); 657 mutex_exit(&sdev_nsrdr_thread_lock); 658 } 659 660 static void 661 sdev_devfsadmd_nsrdr(sdev_nsrdr_work_t *work) 662 { 663 int32_t error; 664 struct sdev_door_arg *argp; 665 struct sdev_door_res res; 666 struct sdev_node *ddv = work->dir_dv; 667 uint32_t mapcount; 668 669 argp = kmem_zalloc(sizeof (sdev_door_arg_t), KM_SLEEP); 670 argp->devfsadm_cmd = DEVFSADMD_NS_READDIR; 671 672 (void) snprintf(argp->ns_hdl.ns_name, 673 strlen(work->dir_dv->sdev_path) + 1, "%s", work->dir_dv->sdev_path); 674 (void) snprintf(argp->ns_hdl.ns_map, strlen(work->dir_map) + 1, "%s", 675 work->dir_map); 676 677 sdcmn_err6(("sdev_devfsadmd_nsrdr: ns_name %s, ns_map %s\n", 678 argp->ns_hdl.ns_name, argp->ns_hdl.ns_map)); 679 error = sdev_ki_call_devfsadmd(argp, &res); 680 sdcmn_err6(("sdev_devfsadmd_nsrdr error %d\n", error)); 681 if (error == 0) { 682 error = res.devfsadm_error; 683 if (error) { 684 goto out; 685 } 686 687 mapcount = (uint32_t)res.ns_rdr_hdl.ns_mapcount; 688 sdcmn_err6(("nsmapcount %d\n", mapcount)); 689 if (mapcount > 0) { 690 struct devname_nsmap *map = 691 ddv->sdev_mapinfo; 692 ASSERT(map && map->dir_map); 693 rw_enter(&map->dir_lock, RW_WRITER); 694 map->dir_maploaded = 1; 695 rw_exit(&map->dir_lock); 696 } 697 } 698 699 out: 700 mutex_enter(&ddv->sdev_lookup_lock); 701 SDEV_UNBLOCK_OTHERS(ddv, SDEV_READDIR); 702 mutex_exit(&ddv->sdev_lookup_lock); 703 704 kmem_free(argp, sizeof (sdev_door_arg_t)); 705 } 706 707 708 int 709 devname_nsmap_lookup(devname_lkp_arg_t *args, devname_lkp_result_t **result) 710 { 711 int32_t error = 0; 712 struct sdev_door_arg *argp; 713 struct sdev_door_res resp; 714 char *link; 715 devname_spec_t spec; 716 717 argp = kmem_zalloc(sizeof (sdev_door_arg_t), KM_SLEEP); 718 argp->devfsadm_cmd = DEVFSADMD_NS_LOOKUP; 719 720 (void) snprintf(argp->ns_hdl.ns_name, strlen(args->devname_name) + 1, 721 "%s", args->devname_name); 722 (void) snprintf(argp->ns_hdl.ns_map, strlen(args->devname_map) + 1, 723 "%s", args->devname_map); 724 725 error = sdev_ki_call_devfsadmd(argp, &resp); 726 if (error == 0) { 727 error = resp.devfsadm_error; 728 sdcmn_err6(("devfsadm: error %d\n", error)); 729 if (error) { 730 goto done; 731 } 732 link = resp.ns_lkp_hdl.devfsadm_link; 733 if (link == NULL) { 734 error = ENOENT; 735 goto done; 736 } 737 spec = resp.ns_lkp_hdl.devfsadm_spec; 738 sdcmn_err6(("devfsadm_link %s spec %d\n", 739 link, (int)spec)); 740 741 742 (*result)->devname_spec = (devname_spec_t)spec; 743 (*result)->devname_link = i_ddi_strdup(link, KM_SLEEP); 744 } else { 745 (*result)->devname_spec = DEVNAME_NS_NONE; 746 (*result)->devname_link = NULL; 747 } 748 done: 749 kmem_free(argp, sizeof (sdev_door_arg_t)); 750 return (error); 751 } 752