12621Sllai1 /* 22621Sllai1 * CDDL HEADER START 32621Sllai1 * 42621Sllai1 * The contents of this file are subject to the terms of the 52621Sllai1 * Common Development and Distribution License (the "License"). 62621Sllai1 * You may not use this file except in compliance with the License. 72621Sllai1 * 82621Sllai1 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92621Sllai1 * or http://www.opensolaris.org/os/licensing. 102621Sllai1 * See the License for the specific language governing permissions 112621Sllai1 * and limitations under the License. 122621Sllai1 * 132621Sllai1 * When distributing Covered Code, include this CDDL HEADER in each 142621Sllai1 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152621Sllai1 * If applicable, add the following below this CDDL HEADER, with the 162621Sllai1 * fields enclosed by brackets "[]" replaced with your own identifying 172621Sllai1 * information: Portions Copyright [yyyy] [name of copyright owner] 182621Sllai1 * 192621Sllai1 * CDDL HEADER END 202621Sllai1 */ 212621Sllai1 /* 22*10097SEric.Taylor@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 232621Sllai1 * Use is subject to license terms. 242621Sllai1 */ 252621Sllai1 262621Sllai1 /* 272621Sllai1 * routines to invoke user level name lookup services 282621Sllai1 */ 292621Sllai1 302621Sllai1 #include <sys/types.h> 312621Sllai1 #include <sys/param.h> 322621Sllai1 #include <sys/t_lock.h> 332621Sllai1 #include <sys/systm.h> 342621Sllai1 #include <sys/sysmacros.h> 352621Sllai1 #include <sys/user.h> 362621Sllai1 #include <sys/time.h> 372621Sllai1 #include <sys/vfs.h> 382621Sllai1 #include <sys/vnode.h> 392621Sllai1 #include <sys/file.h> 402621Sllai1 #include <sys/fcntl.h> 412621Sllai1 #include <sys/flock.h> 422621Sllai1 #include <sys/kmem.h> 432621Sllai1 #include <sys/uio.h> 442621Sllai1 #include <sys/errno.h> 452621Sllai1 #include <sys/stat.h> 462621Sllai1 #include <sys/cred.h> 472621Sllai1 #include <sys/dirent.h> 482621Sllai1 #include <sys/pathname.h> 492621Sllai1 #include <sys/cmn_err.h> 502621Sllai1 #include <sys/debug.h> 512621Sllai1 #include <sys/mode.h> 522621Sllai1 #include <sys/policy.h> 532621Sllai1 #include <sys/disp.h> 542621Sllai1 #include <sys/door.h> 552621Sllai1 #include <fs/fs_subr.h> 562621Sllai1 #include <sys/mount.h> 572621Sllai1 #include <sys/fs/snode.h> 582621Sllai1 #include <sys/fs/dv_node.h> 592621Sllai1 #include <sys/fs/sdev_impl.h> 602621Sllai1 #include <sys/sunndi.h> 612621Sllai1 #include <sys/sunddi.h> 622621Sllai1 #include <sys/sunmdi.h> 632621Sllai1 #include <sys/conf.h> 642621Sllai1 #include <sys/modctl.h> 652621Sllai1 #include <sys/ddi.h> 662621Sllai1 672621Sllai1 /* default timeout to wait for devfsadm response in seconds */ 682621Sllai1 #define DEV_DEVFSADM_STARTUP (1 * 60) 692621Sllai1 #define DEV_NODE_WAIT_TIMEOUT (5 * 60) 702621Sllai1 712621Sllai1 /* atomic bitset for devfsadm status */ 722621Sllai1 volatile uint_t devfsadm_state; 732621Sllai1 742621Sllai1 static kmutex_t devfsadm_lock; 752621Sllai1 static kcondvar_t devfsadm_cv; 762621Sllai1 772621Sllai1 static int dev_node_wait_timeout = DEV_NODE_WAIT_TIMEOUT; 782621Sllai1 static int dev_devfsadm_startup = DEV_DEVFSADM_STARTUP; 792621Sllai1 802621Sllai1 /* 812621Sllai1 * Door used to communicate with devfsadmd 822621Sllai1 */ 832621Sllai1 static door_handle_t sdev_upcall_door = NULL; /* Door for upcalls */ 842621Sllai1 static char *sdev_door_upcall_filename = NULL; 852621Sllai1 static int sdev_upcall_door_revoked = 0; 862621Sllai1 static int sdev_door_upcall_filename_size; 872621Sllai1 882621Sllai1 static int sdev_devfsadm_revoked(void); 892621Sllai1 static int sdev_ki_call_devfsadmd(sdev_door_arg_t *, sdev_door_res_t *); 902621Sllai1 912621Sllai1 void 922621Sllai1 sdev_devfsadm_lockinit(void) 932621Sllai1 { 942621Sllai1 mutex_init(&devfsadm_lock, NULL, MUTEX_DEFAULT, NULL); 952621Sllai1 cv_init(&devfsadm_cv, NULL, CV_DEFAULT, NULL); 962621Sllai1 } 972621Sllai1 982621Sllai1 void 992621Sllai1 sdev_devfsadm_lockdestroy(void) 1002621Sllai1 { 1012621Sllai1 mutex_destroy(&devfsadm_lock); 1022621Sllai1 cv_destroy(&devfsadm_cv); 1032621Sllai1 } 1042621Sllai1 1052621Sllai1 /* 1062621Sllai1 * Wait for node to be created 1072621Sllai1 */ 1082621Sllai1 int 1092621Sllai1 sdev_wait4lookup(struct sdev_node *dv, int cmd) 1102621Sllai1 { 1112621Sllai1 clock_t expire; 1122621Sllai1 clock_t rv; 1132621Sllai1 int rval = ENOENT; 1142621Sllai1 int is_lookup = (cmd == SDEV_LOOKUP); 1152621Sllai1 1162621Sllai1 ASSERT(cmd == SDEV_LOOKUP || cmd == SDEV_READDIR); 1172621Sllai1 ASSERT(MUTEX_HELD(&dv->sdev_lookup_lock)); 1182621Sllai1 1192621Sllai1 /* tick value at which wait expires */ 1202621Sllai1 expire = ddi_get_lbolt() + 1212621Sllai1 drv_usectohz(dev_node_wait_timeout * 1000000); 1222621Sllai1 1232621Sllai1 sdcmn_err6(("wait4lookup %s %s, %ld %d\n", 1242621Sllai1 is_lookup ? "lookup" : "readdir", 1252621Sllai1 dv->sdev_name, expire - ddi_get_lbolt(), dv->sdev_state)); 1262621Sllai1 1272621Sllai1 if (SDEV_IS_LGWAITING(dv)) { 1282621Sllai1 /* devfsadm nodes */ 1292621Sllai1 while (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state) && 1302621Sllai1 !sdev_devfsadm_revoked()) { 1312621Sllai1 /* wait 2 sec and check devfsadm completion */ 1322621Sllai1 rv = cv_timedwait_sig(&dv->sdev_lookup_cv, 1332621Sllai1 &dv->sdev_lookup_lock, ddi_get_lbolt() + 1342621Sllai1 drv_usectohz(2 * 1000000)); 1352621Sllai1 1362621Sllai1 if (is_lookup && (rv > 0)) { 1372621Sllai1 /* was this node constructed ? */ 1382621Sllai1 if (dv->sdev_state == SDEV_READY) { 1392621Sllai1 rval = 0; 1402621Sllai1 } 1412621Sllai1 sdcmn_err6(("%s: wait done, %screated %d\n", 1422621Sllai1 dv->sdev_name, rval ? "not " : "", 1432621Sllai1 dv->sdev_state)); 1442621Sllai1 break; 1452621Sllai1 } else if (rv == 0) { 1462621Sllai1 /* interrupted */ 1472621Sllai1 sdcmn_err6(("%s: wait interrupted\n", 1482621Sllai1 dv->sdev_name)); 1492621Sllai1 break; 1502621Sllai1 } else if ((rv == -1) && 1512621Sllai1 (ddi_get_lbolt() >= expire)) { 1522621Sllai1 sdcmn_err6(("%s: wait time is up\n", 153*10097SEric.Taylor@Sun.COM dv->sdev_name)); 1542621Sllai1 break; 1552621Sllai1 } 1562621Sllai1 sdcmn_err6(("%s: wait " 1572621Sllai1 "rv %ld state 0x%x expire %ld\n", 1582621Sllai1 dv->sdev_name, rv, devfsadm_state, 1592621Sllai1 expire - ddi_get_lbolt())); 1602621Sllai1 } 1612621Sllai1 } else { 1622621Sllai1 /* 1632621Sllai1 * for the nodes created by 1642621Sllai1 * devname_lookup_func callback 1652621Sllai1 * or plug-in modules 1662621Sllai1 */ 1672621Sllai1 while (SDEV_IS_LOOKUP(dv) || SDEV_IS_READDIR(dv)) { 1682621Sllai1 cv_wait(&dv->sdev_lookup_cv, &dv->sdev_lookup_lock); 1692621Sllai1 } 1702621Sllai1 rval = 0; 1712621Sllai1 } 1722621Sllai1 1732621Sllai1 sdcmn_err6(("wait4lookup unblocking %s state 0x%x %d\n", 1742621Sllai1 dv->sdev_name, devfsadm_state, dv->sdev_state)); 1752621Sllai1 1762621Sllai1 if (is_lookup) { 1772621Sllai1 SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP); 1782621Sllai1 } else { 1792621Sllai1 SDEV_UNBLOCK_OTHERS(dv, SDEV_READDIR); 1802621Sllai1 } 1812621Sllai1 1822621Sllai1 return (rval); 1832621Sllai1 } 1842621Sllai1 1852621Sllai1 void 1862621Sllai1 sdev_unblock_others(struct sdev_node *dv, uint_t cmd) 1872621Sllai1 { 1882621Sllai1 ASSERT(MUTEX_HELD(&dv->sdev_lookup_lock)); 1892621Sllai1 1902621Sllai1 SDEV_CLEAR_LOOKUP_FLAGS(dv, cmd); 1912621Sllai1 if (SDEV_IS_LGWAITING(dv)) { 1922621Sllai1 SDEV_CLEAR_LOOKUP_FLAGS(dv, SDEV_LGWAITING); 1932621Sllai1 } 1942621Sllai1 cv_broadcast(&dv->sdev_lookup_cv); 1952621Sllai1 } 1962621Sllai1 1972621Sllai1 /* 1982621Sllai1 * In the case devfsadmd is down, it is re-started by syseventd 1992621Sllai1 * upon receiving an event subscribed to by devfsadmd. 2002621Sllai1 */ 2012621Sllai1 static int 2022621Sllai1 sdev_start_devfsadmd() 2032621Sllai1 { 2042621Sllai1 int se_err = 0; 2052621Sllai1 sysevent_t *ev; 2062621Sllai1 sysevent_id_t eid; 2072621Sllai1 2082621Sllai1 ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_START, EP_DDI, SE_SLEEP); 2092621Sllai1 ASSERT(ev); 2102621Sllai1 if ((se_err = log_sysevent(ev, SE_SLEEP, &eid)) != 0) { 2112621Sllai1 switch (se_err) { 2122621Sllai1 case SE_NO_TRANSPORT: 2132621Sllai1 cmn_err(CE_WARN, "unable to start devfsadm - " 2142621Sllai1 "syseventd may not be responding\n"); 2152621Sllai1 break; 2162621Sllai1 default: 2172621Sllai1 cmn_err(CE_WARN, "unable to start devfsadm - " 2182621Sllai1 "sysevent error %d\n", se_err); 2192621Sllai1 break; 2202621Sllai1 } 2212621Sllai1 } 2222621Sllai1 2232621Sllai1 sysevent_free(ev); 2242621Sllai1 return (se_err); 2252621Sllai1 } 2262621Sllai1 2272621Sllai1 static int 2282621Sllai1 sdev_open_upcall_door() 2292621Sllai1 { 2302621Sllai1 int error; 2312621Sllai1 clock_t rv; 2322621Sllai1 clock_t expire; 2332621Sllai1 2342621Sllai1 ASSERT(sdev_upcall_door == NULL); 2352621Sllai1 2362621Sllai1 /* tick value at which wait expires */ 2372621Sllai1 expire = ddi_get_lbolt() + 2382621Sllai1 drv_usectohz(dev_devfsadm_startup * 1000000); 2392621Sllai1 2402621Sllai1 if (sdev_door_upcall_filename == NULL) { 2412621Sllai1 if ((error = sdev_start_devfsadmd()) != 0) { 2422621Sllai1 return (error); 2432621Sllai1 } 2442621Sllai1 2452621Sllai1 /* wait for devfsadmd start */ 2462621Sllai1 mutex_enter(&devfsadm_lock); 2472621Sllai1 while (sdev_door_upcall_filename == NULL) { 2482621Sllai1 sdcmn_err6(("waiting for dev_door creation, %ld\n", 2492621Sllai1 expire - ddi_get_lbolt())); 2502621Sllai1 rv = cv_timedwait_sig(&devfsadm_cv, &devfsadm_lock, 2512621Sllai1 expire); 2522621Sllai1 sdcmn_err6(("dev_door wait rv %ld\n", rv)); 2532621Sllai1 if (rv <= 0) { 2542621Sllai1 sdcmn_err6(("devfsadmd startup error\n")); 2552621Sllai1 mutex_exit(&devfsadm_lock); 2562621Sllai1 return (EBADF); 2572621Sllai1 } 2582621Sllai1 } 2592621Sllai1 sdcmn_err6(("devfsadmd is ready\n")); 2602621Sllai1 mutex_exit(&devfsadm_lock); 2612621Sllai1 } 2622621Sllai1 2632621Sllai1 if ((error = door_ki_open(sdev_door_upcall_filename, 2642621Sllai1 &sdev_upcall_door)) != 0) { 2652621Sllai1 sdcmn_err6(("upcall_lookup: door open error %d\n", 2662621Sllai1 error)); 2672621Sllai1 return (error); 2682621Sllai1 } 2692621Sllai1 2702621Sllai1 return (0); 2712621Sllai1 } 2722621Sllai1 2732621Sllai1 static void 2742621Sllai1 sdev_release_door() 2752621Sllai1 { 2762621Sllai1 if (sdev_upcall_door) { 2772621Sllai1 door_ki_rele(sdev_upcall_door); 2782621Sllai1 sdev_upcall_door = NULL; 2792621Sllai1 } 2802621Sllai1 if (sdev_door_upcall_filename) { 2812621Sllai1 kmem_free(sdev_door_upcall_filename, 2822621Sllai1 sdev_door_upcall_filename_size); 2832621Sllai1 sdev_door_upcall_filename = NULL; 2842621Sllai1 } 2852621Sllai1 } 2862621Sllai1 2872621Sllai1 static int 2882621Sllai1 sdev_ki_call_devfsadmd(sdev_door_arg_t *argp, sdev_door_res_t *resultp) 2892621Sllai1 { 2902621Sllai1 door_arg_t darg, save_arg; 2912621Sllai1 int error; 2922621Sllai1 int retry; 2932621Sllai1 2942621Sllai1 if (((sdev_upcall_door == NULL) && 2952621Sllai1 ((error = sdev_open_upcall_door()) != 0)) || 2962621Sllai1 sdev_devfsadm_revoked()) { 2972621Sllai1 sdcmn_err6(("call_devfsadm: upcall lookup error\n")); 2982621Sllai1 return (error); 2992621Sllai1 } 3002621Sllai1 3012621Sllai1 ASSERT(argp); 3022621Sllai1 darg.data_ptr = (char *)argp; 3032621Sllai1 darg.data_size = sizeof (struct sdev_door_arg); 3042621Sllai1 darg.desc_ptr = NULL; 3052621Sllai1 darg.desc_num = 0; 3062621Sllai1 darg.rbuf = (char *)(resultp); 3072621Sllai1 darg.rsize = sizeof (struct sdev_door_res); 3082621Sllai1 3092621Sllai1 ASSERT(sdev_upcall_door); 3102621Sllai1 save_arg = darg; 3112621Sllai1 for (retry = 0; ; retry++) { 3122621Sllai1 sdcmn_err6(("call devfsadm: upcall lookup, retry %d\n", retry)); 3136997Sjwadams if ((error = door_ki_upcall_limited(sdev_upcall_door, &darg, 3146997Sjwadams NULL, SIZE_MAX, 0)) == 0) { 3152621Sllai1 sdcmn_err6(("call devfsadm: upcall lookup ok\n")); 3162621Sllai1 break; 3172621Sllai1 } 3182621Sllai1 3192621Sllai1 /* 3202621Sllai1 * handle door call errors 3212621Sllai1 */ 3222621Sllai1 if (sdev_devfsadm_revoked()) { 3232621Sllai1 sdcmn_err6(("upcall lookup door revoked, " 3242621Sllai1 "error %d\n", error)); 3252621Sllai1 return (error); 3262621Sllai1 } 3272621Sllai1 3282621Sllai1 switch (error) { 3292621Sllai1 case EINTR: 3302621Sllai1 /* return error here? */ 3312621Sllai1 sdcmn_err6(("sdev_ki_call_devfsadm: EINTR\n")); 3322621Sllai1 delay(hz); 3332621Sllai1 break; 3342621Sllai1 case EAGAIN: 3352621Sllai1 sdcmn_err6(("sdev_ki_call_devfsadm: EAGAIN\n")); 3362621Sllai1 delay(2 * hz); 3372621Sllai1 break; 3382621Sllai1 case EBADF: 3392621Sllai1 if (retry > 4) { 3402621Sllai1 sdcmn_err6(("sdev_ki_call_devfsadm: EBADF\n")); 3412621Sllai1 return (EBADF); 3422621Sllai1 } 3432621Sllai1 sdcmn_err6(( 3442621Sllai1 "sdev_ki_call_devfsadm: EBADF, re-binding\n")); 3452621Sllai1 sdev_release_door(); 3462621Sllai1 delay(retry * hz); 3472621Sllai1 error = sdev_open_upcall_door(); 3482621Sllai1 if (error != 0) { 3492621Sllai1 sdcmn_err6(("sdev_ki_call_devfsadm: " 3502621Sllai1 "EBADF lookup error %d\n", error)); 3512621Sllai1 if (!sdev_devfsadm_revoked()) 3522621Sllai1 cmn_err(CE_NOTE, 3532621Sllai1 "?unable to invoke devfsadm - " 3542621Sllai1 "please run manually\n"); 3552621Sllai1 return (EBADF); 3562621Sllai1 } 3572621Sllai1 break; 3582621Sllai1 case EINVAL: 3592621Sllai1 default: 3602621Sllai1 cmn_err(CE_CONT, 3612621Sllai1 "?sdev: door_ki_upcall unexpected result %d\n", 3622621Sllai1 error); 3632621Sllai1 return (error); 3642621Sllai1 } 3652621Sllai1 3662621Sllai1 darg = save_arg; 3672621Sllai1 } 3682621Sllai1 3692621Sllai1 if (!error) { 3703133Sjg ASSERT((struct sdev_door_res *)(intptr_t)darg.rbuf == resultp); 3712621Sllai1 if (resultp->devfsadm_error != 0) { 3722621Sllai1 sdcmn_err6(("sdev_ki_call_devfsadmd: result %d\n", 3732621Sllai1 resultp->devfsadm_error)); 3742621Sllai1 error = resultp->devfsadm_error; 3752621Sllai1 } 3762621Sllai1 } else { 3772621Sllai1 sdcmn_err6(("sdev_ki_call_devfsadmd with error %d\n", error)); 3782621Sllai1 } 3792621Sllai1 3802621Sllai1 return (error); 3812621Sllai1 } 3822621Sllai1 3832621Sllai1 static int 3842621Sllai1 sdev_devfsadm_revoked(void) 3852621Sllai1 { 3862621Sllai1 struct door_info info; 3872621Sllai1 int rv; 3882621Sllai1 extern int sys_shutdown; 3892621Sllai1 3902621Sllai1 if (sys_shutdown) { 3912621Sllai1 sdcmn_err6(("dev: shutdown observed\n")); 3922621Sllai1 return (1); 3932621Sllai1 } 3942621Sllai1 3952621Sllai1 if (sdev_upcall_door && !sdev_upcall_door_revoked) { 3962621Sllai1 rv = door_ki_info(sdev_upcall_door, &info); 3972621Sllai1 if ((rv == 0) && info.di_attributes & DOOR_REVOKED) { 3982621Sllai1 sdcmn_err6(("lookup door: revoked\n")); 3992621Sllai1 sdev_upcall_door_revoked = 1; 4002621Sllai1 } 4012621Sllai1 } 4022621Sllai1 4032621Sllai1 return (sdev_upcall_door_revoked); 4042621Sllai1 } 4052621Sllai1 4062621Sllai1 /*ARGSUSED*/ 4072621Sllai1 static void 4082621Sllai1 sdev_config_all_thread(struct sdev_node *dv) 4092621Sllai1 { 4102621Sllai1 int32_t error = 0; 4112621Sllai1 sdev_door_arg_t *argp; 4122621Sllai1 sdev_door_res_t result; 4132621Sllai1 4142621Sllai1 argp = kmem_zalloc(sizeof (sdev_door_arg_t), KM_SLEEP); 4152621Sllai1 argp->devfsadm_cmd = DEVFSADMD_RUN_ALL; 4162621Sllai1 4172621Sllai1 error = sdev_ki_call_devfsadmd(argp, &result); 4182621Sllai1 if (!error) { 4192621Sllai1 sdcmn_err6(("devfsadm result error: %d\n", 4202621Sllai1 result.devfsadm_error)); 4212621Sllai1 if (!result.devfsadm_error) { 4222621Sllai1 DEVNAME_DEVFSADM_SET_RUN(devfsadm_state); 4232621Sllai1 } else { 4242621Sllai1 DEVNAME_DEVFSADM_SET_STOP(devfsadm_state); 4252621Sllai1 } 4262621Sllai1 } else { 4272621Sllai1 DEVNAME_DEVFSADM_SET_STOP(devfsadm_state); 4282621Sllai1 } 4292621Sllai1 4302621Sllai1 kmem_free(argp, sizeof (sdev_door_arg_t)); 4312621Sllai1 done: 4322621Sllai1 sdcmn_err6(("sdev_config_all_thread: stopping, devfsadm state 0x%x\n", 4332621Sllai1 devfsadm_state)); 4342621Sllai1 thread_exit(); 4352621Sllai1 } 4362621Sllai1 4372621Sllai1 /* 4382621Sllai1 * launch an asynchronous thread to do the devfsadm dev_config_all 4392621Sllai1 */ 4402621Sllai1 /*ARGSUSED*/ 4412621Sllai1 void 4422621Sllai1 sdev_devfsadmd_thread(struct sdev_node *ddv, struct sdev_node *dv, 4432621Sllai1 struct cred *cred) 4442621Sllai1 { 4452621Sllai1 ASSERT(i_ddi_io_initialized()); 4462621Sllai1 DEVNAME_DEVFSADM_SET_RUNNING(devfsadm_state); 4472621Sllai1 (void) thread_create(NULL, 0, sdev_config_all_thread, dv, 0, 4482621Sllai1 &p0, TS_RUN, MINCLSYSPRI); 4492621Sllai1 } 4502621Sllai1 4512621Sllai1 int 452*10097SEric.Taylor@Sun.COM devname_filename_register(char *name) 4532621Sllai1 { 4542621Sllai1 int error = 0; 4552621Sllai1 char *strbuf; 4562621Sllai1 char *namep; 4572621Sllai1 int n; 4582621Sllai1 4592621Sllai1 strbuf = kmem_zalloc(MOD_MAXPATH, KM_SLEEP); 4602621Sllai1 4612621Sllai1 if (copyinstr(name, strbuf, MOD_MAXPATH, 0)) { 4622621Sllai1 sdcmn_err6(("error copyin \n")); 4632621Sllai1 error = EFAULT; 4642621Sllai1 } else { 4652621Sllai1 sdcmn_err6(("file %s is registering\n", strbuf)); 466*10097SEric.Taylor@Sun.COM /* handling the daemon re-start situations */ 467*10097SEric.Taylor@Sun.COM n = strlen(strbuf) + 1; 468*10097SEric.Taylor@Sun.COM namep = i_ddi_strdup(strbuf, KM_SLEEP); 469*10097SEric.Taylor@Sun.COM mutex_enter(&devfsadm_lock); 470*10097SEric.Taylor@Sun.COM sdev_release_door(); 471*10097SEric.Taylor@Sun.COM sdev_door_upcall_filename_size = n; 472*10097SEric.Taylor@Sun.COM sdev_door_upcall_filename = namep; 473*10097SEric.Taylor@Sun.COM sdcmn_err6(("size %d file name %s\n", 474*10097SEric.Taylor@Sun.COM sdev_door_upcall_filename_size, 475*10097SEric.Taylor@Sun.COM sdev_door_upcall_filename)); 476*10097SEric.Taylor@Sun.COM cv_broadcast(&devfsadm_cv); 477*10097SEric.Taylor@Sun.COM mutex_exit(&devfsadm_lock); 4782621Sllai1 } 4792621Sllai1 4802621Sllai1 kmem_free(strbuf, MOD_MAXPATH); 4812621Sllai1 return (error); 4822621Sllai1 } 483