Print this page
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/dev/sdev_subr.c
+++ new/usr/src/uts/common/fs/dev/sdev_subr.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) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 * Copyright (c) 2013, 2016 Joyent, Inc. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * utility routines for the /dev fs
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 <fs/fs_subr.h>
54 54 #include <sys/mount.h>
55 55 #include <sys/fs/snode.h>
56 56 #include <sys/fs/dv_node.h>
57 57 #include <sys/fs/sdev_impl.h>
58 58 #include <sys/sunndi.h>
59 59 #include <sys/sunmdi.h>
60 60 #include <sys/conf.h>
61 61 #include <sys/proc.h>
62 62 #include <sys/user.h>
63 63 #include <sys/modctl.h>
64 64
65 65 #ifdef DEBUG
66 66 int sdev_debug = 0x00000001;
67 67 int sdev_debug_cache_flags = 0;
68 68 #endif
69 69
70 70 /*
71 71 * globals
72 72 */
73 73 /* prototype memory vattrs */
74 74 vattr_t sdev_vattr_dir = {
75 75 AT_TYPE|AT_MODE|AT_UID|AT_GID, /* va_mask */
76 76 VDIR, /* va_type */
77 77 SDEV_DIRMODE_DEFAULT, /* va_mode */
78 78 SDEV_UID_DEFAULT, /* va_uid */
79 79 SDEV_GID_DEFAULT, /* va_gid */
80 80 0, /* va_fsid */
81 81 0, /* va_nodeid */
82 82 0, /* va_nlink */
83 83 0, /* va_size */
84 84 0, /* va_atime */
85 85 0, /* va_mtime */
86 86 0, /* va_ctime */
87 87 0, /* va_rdev */
88 88 0, /* va_blksize */
89 89 0, /* va_nblocks */
90 90 0 /* va_vcode */
91 91 };
92 92
93 93 vattr_t sdev_vattr_lnk = {
94 94 AT_TYPE|AT_MODE, /* va_mask */
95 95 VLNK, /* va_type */
96 96 SDEV_LNKMODE_DEFAULT, /* va_mode */
97 97 SDEV_UID_DEFAULT, /* va_uid */
98 98 SDEV_GID_DEFAULT, /* va_gid */
99 99 0, /* va_fsid */
100 100 0, /* va_nodeid */
101 101 0, /* va_nlink */
102 102 0, /* va_size */
103 103 0, /* va_atime */
104 104 0, /* va_mtime */
105 105 0, /* va_ctime */
106 106 0, /* va_rdev */
107 107 0, /* va_blksize */
108 108 0, /* va_nblocks */
109 109 0 /* va_vcode */
110 110 };
111 111
112 112 vattr_t sdev_vattr_blk = {
113 113 AT_TYPE|AT_MODE|AT_UID|AT_GID, /* va_mask */
114 114 VBLK, /* va_type */
115 115 S_IFBLK | SDEV_DEVMODE_DEFAULT, /* va_mode */
116 116 SDEV_UID_DEFAULT, /* va_uid */
117 117 SDEV_GID_DEFAULT, /* va_gid */
118 118 0, /* va_fsid */
119 119 0, /* va_nodeid */
120 120 0, /* va_nlink */
121 121 0, /* va_size */
122 122 0, /* va_atime */
123 123 0, /* va_mtime */
124 124 0, /* va_ctime */
125 125 0, /* va_rdev */
126 126 0, /* va_blksize */
127 127 0, /* va_nblocks */
128 128 0 /* va_vcode */
129 129 };
130 130
131 131 vattr_t sdev_vattr_chr = {
132 132 AT_TYPE|AT_MODE|AT_UID|AT_GID, /* va_mask */
133 133 VCHR, /* va_type */
134 134 S_IFCHR | SDEV_DEVMODE_DEFAULT, /* va_mode */
135 135 SDEV_UID_DEFAULT, /* va_uid */
136 136 SDEV_GID_DEFAULT, /* va_gid */
137 137 0, /* va_fsid */
138 138 0, /* va_nodeid */
139 139 0, /* va_nlink */
140 140 0, /* va_size */
141 141 0, /* va_atime */
142 142 0, /* va_mtime */
|
↓ open down ↓ |
142 lines elided |
↑ open up ↑ |
143 143 0, /* va_ctime */
144 144 0, /* va_rdev */
145 145 0, /* va_blksize */
146 146 0, /* va_nblocks */
147 147 0 /* va_vcode */
148 148 };
149 149
150 150 kmem_cache_t *sdev_node_cache; /* sdev_node cache */
151 151 int devtype; /* fstype */
152 152
153 +/* static */
154 +static struct vnodeops *sdev_get_vop(struct sdev_node *);
155 +static void sdev_set_no_negcache(struct sdev_node *);
156 +static fs_operation_def_t *sdev_merge_vtab(const fs_operation_def_t []);
157 +static void sdev_free_vtab(fs_operation_def_t *);
158 +
153 159 static void
154 160 sdev_prof_free(struct sdev_node *dv)
155 161 {
156 162 ASSERT(!SDEV_IS_GLOBAL(dv));
157 163 nvlist_free(dv->sdev_prof.dev_name);
158 164 nvlist_free(dv->sdev_prof.dev_map);
159 165 nvlist_free(dv->sdev_prof.dev_symlink);
160 166 nvlist_free(dv->sdev_prof.dev_glob_incdir);
161 167 nvlist_free(dv->sdev_prof.dev_glob_excdir);
162 168 bzero(&dv->sdev_prof, sizeof (dv->sdev_prof));
163 169 }
164 170
165 171 /* sdev_node cache constructor */
166 172 /*ARGSUSED1*/
167 173 static int
168 174 i_sdev_node_ctor(void *buf, void *cfarg, int flag)
169 175 {
170 176 struct sdev_node *dv = (struct sdev_node *)buf;
171 177 struct vnode *vp;
172 178
173 179 bzero(buf, sizeof (struct sdev_node));
174 180 vp = dv->sdev_vnode = vn_alloc(flag);
175 181 if (vp == NULL) {
176 182 return (-1);
177 183 }
178 184 vp->v_data = dv;
179 185 rw_init(&dv->sdev_contents, NULL, RW_DEFAULT, NULL);
180 186 return (0);
181 187 }
182 188
183 189 /* sdev_node cache destructor */
184 190 /*ARGSUSED1*/
185 191 static void
186 192 i_sdev_node_dtor(void *buf, void *arg)
187 193 {
188 194 struct sdev_node *dv = (struct sdev_node *)buf;
189 195 struct vnode *vp = SDEVTOV(dv);
190 196
191 197 rw_destroy(&dv->sdev_contents);
192 198 vn_free(vp);
193 199 }
194 200
195 201 /* initialize sdev_node cache */
196 202 void
197 203 sdev_node_cache_init()
198 204 {
199 205 int flags = 0;
200 206
201 207 #ifdef DEBUG
202 208 flags = sdev_debug_cache_flags;
203 209 if (flags)
204 210 sdcmn_err(("cache debug flags 0x%x\n", flags));
205 211 #endif /* DEBUG */
206 212
207 213 ASSERT(sdev_node_cache == NULL);
208 214 sdev_node_cache = kmem_cache_create("sdev_node_cache",
209 215 sizeof (struct sdev_node), 0, i_sdev_node_ctor, i_sdev_node_dtor,
210 216 NULL, NULL, NULL, flags);
211 217 }
212 218
213 219 /* destroy sdev_node cache */
214 220 void
215 221 sdev_node_cache_fini()
216 222 {
217 223 ASSERT(sdev_node_cache != NULL);
218 224 kmem_cache_destroy(sdev_node_cache);
219 225 sdev_node_cache = NULL;
220 226 }
221 227
222 228 /*
223 229 * Compare two nodes lexographically to balance avl tree
224 230 */
225 231 static int
226 232 sdev_compare_nodes(const struct sdev_node *dv1, const struct sdev_node *dv2)
227 233 {
228 234 int rv;
229 235 if ((rv = strcmp(dv1->sdev_name, dv2->sdev_name)) == 0)
230 236 return (0);
231 237 return ((rv < 0) ? -1 : 1);
232 238 }
233 239
234 240 void
235 241 sdev_set_nodestate(struct sdev_node *dv, sdev_node_state_t state)
236 242 {
237 243 ASSERT(dv);
238 244 ASSERT(RW_WRITE_HELD(&dv->sdev_contents));
239 245 dv->sdev_state = state;
240 246 }
241 247
242 248 static void
243 249 sdev_attr_update(struct sdev_node *dv, vattr_t *vap)
244 250 {
245 251 timestruc_t now;
246 252 struct vattr *attrp;
247 253 uint_t mask;
248 254
249 255 ASSERT(dv->sdev_attr);
250 256 ASSERT(vap);
251 257
252 258 attrp = dv->sdev_attr;
253 259 mask = vap->va_mask;
254 260 if (mask & AT_TYPE)
255 261 attrp->va_type = vap->va_type;
256 262 if (mask & AT_MODE)
257 263 attrp->va_mode = vap->va_mode;
258 264 if (mask & AT_UID)
259 265 attrp->va_uid = vap->va_uid;
260 266 if (mask & AT_GID)
261 267 attrp->va_gid = vap->va_gid;
262 268 if (mask & AT_RDEV)
263 269 attrp->va_rdev = vap->va_rdev;
264 270
265 271 gethrestime(&now);
266 272 attrp->va_atime = (mask & AT_ATIME) ? vap->va_atime : now;
267 273 attrp->va_mtime = (mask & AT_MTIME) ? vap->va_mtime : now;
268 274 attrp->va_ctime = (mask & AT_CTIME) ? vap->va_ctime : now;
269 275 }
270 276
271 277 static void
272 278 sdev_attr_alloc(struct sdev_node *dv, vattr_t *vap)
273 279 {
274 280 ASSERT(dv->sdev_attr == NULL);
275 281 ASSERT(vap->va_mask & AT_TYPE);
276 282 ASSERT(vap->va_mask & AT_MODE);
277 283
278 284 dv->sdev_attr = kmem_zalloc(sizeof (struct vattr), KM_SLEEP);
279 285 sdev_attr_update(dv, vap);
280 286 }
281 287
282 288 /* alloc and initialize a sdev_node */
283 289 int
284 290 sdev_nodeinit(struct sdev_node *ddv, char *nm, struct sdev_node **newdv,
285 291 vattr_t *vap)
286 292 {
287 293 struct sdev_node *dv = NULL;
288 294 struct vnode *vp;
289 295 size_t nmlen, len;
290 296 devname_handle_t *dhl;
291 297
292 298 nmlen = strlen(nm) + 1;
293 299 if (nmlen > MAXNAMELEN) {
294 300 sdcmn_err9(("sdev_nodeinit: node name %s"
295 301 " too long\n", nm));
296 302 *newdv = NULL;
297 303 return (ENAMETOOLONG);
298 304 }
299 305
|
↓ open down ↓ |
137 lines elided |
↑ open up ↑ |
300 306 dv = kmem_cache_alloc(sdev_node_cache, KM_SLEEP);
301 307
302 308 dv->sdev_name = kmem_alloc(nmlen, KM_SLEEP);
303 309 bcopy(nm, dv->sdev_name, nmlen);
304 310 dv->sdev_namelen = nmlen - 1; /* '\0' not included */
305 311 len = strlen(ddv->sdev_path) + strlen(nm) + 2;
306 312 dv->sdev_path = kmem_alloc(len, KM_SLEEP);
307 313 (void) snprintf(dv->sdev_path, len, "%s/%s", ddv->sdev_path, nm);
308 314 /* overwritten for VLNK nodes */
309 315 dv->sdev_symlink = NULL;
310 - list_link_init(&dv->sdev_plist);
311 316
312 317 vp = SDEVTOV(dv);
313 318 vn_reinit(vp);
314 319 vp->v_vfsp = SDEVTOV(ddv)->v_vfsp;
315 320 if (vap)
316 321 vp->v_type = vap->va_type;
317 322
318 323 /*
319 324 * initialized to the parent's vnodeops.
320 325 * maybe overwriten for a VDIR
321 326 */
322 327 vn_setops(vp, vn_getops(SDEVTOV(ddv)));
323 328 vn_exists(vp);
324 329
325 330 dv->sdev_dotdot = NULL;
326 331 dv->sdev_attrvp = NULL;
327 332 if (vap) {
328 333 sdev_attr_alloc(dv, vap);
329 334 } else {
330 335 dv->sdev_attr = NULL;
331 336 }
332 337
333 338 dv->sdev_ino = sdev_mkino(dv);
334 339 dv->sdev_nlink = 0; /* updated on insert */
335 340 dv->sdev_flags = ddv->sdev_flags; /* inherit from the parent first */
336 341 dv->sdev_flags |= SDEV_BUILD;
337 342 mutex_init(&dv->sdev_lookup_lock, NULL, MUTEX_DEFAULT, NULL);
338 343 cv_init(&dv->sdev_lookup_cv, NULL, CV_DEFAULT, NULL);
339 344 if (SDEV_IS_GLOBAL(ddv)) {
340 345 dv->sdev_flags |= SDEV_GLOBAL;
341 346 dhl = &(dv->sdev_handle);
342 347 dhl->dh_data = dv;
343 348 dhl->dh_args = NULL;
344 349 sdev_set_no_negcache(dv);
345 350 dv->sdev_gdir_gen = 0;
346 351 } else {
347 352 dv->sdev_flags &= ~SDEV_GLOBAL;
348 353 dv->sdev_origin = NULL; /* set later */
349 354 bzero(&dv->sdev_prof, sizeof (dv->sdev_prof));
350 355 dv->sdev_ldir_gen = 0;
351 356 dv->sdev_devtree_gen = 0;
352 357 }
353 358
354 359 rw_enter(&dv->sdev_contents, RW_WRITER);
355 360 sdev_set_nodestate(dv, SDEV_INIT);
356 361 rw_exit(&dv->sdev_contents);
357 362 *newdv = dv;
358 363
359 364 return (0);
360 365 }
361 366
362 367 /*
363 368 * Transition a sdev_node into SDEV_READY state. If this fails, it is up to the
364 369 * caller to transition the node to the SDEV_ZOMBIE state.
365 370 */
366 371 int
367 372 sdev_nodeready(struct sdev_node *dv, struct vattr *vap, struct vnode *avp,
368 373 void *args, struct cred *cred)
369 374 {
370 375 int error = 0;
371 376 struct vnode *vp = SDEVTOV(dv);
372 377 vtype_t type;
373 378
374 379 ASSERT(dv && (dv->sdev_state != SDEV_READY) && vap);
375 380
376 381 type = vap->va_type;
377 382 vp->v_type = type;
378 383 vp->v_rdev = vap->va_rdev;
379 384 rw_enter(&dv->sdev_contents, RW_WRITER);
380 385 if (type == VDIR) {
381 386 dv->sdev_nlink = 2;
382 387 dv->sdev_flags &= ~SDEV_PERSIST;
383 388 dv->sdev_flags &= ~SDEV_DYNAMIC;
384 389 vn_setops(vp, sdev_get_vop(dv)); /* from internal vtab */
385 390 ASSERT(dv->sdev_dotdot);
386 391 ASSERT(SDEVTOV(dv->sdev_dotdot)->v_type == VDIR);
387 392 vp->v_rdev = SDEVTOV(dv->sdev_dotdot)->v_rdev;
388 393 avl_create(&dv->sdev_entries,
|
↓ open down ↓ |
68 lines elided |
↑ open up ↑ |
389 394 (int (*)(const void *, const void *))sdev_compare_nodes,
390 395 sizeof (struct sdev_node),
391 396 offsetof(struct sdev_node, sdev_avllink));
392 397 } else if (type == VLNK) {
393 398 ASSERT(args);
394 399 dv->sdev_nlink = 1;
395 400 dv->sdev_symlink = i_ddi_strdup((char *)args, KM_SLEEP);
396 401 } else {
397 402 dv->sdev_nlink = 1;
398 403 }
399 - sdev_plugin_nodeready(dv);
400 404
401 405 if (!(SDEV_IS_GLOBAL(dv))) {
402 406 dv->sdev_origin = (struct sdev_node *)args;
403 407 dv->sdev_flags &= ~SDEV_PERSIST;
404 408 }
405 409
406 410 /*
407 411 * shadow node is created here OR
408 412 * if failed (indicated by dv->sdev_attrvp == NULL),
409 413 * created later in sdev_setattr
410 414 */
411 415 if (avp) {
412 416 dv->sdev_attrvp = avp;
413 417 } else {
414 418 if (dv->sdev_attr == NULL) {
415 419 sdev_attr_alloc(dv, vap);
416 420 } else {
417 421 sdev_attr_update(dv, vap);
418 422 }
419 423
420 424 if ((dv->sdev_attrvp == NULL) && SDEV_IS_PERSIST(dv))
421 425 error = sdev_shadow_node(dv, cred);
422 426 }
423 427
424 428 if (error == 0) {
425 429 /* transition to READY state */
426 430 sdev_set_nodestate(dv, SDEV_READY);
427 431 sdev_nc_node_exists(dv);
428 432 }
429 433 rw_exit(&dv->sdev_contents);
430 434 return (error);
431 435 }
432 436
433 437 /*
434 438 * Build the VROOT sdev_node.
435 439 */
436 440 /*ARGSUSED*/
437 441 struct sdev_node *
438 442 sdev_mkroot(struct vfs *vfsp, dev_t devdev, struct vnode *mvp,
439 443 struct vnode *avp, struct cred *cred)
440 444 {
441 445 struct sdev_node *dv;
442 446 struct vnode *vp;
443 447 char devdir[] = "/dev";
444 448
445 449 ASSERT(sdev_node_cache != NULL);
446 450 ASSERT(avp);
447 451 dv = kmem_cache_alloc(sdev_node_cache, KM_SLEEP);
448 452 vp = SDEVTOV(dv);
449 453 vn_reinit(vp);
450 454 vp->v_flag |= VROOT;
451 455 vp->v_vfsp = vfsp;
452 456 vp->v_type = VDIR;
453 457 vp->v_rdev = devdev;
454 458 vn_setops(vp, sdev_vnodeops); /* apply the default vnodeops at /dev */
455 459 vn_exists(vp);
456 460
457 461 if (vfsp->vfs_mntpt)
458 462 dv->sdev_name = i_ddi_strdup(
459 463 (char *)refstr_value(vfsp->vfs_mntpt), KM_SLEEP);
460 464 else
461 465 /* vfs_mountdev1 set mount point later */
462 466 dv->sdev_name = i_ddi_strdup("/dev", KM_SLEEP);
463 467 dv->sdev_namelen = strlen(dv->sdev_name); /* '\0' not included */
464 468 dv->sdev_path = i_ddi_strdup(devdir, KM_SLEEP);
465 469 dv->sdev_ino = SDEV_ROOTINO;
466 470 dv->sdev_nlink = 2; /* name + . (no sdev_insert) */
467 471 dv->sdev_dotdot = dv; /* .. == self */
468 472 dv->sdev_attrvp = avp;
469 473 dv->sdev_attr = NULL;
470 474 mutex_init(&dv->sdev_lookup_lock, NULL, MUTEX_DEFAULT, NULL);
471 475 cv_init(&dv->sdev_lookup_cv, NULL, CV_DEFAULT, NULL);
472 476 if (strcmp(dv->sdev_name, "/dev") == 0) {
473 477 dv->sdev_flags = SDEV_BUILD|SDEV_GLOBAL|SDEV_PERSIST;
474 478 bzero(&dv->sdev_handle, sizeof (dv->sdev_handle));
475 479 dv->sdev_gdir_gen = 0;
476 480 } else {
477 481 dv->sdev_flags = SDEV_BUILD;
478 482 dv->sdev_flags &= ~SDEV_PERSIST;
479 483 bzero(&dv->sdev_prof, sizeof (dv->sdev_prof));
480 484 dv->sdev_ldir_gen = 0;
481 485 dv->sdev_devtree_gen = 0;
482 486 }
483 487
484 488 avl_create(&dv->sdev_entries,
485 489 (int (*)(const void *, const void *))sdev_compare_nodes,
|
↓ open down ↓ |
76 lines elided |
↑ open up ↑ |
486 490 sizeof (struct sdev_node),
487 491 offsetof(struct sdev_node, sdev_avllink));
488 492
489 493 rw_enter(&dv->sdev_contents, RW_WRITER);
490 494 sdev_set_nodestate(dv, SDEV_READY);
491 495 rw_exit(&dv->sdev_contents);
492 496 sdev_nc_node_exists(dv);
493 497 return (dv);
494 498 }
495 499
496 -struct sdev_vop_table vtab[] = {
497 - { "pts", devpts_vnodeops_tbl, &devpts_vnodeops, devpts_validate,
500 +/* directory dependent vop table */
501 +struct sdev_vop_table {
502 + char *vt_name; /* subdirectory name */
503 + const fs_operation_def_t *vt_service; /* vnodeops table */
504 + struct vnodeops *vt_vops; /* constructed vop */
505 + struct vnodeops **vt_global_vops; /* global container for vop */
506 + int (*vt_vtor)(struct sdev_node *); /* validate sdev_node */
507 + int vt_flags;
508 +};
509 +
510 +/*
511 + * A nice improvement would be to provide a plug-in mechanism
512 + * for this table instead of a const table.
513 + */
514 +static struct sdev_vop_table vtab[] =
515 +{
516 + { "pts", devpts_vnodeops_tbl, NULL, &devpts_vnodeops, devpts_validate,
498 517 SDEV_DYNAMIC | SDEV_VTOR },
499 518
500 - { "vt", devvt_vnodeops_tbl, &devvt_vnodeops, devvt_validate,
519 + { "vt", devvt_vnodeops_tbl, NULL, &devvt_vnodeops, devvt_validate,
501 520 SDEV_DYNAMIC | SDEV_VTOR },
502 521
503 - { "zvol", devzvol_vnodeops_tbl, &devzvol_vnodeops,
522 + { "zvol", devzvol_vnodeops_tbl, NULL, &devzvol_vnodeops,
504 523 devzvol_validate, SDEV_ZONED | SDEV_DYNAMIC | SDEV_VTOR | SDEV_SUBDIR },
505 524
506 - { "zcons", NULL, NULL, NULL, SDEV_NO_NCACHE },
525 + { "zcons", NULL, NULL, NULL, NULL, SDEV_NO_NCACHE },
507 526
508 - { "net", devnet_vnodeops_tbl, &devnet_vnodeops, devnet_validate,
509 - SDEV_DYNAMIC | SDEV_VTOR | SDEV_SUBDIR },
527 + { "net", devnet_vnodeops_tbl, NULL, &devnet_vnodeops, devnet_validate,
528 + SDEV_DYNAMIC | SDEV_VTOR },
510 529
511 - { "ipnet", devipnet_vnodeops_tbl, &devipnet_vnodeops,
530 + { "ipnet", devipnet_vnodeops_tbl, NULL, &devipnet_vnodeops,
512 531 devipnet_validate, SDEV_DYNAMIC | SDEV_VTOR | SDEV_NO_NCACHE },
513 532
514 533 /*
515 534 * SDEV_DYNAMIC: prevent calling out to devfsadm, since only the
516 535 * lofi driver controls child nodes.
517 536 *
518 537 * SDEV_PERSIST: ensure devfsadm knows to clean up any persisted
519 538 * stale nodes (e.g. from devfsadm -R).
520 539 *
521 540 * In addition, devfsadm knows not to attempt a rmdir: a zone
522 541 * may hold a reference, which would zombify the node,
523 542 * preventing a mkdir.
524 543 */
525 544
526 - { "lofi", NULL, NULL, NULL,
545 + { "lofi", NULL, NULL, NULL, NULL,
527 546 SDEV_ZONED | SDEV_DYNAMIC | SDEV_PERSIST },
528 - { "rlofi", NULL, NULL, NULL,
547 + { "rlofi", NULL, NULL, NULL, NULL,
529 548 SDEV_ZONED | SDEV_DYNAMIC | SDEV_PERSIST },
530 549
531 - { NULL, NULL, NULL, NULL, 0}
550 + { NULL, NULL, NULL, NULL, NULL, 0}
532 551 };
533 552
553 +/*
554 + * We need to match off of the sdev_path, not the sdev_name. We are only allowed
555 + * to exist directly under /dev.
556 + */
557 +struct sdev_vop_table *
558 +sdev_match(struct sdev_node *dv)
559 +{
560 + int vlen;
561 + int i;
562 + const char *path;
534 563
564 + if (strlen(dv->sdev_path) <= 5)
565 + return (NULL);
566 +
567 + if (strncmp(dv->sdev_path, "/dev/", 5) != 0)
568 + return (NULL);
569 + path = dv->sdev_path + 5;
570 +
571 + for (i = 0; vtab[i].vt_name; i++) {
572 + if (strcmp(vtab[i].vt_name, path) == 0)
573 + return (&vtab[i]);
574 + if (vtab[i].vt_flags & SDEV_SUBDIR) {
575 + vlen = strlen(vtab[i].vt_name);
576 + if ((strncmp(vtab[i].vt_name, path,
577 + vlen - 1) == 0) && path[vlen] == '/')
578 + return (&vtab[i]);
579 + }
580 +
581 + }
582 + return (NULL);
583 +}
584 +
535 585 /*
586 + * sets a directory's vnodeops if the directory is in the vtab;
587 + */
588 +static struct vnodeops *
589 +sdev_get_vop(struct sdev_node *dv)
590 +{
591 + struct sdev_vop_table *vtp;
592 + char *path;
593 +
594 + path = dv->sdev_path;
595 + ASSERT(path);
596 +
597 + /* gets the relative path to /dev/ */
598 + path += 5;
599 +
600 + /* gets the vtab entry it matches */
601 + if ((vtp = sdev_match(dv)) != NULL) {
602 + dv->sdev_flags |= vtp->vt_flags;
603 + if (SDEV_IS_PERSIST(dv->sdev_dotdot) &&
604 + (SDEV_IS_PERSIST(dv) || !SDEV_IS_DYNAMIC(dv)))
605 + dv->sdev_flags |= SDEV_PERSIST;
606 +
607 + if (vtp->vt_vops) {
608 + if (vtp->vt_global_vops)
609 + *(vtp->vt_global_vops) = vtp->vt_vops;
610 +
611 + return (vtp->vt_vops);
612 + }
613 +
614 + if (vtp->vt_service) {
615 + fs_operation_def_t *templ;
616 + templ = sdev_merge_vtab(vtp->vt_service);
617 + if (vn_make_ops(vtp->vt_name,
618 + (const fs_operation_def_t *)templ,
619 + &vtp->vt_vops) != 0) {
620 + cmn_err(CE_PANIC, "%s: malformed vnode ops\n",
621 + vtp->vt_name);
622 + /*NOTREACHED*/
623 + }
624 + if (vtp->vt_global_vops) {
625 + *(vtp->vt_global_vops) = vtp->vt_vops;
626 + }
627 + sdev_free_vtab(templ);
628 +
629 + return (vtp->vt_vops);
630 + }
631 +
632 + return (sdev_vnodeops);
633 + }
634 +
635 + /* child inherits the persistence of the parent */
636 + if (SDEV_IS_PERSIST(dv->sdev_dotdot))
637 + dv->sdev_flags |= SDEV_PERSIST;
638 +
639 + return (sdev_vnodeops);
640 +}
641 +
642 +static void
643 +sdev_set_no_negcache(struct sdev_node *dv)
644 +{
645 + int i;
646 + char *path;
647 +
648 + ASSERT(dv->sdev_path);
649 + path = dv->sdev_path + strlen("/dev/");
650 +
651 + for (i = 0; vtab[i].vt_name; i++) {
652 + if (strcmp(vtab[i].vt_name, path) == 0) {
653 + if (vtab[i].vt_flags & SDEV_NO_NCACHE)
654 + dv->sdev_flags |= SDEV_NO_NCACHE;
655 + break;
656 + }
657 + }
658 +}
659 +
660 +void *
661 +sdev_get_vtor(struct sdev_node *dv)
662 +{
663 + struct sdev_vop_table *vtp;
664 +
665 + vtp = sdev_match(dv);
666 + if (vtp)
667 + return ((void *)vtp->vt_vtor);
668 + else
669 + return (NULL);
670 +}
671 +
672 +/*
536 673 * Build the base root inode
537 674 */
538 675 ino_t
539 676 sdev_mkino(struct sdev_node *dv)
540 677 {
541 678 ino_t ino;
542 679
543 680 /*
544 681 * for now, follow the lead of tmpfs here
545 682 * need to someday understand the requirements here
546 683 */
547 684 ino = (ino_t)(uint32_t)((uintptr_t)dv >> 3);
548 685 ino += SDEV_ROOTINO + 1;
549 686
550 687 return (ino);
551 688 }
552 689
553 690 int
554 691 sdev_getlink(struct vnode *linkvp, char **link)
555 692 {
556 693 int err;
557 694 char *buf;
558 695 struct uio uio = {0};
559 696 struct iovec iov = {0};
560 697
561 698 if (linkvp == NULL)
562 699 return (ENOENT);
563 700 ASSERT(linkvp->v_type == VLNK);
564 701
565 702 buf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
566 703 iov.iov_base = buf;
567 704 iov.iov_len = MAXPATHLEN;
568 705 uio.uio_iov = &iov;
569 706 uio.uio_iovcnt = 1;
570 707 uio.uio_resid = MAXPATHLEN;
571 708 uio.uio_segflg = UIO_SYSSPACE;
572 709 uio.uio_llimit = MAXOFFSET_T;
573 710
574 711 err = VOP_READLINK(linkvp, &uio, kcred, NULL);
575 712 if (err) {
576 713 cmn_err(CE_WARN, "readlink %s failed in dev\n", buf);
577 714 kmem_free(buf, MAXPATHLEN);
578 715 return (ENOENT);
579 716 }
580 717
581 718 /* mission complete */
582 719 *link = i_ddi_strdup(buf, KM_SLEEP);
583 720 kmem_free(buf, MAXPATHLEN);
584 721 return (0);
585 722 }
586 723
587 724 /*
588 725 * A convenient wrapper to get the devfs node vnode for a device
589 726 * minor functionality: readlink() of a /dev symlink
590 727 * Place the link into dv->sdev_symlink
591 728 */
592 729 static int
593 730 sdev_follow_link(struct sdev_node *dv)
594 731 {
595 732 int err;
596 733 struct vnode *linkvp;
597 734 char *link = NULL;
598 735
599 736 linkvp = SDEVTOV(dv);
600 737 if (linkvp == NULL)
601 738 return (ENOENT);
602 739 ASSERT(linkvp->v_type == VLNK);
603 740 err = sdev_getlink(linkvp, &link);
604 741 if (err) {
605 742 dv->sdev_symlink = NULL;
606 743 return (ENOENT);
607 744 }
608 745
609 746 ASSERT(link != NULL);
610 747 dv->sdev_symlink = link;
611 748 return (0);
612 749 }
613 750
614 751 static int
615 752 sdev_node_check(struct sdev_node *dv, struct vattr *nvap, void *nargs)
616 753 {
617 754 vtype_t otype = SDEVTOV(dv)->v_type;
618 755
619 756 /*
620 757 * existing sdev_node has a different type.
621 758 */
622 759 if (otype != nvap->va_type) {
623 760 sdcmn_err9(("sdev_node_check: existing node "
624 761 " %s type %d does not match new node type %d\n",
625 762 dv->sdev_name, otype, nvap->va_type));
626 763 return (EEXIST);
627 764 }
628 765
629 766 /*
630 767 * For a symlink, the target should be the same.
631 768 */
632 769 if (otype == VLNK) {
633 770 ASSERT(nargs != NULL);
634 771 ASSERT(dv->sdev_symlink != NULL);
635 772 if (strcmp(dv->sdev_symlink, (char *)nargs) != 0) {
636 773 sdcmn_err9(("sdev_node_check: existing node "
637 774 " %s has different symlink %s as new node "
638 775 " %s\n", dv->sdev_name, dv->sdev_symlink,
639 776 (char *)nargs));
640 777 return (EEXIST);
641 778 }
642 779 }
643 780
644 781 return (0);
645 782 }
646 783
647 784 /*
648 785 * sdev_mknode - a wrapper for sdev_nodeinit(), sdev_nodeready()
649 786 *
650 787 * arguments:
651 788 * - ddv (parent)
652 789 * - nm (child name)
653 790 * - newdv (sdev_node for nm is returned here)
654 791 * - vap (vattr for the node to be created, va_type should be set.
655 792 * - avp (attribute vnode)
656 793 * the defaults should be used if unknown)
657 794 * - cred
658 795 * - args
659 796 * . tnm (for VLNK)
660 797 * . global sdev_node (for !SDEV_GLOBAL)
661 798 * - state: SDEV_INIT, SDEV_READY
662 799 *
663 800 * only ddv, nm, newddv, vap, cred are required for sdev_mknode(SDEV_INIT)
664 801 *
665 802 * NOTE: directory contents writers lock needs to be held before
666 803 * calling this routine.
667 804 */
668 805 int
669 806 sdev_mknode(struct sdev_node *ddv, char *nm, struct sdev_node **newdv,
670 807 struct vattr *vap, struct vnode *avp, void *args, struct cred *cred,
671 808 sdev_node_state_t state)
672 809 {
673 810 int error = 0;
674 811 sdev_node_state_t node_state;
675 812 struct sdev_node *dv = NULL;
676 813
677 814 ASSERT(state != SDEV_ZOMBIE);
678 815 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
679 816
680 817 if (*newdv) {
681 818 dv = *newdv;
682 819 } else {
683 820 /* allocate and initialize a sdev_node */
684 821 if (ddv->sdev_state == SDEV_ZOMBIE) {
685 822 sdcmn_err9(("sdev_mknode: parent %s ZOMBIEd\n",
686 823 ddv->sdev_path));
687 824 return (ENOENT);
688 825 }
689 826
690 827 error = sdev_nodeinit(ddv, nm, &dv, vap);
691 828 if (error != 0) {
692 829 sdcmn_err9(("sdev_mknode: error %d,"
693 830 " name %s can not be initialized\n",
694 831 error, nm));
695 832 return (error);
696 833 }
697 834 ASSERT(dv);
698 835
699 836 /* insert into the directory cache */
700 837 sdev_cache_update(ddv, &dv, nm, SDEV_CACHE_ADD);
701 838 }
702 839
703 840 ASSERT(dv);
704 841 node_state = dv->sdev_state;
705 842 ASSERT(node_state != SDEV_ZOMBIE);
706 843
707 844 if (state == SDEV_READY) {
708 845 switch (node_state) {
709 846 case SDEV_INIT:
710 847 error = sdev_nodeready(dv, vap, avp, args, cred);
711 848 if (error) {
712 849 sdcmn_err9(("sdev_mknode: node %s can NOT"
713 850 " be transitioned into READY state, "
714 851 "error %d\n", nm, error));
715 852 }
716 853 break;
717 854 case SDEV_READY:
718 855 /*
719 856 * Do some sanity checking to make sure
720 857 * the existing sdev_node is what has been
721 858 * asked for.
722 859 */
723 860 error = sdev_node_check(dv, vap, args);
724 861 break;
725 862 default:
726 863 break;
727 864 }
728 865 }
729 866
730 867 if (!error) {
731 868 *newdv = dv;
732 869 ASSERT((*newdv)->sdev_state != SDEV_ZOMBIE);
733 870 } else {
734 871 sdev_cache_update(ddv, &dv, nm, SDEV_CACHE_DELETE);
735 872 /*
736 873 * We created this node, it wasn't passed into us. Therefore it
737 874 * is up to us to delete it.
738 875 */
739 876 if (*newdv == NULL)
740 877 SDEV_SIMPLE_RELE(dv);
741 878 *newdv = NULL;
742 879 }
743 880
744 881 return (error);
745 882 }
746 883
747 884 /*
748 885 * convenient wrapper to change vp's ATIME, CTIME and MTIME
749 886 */
750 887 void
751 888 sdev_update_timestamps(struct vnode *vp, cred_t *cred, uint_t mask)
752 889 {
753 890 struct vattr attr;
754 891 timestruc_t now;
755 892 int err;
756 893
757 894 ASSERT(vp);
758 895 gethrestime(&now);
759 896 if (mask & AT_CTIME)
760 897 attr.va_ctime = now;
761 898 if (mask & AT_MTIME)
762 899 attr.va_mtime = now;
763 900 if (mask & AT_ATIME)
764 901 attr.va_atime = now;
765 902
766 903 attr.va_mask = (mask & AT_TIMES);
767 904 err = VOP_SETATTR(vp, &attr, 0, cred, NULL);
768 905 if (err && (err != EROFS)) {
769 906 sdcmn_err(("update timestamps error %d\n", err));
770 907 }
771 908 }
772 909
773 910 /*
774 911 * the backing store vnode is released here
775 912 */
776 913 /*ARGSUSED1*/
777 914 void
778 915 sdev_nodedestroy(struct sdev_node *dv, uint_t flags)
779 916 {
780 917 /* no references */
781 918 ASSERT(dv->sdev_nlink == 0);
782 919
783 920 if (dv->sdev_attrvp != NULLVP) {
784 921 VN_RELE(dv->sdev_attrvp);
785 922 /*
786 923 * reset the attrvp so that no more
787 924 * references can be made on this already
788 925 * vn_rele() vnode
789 926 */
790 927 dv->sdev_attrvp = NULLVP;
791 928 }
792 929
793 930 if (dv->sdev_attr != NULL) {
794 931 kmem_free(dv->sdev_attr, sizeof (struct vattr));
795 932 dv->sdev_attr = NULL;
796 933 }
797 934
798 935 if (dv->sdev_name != NULL) {
799 936 kmem_free(dv->sdev_name, dv->sdev_namelen + 1);
800 937 dv->sdev_name = NULL;
801 938 }
802 939
|
↓ open down ↓ |
257 lines elided |
↑ open up ↑ |
803 940 if (dv->sdev_symlink != NULL) {
804 941 kmem_free(dv->sdev_symlink, strlen(dv->sdev_symlink) + 1);
805 942 dv->sdev_symlink = NULL;
806 943 }
807 944
808 945 if (dv->sdev_path) {
809 946 kmem_free(dv->sdev_path, strlen(dv->sdev_path) + 1);
810 947 dv->sdev_path = NULL;
811 948 }
812 949
813 - if (!SDEV_IS_GLOBAL(dv)) {
950 + if (!SDEV_IS_GLOBAL(dv))
814 951 sdev_prof_free(dv);
815 - if (dv->sdev_vnode->v_type != VLNK && dv->sdev_origin != NULL)
816 - SDEV_RELE(dv->sdev_origin);
817 - }
818 952
819 953 if (SDEVTOV(dv)->v_type == VDIR) {
820 954 ASSERT(SDEV_FIRST_ENTRY(dv) == NULL);
821 955 avl_destroy(&dv->sdev_entries);
822 956 }
823 957
824 958 mutex_destroy(&dv->sdev_lookup_lock);
825 959 cv_destroy(&dv->sdev_lookup_cv);
826 960
827 961 /* return node to initial state as per constructor */
828 962 (void) memset((void *)&dv->sdev_instance_data, 0,
829 963 sizeof (dv->sdev_instance_data));
830 964 vn_invalid(SDEVTOV(dv));
831 965 dv->sdev_private = NULL;
832 966 kmem_cache_free(sdev_node_cache, dv);
833 967 }
834 968
835 969 /*
836 970 * DIRECTORY CACHE lookup
837 971 */
838 972 struct sdev_node *
839 973 sdev_findbyname(struct sdev_node *ddv, char *nm)
840 974 {
841 975 struct sdev_node *dv;
842 976 struct sdev_node dvtmp;
843 977 avl_index_t where;
844 978
845 979 ASSERT(RW_LOCK_HELD(&ddv->sdev_contents));
846 980
847 981 dvtmp.sdev_name = nm;
848 982 dv = avl_find(&ddv->sdev_entries, &dvtmp, &where);
849 983 if (dv) {
850 984 ASSERT(dv->sdev_dotdot == ddv);
851 985 ASSERT(strcmp(dv->sdev_name, nm) == 0);
852 986 ASSERT(dv->sdev_state != SDEV_ZOMBIE);
853 987 SDEV_HOLD(dv);
854 988 return (dv);
855 989 }
856 990 return (NULL);
857 991 }
858 992
859 993 /*
860 994 * Inserts a new sdev_node in a parent directory
861 995 */
862 996 void
863 997 sdev_direnter(struct sdev_node *ddv, struct sdev_node *dv)
864 998 {
865 999 avl_index_t where;
866 1000
867 1001 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
868 1002 ASSERT(SDEVTOV(ddv)->v_type == VDIR);
869 1003 ASSERT(ddv->sdev_nlink >= 2);
870 1004 ASSERT(dv->sdev_nlink == 0);
871 1005 ASSERT(dv->sdev_state != SDEV_ZOMBIE);
872 1006
873 1007 dv->sdev_dotdot = ddv;
874 1008 VERIFY(avl_find(&ddv->sdev_entries, dv, &where) == NULL);
875 1009 avl_insert(&ddv->sdev_entries, dv, where);
876 1010 ddv->sdev_nlink++;
877 1011 }
878 1012
879 1013 /*
880 1014 * The following check is needed because while sdev_nodes are linked
881 1015 * in SDEV_INIT state, they have their link counts incremented only
882 1016 * in SDEV_READY state.
883 1017 */
884 1018 static void
885 1019 decr_link(struct sdev_node *dv)
886 1020 {
887 1021 VERIFY(RW_WRITE_HELD(&dv->sdev_contents));
888 1022 if (dv->sdev_state != SDEV_INIT) {
889 1023 VERIFY(dv->sdev_nlink >= 1);
890 1024 dv->sdev_nlink--;
891 1025 } else {
892 1026 VERIFY(dv->sdev_nlink == 0);
893 1027 }
894 1028 }
895 1029
896 1030 /*
897 1031 * Delete an existing dv from directory cache
898 1032 *
899 1033 * In the case of a node is still held by non-zero reference count, the node is
900 1034 * put into ZOMBIE state. The node is always unlinked from its parent, but it is
901 1035 * not destroyed via sdev_inactive until its reference count reaches "0".
902 1036 */
903 1037 static void
904 1038 sdev_dirdelete(struct sdev_node *ddv, struct sdev_node *dv)
905 1039 {
906 1040 struct vnode *vp;
907 1041 sdev_node_state_t os;
908 1042
909 1043 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
910 1044
911 1045 vp = SDEVTOV(dv);
912 1046 mutex_enter(&vp->v_lock);
913 1047 rw_enter(&dv->sdev_contents, RW_WRITER);
914 1048 os = dv->sdev_state;
915 1049 ASSERT(os != SDEV_ZOMBIE);
916 1050 dv->sdev_state = SDEV_ZOMBIE;
917 1051
918 1052 /*
919 1053 * unlink ourselves from the parent directory now to take care of the ..
920 1054 * link. However, if we're a directory, we don't remove our reference to
921 1055 * ourself eg. '.' until we are torn down in the inactive callback.
922 1056 */
923 1057 decr_link(ddv);
924 1058 avl_remove(&ddv->sdev_entries, dv);
925 1059 /*
926 1060 * sdev_inactive expects nodes to have a link to themselves when we're
927 1061 * tearing them down. If we're transitioning from the initial state to
928 1062 * zombie and not via ready, then we're not going to have this link that
929 1063 * comes from the node being ready. As a result, we need to increment
930 1064 * our link count by one to account for this.
931 1065 */
932 1066 if (os == SDEV_INIT && dv->sdev_nlink == 0)
933 1067 dv->sdev_nlink++;
934 1068 rw_exit(&dv->sdev_contents);
935 1069 mutex_exit(&vp->v_lock);
936 1070 }
937 1071
938 1072 /*
939 1073 * check if the source is in the path of the target
940 1074 *
941 1075 * source and target are different
942 1076 */
943 1077 /*ARGSUSED2*/
944 1078 static int
945 1079 sdev_checkpath(struct sdev_node *sdv, struct sdev_node *tdv, struct cred *cred)
946 1080 {
947 1081 int error = 0;
948 1082 struct sdev_node *dotdot, *dir;
949 1083
950 1084 dotdot = tdv->sdev_dotdot;
951 1085 ASSERT(dotdot);
952 1086
953 1087 /* fs root */
954 1088 if (dotdot == tdv) {
955 1089 return (0);
956 1090 }
957 1091
958 1092 for (;;) {
959 1093 /*
960 1094 * avoid error cases like
961 1095 * mv a a/b
962 1096 * mv a a/b/c
963 1097 * etc.
964 1098 */
965 1099 if (dotdot == sdv) {
966 1100 error = EINVAL;
967 1101 break;
968 1102 }
969 1103
970 1104 dir = dotdot;
971 1105 dotdot = dir->sdev_dotdot;
972 1106
973 1107 /* done checking because root is reached */
974 1108 if (dir == dotdot) {
975 1109 break;
976 1110 }
977 1111 }
978 1112 return (error);
979 1113 }
980 1114
981 1115 int
982 1116 sdev_rnmnode(struct sdev_node *oddv, struct sdev_node *odv,
983 1117 struct sdev_node *nddv, struct sdev_node **ndvp, char *nnm,
984 1118 struct cred *cred)
985 1119 {
986 1120 int error = 0;
987 1121 struct vnode *ovp = SDEVTOV(odv);
988 1122 struct vnode *nvp;
989 1123 struct vattr vattr;
990 1124 int doingdir = (ovp->v_type == VDIR);
991 1125 char *link = NULL;
992 1126 int samedir = (oddv == nddv) ? 1 : 0;
993 1127 int bkstore = 0;
994 1128 struct sdev_node *idv = NULL;
995 1129 struct sdev_node *ndv = NULL;
996 1130 timestruc_t now;
997 1131
998 1132 vattr.va_mask = AT_TYPE|AT_MODE|AT_UID|AT_GID;
999 1133 error = VOP_GETATTR(ovp, &vattr, 0, cred, NULL);
1000 1134 if (error)
1001 1135 return (error);
1002 1136
1003 1137 if (!samedir)
1004 1138 rw_enter(&oddv->sdev_contents, RW_WRITER);
1005 1139 rw_enter(&nddv->sdev_contents, RW_WRITER);
1006 1140
1007 1141 /*
1008 1142 * the source may have been deleted by another thread before
1009 1143 * we gets here.
1010 1144 */
1011 1145 if (odv->sdev_state != SDEV_READY) {
1012 1146 error = ENOENT;
1013 1147 goto err_out;
1014 1148 }
1015 1149
1016 1150 if (doingdir && (odv == nddv)) {
1017 1151 error = EINVAL;
1018 1152 goto err_out;
1019 1153 }
1020 1154
1021 1155 /*
1022 1156 * If renaming a directory, and the parents are different (".." must be
1023 1157 * changed) then the source dir must not be in the dir hierarchy above
1024 1158 * the target since it would orphan everything below the source dir.
1025 1159 */
1026 1160 if (doingdir && (oddv != nddv)) {
1027 1161 error = sdev_checkpath(odv, nddv, cred);
1028 1162 if (error)
1029 1163 goto err_out;
1030 1164 }
1031 1165
1032 1166 /* fix the source for a symlink */
1033 1167 if (vattr.va_type == VLNK) {
1034 1168 if (odv->sdev_symlink == NULL) {
1035 1169 error = sdev_follow_link(odv);
1036 1170 if (error) {
1037 1171 /*
1038 1172 * The underlying symlink doesn't exist. This
1039 1173 * node probably shouldn't even exist. While
1040 1174 * it's a bit jarring to consumers, we're going
1041 1175 * to remove the node from /dev.
1042 1176 */
1043 1177 if (SDEV_IS_PERSIST((*ndvp)))
1044 1178 bkstore = 1;
1045 1179 sdev_dirdelete(oddv, odv);
1046 1180 if (bkstore) {
1047 1181 ASSERT(nddv->sdev_attrvp);
1048 1182 error = VOP_REMOVE(nddv->sdev_attrvp,
1049 1183 nnm, cred, NULL, 0);
1050 1184 if (error)
1051 1185 goto err_out;
1052 1186 }
1053 1187 error = ENOENT;
1054 1188 goto err_out;
1055 1189 }
1056 1190 }
1057 1191 ASSERT(odv->sdev_symlink);
1058 1192 link = i_ddi_strdup(odv->sdev_symlink, KM_SLEEP);
1059 1193 }
1060 1194
1061 1195 /* destination existing */
1062 1196 if (*ndvp) {
1063 1197 nvp = SDEVTOV(*ndvp);
1064 1198 ASSERT(nvp);
1065 1199
1066 1200 /* handling renaming to itself */
1067 1201 if (odv == *ndvp) {
1068 1202 error = 0;
1069 1203 goto err_out;
1070 1204 }
1071 1205
1072 1206 if (nvp->v_type == VDIR) {
1073 1207 if (!doingdir) {
1074 1208 error = EISDIR;
1075 1209 goto err_out;
1076 1210 }
1077 1211
1078 1212 if (vn_vfswlock(nvp)) {
1079 1213 error = EBUSY;
1080 1214 goto err_out;
1081 1215 }
1082 1216
1083 1217 if (vn_mountedvfs(nvp) != NULL) {
1084 1218 vn_vfsunlock(nvp);
1085 1219 error = EBUSY;
1086 1220 goto err_out;
1087 1221 }
1088 1222
1089 1223 /* in case dir1 exists in dir2 and "mv dir1 dir2" */
1090 1224 if ((*ndvp)->sdev_nlink > 2) {
1091 1225 vn_vfsunlock(nvp);
1092 1226 error = EEXIST;
1093 1227 goto err_out;
1094 1228 }
1095 1229 vn_vfsunlock(nvp);
1096 1230
1097 1231 /*
1098 1232 * We did not place the hold on *ndvp, so even though
1099 1233 * we're deleting the node, we should not get rid of our
1100 1234 * reference.
1101 1235 */
1102 1236 sdev_dirdelete(nddv, *ndvp);
1103 1237 *ndvp = NULL;
1104 1238 ASSERT(nddv->sdev_attrvp);
1105 1239 error = VOP_RMDIR(nddv->sdev_attrvp, nnm,
1106 1240 nddv->sdev_attrvp, cred, NULL, 0);
1107 1241 if (error)
1108 1242 goto err_out;
1109 1243 } else {
1110 1244 if (doingdir) {
1111 1245 error = ENOTDIR;
1112 1246 goto err_out;
1113 1247 }
1114 1248
1115 1249 if (SDEV_IS_PERSIST((*ndvp))) {
1116 1250 bkstore = 1;
1117 1251 }
1118 1252
1119 1253 /*
1120 1254 * Get rid of the node from the directory cache note.
1121 1255 * Don't forget that it's not up to us to remove the vn
1122 1256 * ref on the sdev node, as we did not place it.
1123 1257 */
1124 1258 sdev_dirdelete(nddv, *ndvp);
1125 1259 *ndvp = NULL;
1126 1260 if (bkstore) {
1127 1261 ASSERT(nddv->sdev_attrvp);
1128 1262 error = VOP_REMOVE(nddv->sdev_attrvp,
1129 1263 nnm, cred, NULL, 0);
1130 1264 if (error)
1131 1265 goto err_out;
1132 1266 }
1133 1267 }
1134 1268 }
1135 1269
1136 1270 /*
1137 1271 * make a fresh node from the source attrs
1138 1272 */
1139 1273 ASSERT(RW_WRITE_HELD(&nddv->sdev_contents));
1140 1274 error = sdev_mknode(nddv, nnm, ndvp, &vattr,
1141 1275 NULL, (void *)link, cred, SDEV_READY);
1142 1276
1143 1277 if (link != NULL) {
1144 1278 kmem_free(link, strlen(link) + 1);
1145 1279 link = NULL;
1146 1280 }
1147 1281
1148 1282 if (error)
1149 1283 goto err_out;
1150 1284 ASSERT(*ndvp);
1151 1285 ASSERT((*ndvp)->sdev_state == SDEV_READY);
1152 1286
1153 1287 /* move dir contents */
1154 1288 if (doingdir) {
1155 1289 for (idv = SDEV_FIRST_ENTRY(odv); idv;
1156 1290 idv = SDEV_NEXT_ENTRY(odv, idv)) {
1157 1291 SDEV_HOLD(idv);
1158 1292 error = sdev_rnmnode(odv, idv,
1159 1293 (struct sdev_node *)(*ndvp), &ndv,
1160 1294 idv->sdev_name, cred);
1161 1295 SDEV_RELE(idv);
1162 1296 if (error)
1163 1297 goto err_out;
1164 1298 ndv = NULL;
1165 1299 }
1166 1300 }
1167 1301
1168 1302 if ((*ndvp)->sdev_attrvp) {
1169 1303 sdev_update_timestamps((*ndvp)->sdev_attrvp, kcred,
1170 1304 AT_CTIME|AT_ATIME);
1171 1305 } else {
1172 1306 ASSERT((*ndvp)->sdev_attr);
1173 1307 gethrestime(&now);
1174 1308 (*ndvp)->sdev_attr->va_ctime = now;
1175 1309 (*ndvp)->sdev_attr->va_atime = now;
1176 1310 }
1177 1311
1178 1312 if (nddv->sdev_attrvp) {
1179 1313 sdev_update_timestamps(nddv->sdev_attrvp, kcred,
1180 1314 AT_MTIME|AT_ATIME);
1181 1315 } else {
1182 1316 ASSERT(nddv->sdev_attr);
1183 1317 gethrestime(&now);
1184 1318 nddv->sdev_attr->va_mtime = now;
1185 1319 nddv->sdev_attr->va_atime = now;
1186 1320 }
1187 1321 rw_exit(&nddv->sdev_contents);
1188 1322 if (!samedir)
1189 1323 rw_exit(&oddv->sdev_contents);
1190 1324
1191 1325 SDEV_RELE(*ndvp);
1192 1326 return (error);
1193 1327
1194 1328 err_out:
1195 1329 if (link != NULL) {
1196 1330 kmem_free(link, strlen(link) + 1);
1197 1331 link = NULL;
1198 1332 }
1199 1333
1200 1334 rw_exit(&nddv->sdev_contents);
1201 1335 if (!samedir)
1202 1336 rw_exit(&oddv->sdev_contents);
1203 1337 return (error);
1204 1338 }
1205 1339
1206 1340 /*
1207 1341 * Merge sdev_node specific information into an attribute structure.
1208 1342 *
1209 1343 * note: sdev_node is not locked here
1210 1344 */
1211 1345 void
1212 1346 sdev_vattr_merge(struct sdev_node *dv, struct vattr *vap)
1213 1347 {
1214 1348 struct vnode *vp = SDEVTOV(dv);
1215 1349
1216 1350 vap->va_nlink = dv->sdev_nlink;
1217 1351 vap->va_nodeid = dv->sdev_ino;
1218 1352 vap->va_fsid = SDEVTOV(dv->sdev_dotdot)->v_rdev;
1219 1353 vap->va_type = vp->v_type;
1220 1354
1221 1355 if (vp->v_type == VDIR) {
1222 1356 vap->va_rdev = 0;
1223 1357 vap->va_fsid = vp->v_rdev;
1224 1358 } else if (vp->v_type == VLNK) {
1225 1359 vap->va_rdev = 0;
1226 1360 vap->va_mode &= ~S_IFMT;
1227 1361 vap->va_mode |= S_IFLNK;
1228 1362 } else if ((vp->v_type == VCHR) || (vp->v_type == VBLK)) {
1229 1363 vap->va_rdev = vp->v_rdev;
1230 1364 vap->va_mode &= ~S_IFMT;
1231 1365 if (vap->va_type == VCHR)
1232 1366 vap->va_mode |= S_IFCHR;
1233 1367 else
1234 1368 vap->va_mode |= S_IFBLK;
1235 1369 } else {
1236 1370 vap->va_rdev = 0;
1237 1371 }
1238 1372 }
1239 1373
1240 1374 struct vattr *
1241 1375 sdev_getdefault_attr(enum vtype type)
1242 1376 {
1243 1377 if (type == VDIR)
1244 1378 return (&sdev_vattr_dir);
1245 1379 else if (type == VCHR)
1246 1380 return (&sdev_vattr_chr);
1247 1381 else if (type == VBLK)
1248 1382 return (&sdev_vattr_blk);
1249 1383 else if (type == VLNK)
1250 1384 return (&sdev_vattr_lnk);
1251 1385 else
1252 1386 return (NULL);
1253 1387 }
1254 1388 int
1255 1389 sdev_to_vp(struct sdev_node *dv, struct vnode **vpp)
1256 1390 {
1257 1391 int rv = 0;
1258 1392 struct vnode *vp = SDEVTOV(dv);
1259 1393
1260 1394 switch (vp->v_type) {
1261 1395 case VCHR:
1262 1396 case VBLK:
1263 1397 /*
1264 1398 * If vnode is a device, return special vnode instead
1265 1399 * (though it knows all about -us- via sp->s_realvp)
1266 1400 */
1267 1401 *vpp = specvp(vp, vp->v_rdev, vp->v_type, kcred);
1268 1402 VN_RELE(vp);
1269 1403 if (*vpp == NULLVP)
1270 1404 rv = ENOSYS;
1271 1405 break;
1272 1406 default: /* most types are returned as is */
1273 1407 *vpp = vp;
1274 1408 break;
1275 1409 }
1276 1410 return (rv);
1277 1411 }
1278 1412
1279 1413 /*
1280 1414 * junction between devname and root file system, e.g. ufs
1281 1415 */
1282 1416 int
1283 1417 devname_backstore_lookup(struct sdev_node *ddv, char *nm, struct vnode **rvp)
1284 1418 {
1285 1419 struct vnode *rdvp = ddv->sdev_attrvp;
1286 1420 int rval = 0;
1287 1421
1288 1422 ASSERT(rdvp);
1289 1423
1290 1424 rval = VOP_LOOKUP(rdvp, nm, rvp, NULL, 0, NULL, kcred, NULL, NULL,
1291 1425 NULL);
1292 1426 return (rval);
1293 1427 }
1294 1428
1295 1429 static int
1296 1430 sdev_filldir_from_store(struct sdev_node *ddv, int dlen, struct cred *cred)
1297 1431 {
1298 1432 struct sdev_node *dv = NULL;
1299 1433 char *nm;
1300 1434 struct vnode *dirvp;
1301 1435 int error;
1302 1436 vnode_t *vp;
1303 1437 int eof;
1304 1438 struct iovec iov;
1305 1439 struct uio uio;
1306 1440 struct dirent64 *dp;
1307 1441 dirent64_t *dbuf;
1308 1442 size_t dbuflen;
1309 1443 struct vattr vattr;
1310 1444 char *link = NULL;
1311 1445
1312 1446 if (ddv->sdev_attrvp == NULL)
1313 1447 return (0);
1314 1448 if (!(ddv->sdev_flags & SDEV_BUILD))
1315 1449 return (0);
1316 1450
1317 1451 dirvp = ddv->sdev_attrvp;
1318 1452 VN_HOLD(dirvp);
1319 1453 dbuf = kmem_zalloc(dlen, KM_SLEEP);
1320 1454
1321 1455 uio.uio_iov = &iov;
1322 1456 uio.uio_iovcnt = 1;
1323 1457 uio.uio_segflg = UIO_SYSSPACE;
1324 1458 uio.uio_fmode = 0;
1325 1459 uio.uio_extflg = UIO_COPY_CACHED;
1326 1460 uio.uio_loffset = 0;
1327 1461 uio.uio_llimit = MAXOFFSET_T;
1328 1462
1329 1463 eof = 0;
1330 1464 error = 0;
1331 1465 while (!error && !eof) {
1332 1466 uio.uio_resid = dlen;
1333 1467 iov.iov_base = (char *)dbuf;
1334 1468 iov.iov_len = dlen;
1335 1469 (void) VOP_RWLOCK(dirvp, V_WRITELOCK_FALSE, NULL);
1336 1470 error = VOP_READDIR(dirvp, &uio, kcred, &eof, NULL, 0);
1337 1471 VOP_RWUNLOCK(dirvp, V_WRITELOCK_FALSE, NULL);
1338 1472
1339 1473 dbuflen = dlen - uio.uio_resid;
1340 1474 if (error || dbuflen == 0)
1341 1475 break;
1342 1476
1343 1477 if (!(ddv->sdev_flags & SDEV_BUILD))
1344 1478 break;
1345 1479
1346 1480 for (dp = dbuf; ((intptr_t)dp <
1347 1481 (intptr_t)dbuf + dbuflen);
1348 1482 dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen)) {
1349 1483 nm = dp->d_name;
1350 1484
1351 1485 if (strcmp(nm, ".") == 0 ||
1352 1486 strcmp(nm, "..") == 0)
1353 1487 continue;
1354 1488
1355 1489 vp = NULLVP;
1356 1490 dv = sdev_cache_lookup(ddv, nm);
1357 1491 if (dv) {
1358 1492 VERIFY(dv->sdev_state != SDEV_ZOMBIE);
1359 1493 SDEV_SIMPLE_RELE(dv);
1360 1494 continue;
1361 1495 }
1362 1496
1363 1497 /* refill the cache if not already */
1364 1498 error = devname_backstore_lookup(ddv, nm, &vp);
1365 1499 if (error)
1366 1500 continue;
1367 1501
1368 1502 vattr.va_mask = AT_TYPE|AT_MODE|AT_UID|AT_GID;
1369 1503 error = VOP_GETATTR(vp, &vattr, 0, cred, NULL);
1370 1504 if (error)
1371 1505 continue;
1372 1506
1373 1507 if (vattr.va_type == VLNK) {
1374 1508 error = sdev_getlink(vp, &link);
1375 1509 if (error) {
1376 1510 continue;
1377 1511 }
1378 1512 ASSERT(link != NULL);
1379 1513 }
1380 1514
1381 1515 if (!rw_tryupgrade(&ddv->sdev_contents)) {
1382 1516 rw_exit(&ddv->sdev_contents);
1383 1517 rw_enter(&ddv->sdev_contents, RW_WRITER);
1384 1518 }
1385 1519 error = sdev_mknode(ddv, nm, &dv, &vattr, vp, link,
1386 1520 cred, SDEV_READY);
1387 1521 rw_downgrade(&ddv->sdev_contents);
1388 1522
1389 1523 if (link != NULL) {
1390 1524 kmem_free(link, strlen(link) + 1);
1391 1525 link = NULL;
1392 1526 }
1393 1527
1394 1528 if (!error) {
1395 1529 ASSERT(dv);
1396 1530 ASSERT(dv->sdev_state != SDEV_ZOMBIE);
1397 1531 SDEV_SIMPLE_RELE(dv);
1398 1532 }
1399 1533 vp = NULL;
1400 1534 dv = NULL;
1401 1535 }
1402 1536 }
1403 1537
1404 1538 done:
1405 1539 VN_RELE(dirvp);
1406 1540 kmem_free(dbuf, dlen);
1407 1541
1408 1542 return (error);
1409 1543 }
1410 1544
1411 1545 void
1412 1546 sdev_filldir_dynamic(struct sdev_node *ddv)
1413 1547 {
1414 1548 int error;
1415 1549 int i;
1416 1550 struct vattr vattr;
1417 1551 struct vattr *vap = &vattr;
1418 1552 char *nm = NULL;
1419 1553 struct sdev_node *dv = NULL;
1420 1554
1421 1555 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
1422 1556 ASSERT((ddv->sdev_flags & SDEV_BUILD));
1423 1557
1424 1558 *vap = *sdev_getdefault_attr(VDIR); /* note structure copy here */
1425 1559 gethrestime(&vap->va_atime);
1426 1560 vap->va_mtime = vap->va_atime;
1427 1561 vap->va_ctime = vap->va_atime;
1428 1562 for (i = 0; vtab[i].vt_name != NULL; i++) {
1429 1563 /*
1430 1564 * This early, we may be in a read-only /dev environment: leave
1431 1565 * the creation of any nodes we'd attempt to persist to
1432 1566 * devfsadm. Because /dev itself is normally persistent, any
1433 1567 * node which is not marked dynamic will end up being marked
1434 1568 * persistent. However, some nodes are both dynamic and
1435 1569 * persistent, mostly lofi and rlofi, so we need to be careful
1436 1570 * in our check.
1437 1571 */
1438 1572 if ((vtab[i].vt_flags & SDEV_PERSIST) ||
1439 1573 !(vtab[i].vt_flags & SDEV_DYNAMIC))
1440 1574 continue;
1441 1575 nm = vtab[i].vt_name;
1442 1576 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
1443 1577 dv = NULL;
1444 1578 error = sdev_mknode(ddv, nm, &dv, vap, NULL,
1445 1579 NULL, kcred, SDEV_READY);
1446 1580 if (error) {
1447 1581 cmn_err(CE_WARN, "%s/%s: error %d\n",
1448 1582 ddv->sdev_name, nm, error);
1449 1583 } else {
1450 1584 ASSERT(dv);
1451 1585 ASSERT(dv->sdev_state != SDEV_ZOMBIE);
1452 1586 SDEV_SIMPLE_RELE(dv);
1453 1587 }
1454 1588 }
1455 1589 }
1456 1590
1457 1591 /*
1458 1592 * Creating a backing store entry based on sdev_attr.
1459 1593 * This is called either as part of node creation in a persistent directory
1460 1594 * or from setattr/setsecattr to persist access attributes across reboot.
1461 1595 */
1462 1596 int
1463 1597 sdev_shadow_node(struct sdev_node *dv, struct cred *cred)
1464 1598 {
1465 1599 int error = 0;
1466 1600 struct vnode *dvp = SDEVTOV(dv->sdev_dotdot);
1467 1601 struct vnode *rdvp = VTOSDEV(dvp)->sdev_attrvp;
1468 1602 struct vattr *vap = dv->sdev_attr;
1469 1603 char *nm = dv->sdev_name;
1470 1604 struct vnode *tmpvp, **rvp = &tmpvp, *rrvp = NULL;
1471 1605
1472 1606 ASSERT(dv && dv->sdev_name && rdvp);
1473 1607 ASSERT(RW_WRITE_HELD(&dv->sdev_contents) && dv->sdev_attrvp == NULL);
1474 1608
1475 1609 lookup:
1476 1610 /* try to find it in the backing store */
1477 1611 error = VOP_LOOKUP(rdvp, nm, rvp, NULL, 0, NULL, cred, NULL, NULL,
1478 1612 NULL);
1479 1613 if (error == 0) {
1480 1614 if (VOP_REALVP(*rvp, &rrvp, NULL) == 0) {
1481 1615 VN_HOLD(rrvp);
1482 1616 VN_RELE(*rvp);
1483 1617 *rvp = rrvp;
1484 1618 }
1485 1619
1486 1620 kmem_free(dv->sdev_attr, sizeof (vattr_t));
1487 1621 dv->sdev_attr = NULL;
1488 1622 dv->sdev_attrvp = *rvp;
1489 1623 return (0);
1490 1624 }
1491 1625
1492 1626 /* let's try to persist the node */
1493 1627 gethrestime(&vap->va_atime);
1494 1628 vap->va_mtime = vap->va_atime;
1495 1629 vap->va_ctime = vap->va_atime;
1496 1630 vap->va_mask |= AT_TYPE|AT_MODE;
1497 1631 switch (vap->va_type) {
1498 1632 case VDIR:
1499 1633 error = VOP_MKDIR(rdvp, nm, vap, rvp, cred, NULL, 0, NULL);
1500 1634 sdcmn_err9(("sdev_shadow_node: mkdir vp %p error %d\n",
1501 1635 (void *)(*rvp), error));
1502 1636 if (!error)
1503 1637 VN_RELE(*rvp);
1504 1638 break;
1505 1639 case VCHR:
1506 1640 case VBLK:
1507 1641 case VREG:
1508 1642 case VDOOR:
1509 1643 error = VOP_CREATE(rdvp, nm, vap, NONEXCL, VREAD|VWRITE,
1510 1644 rvp, cred, 0, NULL, NULL);
1511 1645 sdcmn_err9(("sdev_shadow_node: create vp %p, error %d\n",
1512 1646 (void *)(*rvp), error));
1513 1647 if (!error)
1514 1648 VN_RELE(*rvp);
1515 1649 break;
1516 1650 case VLNK:
1517 1651 ASSERT(dv->sdev_symlink);
1518 1652 error = VOP_SYMLINK(rdvp, nm, vap, dv->sdev_symlink, cred,
1519 1653 NULL, 0);
1520 1654 sdcmn_err9(("sdev_shadow_node: create symlink error %d\n",
1521 1655 error));
1522 1656 break;
1523 1657 default:
1524 1658 cmn_err(CE_PANIC, "dev: %s: sdev_shadow_node "
1525 1659 "create\n", nm);
1526 1660 /*NOTREACHED*/
1527 1661 }
1528 1662
1529 1663 /* go back to lookup to factor out spec node and set attrvp */
1530 1664 if (error == 0)
1531 1665 goto lookup;
1532 1666
1533 1667 sdcmn_err(("cannot persist %s - error %d\n", dv->sdev_path, error));
1534 1668 return (error);
1535 1669 }
1536 1670
1537 1671 static void
1538 1672 sdev_cache_add(struct sdev_node *ddv, struct sdev_node **dv, char *nm)
1539 1673 {
1540 1674 struct sdev_node *dup = NULL;
1541 1675
1542 1676 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
1543 1677 if ((dup = sdev_findbyname(ddv, nm)) == NULL) {
1544 1678 sdev_direnter(ddv, *dv);
1545 1679 } else {
1546 1680 VERIFY(dup->sdev_state != SDEV_ZOMBIE);
1547 1681 SDEV_SIMPLE_RELE(*dv);
1548 1682 sdev_nodedestroy(*dv, 0);
1549 1683 *dv = dup;
1550 1684 }
1551 1685 }
1552 1686
1553 1687 static void
1554 1688 sdev_cache_delete(struct sdev_node *ddv, struct sdev_node **dv)
1555 1689 {
1556 1690 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
1557 1691 sdev_dirdelete(ddv, *dv);
1558 1692 }
1559 1693
1560 1694 /*
1561 1695 * update the in-core directory cache
1562 1696 */
1563 1697 void
1564 1698 sdev_cache_update(struct sdev_node *ddv, struct sdev_node **dv, char *nm,
1565 1699 sdev_cache_ops_t ops)
1566 1700 {
1567 1701 ASSERT((SDEV_HELD(*dv)));
1568 1702
1569 1703 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
1570 1704 switch (ops) {
1571 1705 case SDEV_CACHE_ADD:
1572 1706 sdev_cache_add(ddv, dv, nm);
1573 1707 break;
1574 1708 case SDEV_CACHE_DELETE:
1575 1709 sdev_cache_delete(ddv, dv);
1576 1710 break;
1577 1711 default:
1578 1712 break;
1579 1713 }
1580 1714 }
1581 1715
1582 1716 /*
1583 1717 * retrieve the named entry from the directory cache
1584 1718 */
1585 1719 struct sdev_node *
1586 1720 sdev_cache_lookup(struct sdev_node *ddv, char *nm)
1587 1721 {
1588 1722 struct sdev_node *dv = NULL;
1589 1723
1590 1724 ASSERT(RW_LOCK_HELD(&ddv->sdev_contents));
1591 1725 dv = sdev_findbyname(ddv, nm);
1592 1726
1593 1727 return (dv);
1594 1728 }
1595 1729
1596 1730 /*
1597 1731 * Implicit reconfig for nodes constructed by a link generator
1598 1732 * Start devfsadm if needed, or if devfsadm is in progress,
1599 1733 * prepare to block on devfsadm either completing or
1600 1734 * constructing the desired node. As devfsadmd is global
1601 1735 * in scope, constructing all necessary nodes, we only
1602 1736 * need to initiate it once.
1603 1737 */
1604 1738 static int
1605 1739 sdev_call_devfsadmd(struct sdev_node *ddv, struct sdev_node *dv, char *nm)
1606 1740 {
1607 1741 int error = 0;
1608 1742
1609 1743 if (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state)) {
1610 1744 sdcmn_err6(("lookup: waiting for %s/%s, 0x%x\n",
1611 1745 ddv->sdev_name, nm, devfsadm_state));
1612 1746 mutex_enter(&dv->sdev_lookup_lock);
1613 1747 SDEV_BLOCK_OTHERS(dv, (SDEV_LOOKUP | SDEV_LGWAITING));
1614 1748 mutex_exit(&dv->sdev_lookup_lock);
1615 1749 error = 0;
1616 1750 } else if (!DEVNAME_DEVFSADM_HAS_RUN(devfsadm_state)) {
1617 1751 sdcmn_err6(("lookup %s/%s starting devfsadm, 0x%x\n",
1618 1752 ddv->sdev_name, nm, devfsadm_state));
1619 1753
1620 1754 sdev_devfsadmd_thread(ddv, dv, kcred);
1621 1755 mutex_enter(&dv->sdev_lookup_lock);
1622 1756 SDEV_BLOCK_OTHERS(dv,
1623 1757 (SDEV_LOOKUP | SDEV_LGWAITING));
1624 1758 mutex_exit(&dv->sdev_lookup_lock);
1625 1759 error = 0;
1626 1760 } else {
1627 1761 error = -1;
1628 1762 }
1629 1763
1630 1764 return (error);
1631 1765 }
1632 1766
1633 1767 /*
1634 1768 * Support for specialized device naming construction mechanisms
1635 1769 */
1636 1770 static int
1637 1771 sdev_call_dircallback(struct sdev_node *ddv, struct sdev_node **dvp, char *nm,
1638 1772 int (*callback)(struct sdev_node *, char *, void **, struct cred *,
1639 1773 void *, char *), int flags, struct cred *cred)
1640 1774 {
1641 1775 int rv = 0;
1642 1776 char *physpath = NULL;
1643 1777 struct vattr vattr;
1644 1778 struct vattr *vap = &vattr;
1645 1779 struct sdev_node *dv = NULL;
1646 1780
1647 1781 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
1648 1782 if (flags & SDEV_VLINK) {
1649 1783 physpath = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1650 1784 rv = callback(ddv, nm, (void *)&physpath, kcred, NULL,
1651 1785 NULL);
1652 1786 if (rv) {
1653 1787 kmem_free(physpath, MAXPATHLEN);
1654 1788 return (-1);
1655 1789 }
1656 1790
1657 1791 *vap = *sdev_getdefault_attr(VLNK); /* structure copy */
1658 1792 vap->va_size = strlen(physpath);
1659 1793 gethrestime(&vap->va_atime);
1660 1794 vap->va_mtime = vap->va_atime;
1661 1795 vap->va_ctime = vap->va_atime;
1662 1796
1663 1797 rv = sdev_mknode(ddv, nm, &dv, vap, NULL,
1664 1798 (void *)physpath, cred, SDEV_READY);
1665 1799 kmem_free(physpath, MAXPATHLEN);
1666 1800 if (rv)
1667 1801 return (rv);
1668 1802 } else if (flags & SDEV_VATTR) {
1669 1803 /*
1670 1804 * /dev/pts
1671 1805 *
1672 1806 * callback is responsible to set the basic attributes,
1673 1807 * e.g. va_type/va_uid/va_gid/
1674 1808 * dev_t if VCHR or VBLK/
1675 1809 */
1676 1810 ASSERT(callback);
1677 1811 rv = callback(ddv, nm, (void *)&vattr, kcred, NULL, NULL);
1678 1812 if (rv) {
1679 1813 sdcmn_err3(("devname_lookup_func: SDEV_NONE "
1680 1814 "callback failed \n"));
1681 1815 return (-1);
1682 1816 }
1683 1817
1684 1818 rv = sdev_mknode(ddv, nm, &dv, &vattr, NULL, NULL,
1685 1819 cred, SDEV_READY);
1686 1820
1687 1821 if (rv)
1688 1822 return (rv);
1689 1823
1690 1824 } else {
1691 1825 impossible(("lookup: %s/%s by %s not supported (%d)\n",
1692 1826 SDEVTOV(ddv)->v_path, nm, curproc->p_user.u_comm,
1693 1827 __LINE__));
1694 1828 rv = -1;
1695 1829 }
1696 1830
1697 1831 *dvp = dv;
1698 1832 return (rv);
1699 1833 }
1700 1834
1701 1835 static int
1702 1836 is_devfsadm_thread(char *exec_name)
1703 1837 {
1704 1838 /*
1705 1839 * note: because devfsadmd -> /usr/sbin/devfsadm
1706 1840 * it is safe to use "devfsadm" to capture the lookups
1707 1841 * from devfsadm and its daemon version.
1708 1842 */
1709 1843 if (strcmp(exec_name, "devfsadm") == 0)
1710 1844 return (1);
1711 1845 return (0);
1712 1846 }
1713 1847
1714 1848 /*
1715 1849 * Lookup Order:
1716 1850 * sdev_node cache;
1717 1851 * backing store (SDEV_PERSIST);
1718 1852 * DBNR: a. dir_ops implemented in the loadable modules;
1719 1853 * b. vnode ops in vtab.
1720 1854 */
1721 1855 int
1722 1856 devname_lookup_func(struct sdev_node *ddv, char *nm, struct vnode **vpp,
1723 1857 struct cred *cred, int (*callback)(struct sdev_node *, char *, void **,
1724 1858 struct cred *, void *, char *), int flags)
1725 1859 {
1726 1860 int rv = 0, nmlen;
1727 1861 struct vnode *rvp = NULL;
1728 1862 struct sdev_node *dv = NULL;
1729 1863 int retried = 0;
1730 1864 int error = 0;
1731 1865 struct vattr vattr;
1732 1866 char *lookup_thread = curproc->p_user.u_comm;
1733 1867 int failed_flags = 0;
1734 1868 int (*vtor)(struct sdev_node *) = NULL;
1735 1869 int state;
1736 1870 int parent_state;
1737 1871 char *link = NULL;
1738 1872
1739 1873 if (SDEVTOV(ddv)->v_type != VDIR)
1740 1874 return (ENOTDIR);
1741 1875
1742 1876 /*
1743 1877 * Empty name or ., return node itself.
1744 1878 */
1745 1879 nmlen = strlen(nm);
1746 1880 if ((nmlen == 0) || ((nmlen == 1) && (nm[0] == '.'))) {
1747 1881 *vpp = SDEVTOV(ddv);
1748 1882 VN_HOLD(*vpp);
1749 1883 return (0);
1750 1884 }
1751 1885
1752 1886 /*
1753 1887 * .., return the parent directory
1754 1888 */
1755 1889 if ((nmlen == 2) && (strcmp(nm, "..") == 0)) {
1756 1890 *vpp = SDEVTOV(ddv->sdev_dotdot);
1757 1891 VN_HOLD(*vpp);
1758 1892 return (0);
1759 1893 }
1760 1894
1761 1895 rw_enter(&ddv->sdev_contents, RW_READER);
1762 1896 if (ddv->sdev_flags & SDEV_VTOR) {
1763 1897 vtor = (int (*)(struct sdev_node *))sdev_get_vtor(ddv);
1764 1898 ASSERT(vtor);
1765 1899 }
1766 1900
1767 1901 tryagain:
1768 1902 /*
1769 1903 * (a) directory cache lookup:
1770 1904 */
1771 1905 ASSERT(RW_READ_HELD(&ddv->sdev_contents));
1772 1906 parent_state = ddv->sdev_state;
1773 1907 dv = sdev_cache_lookup(ddv, nm);
1774 1908 if (dv) {
1775 1909 state = dv->sdev_state;
1776 1910 switch (state) {
1777 1911 case SDEV_INIT:
1778 1912 if (is_devfsadm_thread(lookup_thread))
1779 1913 break;
1780 1914
1781 1915 /* ZOMBIED parent won't allow node creation */
1782 1916 if (parent_state == SDEV_ZOMBIE) {
1783 1917 SD_TRACE_FAILED_LOOKUP(ddv, nm,
1784 1918 retried);
1785 1919 goto nolock_notfound;
1786 1920 }
1787 1921
1788 1922 mutex_enter(&dv->sdev_lookup_lock);
1789 1923 /* compensate the threads started after devfsadm */
1790 1924 if (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state) &&
1791 1925 !(SDEV_IS_LOOKUP(dv)))
1792 1926 SDEV_BLOCK_OTHERS(dv,
1793 1927 (SDEV_LOOKUP | SDEV_LGWAITING));
1794 1928
1795 1929 if (SDEV_IS_LOOKUP(dv)) {
1796 1930 failed_flags |= SLF_REBUILT;
1797 1931 rw_exit(&ddv->sdev_contents);
1798 1932 error = sdev_wait4lookup(dv, SDEV_LOOKUP);
1799 1933 mutex_exit(&dv->sdev_lookup_lock);
1800 1934 rw_enter(&ddv->sdev_contents, RW_READER);
1801 1935
1802 1936 if (error != 0) {
1803 1937 SD_TRACE_FAILED_LOOKUP(ddv, nm,
1804 1938 retried);
1805 1939 goto nolock_notfound;
1806 1940 }
1807 1941
1808 1942 state = dv->sdev_state;
1809 1943 if (state == SDEV_INIT) {
1810 1944 SD_TRACE_FAILED_LOOKUP(ddv, nm,
1811 1945 retried);
1812 1946 goto nolock_notfound;
1813 1947 } else if (state == SDEV_READY) {
1814 1948 goto found;
1815 1949 } else if (state == SDEV_ZOMBIE) {
1816 1950 rw_exit(&ddv->sdev_contents);
1817 1951 SD_TRACE_FAILED_LOOKUP(ddv, nm,
1818 1952 retried);
1819 1953 SDEV_RELE(dv);
1820 1954 goto lookup_failed;
1821 1955 }
1822 1956 } else {
1823 1957 mutex_exit(&dv->sdev_lookup_lock);
1824 1958 }
1825 1959 break;
1826 1960 case SDEV_READY:
1827 1961 goto found;
1828 1962 case SDEV_ZOMBIE:
1829 1963 rw_exit(&ddv->sdev_contents);
1830 1964 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
1831 1965 SDEV_RELE(dv);
1832 1966 goto lookup_failed;
1833 1967 default:
1834 1968 rw_exit(&ddv->sdev_contents);
1835 1969 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
1836 1970 sdev_lookup_failed(ddv, nm, failed_flags);
1837 1971 *vpp = NULLVP;
1838 1972 return (ENOENT);
1839 1973 }
1840 1974 }
1841 1975 ASSERT(RW_READ_HELD(&ddv->sdev_contents));
1842 1976
1843 1977 /*
1844 1978 * ZOMBIED parent does not allow new node creation.
1845 1979 * bail out early
1846 1980 */
1847 1981 if (parent_state == SDEV_ZOMBIE) {
1848 1982 rw_exit(&ddv->sdev_contents);
1849 1983 *vpp = NULLVP;
1850 1984 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
1851 1985 return (ENOENT);
1852 1986 }
1853 1987
1854 1988 /*
1855 1989 * (b0): backing store lookup
1856 1990 * SDEV_PERSIST is default except:
1857 1991 * 1) pts nodes
1858 1992 * 2) non-chmod'ed local nodes
1859 1993 * 3) zvol nodes
1860 1994 */
1861 1995 if (SDEV_IS_PERSIST(ddv)) {
1862 1996 error = devname_backstore_lookup(ddv, nm, &rvp);
1863 1997
1864 1998 if (!error) {
1865 1999
1866 2000 vattr.va_mask = AT_TYPE|AT_MODE|AT_UID|AT_GID;
1867 2001 error = VOP_GETATTR(rvp, &vattr, 0, cred, NULL);
1868 2002 if (error) {
1869 2003 rw_exit(&ddv->sdev_contents);
1870 2004 if (dv)
1871 2005 SDEV_RELE(dv);
1872 2006 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
1873 2007 sdev_lookup_failed(ddv, nm, failed_flags);
1874 2008 *vpp = NULLVP;
1875 2009 return (ENOENT);
1876 2010 }
1877 2011
1878 2012 if (vattr.va_type == VLNK) {
1879 2013 error = sdev_getlink(rvp, &link);
1880 2014 if (error) {
1881 2015 rw_exit(&ddv->sdev_contents);
1882 2016 if (dv)
1883 2017 SDEV_RELE(dv);
1884 2018 SD_TRACE_FAILED_LOOKUP(ddv, nm,
1885 2019 retried);
1886 2020 sdev_lookup_failed(ddv, nm,
1887 2021 failed_flags);
1888 2022 *vpp = NULLVP;
1889 2023 return (ENOENT);
1890 2024 }
1891 2025 ASSERT(link != NULL);
1892 2026 }
1893 2027
1894 2028 if (!rw_tryupgrade(&ddv->sdev_contents)) {
1895 2029 rw_exit(&ddv->sdev_contents);
1896 2030 rw_enter(&ddv->sdev_contents, RW_WRITER);
1897 2031 }
1898 2032 error = sdev_mknode(ddv, nm, &dv, &vattr,
1899 2033 rvp, link, cred, SDEV_READY);
1900 2034 rw_downgrade(&ddv->sdev_contents);
1901 2035
1902 2036 if (link != NULL) {
1903 2037 kmem_free(link, strlen(link) + 1);
1904 2038 link = NULL;
1905 2039 }
1906 2040
1907 2041 if (error) {
1908 2042 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
1909 2043 rw_exit(&ddv->sdev_contents);
1910 2044 if (dv)
1911 2045 SDEV_RELE(dv);
1912 2046 goto lookup_failed;
1913 2047 } else {
1914 2048 goto found;
1915 2049 }
1916 2050 } else if (retried) {
1917 2051 rw_exit(&ddv->sdev_contents);
1918 2052 sdcmn_err3(("retry of lookup of %s/%s: failed\n",
1919 2053 ddv->sdev_name, nm));
1920 2054 if (dv)
1921 2055 SDEV_RELE(dv);
1922 2056 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
1923 2057 sdev_lookup_failed(ddv, nm, failed_flags);
1924 2058 *vpp = NULLVP;
1925 2059 return (ENOENT);
1926 2060 }
1927 2061 }
1928 2062
1929 2063 lookup_create_node:
1930 2064 /* first thread that is doing the lookup on this node */
1931 2065 if (callback) {
1932 2066 ASSERT(dv == NULL);
1933 2067 if (!rw_tryupgrade(&ddv->sdev_contents)) {
1934 2068 rw_exit(&ddv->sdev_contents);
1935 2069 rw_enter(&ddv->sdev_contents, RW_WRITER);
1936 2070 }
1937 2071 error = sdev_call_dircallback(ddv, &dv, nm, callback,
1938 2072 flags, cred);
1939 2073 rw_downgrade(&ddv->sdev_contents);
1940 2074 if (error == 0) {
1941 2075 goto found;
1942 2076 } else {
1943 2077 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
1944 2078 rw_exit(&ddv->sdev_contents);
1945 2079 goto lookup_failed;
1946 2080 }
1947 2081 }
1948 2082 if (!dv) {
1949 2083 if (!rw_tryupgrade(&ddv->sdev_contents)) {
1950 2084 rw_exit(&ddv->sdev_contents);
1951 2085 rw_enter(&ddv->sdev_contents, RW_WRITER);
1952 2086 }
1953 2087 error = sdev_mknode(ddv, nm, &dv, NULL, NULL, NULL,
1954 2088 cred, SDEV_INIT);
1955 2089 if (!dv) {
1956 2090 rw_exit(&ddv->sdev_contents);
1957 2091 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
1958 2092 sdev_lookup_failed(ddv, nm, failed_flags);
1959 2093 *vpp = NULLVP;
1960 2094 return (ENOENT);
1961 2095 }
1962 2096 rw_downgrade(&ddv->sdev_contents);
1963 2097 }
1964 2098
1965 2099 /*
1966 2100 * (b1) invoking devfsadm once per life time for devfsadm nodes
1967 2101 */
1968 2102 ASSERT(SDEV_HELD(dv));
1969 2103
1970 2104 if (SDEV_IS_NO_NCACHE(dv))
1971 2105 failed_flags |= SLF_NO_NCACHE;
1972 2106 if (sdev_reconfig_boot || !i_ddi_io_initialized() ||
1973 2107 SDEV_IS_DYNAMIC(ddv) || SDEV_IS_NO_NCACHE(dv) ||
1974 2108 ((moddebug & MODDEBUG_FINI_EBUSY) != 0)) {
1975 2109 ASSERT(SDEV_HELD(dv));
1976 2110 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
1977 2111 goto nolock_notfound;
1978 2112 }
1979 2113
1980 2114 /*
1981 2115 * filter out known non-existent devices recorded
1982 2116 * during initial reconfiguration boot for which
1983 2117 * reconfig should not be done and lookup may
1984 2118 * be short-circuited now.
1985 2119 */
1986 2120 if (sdev_lookup_filter(ddv, nm)) {
1987 2121 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
1988 2122 goto nolock_notfound;
1989 2123 }
1990 2124
1991 2125 /* bypassing devfsadm internal nodes */
1992 2126 if (is_devfsadm_thread(lookup_thread)) {
1993 2127 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
1994 2128 goto nolock_notfound;
1995 2129 }
1996 2130
1997 2131 if (sdev_reconfig_disable) {
1998 2132 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
1999 2133 goto nolock_notfound;
2000 2134 }
2001 2135
2002 2136 error = sdev_call_devfsadmd(ddv, dv, nm);
2003 2137 if (error == 0) {
2004 2138 sdcmn_err8(("lookup of %s/%s by %s: reconfig\n",
2005 2139 ddv->sdev_name, nm, curproc->p_user.u_comm));
2006 2140 if (sdev_reconfig_verbose) {
2007 2141 cmn_err(CE_CONT,
2008 2142 "?lookup of %s/%s by %s: reconfig\n",
2009 2143 ddv->sdev_name, nm, curproc->p_user.u_comm);
2010 2144 }
2011 2145 retried = 1;
2012 2146 failed_flags |= SLF_REBUILT;
2013 2147 ASSERT(dv->sdev_state != SDEV_ZOMBIE);
2014 2148 SDEV_SIMPLE_RELE(dv);
2015 2149 goto tryagain;
2016 2150 } else {
2017 2151 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
2018 2152 goto nolock_notfound;
2019 2153 }
2020 2154
2021 2155 found:
2022 2156 ASSERT(dv->sdev_state == SDEV_READY);
2023 2157 if (vtor) {
2024 2158 /*
2025 2159 * Check validity of returned node
2026 2160 */
2027 2161 switch (vtor(dv)) {
2028 2162 case SDEV_VTOR_VALID:
2029 2163 break;
2030 2164 case SDEV_VTOR_STALE:
2031 2165 /*
2032 2166 * The name exists, but the cache entry is
2033 2167 * stale and needs to be re-created.
2034 2168 */
2035 2169 ASSERT(RW_READ_HELD(&ddv->sdev_contents));
2036 2170 if (rw_tryupgrade(&ddv->sdev_contents) == 0) {
2037 2171 rw_exit(&ddv->sdev_contents);
2038 2172 rw_enter(&ddv->sdev_contents, RW_WRITER);
2039 2173 }
2040 2174 sdev_cache_update(ddv, &dv, nm, SDEV_CACHE_DELETE);
2041 2175 rw_downgrade(&ddv->sdev_contents);
2042 2176 SDEV_RELE(dv);
2043 2177 dv = NULL;
2044 2178 goto lookup_create_node;
2045 2179 /* FALLTHRU */
2046 2180 case SDEV_VTOR_INVALID:
2047 2181 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
2048 2182 sdcmn_err7(("lookup: destroy invalid "
2049 2183 "node: %s(%p)\n", dv->sdev_name, (void *)dv));
2050 2184 goto nolock_notfound;
2051 2185 case SDEV_VTOR_SKIP:
2052 2186 sdcmn_err7(("lookup: node not applicable - "
2053 2187 "skipping: %s(%p)\n", dv->sdev_name, (void *)dv));
2054 2188 rw_exit(&ddv->sdev_contents);
2055 2189 SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
2056 2190 SDEV_RELE(dv);
2057 2191 goto lookup_failed;
2058 2192 default:
2059 2193 cmn_err(CE_PANIC,
2060 2194 "dev fs: validator failed: %s(%p)\n",
2061 2195 dv->sdev_name, (void *)dv);
2062 2196 break;
2063 2197 }
2064 2198 }
2065 2199
2066 2200 rw_exit(&ddv->sdev_contents);
2067 2201 rv = sdev_to_vp(dv, vpp);
2068 2202 sdcmn_err3(("devname_lookup_func: returning vp %p v_count %d state %d "
2069 2203 "for nm %s, error %d\n", (void *)*vpp, (*vpp)->v_count,
2070 2204 dv->sdev_state, nm, rv));
2071 2205 return (rv);
2072 2206
2073 2207 nolock_notfound:
2074 2208 /*
2075 2209 * Destroy the node that is created for synchronization purposes.
2076 2210 */
2077 2211 sdcmn_err3(("devname_lookup_func: %s with state %d\n",
2078 2212 nm, dv->sdev_state));
2079 2213 ASSERT(RW_READ_HELD(&ddv->sdev_contents));
2080 2214 if (dv->sdev_state == SDEV_INIT) {
2081 2215 if (!rw_tryupgrade(&ddv->sdev_contents)) {
2082 2216 rw_exit(&ddv->sdev_contents);
2083 2217 rw_enter(&ddv->sdev_contents, RW_WRITER);
2084 2218 }
2085 2219
2086 2220 /*
2087 2221 * Node state may have changed during the lock
2088 2222 * changes. Re-check.
2089 2223 */
2090 2224 if (dv->sdev_state == SDEV_INIT) {
2091 2225 sdev_dirdelete(ddv, dv);
2092 2226 rw_exit(&ddv->sdev_contents);
2093 2227 sdev_lookup_failed(ddv, nm, failed_flags);
2094 2228 SDEV_RELE(dv);
2095 2229 *vpp = NULL;
2096 2230 return (ENOENT);
2097 2231 }
2098 2232 }
2099 2233
2100 2234 rw_exit(&ddv->sdev_contents);
2101 2235 SDEV_RELE(dv);
2102 2236
2103 2237 lookup_failed:
2104 2238 sdev_lookup_failed(ddv, nm, failed_flags);
2105 2239 *vpp = NULL;
2106 2240 return (ENOENT);
2107 2241 }
2108 2242
2109 2243 /*
2110 2244 * Given a directory node, mark all nodes beneath as
2111 2245 * STALE, i.e. nodes that don't exist as far as new
2112 2246 * consumers are concerned. Remove them from the
2113 2247 * list of directory entries so that no lookup or
2114 2248 * directory traversal will find them. The node
2115 2249 * not deallocated so existing holds are not affected.
2116 2250 */
2117 2251 void
2118 2252 sdev_stale(struct sdev_node *ddv)
2119 2253 {
2120 2254 struct sdev_node *dv;
2121 2255 struct vnode *vp;
2122 2256
2123 2257 ASSERT(SDEVTOV(ddv)->v_type == VDIR);
2124 2258
2125 2259 rw_enter(&ddv->sdev_contents, RW_WRITER);
2126 2260 while ((dv = SDEV_FIRST_ENTRY(ddv)) != NULL) {
2127 2261 vp = SDEVTOV(dv);
2128 2262 SDEV_HOLD(dv);
2129 2263 if (vp->v_type == VDIR)
2130 2264 sdev_stale(dv);
2131 2265
2132 2266 sdev_dirdelete(ddv, dv);
2133 2267 SDEV_RELE(dv);
2134 2268 }
2135 2269 ddv->sdev_flags |= SDEV_BUILD;
2136 2270 rw_exit(&ddv->sdev_contents);
2137 2271 }
2138 2272
2139 2273 /*
2140 2274 * Given a directory node, clean out all the nodes beneath.
2141 2275 * If expr is specified, clean node with names matching expr.
2142 2276 * If SDEV_ENFORCE is specified in flags, busy nodes are made stale,
2143 2277 * so they are excluded from future lookups.
2144 2278 */
2145 2279 int
2146 2280 sdev_cleandir(struct sdev_node *ddv, char *expr, uint_t flags)
2147 2281 {
2148 2282 int error = 0;
2149 2283 int busy = 0;
2150 2284 struct vnode *vp;
2151 2285 struct sdev_node *dv, *next;
2152 2286 int bkstore = 0;
2153 2287 int len = 0;
2154 2288 char *bks_name = NULL;
2155 2289
2156 2290 ASSERT(SDEVTOV(ddv)->v_type == VDIR);
2157 2291
2158 2292 /*
2159 2293 * We try our best to destroy all unused sdev_node's
2160 2294 */
2161 2295 rw_enter(&ddv->sdev_contents, RW_WRITER);
2162 2296 for (dv = SDEV_FIRST_ENTRY(ddv); dv != NULL; dv = next) {
2163 2297 next = SDEV_NEXT_ENTRY(ddv, dv);
2164 2298 vp = SDEVTOV(dv);
2165 2299
2166 2300 if (expr && gmatch(dv->sdev_name, expr) == 0)
2167 2301 continue;
2168 2302
2169 2303 if (vp->v_type == VDIR &&
2170 2304 sdev_cleandir(dv, NULL, flags) != 0) {
2171 2305 sdcmn_err9(("sdev_cleandir: dir %s busy\n",
2172 2306 dv->sdev_name));
2173 2307 busy++;
2174 2308 continue;
2175 2309 }
2176 2310
2177 2311 if (vp->v_count > 0 && (flags & SDEV_ENFORCE) == 0) {
2178 2312 sdcmn_err9(("sdev_cleandir: dir %s busy\n",
2179 2313 dv->sdev_name));
2180 2314 busy++;
2181 2315 continue;
2182 2316 }
2183 2317
2184 2318 /*
2185 2319 * at this point, either dv is not held or SDEV_ENFORCE
2186 2320 * is specified. In either case, dv needs to be deleted
2187 2321 */
2188 2322 SDEV_HOLD(dv);
2189 2323
2190 2324 bkstore = SDEV_IS_PERSIST(dv) ? 1 : 0;
2191 2325 if (bkstore && (vp->v_type == VDIR))
2192 2326 bkstore += 1;
2193 2327
2194 2328 if (bkstore) {
2195 2329 len = strlen(dv->sdev_name) + 1;
2196 2330 bks_name = kmem_alloc(len, KM_SLEEP);
2197 2331 bcopy(dv->sdev_name, bks_name, len);
2198 2332 }
2199 2333
2200 2334 sdev_dirdelete(ddv, dv);
2201 2335
2202 2336 /* take care the backing store clean up */
2203 2337 if (bkstore) {
2204 2338 ASSERT(bks_name);
2205 2339 ASSERT(ddv->sdev_attrvp);
2206 2340
2207 2341 if (bkstore == 1) {
2208 2342 error = VOP_REMOVE(ddv->sdev_attrvp,
2209 2343 bks_name, kcred, NULL, 0);
2210 2344 } else if (bkstore == 2) {
2211 2345 error = VOP_RMDIR(ddv->sdev_attrvp,
2212 2346 bks_name, ddv->sdev_attrvp, kcred, NULL, 0);
2213 2347 }
2214 2348
2215 2349 /* do not propagate the backing store errors */
2216 2350 if (error) {
2217 2351 sdcmn_err9(("sdev_cleandir: backing store"
2218 2352 "not cleaned\n"));
2219 2353 error = 0;
2220 2354 }
2221 2355
2222 2356 bkstore = 0;
2223 2357 kmem_free(bks_name, len);
2224 2358 bks_name = NULL;
2225 2359 len = 0;
2226 2360 }
2227 2361
2228 2362 ddv->sdev_flags |= SDEV_BUILD;
2229 2363 SDEV_RELE(dv);
2230 2364 }
2231 2365
2232 2366 ddv->sdev_flags |= SDEV_BUILD;
2233 2367 rw_exit(&ddv->sdev_contents);
2234 2368
2235 2369 if (busy) {
2236 2370 error = EBUSY;
2237 2371 }
2238 2372
2239 2373 return (error);
2240 2374 }
2241 2375
2242 2376 /*
2243 2377 * a convenient wrapper for readdir() funcs
2244 2378 */
2245 2379 size_t
2246 2380 add_dir_entry(dirent64_t *de, char *nm, size_t size, ino_t ino, offset_t off)
2247 2381 {
2248 2382 size_t reclen = DIRENT64_RECLEN(strlen(nm));
2249 2383 if (reclen > size)
2250 2384 return (0);
2251 2385
2252 2386 de->d_ino = (ino64_t)ino;
2253 2387 de->d_off = (off64_t)off + 1;
2254 2388 de->d_reclen = (ushort_t)reclen;
2255 2389 (void) strncpy(de->d_name, nm, DIRENT64_NAMELEN(reclen));
2256 2390 return (reclen);
2257 2391 }
2258 2392
2259 2393 /*
2260 2394 * sdev_mount service routines
2261 2395 */
2262 2396 int
2263 2397 sdev_copyin_mountargs(struct mounta *uap, struct sdev_mountargs *args)
2264 2398 {
2265 2399 int error;
2266 2400
2267 2401 if (uap->datalen != sizeof (*args))
2268 2402 return (EINVAL);
2269 2403
2270 2404 if (error = copyin(uap->dataptr, args, sizeof (*args))) {
2271 2405 cmn_err(CE_WARN, "sdev_copyin_mountargs: can not"
2272 2406 "get user data. error %d\n", error);
2273 2407 return (EFAULT);
2274 2408 }
2275 2409
2276 2410 return (0);
2277 2411 }
2278 2412
2279 2413 #ifdef nextdp
2280 2414 #undef nextdp
2281 2415 #endif
2282 2416 #define nextdp(dp) ((struct dirent64 *) \
2283 2417 (intptr_t)((char *)(dp) + (dp)->d_reclen))
2284 2418
2285 2419 /*
2286 2420 * readdir helper func
2287 2421 */
2288 2422 int
2289 2423 devname_readdir_func(vnode_t *vp, uio_t *uiop, cred_t *cred, int *eofp,
2290 2424 int flags)
2291 2425 {
2292 2426 struct sdev_node *ddv = VTOSDEV(vp);
2293 2427 struct sdev_node *dv;
2294 2428 dirent64_t *dp;
2295 2429 ulong_t outcount = 0;
2296 2430 size_t namelen;
2297 2431 ulong_t alloc_count;
2298 2432 void *outbuf;
2299 2433 struct iovec *iovp;
2300 2434 int error = 0;
2301 2435 size_t reclen;
2302 2436 offset_t diroff;
2303 2437 offset_t soff;
2304 2438 int this_reclen;
2305 2439 int (*vtor)(struct sdev_node *) = NULL;
2306 2440 struct vattr attr;
2307 2441 timestruc_t now;
2308 2442
2309 2443 ASSERT(ddv->sdev_attr || ddv->sdev_attrvp);
2310 2444 ASSERT(RW_READ_HELD(&ddv->sdev_contents));
2311 2445
2312 2446 if (uiop->uio_loffset >= MAXOFF_T) {
2313 2447 if (eofp)
2314 2448 *eofp = 1;
2315 2449 return (0);
2316 2450 }
2317 2451
2318 2452 if (uiop->uio_iovcnt != 1)
2319 2453 return (EINVAL);
2320 2454
2321 2455 if (vp->v_type != VDIR)
2322 2456 return (ENOTDIR);
2323 2457
2324 2458 if (ddv->sdev_flags & SDEV_VTOR) {
2325 2459 vtor = (int (*)(struct sdev_node *))sdev_get_vtor(ddv);
2326 2460 ASSERT(vtor);
2327 2461 }
2328 2462
2329 2463 if (eofp != NULL)
2330 2464 *eofp = 0;
2331 2465
2332 2466 soff = uiop->uio_loffset;
2333 2467 iovp = uiop->uio_iov;
2334 2468 alloc_count = iovp->iov_len;
2335 2469 dp = outbuf = kmem_alloc(alloc_count, KM_SLEEP);
2336 2470 outcount = 0;
2337 2471
2338 2472 if (ddv->sdev_state == SDEV_ZOMBIE)
2339 2473 goto get_cache;
2340 2474
2341 2475 if (SDEV_IS_GLOBAL(ddv)) {
2342 2476
2343 2477 if ((sdev_boot_state == SDEV_BOOT_STATE_COMPLETE) &&
2344 2478 !sdev_reconfig_boot && (flags & SDEV_BROWSE) &&
2345 2479 !SDEV_IS_DYNAMIC(ddv) && !SDEV_IS_NO_NCACHE(ddv) &&
2346 2480 ((moddebug & MODDEBUG_FINI_EBUSY) == 0) &&
2347 2481 !DEVNAME_DEVFSADM_HAS_RUN(devfsadm_state) &&
2348 2482 !DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state) &&
2349 2483 !sdev_reconfig_disable) {
2350 2484 /*
2351 2485 * invoking "devfsadm" to do system device reconfig
2352 2486 */
2353 2487 mutex_enter(&ddv->sdev_lookup_lock);
2354 2488 SDEV_BLOCK_OTHERS(ddv,
2355 2489 (SDEV_READDIR|SDEV_LGWAITING));
2356 2490 mutex_exit(&ddv->sdev_lookup_lock);
2357 2491
2358 2492 sdcmn_err8(("readdir of %s by %s: reconfig\n",
2359 2493 ddv->sdev_path, curproc->p_user.u_comm));
2360 2494 if (sdev_reconfig_verbose) {
2361 2495 cmn_err(CE_CONT,
2362 2496 "?readdir of %s by %s: reconfig\n",
2363 2497 ddv->sdev_path, curproc->p_user.u_comm);
2364 2498 }
2365 2499
2366 2500 sdev_devfsadmd_thread(ddv, NULL, kcred);
2367 2501 } else if (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state)) {
2368 2502 /*
2369 2503 * compensate the "ls" started later than "devfsadm"
2370 2504 */
2371 2505 mutex_enter(&ddv->sdev_lookup_lock);
2372 2506 SDEV_BLOCK_OTHERS(ddv, (SDEV_READDIR|SDEV_LGWAITING));
2373 2507 mutex_exit(&ddv->sdev_lookup_lock);
2374 2508 }
2375 2509
2376 2510 /*
2377 2511 * release the contents lock so that
2378 2512 * the cache may be updated by devfsadmd
2379 2513 */
2380 2514 rw_exit(&ddv->sdev_contents);
2381 2515 mutex_enter(&ddv->sdev_lookup_lock);
2382 2516 if (SDEV_IS_READDIR(ddv))
2383 2517 (void) sdev_wait4lookup(ddv, SDEV_READDIR);
2384 2518 mutex_exit(&ddv->sdev_lookup_lock);
2385 2519 rw_enter(&ddv->sdev_contents, RW_READER);
2386 2520
2387 2521 sdcmn_err4(("readdir of directory %s by %s\n",
2388 2522 ddv->sdev_name, curproc->p_user.u_comm));
2389 2523 if (ddv->sdev_flags & SDEV_BUILD) {
2390 2524 if (SDEV_IS_PERSIST(ddv)) {
2391 2525 error = sdev_filldir_from_store(ddv,
2392 2526 alloc_count, cred);
2393 2527 }
2394 2528 ddv->sdev_flags &= ~SDEV_BUILD;
2395 2529 }
2396 2530 }
2397 2531
2398 2532 get_cache:
2399 2533 /* handle "." and ".." */
2400 2534 diroff = 0;
2401 2535 if (soff == 0) {
2402 2536 /* first time */
2403 2537 this_reclen = DIRENT64_RECLEN(1);
2404 2538 if (alloc_count < this_reclen) {
2405 2539 error = EINVAL;
2406 2540 goto done;
2407 2541 }
2408 2542
2409 2543 dp->d_ino = (ino64_t)ddv->sdev_ino;
2410 2544 dp->d_off = (off64_t)1;
2411 2545 dp->d_reclen = (ushort_t)this_reclen;
2412 2546
2413 2547 (void) strncpy(dp->d_name, ".",
2414 2548 DIRENT64_NAMELEN(this_reclen));
2415 2549 outcount += dp->d_reclen;
2416 2550 dp = nextdp(dp);
2417 2551 }
2418 2552
2419 2553 diroff++;
2420 2554 if (soff <= 1) {
2421 2555 this_reclen = DIRENT64_RECLEN(2);
2422 2556 if (alloc_count < outcount + this_reclen) {
2423 2557 error = EINVAL;
2424 2558 goto done;
2425 2559 }
2426 2560
2427 2561 dp->d_reclen = (ushort_t)this_reclen;
2428 2562 dp->d_ino = (ino64_t)ddv->sdev_dotdot->sdev_ino;
2429 2563 dp->d_off = (off64_t)2;
2430 2564
2431 2565 (void) strncpy(dp->d_name, "..",
2432 2566 DIRENT64_NAMELEN(this_reclen));
2433 2567 outcount += dp->d_reclen;
2434 2568
2435 2569 dp = nextdp(dp);
2436 2570 }
2437 2571
2438 2572
2439 2573 /* gets the cache */
2440 2574 diroff++;
2441 2575 for (dv = SDEV_FIRST_ENTRY(ddv); dv;
2442 2576 dv = SDEV_NEXT_ENTRY(ddv, dv), diroff++) {
2443 2577 sdcmn_err3(("sdev_readdir: diroff %lld soff %lld for '%s' \n",
2444 2578 diroff, soff, dv->sdev_name));
2445 2579
2446 2580 /* bypassing pre-matured nodes */
2447 2581 if (diroff < soff || (dv->sdev_state != SDEV_READY)) {
2448 2582 sdcmn_err3(("sdev_readdir: pre-mature node "
2449 2583 "%s %d\n", dv->sdev_name, dv->sdev_state));
2450 2584 continue;
2451 2585 }
2452 2586
2453 2587 /*
2454 2588 * Check validity of node
2455 2589 * Drop invalid and nodes to be skipped.
2456 2590 * A node the validator indicates as stale needs
2457 2591 * to be returned as presumably the node name itself
2458 2592 * is valid and the node data itself will be refreshed
2459 2593 * on lookup. An application performing a readdir then
2460 2594 * stat on each entry should thus always see consistent
2461 2595 * data. In any case, it is not possible to synchronize
2462 2596 * with dynamic kernel state, and any view we return can
2463 2597 * never be anything more than a snapshot at a point in time.
2464 2598 */
2465 2599 if (vtor) {
2466 2600 switch (vtor(dv)) {
2467 2601 case SDEV_VTOR_VALID:
2468 2602 break;
2469 2603 case SDEV_VTOR_INVALID:
2470 2604 case SDEV_VTOR_SKIP:
2471 2605 continue;
2472 2606 case SDEV_VTOR_STALE:
2473 2607 sdcmn_err3(("sdev_readir: %s stale\n",
2474 2608 dv->sdev_name));
2475 2609 break;
2476 2610 default:
2477 2611 cmn_err(CE_PANIC,
2478 2612 "dev fs: validator failed: %s(%p)\n",
2479 2613 dv->sdev_name, (void *)dv);
2480 2614 break;
2481 2615 /*NOTREACHED*/
2482 2616 }
2483 2617 }
2484 2618
2485 2619 namelen = strlen(dv->sdev_name);
2486 2620 reclen = DIRENT64_RECLEN(namelen);
2487 2621 if (outcount + reclen > alloc_count) {
2488 2622 goto full;
2489 2623 }
2490 2624 dp->d_reclen = (ushort_t)reclen;
2491 2625 dp->d_ino = (ino64_t)dv->sdev_ino;
2492 2626 dp->d_off = (off64_t)diroff + 1;
2493 2627 (void) strncpy(dp->d_name, dv->sdev_name,
2494 2628 DIRENT64_NAMELEN(reclen));
2495 2629 outcount += reclen;
2496 2630 dp = nextdp(dp);
2497 2631 }
2498 2632
2499 2633 full:
2500 2634 sdcmn_err4(("sdev_readdir: moving %lu bytes: "
2501 2635 "diroff %lld, soff %lld, dv %p\n", outcount, diroff, soff,
2502 2636 (void *)dv));
2503 2637
2504 2638 if (outcount)
2505 2639 error = uiomove(outbuf, outcount, UIO_READ, uiop);
2506 2640
2507 2641 if (!error) {
2508 2642 uiop->uio_loffset = diroff;
2509 2643 if (eofp)
2510 2644 *eofp = dv ? 0 : 1;
2511 2645 }
2512 2646
2513 2647
2514 2648 if (ddv->sdev_attrvp) {
2515 2649 gethrestime(&now);
2516 2650 attr.va_ctime = now;
2517 2651 attr.va_atime = now;
2518 2652 attr.va_mask = AT_CTIME|AT_ATIME;
2519 2653
2520 2654 (void) VOP_SETATTR(ddv->sdev_attrvp, &attr, 0, kcred, NULL);
2521 2655 }
2522 2656 done:
2523 2657 kmem_free(outbuf, alloc_count);
2524 2658 return (error);
2525 2659 }
2526 2660
2527 2661 static int
2528 2662 sdev_modctl_lookup(const char *path, vnode_t **r_vp)
2529 2663 {
2530 2664 vnode_t *vp;
2531 2665 vnode_t *cvp;
2532 2666 struct sdev_node *svp;
2533 2667 char *nm;
2534 2668 struct pathname pn;
2535 2669 int error;
2536 2670 int persisted = 0;
2537 2671
2538 2672 ASSERT(INGLOBALZONE(curproc));
2539 2673
2540 2674 if (error = pn_get((char *)path, UIO_SYSSPACE, &pn))
2541 2675 return (error);
2542 2676 nm = kmem_alloc(MAXNAMELEN, KM_SLEEP);
2543 2677
2544 2678 vp = rootdir;
2545 2679 VN_HOLD(vp);
2546 2680
2547 2681 while (pn_pathleft(&pn)) {
2548 2682 ASSERT(vp->v_type == VDIR || vp->v_type == VLNK);
2549 2683 (void) pn_getcomponent(&pn, nm);
2550 2684
2551 2685 /*
2552 2686 * Deal with the .. special case where we may be
2553 2687 * traversing up across a mount point, to the
2554 2688 * root of this filesystem or global root.
2555 2689 */
2556 2690 if (nm[0] == '.' && nm[1] == '.' && nm[2] == 0) {
2557 2691 checkforroot:
2558 2692 if (VN_CMP(vp, rootdir)) {
2559 2693 nm[1] = 0;
2560 2694 } else if (vp->v_flag & VROOT) {
2561 2695 vfs_t *vfsp;
2562 2696 cvp = vp;
2563 2697 vfsp = cvp->v_vfsp;
2564 2698 vfs_rlock_wait(vfsp);
2565 2699 vp = cvp->v_vfsp->vfs_vnodecovered;
2566 2700 if (vp == NULL ||
2567 2701 (cvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)) {
2568 2702 vfs_unlock(vfsp);
2569 2703 VN_RELE(cvp);
2570 2704 error = EIO;
2571 2705 break;
2572 2706 }
2573 2707 VN_HOLD(vp);
2574 2708 vfs_unlock(vfsp);
2575 2709 VN_RELE(cvp);
2576 2710 cvp = NULL;
2577 2711 goto checkforroot;
2578 2712 }
2579 2713 }
2580 2714
2581 2715 error = VOP_LOOKUP(vp, nm, &cvp, NULL, 0, NULL, kcred, NULL,
2582 2716 NULL, NULL);
2583 2717 if (error) {
2584 2718 VN_RELE(vp);
2585 2719 break;
2586 2720 }
2587 2721
2588 2722 /* traverse mount points encountered on our journey */
2589 2723 if (vn_ismntpt(cvp) && (error = traverse(&cvp)) != 0) {
2590 2724 VN_RELE(vp);
2591 2725 VN_RELE(cvp);
2592 2726 break;
2593 2727 }
2594 2728
2595 2729 /*
2596 2730 * symbolic link, can be either relative and absolute
2597 2731 */
2598 2732 if ((cvp->v_type == VLNK) && pn_pathleft(&pn)) {
2599 2733 struct pathname linkpath;
2600 2734 pn_alloc(&linkpath);
2601 2735 if (error = pn_getsymlink(cvp, &linkpath, kcred)) {
2602 2736 pn_free(&linkpath);
2603 2737 break;
2604 2738 }
2605 2739 if (pn_pathleft(&linkpath) == 0)
2606 2740 (void) pn_set(&linkpath, ".");
2607 2741 error = pn_insert(&pn, &linkpath, strlen(nm));
2608 2742 pn_free(&linkpath);
2609 2743 if (pn.pn_pathlen == 0) {
2610 2744 VN_RELE(vp);
2611 2745 return (ENOENT);
2612 2746 }
2613 2747 if (pn.pn_path[0] == '/') {
2614 2748 pn_skipslash(&pn);
2615 2749 VN_RELE(vp);
2616 2750 VN_RELE(cvp);
2617 2751 vp = rootdir;
2618 2752 VN_HOLD(vp);
2619 2753 } else {
2620 2754 VN_RELE(cvp);
2621 2755 }
2622 2756 continue;
2623 2757 }
2624 2758
2625 2759 VN_RELE(vp);
2626 2760
2627 2761 /*
2628 2762 * Direct the operation to the persisting filesystem
2629 2763 * underlying /dev. Bail if we encounter a
2630 2764 * non-persistent dev entity here.
2631 2765 */
2632 2766 if (cvp->v_vfsp->vfs_fstype == devtype) {
2633 2767
2634 2768 if ((VTOSDEV(cvp)->sdev_flags & SDEV_PERSIST) == 0) {
2635 2769 error = ENOENT;
2636 2770 VN_RELE(cvp);
2637 2771 break;
2638 2772 }
2639 2773
2640 2774 if (VTOSDEV(cvp) == NULL) {
2641 2775 error = ENOENT;
2642 2776 VN_RELE(cvp);
2643 2777 break;
2644 2778 }
2645 2779 svp = VTOSDEV(cvp);
2646 2780 if ((vp = svp->sdev_attrvp) == NULL) {
2647 2781 error = ENOENT;
2648 2782 VN_RELE(cvp);
2649 2783 break;
2650 2784 }
2651 2785 persisted = 1;
2652 2786 VN_HOLD(vp);
2653 2787 VN_RELE(cvp);
2654 2788 cvp = vp;
2655 2789 }
2656 2790
2657 2791 vp = cvp;
2658 2792 pn_skipslash(&pn);
2659 2793 }
2660 2794
2661 2795 kmem_free(nm, MAXNAMELEN);
2662 2796 pn_free(&pn);
2663 2797
2664 2798 if (error)
2665 2799 return (error);
2666 2800
2667 2801 /*
2668 2802 * Only return persisted nodes in the filesystem underlying /dev.
2669 2803 */
2670 2804 if (!persisted) {
2671 2805 VN_RELE(vp);
2672 2806 return (ENOENT);
2673 2807 }
2674 2808
2675 2809 *r_vp = vp;
2676 2810 return (0);
2677 2811 }
2678 2812
2679 2813 int
2680 2814 sdev_modctl_readdir(const char *dir, char ***dirlistp,
2681 2815 int *npathsp, int *npathsp_alloc, int checking_empty)
2682 2816 {
2683 2817 char **pathlist = NULL;
2684 2818 char **newlist = NULL;
2685 2819 int npaths = 0;
2686 2820 int npaths_alloc = 0;
2687 2821 dirent64_t *dbuf = NULL;
2688 2822 int n;
2689 2823 char *s;
2690 2824 int error;
2691 2825 vnode_t *vp;
2692 2826 int eof;
2693 2827 struct iovec iov;
2694 2828 struct uio uio;
2695 2829 struct dirent64 *dp;
2696 2830 size_t dlen;
2697 2831 size_t dbuflen;
2698 2832 int ndirents = 64;
2699 2833 char *nm;
2700 2834
2701 2835 error = sdev_modctl_lookup(dir, &vp);
2702 2836 sdcmn_err11(("modctl readdir: %s by %s: %s\n",
2703 2837 dir, curproc->p_user.u_comm,
2704 2838 (error == 0) ? "ok" : "failed"));
2705 2839 if (error)
2706 2840 return (error);
2707 2841
2708 2842 dlen = ndirents * (sizeof (*dbuf));
2709 2843 dbuf = kmem_alloc(dlen, KM_SLEEP);
2710 2844
2711 2845 uio.uio_iov = &iov;
2712 2846 uio.uio_iovcnt = 1;
2713 2847 uio.uio_segflg = UIO_SYSSPACE;
2714 2848 uio.uio_fmode = 0;
2715 2849 uio.uio_extflg = UIO_COPY_CACHED;
2716 2850 uio.uio_loffset = 0;
2717 2851 uio.uio_llimit = MAXOFFSET_T;
2718 2852
2719 2853 eof = 0;
2720 2854 error = 0;
2721 2855 while (!error && !eof) {
2722 2856 uio.uio_resid = dlen;
2723 2857 iov.iov_base = (char *)dbuf;
2724 2858 iov.iov_len = dlen;
2725 2859
2726 2860 (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
2727 2861 error = VOP_READDIR(vp, &uio, kcred, &eof, NULL, 0);
2728 2862 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
2729 2863
2730 2864 dbuflen = dlen - uio.uio_resid;
2731 2865
2732 2866 if (error || dbuflen == 0)
2733 2867 break;
2734 2868
2735 2869 for (dp = dbuf; ((intptr_t)dp < (intptr_t)dbuf + dbuflen);
2736 2870 dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen)) {
2737 2871
2738 2872 nm = dp->d_name;
2739 2873
2740 2874 if (strcmp(nm, ".") == 0 || strcmp(nm, "..") == 0)
2741 2875 continue;
2742 2876 if (npaths == npaths_alloc) {
2743 2877 npaths_alloc += 64;
2744 2878 newlist = (char **)
2745 2879 kmem_zalloc((npaths_alloc + 1) *
2746 2880 sizeof (char *), KM_SLEEP);
2747 2881 if (pathlist) {
2748 2882 bcopy(pathlist, newlist,
2749 2883 npaths * sizeof (char *));
2750 2884 kmem_free(pathlist,
2751 2885 (npaths + 1) * sizeof (char *));
2752 2886 }
2753 2887 pathlist = newlist;
2754 2888 }
2755 2889 n = strlen(nm) + 1;
2756 2890 s = kmem_alloc(n, KM_SLEEP);
2757 2891 bcopy(nm, s, n);
2758 2892 pathlist[npaths++] = s;
2759 2893 sdcmn_err11((" %s/%s\n", dir, s));
2760 2894
2761 2895 /* if checking empty, one entry is as good as many */
2762 2896 if (checking_empty) {
2763 2897 eof = 1;
2764 2898 break;
2765 2899 }
2766 2900 }
2767 2901 }
2768 2902
2769 2903 exit:
2770 2904 VN_RELE(vp);
2771 2905
2772 2906 if (dbuf)
2773 2907 kmem_free(dbuf, dlen);
2774 2908
2775 2909 if (error)
2776 2910 return (error);
2777 2911
2778 2912 *dirlistp = pathlist;
2779 2913 *npathsp = npaths;
2780 2914 *npathsp_alloc = npaths_alloc;
2781 2915
2782 2916 return (0);
2783 2917 }
2784 2918
2785 2919 void
2786 2920 sdev_modctl_readdir_free(char **pathlist, int npaths, int npaths_alloc)
2787 2921 {
2788 2922 int i, n;
2789 2923
2790 2924 for (i = 0; i < npaths; i++) {
2791 2925 n = strlen(pathlist[i]) + 1;
2792 2926 kmem_free(pathlist[i], n);
2793 2927 }
2794 2928
2795 2929 kmem_free(pathlist, (npaths_alloc + 1) * sizeof (char *));
2796 2930 }
2797 2931
2798 2932 int
2799 2933 sdev_modctl_devexists(const char *path)
2800 2934 {
2801 2935 vnode_t *vp;
2802 2936 int error;
2803 2937
|
↓ open down ↓ |
1976 lines elided |
↑ open up ↑ |
2804 2938 error = sdev_modctl_lookup(path, &vp);
2805 2939 sdcmn_err11(("modctl dev exists: %s by %s: %s\n",
2806 2940 path, curproc->p_user.u_comm,
2807 2941 (error == 0) ? "ok" : "failed"));
2808 2942 if (error == 0)
2809 2943 VN_RELE(vp);
2810 2944
2811 2945 return (error);
2812 2946 }
2813 2947
2948 +extern int sdev_vnodeops_tbl_size;
2949 +
2950 +/*
2951 + * construct a new template with overrides from vtab
2952 + */
2953 +static fs_operation_def_t *
2954 +sdev_merge_vtab(const fs_operation_def_t tab[])
2955 +{
2956 + fs_operation_def_t *new;
2957 + const fs_operation_def_t *tab_entry;
2958 +
2959 + /* make a copy of standard vnode ops table */
2960 + new = kmem_alloc(sdev_vnodeops_tbl_size, KM_SLEEP);
2961 + bcopy((void *)sdev_vnodeops_tbl, new, sdev_vnodeops_tbl_size);
2962 +
2963 + /* replace the overrides from tab */
2964 + for (tab_entry = tab; tab_entry->name != NULL; tab_entry++) {
2965 + fs_operation_def_t *std_entry = new;
2966 + while (std_entry->name) {
2967 + if (strcmp(tab_entry->name, std_entry->name) == 0) {
2968 + std_entry->func = tab_entry->func;
2969 + break;
2970 + }
2971 + std_entry++;
2972 + }
2973 + if (std_entry->name == NULL)
2974 + cmn_err(CE_NOTE, "sdev_merge_vtab: entry %s unused.",
2975 + tab_entry->name);
2976 + }
2977 +
2978 + return (new);
2979 +}
2980 +
2981 +/* free memory allocated by sdev_merge_vtab */
2982 +static void
2983 +sdev_free_vtab(fs_operation_def_t *new)
2984 +{
2985 + kmem_free(new, sdev_vnodeops_tbl_size);
2986 +}
2987 +
2814 2988 /*
2815 2989 * a generic setattr() function
2816 2990 *
2817 2991 * note: flags only supports AT_UID and AT_GID.
2818 2992 * Future enhancements can be done for other types, e.g. AT_MODE
2819 2993 */
2820 2994 int
2821 2995 devname_setattr_func(struct vnode *vp, struct vattr *vap, int flags,
2822 2996 struct cred *cred, int (*callback)(struct sdev_node *, struct vattr *,
2823 2997 int), int protocol)
2824 2998 {
2825 2999 struct sdev_node *dv = VTOSDEV(vp);
2826 3000 struct sdev_node *parent = dv->sdev_dotdot;
2827 3001 struct vattr *get;
2828 3002 uint_t mask = vap->va_mask;
2829 3003 int error;
2830 3004
2831 3005 /* some sanity checks */
2832 3006 if (vap->va_mask & AT_NOSET)
2833 3007 return (EINVAL);
2834 3008
2835 3009 if (vap->va_mask & AT_SIZE) {
2836 3010 if (vp->v_type == VDIR) {
2837 3011 return (EISDIR);
2838 3012 }
2839 3013 }
2840 3014
2841 3015 /* no need to set attribute, but do not fail either */
2842 3016 ASSERT(parent);
2843 3017 rw_enter(&parent->sdev_contents, RW_READER);
2844 3018 if (dv->sdev_state == SDEV_ZOMBIE) {
2845 3019 rw_exit(&parent->sdev_contents);
2846 3020 return (0);
2847 3021 }
2848 3022
2849 3023 /* If backing store exists, just set it. */
2850 3024 if (dv->sdev_attrvp) {
2851 3025 rw_exit(&parent->sdev_contents);
2852 3026 return (VOP_SETATTR(dv->sdev_attrvp, vap, flags, cred, NULL));
2853 3027 }
2854 3028
2855 3029 /*
2856 3030 * Otherwise, for nodes with the persistence attribute, create it.
2857 3031 */
2858 3032 ASSERT(dv->sdev_attr);
2859 3033 if (SDEV_IS_PERSIST(dv) ||
2860 3034 ((vap->va_mask & ~AT_TIMES) != 0 && !SDEV_IS_DYNAMIC(dv))) {
2861 3035 sdev_vattr_merge(dv, vap);
2862 3036 rw_enter(&dv->sdev_contents, RW_WRITER);
2863 3037 error = sdev_shadow_node(dv, cred);
2864 3038 rw_exit(&dv->sdev_contents);
2865 3039 rw_exit(&parent->sdev_contents);
2866 3040
2867 3041 if (error)
2868 3042 return (error);
2869 3043 return (VOP_SETATTR(dv->sdev_attrvp, vap, flags, cred, NULL));
2870 3044 }
2871 3045
2872 3046
2873 3047 /*
2874 3048 * sdev_attr was allocated in sdev_mknode
2875 3049 */
2876 3050 rw_enter(&dv->sdev_contents, RW_WRITER);
2877 3051 error = secpolicy_vnode_setattr(cred, vp, vap,
2878 3052 dv->sdev_attr, flags, sdev_unlocked_access, dv);
2879 3053 if (error) {
2880 3054 rw_exit(&dv->sdev_contents);
2881 3055 rw_exit(&parent->sdev_contents);
2882 3056 return (error);
2883 3057 }
2884 3058
2885 3059 get = dv->sdev_attr;
2886 3060 if (mask & AT_MODE) {
2887 3061 get->va_mode &= S_IFMT;
2888 3062 get->va_mode |= vap->va_mode & ~S_IFMT;
2889 3063 }
2890 3064
2891 3065 if ((mask & AT_UID) || (mask & AT_GID)) {
2892 3066 if (mask & AT_UID)
2893 3067 get->va_uid = vap->va_uid;
2894 3068 if (mask & AT_GID)
2895 3069 get->va_gid = vap->va_gid;
2896 3070 /*
2897 3071 * a callback must be provided if the protocol is set
2898 3072 */
2899 3073 if ((protocol & AT_UID) || (protocol & AT_GID)) {
2900 3074 ASSERT(callback);
2901 3075 error = callback(dv, get, protocol);
2902 3076 if (error) {
2903 3077 rw_exit(&dv->sdev_contents);
2904 3078 rw_exit(&parent->sdev_contents);
2905 3079 return (error);
2906 3080 }
2907 3081 }
2908 3082 }
2909 3083
2910 3084 if (mask & AT_ATIME)
2911 3085 get->va_atime = vap->va_atime;
2912 3086 if (mask & AT_MTIME)
2913 3087 get->va_mtime = vap->va_mtime;
2914 3088 if (mask & (AT_MODE | AT_UID | AT_GID | AT_CTIME)) {
2915 3089 gethrestime(&get->va_ctime);
2916 3090 }
2917 3091
2918 3092 sdev_vattr_merge(dv, get);
2919 3093 rw_exit(&dv->sdev_contents);
2920 3094 rw_exit(&parent->sdev_contents);
2921 3095 return (0);
2922 3096 }
2923 3097
2924 3098 /*
2925 3099 * a generic inactive() function
2926 3100 */
2927 3101 /*ARGSUSED*/
2928 3102 void
2929 3103 devname_inactive_func(struct vnode *vp, struct cred *cred,
2930 3104 void (*callback)(struct vnode *))
2931 3105 {
2932 3106 int clean;
2933 3107 struct sdev_node *dv = VTOSDEV(vp);
2934 3108 int state;
2935 3109
2936 3110 mutex_enter(&vp->v_lock);
2937 3111 ASSERT(vp->v_count >= 1);
2938 3112
2939 3113
2940 3114 if (vp->v_count == 1 && callback != NULL)
2941 3115 callback(vp);
2942 3116
2943 3117 rw_enter(&dv->sdev_contents, RW_WRITER);
2944 3118 state = dv->sdev_state;
2945 3119
2946 3120 clean = (vp->v_count == 1) && (state == SDEV_ZOMBIE);
2947 3121
2948 3122 /*
2949 3123 * sdev is a rather bad public citizen. It violates the general
2950 3124 * agreement that in memory nodes should always have a valid reference
2951 3125 * count on their vnode. But that's not the case here. This means that
2952 3126 * we do actually have to distinguish between getting inactive callbacks
2953 3127 * for zombies and otherwise. This should probably be fixed.
2954 3128 */
2955 3129 if (clean) {
2956 3130 /* Remove the . entry to ourselves */
2957 3131 if (vp->v_type == VDIR) {
2958 3132 decr_link(dv);
2959 3133 }
2960 3134 VERIFY(dv->sdev_nlink == 1);
2961 3135 decr_link(dv);
2962 3136 --vp->v_count;
2963 3137 rw_exit(&dv->sdev_contents);
2964 3138 mutex_exit(&vp->v_lock);
2965 3139 sdev_nodedestroy(dv, 0);
2966 3140 } else {
2967 3141 --vp->v_count;
2968 3142 rw_exit(&dv->sdev_contents);
2969 3143 mutex_exit(&vp->v_lock);
2970 3144 }
2971 3145 }
|
↓ open down ↓ |
148 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX