Print this page
XXXX introduce drv_sectohz
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/dev/sdev_comm.c
+++ new/usr/src/uts/common/fs/dev/sdev_comm.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /*
27 27 * routines to invoke user level name lookup services
28 28 */
29 29
30 30 #include <sys/types.h>
31 31 #include <sys/param.h>
32 32 #include <sys/t_lock.h>
33 33 #include <sys/systm.h>
34 34 #include <sys/sysmacros.h>
35 35 #include <sys/user.h>
36 36 #include <sys/time.h>
37 37 #include <sys/vfs.h>
38 38 #include <sys/vnode.h>
39 39 #include <sys/file.h>
40 40 #include <sys/fcntl.h>
41 41 #include <sys/flock.h>
42 42 #include <sys/kmem.h>
43 43 #include <sys/uio.h>
44 44 #include <sys/errno.h>
45 45 #include <sys/stat.h>
46 46 #include <sys/cred.h>
47 47 #include <sys/dirent.h>
48 48 #include <sys/pathname.h>
49 49 #include <sys/cmn_err.h>
50 50 #include <sys/debug.h>
51 51 #include <sys/mode.h>
52 52 #include <sys/policy.h>
53 53 #include <sys/disp.h>
54 54 #include <sys/door.h>
55 55 #include <fs/fs_subr.h>
56 56 #include <sys/mount.h>
57 57 #include <sys/fs/snode.h>
58 58 #include <sys/fs/dv_node.h>
59 59 #include <sys/fs/sdev_impl.h>
60 60 #include <sys/sunndi.h>
61 61 #include <sys/sunddi.h>
62 62 #include <sys/sunmdi.h>
63 63 #include <sys/conf.h>
64 64 #include <sys/modctl.h>
65 65 #include <sys/ddi.h>
66 66
67 67 /* default timeout to wait for devfsadm response in seconds */
68 68 #define DEV_DEVFSADM_STARTUP (1 * 60)
69 69 #define DEV_NODE_WAIT_TIMEOUT (5 * 60)
70 70
71 71 /* atomic bitset for devfsadm status */
72 72 volatile uint_t devfsadm_state;
73 73
74 74 static kmutex_t devfsadm_lock;
75 75 static kcondvar_t devfsadm_cv;
76 76
77 77 static int dev_node_wait_timeout = DEV_NODE_WAIT_TIMEOUT;
78 78 static int dev_devfsadm_startup = DEV_DEVFSADM_STARTUP;
79 79
80 80 /*
81 81 * Door used to communicate with devfsadmd
82 82 */
83 83 static door_handle_t sdev_upcall_door = NULL; /* Door for upcalls */
84 84 static char *sdev_door_upcall_filename = NULL;
85 85 static int sdev_upcall_door_revoked = 0;
86 86 static int sdev_door_upcall_filename_size;
87 87
88 88 static int sdev_devfsadm_revoked(void);
89 89 static int sdev_ki_call_devfsadmd(sdev_door_arg_t *, sdev_door_res_t *);
90 90
91 91 void
92 92 sdev_devfsadm_lockinit(void)
93 93 {
94 94 mutex_init(&devfsadm_lock, NULL, MUTEX_DEFAULT, NULL);
95 95 cv_init(&devfsadm_cv, NULL, CV_DEFAULT, NULL);
96 96 }
97 97
98 98 void
99 99 sdev_devfsadm_lockdestroy(void)
100 100 {
101 101 mutex_destroy(&devfsadm_lock);
102 102 cv_destroy(&devfsadm_cv);
↓ open down ↓ |
102 lines elided |
↑ open up ↑ |
103 103 }
104 104
105 105 /*
106 106 * Wait for node to be created
107 107 */
108 108 int
109 109 sdev_wait4lookup(struct sdev_node *dv, int cmd)
110 110 {
111 111 clock_t expire;
112 112 clock_t rv;
113 - clock_t wakeup = drv_usectohz(2 * 1000000);
113 + clock_t wakeup = drv_sectohz(2);
114 114 int rval = ENOENT;
115 115 int is_lookup = (cmd == SDEV_LOOKUP);
116 116
117 117 ASSERT(cmd == SDEV_LOOKUP || cmd == SDEV_READDIR);
118 118 ASSERT(MUTEX_HELD(&dv->sdev_lookup_lock));
119 119
120 120 /* tick value at which wait expires */
121 121 expire = ddi_get_lbolt() +
122 - drv_usectohz(dev_node_wait_timeout * 1000000);
122 + drv_sectohz(dev_node_wait_timeout);
123 123
124 124 sdcmn_err6(("wait4lookup %s %s, %ld %d\n",
125 125 is_lookup ? "lookup" : "readdir",
126 126 dv->sdev_name, expire - ddi_get_lbolt(), dv->sdev_state));
127 127
128 128 if (SDEV_IS_LGWAITING(dv)) {
129 129 /* devfsadm nodes */
130 130 while (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state) &&
131 131 !sdev_devfsadm_revoked()) {
132 132 /* wait 2 sec and check devfsadm completion */
133 133 rv = cv_reltimedwait_sig(&dv->sdev_lookup_cv,
134 134 &dv->sdev_lookup_lock, wakeup, TR_CLOCK_TICK);
135 135
136 136 if (is_lookup && (rv > 0)) {
137 137 /* was this node constructed ? */
138 138 if (dv->sdev_state == SDEV_READY) {
139 139 rval = 0;
140 140 }
141 141 sdcmn_err6(("%s: wait done, %screated %d\n",
142 142 dv->sdev_name, rval ? "not " : "",
143 143 dv->sdev_state));
144 144 break;
145 145 } else if (rv == 0) {
146 146 /* interrupted */
147 147 sdcmn_err6(("%s: wait interrupted\n",
148 148 dv->sdev_name));
149 149 break;
150 150 } else if ((rv == -1) &&
151 151 (ddi_get_lbolt() >= expire)) {
152 152 sdcmn_err6(("%s: wait time is up\n",
153 153 dv->sdev_name));
154 154 break;
155 155 }
156 156 sdcmn_err6(("%s: wait "
157 157 "rv %ld state 0x%x expire %ld\n",
158 158 dv->sdev_name, rv, devfsadm_state,
159 159 expire - ddi_get_lbolt()));
160 160 }
161 161 } else {
162 162 /*
163 163 * for the nodes created by
164 164 * devname_lookup_func callback
165 165 * or plug-in modules
166 166 */
167 167 while (SDEV_IS_LOOKUP(dv) || SDEV_IS_READDIR(dv)) {
168 168 cv_wait(&dv->sdev_lookup_cv, &dv->sdev_lookup_lock);
169 169 }
170 170 rval = 0;
171 171 }
172 172
173 173 sdcmn_err6(("wait4lookup unblocking %s state 0x%x %d\n",
174 174 dv->sdev_name, devfsadm_state, dv->sdev_state));
175 175
176 176 if (is_lookup) {
177 177 SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP);
178 178 } else {
179 179 SDEV_UNBLOCK_OTHERS(dv, SDEV_READDIR);
180 180 }
181 181
182 182 return (rval);
183 183 }
184 184
185 185 void
186 186 sdev_unblock_others(struct sdev_node *dv, uint_t cmd)
187 187 {
188 188 ASSERT(MUTEX_HELD(&dv->sdev_lookup_lock));
189 189
190 190 SDEV_CLEAR_LOOKUP_FLAGS(dv, cmd);
191 191 if (SDEV_IS_LGWAITING(dv)) {
192 192 SDEV_CLEAR_LOOKUP_FLAGS(dv, SDEV_LGWAITING);
193 193 }
194 194 cv_broadcast(&dv->sdev_lookup_cv);
195 195 }
196 196
197 197 /*
198 198 * In the case devfsadmd is down, it is re-started by syseventd
199 199 * upon receiving an event subscribed to by devfsadmd.
200 200 */
201 201 static int
202 202 sdev_start_devfsadmd()
203 203 {
204 204 int se_err = 0;
205 205 sysevent_t *ev;
206 206 sysevent_id_t eid;
207 207
208 208 ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_START, EP_DDI, SE_SLEEP);
209 209 ASSERT(ev);
210 210 if ((se_err = log_sysevent(ev, SE_SLEEP, &eid)) != 0) {
211 211 switch (se_err) {
212 212 case SE_NO_TRANSPORT:
213 213 cmn_err(CE_WARN, "unable to start devfsadm - "
214 214 "syseventd may not be responding\n");
215 215 break;
216 216 default:
217 217 cmn_err(CE_WARN, "unable to start devfsadm - "
218 218 "sysevent error %d\n", se_err);
219 219 break;
220 220 }
221 221 }
222 222
223 223 sysevent_free(ev);
224 224 return (se_err);
225 225 }
226 226
↓ open down ↓ |
94 lines elided |
↑ open up ↑ |
227 227 static int
228 228 sdev_open_upcall_door()
229 229 {
230 230 int error;
231 231 clock_t rv;
232 232 clock_t expire;
233 233
234 234 ASSERT(sdev_upcall_door == NULL);
235 235
236 236 /* timeout expires this many ticks in the future */
237 - expire = ddi_get_lbolt() + drv_usectohz(dev_devfsadm_startup * 1000000);
237 + expire = ddi_get_lbolt() + drv_sectohz(dev_devfsadm_startup);
238 238
239 239 if (sdev_door_upcall_filename == NULL) {
240 240 if ((error = sdev_start_devfsadmd()) != 0) {
241 241 return (error);
242 242 }
243 243
244 244 /* wait for devfsadmd start */
245 245 mutex_enter(&devfsadm_lock);
246 246 while (sdev_door_upcall_filename == NULL) {
247 247 sdcmn_err6(("waiting for dev_door creation, %ld\n",
248 248 expire - ddi_get_lbolt()));
249 249 rv = cv_timedwait_sig(&devfsadm_cv, &devfsadm_lock,
250 250 expire);
251 251 sdcmn_err6(("dev_door wait rv %ld\n", rv));
252 252 if (rv <= 0) {
253 253 sdcmn_err6(("devfsadmd startup error\n"));
254 254 mutex_exit(&devfsadm_lock);
255 255 return (EBADF);
256 256 }
257 257 }
258 258 sdcmn_err6(("devfsadmd is ready\n"));
259 259 mutex_exit(&devfsadm_lock);
260 260 }
261 261
262 262 if ((error = door_ki_open(sdev_door_upcall_filename,
263 263 &sdev_upcall_door)) != 0) {
264 264 sdcmn_err6(("upcall_lookup: door open error %d\n",
265 265 error));
266 266 return (error);
267 267 }
268 268
269 269 return (0);
270 270 }
271 271
272 272 static void
273 273 sdev_release_door()
274 274 {
275 275 if (sdev_upcall_door) {
276 276 door_ki_rele(sdev_upcall_door);
277 277 sdev_upcall_door = NULL;
278 278 }
279 279 if (sdev_door_upcall_filename) {
280 280 kmem_free(sdev_door_upcall_filename,
281 281 sdev_door_upcall_filename_size);
282 282 sdev_door_upcall_filename = NULL;
283 283 }
284 284 }
285 285
286 286 static int
287 287 sdev_ki_call_devfsadmd(sdev_door_arg_t *argp, sdev_door_res_t *resultp)
288 288 {
289 289 door_arg_t darg, save_arg;
290 290 int error;
291 291 int retry;
292 292
293 293 if (((sdev_upcall_door == NULL) &&
294 294 ((error = sdev_open_upcall_door()) != 0)) ||
295 295 sdev_devfsadm_revoked()) {
296 296 sdcmn_err6(("call_devfsadm: upcall lookup error\n"));
297 297 return (error);
298 298 }
299 299
300 300 ASSERT(argp);
301 301 darg.data_ptr = (char *)argp;
302 302 darg.data_size = sizeof (struct sdev_door_arg);
303 303 darg.desc_ptr = NULL;
304 304 darg.desc_num = 0;
305 305 darg.rbuf = (char *)(resultp);
306 306 darg.rsize = sizeof (struct sdev_door_res);
307 307
308 308 ASSERT(sdev_upcall_door);
309 309 save_arg = darg;
310 310 for (retry = 0; ; retry++) {
311 311 sdcmn_err6(("call devfsadm: upcall lookup, retry %d\n", retry));
312 312 if ((error = door_ki_upcall_limited(sdev_upcall_door, &darg,
313 313 NULL, SIZE_MAX, 0)) == 0) {
314 314 sdcmn_err6(("call devfsadm: upcall lookup ok\n"));
315 315 break;
316 316 }
317 317
318 318 /*
319 319 * handle door call errors
320 320 */
321 321 if (sdev_devfsadm_revoked()) {
322 322 sdcmn_err6(("upcall lookup door revoked, "
323 323 "error %d\n", error));
324 324 return (error);
325 325 }
326 326
327 327 switch (error) {
328 328 case EINTR:
329 329 /* return error here? */
330 330 sdcmn_err6(("sdev_ki_call_devfsadm: EINTR\n"));
331 331 delay(hz);
332 332 break;
333 333 case EAGAIN:
334 334 sdcmn_err6(("sdev_ki_call_devfsadm: EAGAIN\n"));
335 335 delay(2 * hz);
336 336 break;
337 337 case EBADF:
338 338 if (retry > 4) {
339 339 sdcmn_err6(("sdev_ki_call_devfsadm: EBADF\n"));
340 340 return (EBADF);
341 341 }
342 342 sdcmn_err6((
343 343 "sdev_ki_call_devfsadm: EBADF, re-binding\n"));
344 344 sdev_release_door();
345 345 delay(retry * hz);
346 346 error = sdev_open_upcall_door();
347 347 if (error != 0) {
348 348 sdcmn_err6(("sdev_ki_call_devfsadm: "
349 349 "EBADF lookup error %d\n", error));
350 350 if (!sdev_devfsadm_revoked())
351 351 cmn_err(CE_NOTE,
352 352 "?unable to invoke devfsadm - "
353 353 "please run manually\n");
354 354 return (EBADF);
355 355 }
356 356 break;
357 357 case EINVAL:
358 358 default:
359 359 cmn_err(CE_CONT,
360 360 "?sdev: door_ki_upcall unexpected result %d\n",
361 361 error);
362 362 return (error);
363 363 }
364 364
365 365 darg = save_arg;
366 366 }
367 367
368 368 if (!error) {
369 369 ASSERT((struct sdev_door_res *)(intptr_t)darg.rbuf == resultp);
370 370 if (resultp->devfsadm_error != 0) {
371 371 sdcmn_err6(("sdev_ki_call_devfsadmd: result %d\n",
372 372 resultp->devfsadm_error));
373 373 error = resultp->devfsadm_error;
374 374 }
375 375 } else {
376 376 sdcmn_err6(("sdev_ki_call_devfsadmd with error %d\n", error));
377 377 }
378 378
379 379 return (error);
380 380 }
381 381
382 382 static int
383 383 sdev_devfsadm_revoked(void)
384 384 {
385 385 struct door_info info;
386 386 int rv;
387 387 extern int sys_shutdown;
388 388
389 389 if (sys_shutdown) {
390 390 sdcmn_err6(("dev: shutdown observed\n"));
391 391 return (1);
392 392 }
393 393
394 394 if (sdev_upcall_door && !sdev_upcall_door_revoked) {
395 395 rv = door_ki_info(sdev_upcall_door, &info);
396 396 if ((rv == 0) && info.di_attributes & DOOR_REVOKED) {
397 397 sdcmn_err6(("lookup door: revoked\n"));
398 398 sdev_upcall_door_revoked = 1;
399 399 }
400 400 }
401 401
402 402 return (sdev_upcall_door_revoked);
403 403 }
404 404
405 405 /*ARGSUSED*/
406 406 static void
407 407 sdev_config_all_thread(struct sdev_node *dv)
408 408 {
409 409 int32_t error = 0;
410 410 sdev_door_arg_t *argp;
411 411 sdev_door_res_t result;
412 412
413 413 argp = kmem_zalloc(sizeof (sdev_door_arg_t), KM_SLEEP);
414 414 argp->devfsadm_cmd = DEVFSADMD_RUN_ALL;
415 415
416 416 error = sdev_ki_call_devfsadmd(argp, &result);
417 417 if (!error) {
418 418 sdcmn_err6(("devfsadm result error: %d\n",
419 419 result.devfsadm_error));
420 420 if (!result.devfsadm_error) {
421 421 DEVNAME_DEVFSADM_SET_RUN(devfsadm_state);
422 422 } else {
423 423 DEVNAME_DEVFSADM_SET_STOP(devfsadm_state);
424 424 }
425 425 } else {
426 426 DEVNAME_DEVFSADM_SET_STOP(devfsadm_state);
427 427 }
428 428
429 429 kmem_free(argp, sizeof (sdev_door_arg_t));
430 430 done:
431 431 sdcmn_err6(("sdev_config_all_thread: stopping, devfsadm state 0x%x\n",
432 432 devfsadm_state));
433 433 thread_exit();
434 434 }
435 435
436 436 /*
437 437 * launch an asynchronous thread to do the devfsadm dev_config_all
438 438 */
439 439 /*ARGSUSED*/
440 440 void
441 441 sdev_devfsadmd_thread(struct sdev_node *ddv, struct sdev_node *dv,
442 442 struct cred *cred)
443 443 {
444 444 ASSERT(i_ddi_io_initialized());
445 445 DEVNAME_DEVFSADM_SET_RUNNING(devfsadm_state);
446 446 (void) thread_create(NULL, 0, sdev_config_all_thread, dv, 0,
447 447 &p0, TS_RUN, MINCLSYSPRI);
448 448 }
449 449
450 450 int
451 451 devname_filename_register(char *name)
452 452 {
453 453 int error = 0;
454 454 char *strbuf;
455 455 char *namep;
456 456 int n;
457 457
458 458 strbuf = kmem_zalloc(MOD_MAXPATH, KM_SLEEP);
459 459
460 460 if (copyinstr(name, strbuf, MOD_MAXPATH, 0)) {
461 461 sdcmn_err6(("error copyin \n"));
462 462 error = EFAULT;
463 463 } else {
464 464 sdcmn_err6(("file %s is registering\n", strbuf));
465 465 /* handling the daemon re-start situations */
466 466 n = strlen(strbuf) + 1;
467 467 namep = i_ddi_strdup(strbuf, KM_SLEEP);
468 468 mutex_enter(&devfsadm_lock);
469 469 sdev_release_door();
470 470 sdev_door_upcall_filename_size = n;
471 471 sdev_door_upcall_filename = namep;
472 472 sdcmn_err6(("size %d file name %s\n",
473 473 sdev_door_upcall_filename_size,
474 474 sdev_door_upcall_filename));
475 475 cv_broadcast(&devfsadm_cv);
476 476 mutex_exit(&devfsadm_lock);
477 477 }
478 478
479 479 kmem_free(strbuf, MOD_MAXPATH);
480 480 return (error);
481 481 }
↓ open down ↓ |
234 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX