Print this page
8368 remove warlock leftovers from usr/src/uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/dev/sdev_vtops.c
+++ new/usr/src/uts/common/fs/dev/sdev_vtops.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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 /*
26 26 * vnode ops for the /dev/vt directory
27 27 */
28 28
29 29 #include <sys/types.h>
30 30 #include <sys/param.h>
31 31 #include <sys/sysmacros.h>
32 32 #include <sys/sunndi.h>
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
33 33 #include <fs/fs_subr.h>
34 34 #include <sys/fs/dv_node.h>
35 35 #include <sys/fs/sdev_impl.h>
36 36 #include <sys/policy.h>
37 37 #include <sys/stat.h>
38 38 #include <sys/vfs_opreg.h>
39 39 #include <sys/tty.h>
40 40 #include <sys/vt_impl.h>
41 41 #include <sys/note.h>
42 42
43 -/* warlock in this file only cares about variables shared by vt and devfs */
44 -_NOTE(SCHEME_PROTECTS_DATA("Do not care", sdev_node vattr vnode))
45 -
46 43 #define DEVVT_UID_DEFAULT SDEV_UID_DEFAULT
47 44 #define DEVVT_GID_DEFAULT (0)
48 45 #define DEVVT_DEVMODE_DEFAULT (0600)
49 46 #define DEVVT_ACTIVE_NAME "active"
50 47 #define DEVVT_CONSUSER_NAME "console_user"
51 48
52 49 #define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
53 50
54 51 /* attributes for VT nodes */
55 52 static vattr_t devvt_vattr = {
56 53 AT_TYPE|AT_MODE|AT_UID|AT_GID, /* va_mask */
57 54 VCHR, /* va_type */
58 55 S_IFCHR | DEVVT_DEVMODE_DEFAULT, /* va_mode */
59 56 DEVVT_UID_DEFAULT, /* va_uid */
60 57 DEVVT_GID_DEFAULT, /* va_gid */
61 58 0 /* 0 hereafter */
62 59 };
63 60
64 61 struct vnodeops *devvt_vnodeops;
65 62
66 63 struct vnodeops *
67 64 devvt_getvnodeops(void)
68 65 {
69 66 return (devvt_vnodeops);
70 67 }
71 68
72 69 static int
73 70 devvt_str2minor(const char *nm, minor_t *mp)
74 71 {
75 72 long uminor = 0;
76 73 char *endptr = NULL;
77 74
78 75 if (nm == NULL || !isdigit(*nm))
79 76 return (EINVAL);
80 77
81 78 *mp = 0;
82 79 if (ddi_strtol(nm, &endptr, 10, &uminor) != 0 ||
83 80 *endptr != '\0' || uminor < 0) {
84 81 return (EINVAL);
85 82 }
86 83
87 84 *mp = (minor_t)uminor;
88 85 return (0);
89 86 }
90 87
91 88 /*
92 89 * Validate that a node is up-to-date and correct.
93 90 * A validator may not update the node state or
94 91 * contents as a read lock permits entry by
95 92 * multiple threads.
96 93 */
97 94 int
98 95 devvt_validate(struct sdev_node *dv)
99 96 {
100 97 minor_t min;
101 98 char *nm = dv->sdev_name;
102 99 int rval;
103 100
104 101 ASSERT(dv->sdev_state == SDEV_READY);
105 102 ASSERT(RW_LOCK_HELD(&(dv->sdev_dotdot)->sdev_contents));
106 103
107 104 /* validate only READY nodes */
108 105 if (dv->sdev_state != SDEV_READY) {
109 106 sdcmn_err(("dev fs: skipping: node not ready %s(%p)",
110 107 nm, (void *)dv));
111 108 return (SDEV_VTOR_SKIP);
112 109 }
113 110
114 111 if (vt_wc_attached() == (major_t)-1)
115 112 return (SDEV_VTOR_INVALID);
116 113
117 114 if (strcmp(nm, DEVVT_ACTIVE_NAME) == 0) {
118 115 char *link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
119 116 (void) vt_getactive(link, MAXPATHLEN);
120 117 rval = (strcmp(link, dv->sdev_symlink) == 0) ?
121 118 SDEV_VTOR_VALID : SDEV_VTOR_STALE;
122 119 kmem_free(link, MAXPATHLEN);
123 120 return (rval);
124 121 }
125 122
126 123 if (strcmp(nm, DEVVT_CONSUSER_NAME) == 0) {
127 124 char *link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
128 125 (void) vt_getconsuser(link, MAXPATHLEN);
129 126 rval = (strcmp(link, dv->sdev_symlink) == 0) ?
130 127 SDEV_VTOR_VALID : SDEV_VTOR_STALE;
131 128 kmem_free(link, MAXPATHLEN);
132 129 return (rval);
133 130 }
134 131
135 132 if (devvt_str2minor(nm, &min) != 0) {
136 133 return (SDEV_VTOR_INVALID);
137 134 }
138 135
139 136 if (vt_minor_valid(min) == B_FALSE)
140 137 return (SDEV_VTOR_INVALID);
141 138
142 139 return (SDEV_VTOR_VALID);
143 140 }
144 141
145 142 /*
146 143 * This callback is invoked from devname_lookup_func() to create
147 144 * a entry when the node is not found in the cache.
148 145 */
149 146 /*ARGSUSED*/
150 147 static int
151 148 devvt_create_rvp(struct sdev_node *ddv, char *nm,
152 149 void **arg, cred_t *cred, void *whatever, char *whichever)
153 150 {
154 151 minor_t min;
155 152 major_t maj;
156 153 struct vattr *vap = (struct vattr *)arg;
157 154
158 155 if ((maj = vt_wc_attached()) == (major_t)-1)
159 156 return (SDEV_VTOR_INVALID);
160 157
161 158 if (strcmp(nm, DEVVT_ACTIVE_NAME) == 0) {
162 159 (void) vt_getactive((char *)*arg, MAXPATHLEN);
163 160 return (0);
164 161 }
165 162
166 163 if (strcmp(nm, DEVVT_CONSUSER_NAME) == 0) {
167 164 (void) vt_getconsuser((char *)*arg, MAXPATHLEN);
168 165 return (0);
169 166 }
170 167 if (devvt_str2minor(nm, &min) != 0)
171 168 return (-1);
172 169
173 170 if (vt_minor_valid(min) == B_FALSE)
174 171 return (-1);
175 172
176 173 *vap = devvt_vattr;
177 174 vap->va_rdev = makedevice(maj, min);
178 175
179 176 return (0);
180 177 }
181 178
182 179 /*ARGSUSED3*/
183 180 static int
184 181 devvt_lookup(struct vnode *dvp, char *nm, struct vnode **vpp,
185 182 struct pathname *pnp, int flags, struct vnode *rdir, struct cred *cred,
186 183 caller_context_t *ct, int *direntflags, pathname_t *realpnp)
187 184 {
188 185 struct sdev_node *sdvp = VTOSDEV(dvp);
189 186 struct sdev_node *dv;
↓ open down ↓ |
134 lines elided |
↑ open up ↑ |
190 187 struct vnode *rvp = NULL;
191 188 int type, error;
192 189
193 190 if ((strcmp(nm, DEVVT_ACTIVE_NAME) == 0) ||
194 191 (strcmp(nm, DEVVT_CONSUSER_NAME) == 0)) {
195 192 type = SDEV_VLINK;
196 193 } else {
197 194 type = SDEV_VATTR;
198 195 }
199 196
200 -/* Give warlock a more clear call graph */
201 -#ifndef __lock_lint
202 197 error = devname_lookup_func(sdvp, nm, vpp, cred,
203 198 devvt_create_rvp, type);
204 -#else
205 - devvt_create_rvp(0, 0, 0, 0, 0, 0);
206 -#endif
207 199
208 200 if (error == 0) {
209 201 switch ((*vpp)->v_type) {
210 202 case VCHR:
211 203 dv = VTOSDEV(VTOS(*vpp)->s_realvp);
212 204 ASSERT(VOP_REALVP(SDEVTOV(dv), &rvp, NULL) == ENOSYS);
213 205 break;
214 206 case VDIR:
215 207 case VLNK:
216 208 dv = VTOSDEV(*vpp);
217 209 break;
218 210 default:
219 211 cmn_err(CE_PANIC, "devvt_lookup: Unsupported node "
220 212 "type: %p: %d", (void *)(*vpp), (*vpp)->v_type);
221 213 break;
222 214 }
223 215 ASSERT(SDEV_HELD(dv));
224 216 }
225 217
226 218 return (error);
227 219 }
228 220
229 221 static void
230 222 devvt_create_snode(struct sdev_node *ddv, char *nm, struct cred *cred, int type)
231 223 {
232 224 int error;
233 225 struct sdev_node *sdv = NULL;
234 226 struct vattr vattr;
235 227 struct vattr *vap = &vattr;
236 228 major_t maj;
237 229 minor_t min;
238 230
239 231 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
240 232
241 233 if ((maj = vt_wc_attached()) == (major_t)-1)
242 234 return;
243 235
244 236 if (strcmp(nm, DEVVT_ACTIVE_NAME) != 0 &&
245 237 strcmp(nm, DEVVT_CONSUSER_NAME) != 0 &&
246 238 devvt_str2minor(nm, &min) != 0)
247 239 return;
248 240
249 241 error = sdev_mknode(ddv, nm, &sdv, NULL, NULL, NULL, cred, SDEV_INIT);
250 242 if (error || !sdv) {
251 243 return;
252 244 }
253 245
254 246 mutex_enter(&sdv->sdev_lookup_lock);
255 247 SDEV_BLOCK_OTHERS(sdv, SDEV_LOOKUP);
256 248 mutex_exit(&sdv->sdev_lookup_lock);
257 249
258 250 if (type & SDEV_VATTR) {
259 251 *vap = devvt_vattr;
260 252 vap->va_rdev = makedevice(maj, min);
261 253 error = sdev_mknode(ddv, nm, &sdv, vap, NULL,
262 254 NULL, cred, SDEV_READY);
263 255 } else if (type & SDEV_VLINK) {
264 256 char *link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
265 257
266 258 (void) vt_getactive(link, MAXPATHLEN);
267 259 *vap = sdev_vattr_lnk;
268 260 vap->va_size = strlen(link);
269 261 error = sdev_mknode(ddv, nm, &sdv, vap, NULL,
270 262 (void *)link, cred, SDEV_READY);
271 263
272 264 kmem_free(link, MAXPATHLEN);
273 265 }
274 266
275 267 if (error != 0) {
276 268 SDEV_RELE(sdv);
277 269 return;
278 270 }
279 271
280 272 mutex_enter(&sdv->sdev_lookup_lock);
281 273 SDEV_UNBLOCK_OTHERS(sdv, SDEV_LOOKUP);
282 274 mutex_exit(&sdv->sdev_lookup_lock);
283 275
284 276 }
285 277
286 278 static void
287 279 devvt_rebuild_stale_link(struct sdev_node *ddv, struct sdev_node *dv)
288 280 {
289 281 char *link;
290 282
291 283 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
292 284
293 285 ASSERT((strcmp(dv->sdev_name, DEVVT_ACTIVE_NAME) == 0) ||
294 286 (strcmp(dv->sdev_name, DEVVT_CONSUSER_NAME) == 0));
295 287
296 288 link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
297 289 if (strcmp(dv->sdev_name, DEVVT_ACTIVE_NAME) == 0) {
298 290 (void) vt_getactive(link, MAXPATHLEN);
299 291 } else if (strcmp(dv->sdev_name, DEVVT_CONSUSER_NAME) == 0) {
300 292 (void) vt_getconsuser(link, MAXPATHLEN);
301 293 }
302 294
303 295 if (strcmp(link, dv->sdev_symlink) != 0) {
304 296 strfree(dv->sdev_symlink);
305 297 dv->sdev_symlink = strdup(link);
306 298 dv->sdev_attr->va_size = strlen(link);
307 299 }
308 300 kmem_free(link, MAXPATHLEN);
309 301 }
310 302
311 303 /*
312 304 * First step in refreshing directory contents.
313 305 * Remove each invalid entry and rebuild the link
314 306 * reference for each stale entry.
315 307 */
316 308 static void
317 309 devvt_prunedir(struct sdev_node *ddv)
318 310 {
319 311 struct vnode *vp;
320 312 struct sdev_node *dv, *next = NULL;
321 313 int (*vtor)(struct sdev_node *) = NULL;
322 314
323 315 ASSERT(ddv->sdev_flags & SDEV_VTOR);
324 316
325 317 vtor = (int (*)(struct sdev_node *))sdev_get_vtor(ddv);
326 318 ASSERT(vtor);
327 319
328 320 for (dv = SDEV_FIRST_ENTRY(ddv); dv; dv = next) {
329 321 next = SDEV_NEXT_ENTRY(ddv, dv);
330 322
331 323 switch (vtor(dv)) {
332 324 case SDEV_VTOR_VALID:
333 325 break;
334 326 case SDEV_VTOR_SKIP:
335 327 break;
336 328 case SDEV_VTOR_INVALID:
337 329 vp = SDEVTOV(dv);
338 330 if (vp->v_count != 0)
339 331 break;
340 332 /* remove the cached node */
341 333 SDEV_HOLD(dv);
342 334 (void) sdev_cache_update(ddv, &dv,
343 335 dv->sdev_name, SDEV_CACHE_DELETE);
344 336 SDEV_RELE(dv);
345 337 break;
346 338 case SDEV_VTOR_STALE:
347 339 devvt_rebuild_stale_link(ddv, dv);
348 340 break;
349 341 }
350 342 }
351 343 }
352 344
353 345 static void
354 346 devvt_cleandir(struct vnode *dvp, struct cred *cred)
↓ open down ↓ |
138 lines elided |
↑ open up ↑ |
355 347 {
356 348 struct sdev_node *sdvp = VTOSDEV(dvp);
357 349 struct sdev_node *dv, *next = NULL;
358 350 int min, cnt;
359 351 char found = 0;
360 352
361 353 mutex_enter(&vc_lock);
362 354 cnt = VC_INSTANCES_COUNT;
363 355 mutex_exit(&vc_lock);
364 356
365 -/* We have to fool warlock this way, otherwise it will complain */
366 -#ifndef __lock_lint
367 357 if (rw_tryupgrade(&sdvp->sdev_contents) == NULL) {
368 358 rw_exit(&sdvp->sdev_contents);
369 359 rw_enter(&sdvp->sdev_contents, RW_WRITER);
370 360 }
371 -#else
372 - rw_enter(&sdvp->sdev_contents, RW_WRITER);
373 -#endif
374 361
375 362 /* 1. prune invalid nodes and rebuild stale symlinks */
376 363 devvt_prunedir(sdvp);
377 364
378 365 /* 2. create missing nodes */
379 366 for (min = 0; min < cnt; min++) {
380 367 char nm[16];
381 368
382 369 if (vt_minor_valid(min) == B_FALSE)
383 370 continue;
384 371
385 372 (void) snprintf(nm, sizeof (nm), "%d", min);
386 373 found = 0;
387 374 for (dv = SDEV_FIRST_ENTRY(sdvp); dv; dv = next) {
388 375 next = SDEV_NEXT_ENTRY(sdvp, dv);
389 376
390 377 /* validate only ready nodes */
391 378 if (dv->sdev_state != SDEV_READY)
392 379 continue;
393 380 if (strcmp(nm, dv->sdev_name) == 0) {
394 381 found = 1;
395 382 break;
396 383 }
397 384 }
398 385 if (!found) {
399 386 devvt_create_snode(sdvp, nm, cred, SDEV_VATTR);
400 387 }
401 388 }
402 389
403 390 /* 3. create active link node and console user link node */
404 391 found = 0;
405 392 for (dv = SDEV_FIRST_ENTRY(sdvp); dv; dv = next) {
406 393 next = SDEV_NEXT_ENTRY(sdvp, dv);
407 394
408 395 /* validate only ready nodes */
409 396 if (dv->sdev_state != SDEV_READY)
410 397 continue;
411 398 if ((strcmp(dv->sdev_name, DEVVT_ACTIVE_NAME) == NULL))
412 399 found |= 0x01;
413 400 if ((strcmp(dv->sdev_name, DEVVT_CONSUSER_NAME) == NULL))
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
414 401 found |= 0x02;
415 402
416 403 if ((found & 0x01) && (found & 0x02))
417 404 break;
418 405 }
419 406 if (!(found & 0x01))
420 407 devvt_create_snode(sdvp, DEVVT_ACTIVE_NAME, cred, SDEV_VLINK);
421 408 if (!(found & 0x02))
422 409 devvt_create_snode(sdvp, DEVVT_CONSUSER_NAME, cred, SDEV_VLINK);
423 410
424 -#ifndef __lock_lint
425 411 rw_downgrade(&sdvp->sdev_contents);
426 -#else
427 - rw_exit(&sdvp->sdev_contents);
428 -#endif
429 412 }
430 413
431 414 /*ARGSUSED4*/
432 415 static int
433 416 devvt_readdir(struct vnode *dvp, struct uio *uiop, struct cred *cred,
434 417 int *eofp, caller_context_t *ct, int flags)
435 418 {
436 419 if (uiop->uio_offset == 0) {
437 420 devvt_cleandir(dvp, cred);
438 421 }
439 422
440 423 return (devname_readdir_func(dvp, uiop, cred, eofp, 0));
441 424 }
442 425
443 426 /*
444 427 * We allow create to find existing nodes
445 428 * - if the node doesn't exist - EROFS
446 429 * - creating an existing dir read-only succeeds, otherwise EISDIR
447 430 * - exclusive creates fail - EEXIST
448 431 */
449 432 /*ARGSUSED2*/
450 433 static int
451 434 devvt_create(struct vnode *dvp, char *nm, struct vattr *vap, vcexcl_t excl,
452 435 int mode, struct vnode **vpp, struct cred *cred, int flag,
453 436 caller_context_t *ct, vsecattr_t *vsecp)
454 437 {
455 438 int error;
456 439 struct vnode *vp;
457 440
458 441 *vpp = NULL;
459 442
460 443 if ((error = devvt_lookup(dvp, nm, &vp, NULL, 0, NULL, cred, ct, NULL,
461 444 NULL)) != 0) {
462 445 if (error == ENOENT)
463 446 error = EROFS;
464 447 return (error);
465 448 }
466 449
467 450 if (excl == EXCL)
468 451 error = EEXIST;
469 452 else if (vp->v_type == VDIR && (mode & VWRITE))
470 453 error = EISDIR;
471 454 else
472 455 error = VOP_ACCESS(vp, mode, 0, cred, ct);
473 456
474 457 if (error) {
475 458 VN_RELE(vp);
476 459 } else
477 460 *vpp = vp;
478 461
479 462 return (error);
480 463 }
481 464
482 465 const fs_operation_def_t devvt_vnodeops_tbl[] = {
483 466 VOPNAME_READDIR, { .vop_readdir = devvt_readdir },
484 467 VOPNAME_LOOKUP, { .vop_lookup = devvt_lookup },
485 468 VOPNAME_CREATE, { .vop_create = devvt_create },
486 469 VOPNAME_REMOVE, { .error = fs_nosys },
487 470 VOPNAME_MKDIR, { .error = fs_nosys },
488 471 VOPNAME_RMDIR, { .error = fs_nosys },
489 472 VOPNAME_SYMLINK, { .error = fs_nosys },
490 473 VOPNAME_SETSECATTR, { .error = fs_nosys },
491 474 NULL, NULL
492 475 };
↓ open down ↓ |
54 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX