Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/namefs/namevfs.c
+++ new/usr/src/uts/common/fs/namefs/namevfs.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) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
26 26 /* All Rights Reserved */
27 27
28 28
29 29 /*
30 30 * This file supports the vfs operations for the NAMEFS file system.
31 31 */
32 32
33 33 #include <sys/types.h>
34 34 #include <sys/param.h>
35 35 #include <sys/systm.h>
36 36 #include <sys/debug.h>
37 37 #include <sys/errno.h>
38 38 #include <sys/kmem.h>
39 39 #include <sys/inline.h>
40 40 #include <sys/file.h>
41 41 #include <sys/proc.h>
42 42 #include <sys/stat.h>
43 43 #include <sys/statvfs.h>
44 44 #include <sys/mount.h>
45 45 #include <sys/sysmacros.h>
46 46 #include <sys/var.h>
47 47 #include <sys/vfs.h>
48 48 #include <sys/vfs_opreg.h>
49 49 #include <sys/vnode.h>
50 50 #include <sys/mode.h>
51 51 #include <sys/pcb.h>
52 52 #include <sys/signal.h>
53 53 #include <sys/user.h>
54 54 #include <sys/uio.h>
55 55 #include <sys/cred.h>
56 56 #include <sys/fs/namenode.h>
57 57 #include <sys/stream.h>
58 58 #include <sys/strsubr.h>
59 59 #include <sys/cmn_err.h>
60 60 #include <sys/modctl.h>
61 61 #include <fs/fs_subr.h>
62 62 #include <sys/policy.h>
63 63 #include <sys/vmem.h>
64 64 #include <sys/fs/sdev_impl.h>
65 65
66 66 #define NM_INOQUANT (64 * 1024)
67 67
68 68 /*
69 69 * Define global data structures.
70 70 */
71 71 dev_t namedev;
72 72 int namefstype;
73 73 struct namenode *nm_filevp_hash[NM_FILEVP_HASH_SIZE];
74 74 struct vfs namevfs;
75 75 kmutex_t ntable_lock;
76 76
77 77 static vmem_t *nm_inoarena; /* vmem arena to allocate inode no's from */
78 78 static kmutex_t nm_inolock;
79 79
80 80 vfsops_t *namefs_vfsops;
81 81 /*
82 82 * Functions to allocate node id's starting from 1. Based on vmem routines.
83 83 * The vmem arena is extended in NM_INOQUANT chunks.
84 84 */
85 85 uint64_t
86 86 namenodeno_alloc(void)
87 87 {
88 88 uint64_t nno;
89 89
90 90 mutex_enter(&nm_inolock);
91 91 nno = (uint64_t)(uintptr_t)
92 92 vmem_alloc(nm_inoarena, 1, VM_NOSLEEP + VM_FIRSTFIT);
93 93 if (nno == 0) {
94 94 (void) vmem_add(nm_inoarena, (void *)(vmem_size(nm_inoarena,
95 95 VMEM_ALLOC | VMEM_FREE) + 1), NM_INOQUANT, VM_SLEEP);
96 96 nno = (uint64_t)(uintptr_t)
97 97 vmem_alloc(nm_inoarena, 1, VM_SLEEP + VM_FIRSTFIT);
98 98 ASSERT(nno != 0);
99 99 }
100 100 mutex_exit(&nm_inolock);
101 101 ASSERT32(nno <= ULONG_MAX);
102 102 return (nno);
103 103 }
104 104
105 105 static void
106 106 namenodeno_init(void)
107 107 {
108 108 nm_inoarena = vmem_create("namefs_inodes", (void *)1, NM_INOQUANT, 1,
109 109 NULL, NULL, NULL, 1, VM_SLEEP);
110 110 mutex_init(&nm_inolock, NULL, MUTEX_DEFAULT, NULL);
111 111 }
112 112
113 113 void
114 114 namenodeno_free(uint64_t nn)
115 115 {
116 116 void *vaddr = (void *)(uintptr_t)nn;
117 117
118 118 ASSERT32((uint64_t)(uintptr_t)vaddr == nn);
119 119
120 120 mutex_enter(&nm_inolock);
121 121 vmem_free(nm_inoarena, vaddr, 1);
122 122 mutex_exit(&nm_inolock);
123 123 }
124 124
125 125 /*
126 126 * Insert a namenode into the nm_filevp_hash table.
127 127 *
128 128 * Each link has a unique namenode with a unique nm_mountvp field.
129 129 * The nm_filevp field of the namenode need not be unique, since a
130 130 * file descriptor may be mounted to multiple nodes at the same time.
131 131 * We hash on nm_filevp since that's what discriminates the searches
132 132 * in namefind() and nm_unmountall().
133 133 */
134 134 void
135 135 nameinsert(struct namenode *nodep)
136 136 {
137 137 struct namenode **bucket;
138 138
139 139 ASSERT(MUTEX_HELD(&ntable_lock));
140 140
141 141 bucket = NM_FILEVP_HASH(nodep->nm_filevp);
142 142 nodep->nm_nextp = *bucket;
143 143 *bucket = nodep;
144 144 }
145 145
146 146 /*
147 147 * Remove a namenode from the hash table, if present.
148 148 */
149 149 void
150 150 nameremove(struct namenode *nodep)
151 151 {
152 152 struct namenode *np, **npp;
153 153
154 154 ASSERT(MUTEX_HELD(&ntable_lock));
155 155
156 156 for (npp = NM_FILEVP_HASH(nodep->nm_filevp); (np = *npp) != NULL;
157 157 npp = &np->nm_nextp) {
158 158 if (np == nodep) {
159 159 *npp = np->nm_nextp;
160 160 return;
161 161 }
162 162 }
163 163 }
164 164
165 165 /*
166 166 * Search for a namenode that has a nm_filevp == vp and nm_mountpt == mnt.
167 167 * If mnt is NULL, return the first link with nm_filevp of vp.
168 168 * Returns namenode pointer on success, NULL on failure.
169 169 */
170 170 struct namenode *
171 171 namefind(vnode_t *vp, vnode_t *mnt)
172 172 {
173 173 struct namenode *np;
174 174
175 175 ASSERT(MUTEX_HELD(&ntable_lock));
176 176 for (np = *NM_FILEVP_HASH(vp); np != NULL; np = np->nm_nextp)
177 177 if (np->nm_filevp == vp &&
178 178 (mnt == NULL || np->nm_mountpt == mnt))
179 179 break;
180 180 return (np);
181 181 }
182 182
183 183 /*
184 184 * Force the unmouting of a file descriptor from ALL of the nodes
185 185 * that it was mounted to.
186 186 * At the present time, the only usage for this routine is in the
187 187 * event one end of a pipe was mounted. At the time the unmounted
188 188 * end gets closed down, the mounted end is forced to be unmounted.
189 189 *
190 190 * This routine searches the namenode hash list for all namenodes
191 191 * that have a nm_filevp field equal to vp. Each time one is found,
192 192 * the dounmount() routine is called. This causes the nm_unmount()
193 193 * routine to be called and thus, the file descriptor is unmounted
194 194 * from the node.
195 195 *
196 196 * At the start of this routine, the reference count for vp is
197 197 * incremented to protect the vnode from being released in the
198 198 * event the mount was the only thing keeping the vnode active.
199 199 * If that is the case, the VOP_CLOSE operation is applied to
200 200 * the vnode, prior to it being released.
201 201 */
202 202 static int
203 203 nm_umountall(vnode_t *vp, cred_t *crp)
204 204 {
205 205 vfs_t *vfsp;
206 206 struct namenode *nodep;
207 207 int error = 0;
208 208 int realerr = 0;
209 209
210 210 /*
211 211 * For each namenode that is associated with the file:
212 212 * If the v_vfsp field is not namevfs, dounmount it. Otherwise,
213 213 * it was created in nm_open() and will be released in time.
214 214 * The following loop replicates some code from nm_find. That
215 215 * routine can't be used as is since the list isn't strictly
216 216 * consumed as it is traversed.
217 217 */
218 218 mutex_enter(&ntable_lock);
219 219 nodep = *NM_FILEVP_HASH(vp);
220 220 while (nodep) {
221 221 if (nodep->nm_filevp == vp &&
222 222 (vfsp = NMTOV(nodep)->v_vfsp) != NULL &&
223 223 vfsp != &namevfs && (NMTOV(nodep)->v_flag & VROOT)) {
224 224
225 225 /*
226 226 * If the vn_vfswlock fails, skip the vfs since
227 227 * somebody else may be unmounting it.
228 228 */
229 229 if (vn_vfswlock(vfsp->vfs_vnodecovered)) {
230 230 realerr = EBUSY;
231 231 nodep = nodep->nm_nextp;
232 232 continue;
233 233 }
234 234
235 235 /*
236 236 * Can't hold ntable_lock across call to do_unmount
237 237 * because nm_unmount tries to acquire it. This means
238 238 * there is a window where another mount of vp can
239 239 * happen so it is possible that after nm_unmountall
240 240 * there are still some mounts. This situation existed
241 241 * without MT locking because dounmount can sleep
242 242 * so another mount could happen during that time.
243 243 * This situation is unlikely and doesn't really cause
244 244 * any problems.
245 245 */
246 246 mutex_exit(&ntable_lock);
247 247 if ((error = dounmount(vfsp, 0, crp)) != 0)
248 248 realerr = error;
249 249 mutex_enter(&ntable_lock);
250 250 /*
251 251 * Since we dropped the ntable_lock, we
252 252 * have to start over from the beginning.
253 253 * If for some reasons dounmount() fails,
254 254 * start from beginning means that we will keep on
255 255 * trying unless another thread unmounts it for us.
256 256 */
257 257 nodep = *NM_FILEVP_HASH(vp);
258 258 } else
259 259 nodep = nodep->nm_nextp;
260 260 }
261 261 mutex_exit(&ntable_lock);
262 262 return (realerr);
263 263 }
264 264
265 265 /*
266 266 * Force the unmouting of a file descriptor from ALL of the nodes
267 267 * that it was mounted to. XXX: fifo_close() calls this routine.
268 268 *
269 269 * nm_umountall() may return EBUSY.
270 270 * nm_unmountall() will keep on trying until it succeeds.
271 271 */
272 272 int
273 273 nm_unmountall(vnode_t *vp, cred_t *crp)
274 274 {
275 275 int error;
276 276
277 277 /*
278 278 * Nm_umuontall() returns only if it succeeds or
279 279 * return with error EBUSY. If EBUSY, that means
280 280 * it cannot acquire the lock on the covered vnode,
281 281 * and we will keep on trying.
282 282 */
283 283 for (;;) {
284 284 error = nm_umountall(vp, crp);
285 285 if (error != EBUSY)
286 286 break;
287 287 delay(1); /* yield cpu briefly, then try again */
288 288 }
289 289 return (error);
290 290 }
291 291
292 292 /*
293 293 * Mount a file descriptor onto the node in the file system.
294 294 * Create a new vnode, update the attributes with info from the
295 295 * file descriptor and the mount point. The mask, mode, uid, gid,
296 296 * atime, mtime and ctime are taken from the mountpt. Link count is
297 297 * set to one, the file system id is namedev and nodeid is unique
298 298 * for each mounted object. Other attributes are taken from mount point.
299 299 * Make sure user is owner (or root) with write permissions on mount point.
300 300 * Hash the new vnode and return 0.
301 301 * Upon entry to this routine, the file descriptor is in the
302 302 * fd field of a struct namefd. Copy that structure from user
303 303 * space and retrieve the file descriptor.
304 304 */
305 305 static int
306 306 nm_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *crp)
307 307 {
308 308 struct namefd namefdp;
309 309 struct vnode *filevp; /* file descriptor vnode */
310 310 struct file *fp;
311 311 struct vnode *newvp; /* vnode representing this mount */
312 312 struct vnode *rvp; /* realvp (if any) for the mountpt */
313 313 struct namenode *nodep; /* namenode for this mount */
314 314 struct vattr filevattr; /* attributes of file dec. */
315 315 struct vattr *vattrp; /* attributes of this mount */
316 316 char *resource_name;
317 317 char *resource_nodetype;
318 318 statvfs64_t *svfsp;
319 319 int error = 0;
320 320
321 321 /*
322 322 * Get the file descriptor from user space.
323 323 * Make sure the file descriptor is valid and has an
324 324 * associated file pointer.
325 325 * If so, extract the vnode from the file pointer.
326 326 */
327 327 if (uap->datalen != sizeof (struct namefd))
328 328 return (EINVAL);
329 329
330 330 if (copyin(uap->dataptr, &namefdp, uap->datalen))
331 331 return (EFAULT);
332 332
333 333 if ((fp = getf(namefdp.fd)) == NULL)
334 334 return (EBADF);
335 335
336 336 /*
337 337 * If the mount point already has something mounted
338 338 * on it, disallow this mount. (This restriction may
339 339 * be removed in a later release).
340 340 * Or unmount has completed but the namefs ROOT vnode
341 341 * count has not decremented to zero, disallow this mount.
342 342 */
343 343
344 344 mutex_enter(&mvp->v_lock);
345 345 if ((mvp->v_flag & VROOT) ||
346 346 vfs_matchops(mvp->v_vfsp, namefs_vfsops)) {
347 347 mutex_exit(&mvp->v_lock);
348 348 releasef(namefdp.fd);
349 349 return (EBUSY);
350 350 }
351 351 mutex_exit(&mvp->v_lock);
352 352
353 353 /*
354 354 * Cannot allow users to fattach() in /dev/pts.
355 355 * First, there is no need for doing so and secondly
356 356 * we cannot allow arbitrary users to park on a node in
357 357 * /dev/pts or /dev/vt.
358 358 */
359 359 rvp = NULLVP;
360 360 if (vn_matchops(mvp, spec_getvnodeops()) &&
361 361 VOP_REALVP(mvp, &rvp, NULL) == 0 && rvp &&
362 362 (vn_matchops(rvp, devpts_getvnodeops()) ||
363 363 vn_matchops(rvp, devvt_getvnodeops()))) {
364 364 releasef(namefdp.fd);
365 365 return (ENOTSUP);
366 366 }
367 367
368 368 filevp = fp->f_vnode;
369 369 if (filevp->v_type == VDIR || filevp->v_type == VPORT) {
370 370 releasef(namefdp.fd);
371 371 return (EINVAL);
372 372 }
373 373
374 374 /*
375 375 * If the fd being mounted refers to neither a door nor a stream,
376 376 * make sure the caller is privileged.
377 377 */
378 378 if (filevp->v_type != VDOOR && filevp->v_stream == NULL) {
379 379 if (secpolicy_fs_mount(crp, filevp, vfsp) != 0) {
380 380 /* fd is neither a stream nor a door */
381 381 releasef(namefdp.fd);
382 382 return (EINVAL);
383 383 }
384 384 }
385 385
386 386 /*
387 387 * Make sure the file descriptor is not the root of some
388 388 * file system.
389 389 * If it's not, create a reference and allocate a namenode
390 390 * to represent this mount request.
391 391 */
392 392 if (filevp->v_flag & VROOT) {
393 393 releasef(namefdp.fd);
394 394 return (EBUSY);
395 395 }
396 396
397 397 nodep = kmem_zalloc(sizeof (struct namenode), KM_SLEEP);
398 398
399 399 mutex_init(&nodep->nm_lock, NULL, MUTEX_DEFAULT, NULL);
400 400 vattrp = &nodep->nm_vattr;
401 401 vattrp->va_mask = AT_ALL;
402 402 if (error = VOP_GETATTR(mvp, vattrp, 0, crp, NULL))
403 403 goto out;
404 404
405 405 filevattr.va_mask = AT_ALL;
406 406 if (error = VOP_GETATTR(filevp, &filevattr, 0, crp, NULL))
407 407 goto out;
408 408 /*
409 409 * Make sure the user is the owner of the mount point
410 410 * or has sufficient privileges.
411 411 */
412 412 if (error = secpolicy_vnode_owner(crp, vattrp->va_uid))
413 413 goto out;
414 414
415 415 /*
416 416 * Make sure the user has write permissions on the
417 417 * mount point (or has sufficient privileges).
418 418 */
419 419 if (secpolicy_vnode_access2(crp, mvp, vattrp->va_uid, vattrp->va_mode,
420 420 VWRITE) != 0) {
421 421 error = EACCES;
422 422 goto out;
423 423 }
424 424
425 425 /*
426 426 * If the file descriptor has file/record locking, don't
427 427 * allow the mount to succeed.
428 428 */
429 429 if (vn_has_flocks(filevp)) {
430 430 error = EACCES;
431 431 goto out;
432 432 }
433 433
434 434 /*
435 435 * Initialize the namenode.
436 436 */
437 437 if (filevp->v_stream) {
438 438 struct stdata *stp = filevp->v_stream;
439 439 mutex_enter(&stp->sd_lock);
440 440 stp->sd_flag |= STRMOUNT;
441 441 mutex_exit(&stp->sd_lock);
442 442 }
443 443 nodep->nm_filevp = filevp;
444 444 mutex_enter(&fp->f_tlock);
445 445 fp->f_count++;
446 446 mutex_exit(&fp->f_tlock);
447 447
448 448 releasef(namefdp.fd);
449 449 nodep->nm_filep = fp;
450 450 nodep->nm_mountpt = mvp;
451 451
452 452 /*
453 453 * The attributes for the mounted file descriptor were initialized
454 454 * above by applying VOP_GETATTR to the mount point. Some of
455 455 * the fields of the attributes structure will be overwritten
456 456 * by the attributes from the file descriptor.
457 457 */
458 458 vattrp->va_type = filevattr.va_type;
459 459 vattrp->va_fsid = namedev;
460 460 vattrp->va_nodeid = namenodeno_alloc();
461 461 vattrp->va_nlink = 1;
462 462 vattrp->va_size = filevattr.va_size;
463 463 vattrp->va_rdev = filevattr.va_rdev;
464 464 vattrp->va_blksize = filevattr.va_blksize;
465 465 vattrp->va_nblocks = filevattr.va_nblocks;
466 466 vattrp->va_seq = 0;
467 467
468 468 /*
469 469 * Initialize new vnode structure for the mounted file descriptor.
470 470 */
471 471 nodep->nm_vnode = vn_alloc(KM_SLEEP);
472 472 newvp = NMTOV(nodep);
473 473
474 474 newvp->v_flag = filevp->v_flag | VROOT | VNOMAP | VNOSWAP;
475 475 vn_setops(newvp, nm_vnodeops);
476 476 newvp->v_vfsp = vfsp;
477 477 newvp->v_stream = filevp->v_stream;
478 478 newvp->v_type = filevp->v_type;
479 479 newvp->v_rdev = filevp->v_rdev;
480 480 newvp->v_data = (caddr_t)nodep;
481 481 VFS_HOLD(vfsp);
482 482 vn_exists(newvp);
483 483
484 484 /*
485 485 * Initialize the vfs structure.
486 486 */
487 487 vfsp->vfs_vnodecovered = NULL;
488 488 vfsp->vfs_flag |= VFS_UNLINKABLE;
489 489 vfsp->vfs_bsize = 1024;
490 490 vfsp->vfs_fstype = namefstype;
491 491 vfs_make_fsid(&vfsp->vfs_fsid, namedev, namefstype);
492 492 vfsp->vfs_data = (caddr_t)nodep;
493 493 vfsp->vfs_dev = namedev;
494 494 vfsp->vfs_bcount = 0;
495 495
496 496 /*
497 497 * Set the name we mounted from.
498 498 */
499 499 switch (filevp->v_type) {
500 500 case VPROC: /* VOP_GETATTR() translates this to VREG */
501 501 case VREG: resource_nodetype = "file"; break;
502 502 case VDIR: resource_nodetype = "directory"; break;
503 503 case VBLK: resource_nodetype = "device"; break;
504 504 case VCHR: resource_nodetype = "device"; break;
505 505 case VLNK: resource_nodetype = "link"; break;
506 506 case VFIFO: resource_nodetype = "fifo"; break;
507 507 case VDOOR: resource_nodetype = "door"; break;
508 508 case VSOCK: resource_nodetype = "socket"; break;
509 509 default: resource_nodetype = "resource"; break;
510 510 }
511 511
512 512 #define RESOURCE_NAME_SZ 128 /* Maximum length of the resource name */
513 513 resource_name = kmem_alloc(RESOURCE_NAME_SZ, KM_SLEEP);
514 514 svfsp = kmem_alloc(sizeof (statvfs64_t), KM_SLEEP);
515 515
516 516 error = VFS_STATVFS(filevp->v_vfsp, svfsp);
517 517 if (error == 0) {
518 518 (void) snprintf(resource_name, RESOURCE_NAME_SZ,
519 519 "unspecified_%s_%s", svfsp->f_basetype, resource_nodetype);
520 520 } else {
521 521 (void) snprintf(resource_name, RESOURCE_NAME_SZ,
522 522 "unspecified_%s", resource_nodetype);
523 523 }
524 524
525 525 vfs_setresource(vfsp, resource_name, 0);
526 526
527 527 kmem_free(svfsp, sizeof (statvfs64_t));
528 528 kmem_free(resource_name, RESOURCE_NAME_SZ);
529 529 #undef RESOURCE_NAME_SZ
530 530
531 531 /*
532 532 * Insert the namenode.
533 533 */
534 534 mutex_enter(&ntable_lock);
535 535 nameinsert(nodep);
536 536 mutex_exit(&ntable_lock);
537 537 return (0);
538 538 out:
539 539 releasef(namefdp.fd);
540 540 kmem_free(nodep, sizeof (struct namenode));
541 541 return (error);
542 542 }
543 543
544 544 /*
545 545 * Unmount a file descriptor from a node in the file system.
546 546 * If the user is not the owner of the file and is not privileged,
547 547 * the request is denied.
548 548 * Otherwise, remove the namenode from the hash list.
549 549 * If the mounted file descriptor was that of a stream and this
550 550 * was the last mount of the stream, turn off the STRMOUNT flag.
551 551 * If the rootvp is referenced other than through the mount,
552 552 * nm_inactive will clean up.
553 553 */
554 554 static int
555 555 nm_unmount(vfs_t *vfsp, int flag, cred_t *crp)
556 556 {
557 557 struct namenode *nodep = (struct namenode *)vfsp->vfs_data;
558 558 vnode_t *vp, *thisvp;
559 559 struct file *fp = NULL;
560 560
561 561 ASSERT((nodep->nm_flag & NMNMNT) == 0);
562 562
563 563 /*
564 564 * forced unmount is not supported by this file system
565 565 * and thus, ENOTSUP, is being returned.
566 566 */
567 567 if (flag & MS_FORCE) {
568 568 return (ENOTSUP);
569 569 }
570 570
571 571 vp = nodep->nm_filevp;
572 572 mutex_enter(&nodep->nm_lock);
573 573 if (secpolicy_vnode_owner(crp, nodep->nm_vattr.va_uid) != 0) {
574 574 mutex_exit(&nodep->nm_lock);
575 575 return (EPERM);
576 576 }
577 577
578 578 mutex_exit(&nodep->nm_lock);
579 579
580 580 mutex_enter(&ntable_lock);
581 581 nameremove(nodep);
582 582 thisvp = NMTOV(nodep);
583 583 mutex_enter(&thisvp->v_lock);
584 584 if (thisvp->v_count-- == 1) {
585 585 fp = nodep->nm_filep;
586 586 mutex_exit(&thisvp->v_lock);
587 587 vn_invalid(thisvp);
588 588 vn_free(thisvp);
589 589 VFS_RELE(vfsp);
590 590 namenodeno_free(nodep->nm_vattr.va_nodeid);
591 591 kmem_free(nodep, sizeof (struct namenode));
592 592 } else {
593 593 thisvp->v_flag &= ~VROOT;
594 594 mutex_exit(&thisvp->v_lock);
595 595 }
596 596 if (namefind(vp, NULLVP) == NULL && vp->v_stream) {
597 597 struct stdata *stp = vp->v_stream;
598 598 mutex_enter(&stp->sd_lock);
599 599 stp->sd_flag &= ~STRMOUNT;
600 600 mutex_exit(&stp->sd_lock);
601 601 }
602 602 mutex_exit(&ntable_lock);
603 603 if (fp != NULL)
604 604 (void) closef(fp);
605 605 return (0);
606 606 }
607 607
608 608 /*
609 609 * Create a reference to the root of a mounted file descriptor.
610 610 * This routine is called from lookupname() in the event a path
611 611 * is being searched that has a mounted file descriptor in it.
612 612 */
613 613 static int
614 614 nm_root(vfs_t *vfsp, vnode_t **vpp)
615 615 {
616 616 struct namenode *nodep = (struct namenode *)vfsp->vfs_data;
617 617 struct vnode *vp = NMTOV(nodep);
618 618
619 619 VN_HOLD(vp);
620 620 *vpp = vp;
621 621 return (0);
622 622 }
623 623
624 624 /*
625 625 * Return in sp the status of this file system.
626 626 */
627 627 static int
628 628 nm_statvfs(vfs_t *vfsp, struct statvfs64 *sp)
629 629 {
630 630 dev32_t d32;
631 631
632 632 bzero(sp, sizeof (*sp));
633 633 sp->f_bsize = 1024;
634 634 sp->f_frsize = 1024;
635 635 (void) cmpldev(&d32, vfsp->vfs_dev);
636 636 sp->f_fsid = d32;
637 637 (void) strcpy(sp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name);
638 638 sp->f_flag = vf_to_stf(vfsp->vfs_flag);
639 639 return (0);
640 640 }
641 641
642 642 /*
643 643 * Since this file system has no disk blocks of its own, apply
644 644 * the VOP_FSYNC operation on the mounted file descriptor.
645 645 */
646 646 static int
647 647 nm_sync(vfs_t *vfsp, short flag, cred_t *crp)
648 648 {
649 649 struct namenode *nodep;
650 650
651 651 if (vfsp == NULL)
652 652 return (0);
653 653
654 654 nodep = (struct namenode *)vfsp->vfs_data;
655 655 if (flag & SYNC_CLOSE)
656 656 return (nm_umountall(nodep->nm_filevp, crp));
657 657
658 658 return (VOP_FSYNC(nodep->nm_filevp, FSYNC, crp, NULL));
↓ open down ↓ |
658 lines elided |
↑ open up ↑ |
659 659 }
660 660
661 661 /*
662 662 * File system initialization routine. Save the file system type,
663 663 * establish a file system device number and initialize nm_filevp_hash[].
664 664 */
665 665 int
666 666 nameinit(int fstype, char *name)
667 667 {
668 668 static const fs_operation_def_t nm_vfsops_template[] = {
669 - VFSNAME_MOUNT, { .vfs_mount = nm_mount },
670 - VFSNAME_UNMOUNT, { .vfs_unmount = nm_unmount },
671 - VFSNAME_ROOT, { .vfs_root = nm_root },
672 - VFSNAME_STATVFS, { .vfs_statvfs = nm_statvfs },
673 - VFSNAME_SYNC, { .vfs_sync = nm_sync },
674 - NULL, NULL
669 + { VFSNAME_MOUNT, { .vfs_mount = nm_mount } },
670 + { VFSNAME_UNMOUNT, { .vfs_unmount = nm_unmount } },
671 + { VFSNAME_ROOT, { .vfs_root = nm_root } },
672 + { VFSNAME_STATVFS, { .vfs_statvfs = nm_statvfs } },
673 + { VFSNAME_SYNC, { .vfs_sync = nm_sync } },
674 + { NULL, { NULL } }
675 675 };
676 676 static const fs_operation_def_t nm_dummy_vfsops_template[] = {
677 - VFSNAME_STATVFS, { .vfs_statvfs = nm_statvfs },
678 - VFSNAME_SYNC, { .vfs_sync = nm_sync },
679 - NULL, NULL
677 + { VFSNAME_STATVFS, { .vfs_statvfs = nm_statvfs } },
678 + { VFSNAME_SYNC, { .vfs_sync = nm_sync } },
679 + { NULL, { NULL } }
680 680 };
681 681 int error;
682 682 int dev;
683 683 vfsops_t *dummy_vfsops;
684 684
685 685 error = vfs_setfsops(fstype, nm_vfsops_template, &namefs_vfsops);
686 686 if (error != 0) {
687 687 cmn_err(CE_WARN, "nameinit: bad vfs ops template");
688 688 return (error);
689 689 }
690 690
691 691 error = vfs_makefsops(nm_dummy_vfsops_template, &dummy_vfsops);
692 692 if (error != 0) {
693 693 (void) vfs_freevfsops_by_type(fstype);
694 694 cmn_err(CE_WARN, "nameinit: bad dummy vfs ops template");
695 695 return (error);
696 696 }
697 697
698 698 error = vn_make_ops(name, nm_vnodeops_template, &nm_vnodeops);
699 699 if (error != 0) {
700 700 (void) vfs_freevfsops_by_type(fstype);
701 701 vfs_freevfsops(dummy_vfsops);
702 702 cmn_err(CE_WARN, "nameinit: bad vnode ops template");
703 703 return (error);
704 704 }
705 705
706 706 namefstype = fstype;
707 707
708 708 if ((dev = getudev()) == (major_t)-1) {
709 709 cmn_err(CE_WARN, "nameinit: can't get unique device");
710 710 dev = 0;
711 711 }
712 712 mutex_init(&ntable_lock, NULL, MUTEX_DEFAULT, NULL);
713 713 namedev = makedevice(dev, 0);
714 714 bzero(nm_filevp_hash, sizeof (nm_filevp_hash));
715 715 vfs_setops(&namevfs, dummy_vfsops);
716 716 namevfs.vfs_vnodecovered = NULL;
717 717 namevfs.vfs_bsize = 1024;
718 718 namevfs.vfs_fstype = namefstype;
719 719 vfs_make_fsid(&namevfs.vfs_fsid, namedev, namefstype);
720 720 namevfs.vfs_dev = namedev;
721 721 return (0);
722 722 }
723 723
724 724 static mntopts_t nm_mntopts = {
725 725 NULL,
726 726 0
727 727 };
728 728
729 729 static vfsdef_t vfw = {
730 730 VFSDEF_VERSION,
731 731 "namefs",
732 732 nameinit,
733 733 VSW_HASPROTO | VSW_ZMOUNT,
734 734 &nm_mntopts
↓ open down ↓ |
45 lines elided |
↑ open up ↑ |
735 735 };
736 736
737 737 /*
738 738 * Module linkage information for the kernel.
739 739 */
740 740 static struct modlfs modlfs = {
741 741 &mod_fsops, "filesystem for namefs", &vfw
742 742 };
743 743
744 744 static struct modlinkage modlinkage = {
745 - MODREV_1, (void *)&modlfs, NULL
745 + MODREV_1, { (void *)&modlfs, NULL }
746 746 };
747 747
748 748 int
749 749 _init(void)
750 750 {
751 751 namenodeno_init();
752 752 return (mod_install(&modlinkage));
753 753 }
754 754
755 755 int
756 756 _fini(void)
757 757 {
758 758 return (EBUSY);
759 759 }
760 760
761 761 int
762 762 _info(struct modinfo *modinfop)
763 763 {
764 764 return (mod_info(&modlinkage, modinfop));
765 765 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX