|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1989, 1993
28: * The Regents of the University of California. All rights reserved.
29: * (c) UNIX System Laboratories, Inc.
30: * All or some portions of this file are derived from material licensed
31: * to the University of California by American Telephone and Telegraph
32: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
33: * the permission of UNIX System Laboratories, Inc.
34: *
35: * Redistribution and use in source and binary forms, with or without
36: * modification, are permitted provided that the following conditions
37: * are met:
38: * 1. Redistributions of source code must retain the above copyright
39: * notice, this list of conditions and the following disclaimer.
40: * 2. Redistributions in binary form must reproduce the above copyright
41: * notice, this list of conditions and the following disclaimer in the
42: * documentation and/or other materials provided with the distribution.
43: * 3. All advertising materials mentioning features or use of this software
44: * must display the following acknowledgement:
45: * This product includes software developed by the University of
46: * California, Berkeley and its contributors.
47: * 4. Neither the name of the University nor the names of its contributors
48: * may be used to endorse or promote products derived from this software
49: * without specific prior written permission.
50: *
51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61: * SUCH DAMAGE.
62: *
63: * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
64: */
65:
66: /*
67: * External virtual filesystem routines
68: */
69:
70: #include <mach_nbc.h>
71: #include <sys/param.h>
72: #include <sys/systm.h>
73: #include <sys/proc.h>
74: #include <sys/mount.h>
75: #include <sys/time.h>
76: #include <sys/vnode.h>
77: #include <sys/stat.h>
78: #include <sys/namei.h>
79: #include <sys/ucred.h>
80: #include <sys/buf.h>
81: #include <sys/errno.h>
82: #include <sys/malloc.h>
83: #include <sys/domain.h>
84: #include <sys/mbuf.h>
85: #include <sys/syslog.h>
86:
87: #include <sys/vm.h>
88: #include <sys/sysctl.h>
89:
90: #include <miscfs/specfs/specdev.h>
91:
92: #if MACH_NBC
93: #include <kern/mapfs.h>
94: #endif /* MACH_NBC */
95:
96: enum vtype iftovt_tab[16] = {
97: VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
98: VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
99: };
100: int vttoif_tab[9] = {
101: 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK,
102: S_IFSOCK, S_IFIFO, S_IFMT,
103: };
104:
105: /*
106: * Insq/Remq for the vnode usage lists.
107: */
108: #define bufinsvn(bp, dp) LIST_INSERT_HEAD(dp, bp, b_vnbufs)
109: #define bufremvn(bp) { \
110: LIST_REMOVE(bp, b_vnbufs); \
111: (bp)->b_vnbufs.le_next = NOLIST; \
112: }
113: TAILQ_HEAD(freelst, vnode) vnode_free_list; /* vnode free list */
114: struct mntlist mountlist; /* mounted filesystem list */
115:
116: /*
117: * Have to declare first two locks as actual data even if !MACH_SLOCKS, since
118: * a pointers to them get passed around.
119: */
120: simple_lock_data_t mountlist_slock;
121: simple_lock_data_t mntvnode_slock;
122: decl_simple_lock_data(,mntid_slock);
123: decl_simple_lock_data(,vnode_free_list_slock);
124: decl_simple_lock_data(,spechash_slock);
125:
126: extern struct lock__bsd__ exchangelock;
127:
128: /*
129: * vnodetarget is the amount of vnodes we expect to get back from the
130: * VM object cache. As vm_object_cache_steal() is a cpu bound operation
131: * for faster processers this number could be higher.
132: * Having this number too high introduces longer delays in the execution
133: * of getnewvnode().
134: */
135: unsigned long vnodetarget; /* target for vm_object_cache_steal() */
136: #define VNODE_FREE_TARGET 20 /* Default value for vnodetarget */
137:
138: /*
139: * We need quite a few vnodes on the free list to sustain the
140: * rapid stat() the compilation process does, and still benefit from the name
141: * cache. Having too few vnodes on the free list causes serious disk
142: * thrashing as we cycle through them.
143: */
144: #define VNODE_FREE_MIN 100 /* freelist should have at least these many */
145:
146: /*
147: * We need to get vnodes back from the VM object cache when a certain #
148: * of vnodes are reused from the freelist. This is essential for the
149: * caching to be effective in the namecache and the buffer cache [for the
150: * metadata].
151: */
152: #define VNODE_TOOMANY_REUSED (VNODE_FREE_MIN/4)
153:
154: /*
155: * If we have enough vnodes on the freelist we do not want to reclaim
156: * the vnodes from the VM object cache.
157: */
158: #define VNODE_FREE_ENOUGH (VNODE_FREE_MIN + (VNODE_FREE_MIN/2))
159: /*
160: * Initialize the vnode management data structures.
161: */
162: void
163: vntblinit()
164: {
165: simple_lock_init(&mountlist_slock);
166: simple_lock_init(&mntvnode_slock);
167: simple_lock_init(&mntid_slock);
168: simple_lock_init(&spechash_slock);
169: TAILQ_INIT(&vnode_free_list);
170: simple_lock_init(&vnode_free_list_slock);
171: CIRCLEQ_INIT(&mountlist);
172: lockinit(&exchangelock, PVFS, "exchange", 0, 0);
173:
174: if (!vnodetarget)
175: vnodetarget = VNODE_FREE_TARGET;
176:
177: adjust_vm_object_cache(0, desiredvnodes - VNODE_FREE_MIN);
178: }
179:
180: /* Reset the VM Object Cache with the values passed in */
181: kern_return_t
182: reset_vmobjectcache(unsigned int val1, unsigned int val2)
183: {
184: return(adjust_vm_object_cache(val1-VNODE_FREE_MIN, val2 - VNODE_FREE_MIN));
185: }
186:
187:
188:
189: /*
190: * Mark a mount point as busy. Used to synchronize access and to delay
191: * unmounting. Interlock is not released on failure.
192: */
193: int
194: vfs_busy(mp, flags, interlkp, p)
195: struct mount *mp;
196: int flags;
197: struct slock *interlkp;
198: struct proc *p;
199: {
200: int lkflags;
201:
202: if (mp->mnt_flag & MNT_UNMOUNT) {
203: if (flags & LK_NOWAIT)
204: return (ENOENT);
205: mp->mnt_flag |= MNT_MWAIT;
206: if (interlkp)
207: simple_unlock(interlkp);
208: /*
209: * Since all busy locks are shared except the exclusive
210: * lock granted when unmounting, the only place that a
211: * wakeup needs to be done is at the release of the
212: * exclusive lock at the end of dounmount.
213: */
214: sleep((caddr_t)mp, PVFS);
215: if (interlkp)
216: simple_lock(interlkp);
217: return (ENOENT);
218: }
219: lkflags = LK_SHARED;
220: if (interlkp)
221: lkflags |= LK_INTERLOCK;
222: if (lockmgr(&mp->mnt_lock, lkflags, interlkp, p))
223: panic("vfs_busy: unexpected lock failure");
224: return (0);
225: }
226:
227: /*
228: * Free a busy filesystem.
229: */
230: void
231: vfs_unbusy(mp, p)
232: struct mount *mp;
233: struct proc *p;
234: {
235:
236: lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, p);
237: }
238:
239: /*
240: * Lookup a filesystem type, and if found allocate and initialize
241: * a mount structure for it.
242: *
243: * Devname is usually updated by mount(8) after booting.
244: */
245: int
246: vfs_rootmountalloc(fstypename, devname, mpp)
247: char *fstypename;
248: char *devname;
249: struct mount **mpp;
250: {
251: struct proc *p = current_proc(); /* XXX */
252: struct vfsconf *vfsp;
253: struct mount *mp;
254:
255: for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
256: if (!strcmp(vfsp->vfc_name, fstypename))
257: break;
258: if (vfsp == NULL)
259: return (ENODEV);
260: mp = _MALLOC_ZONE((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
261: bzero((char *)mp, (u_long)sizeof(struct mount));
262: lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
263: (void)vfs_busy(mp, LK_NOWAIT, 0, p);
264: LIST_INIT(&mp->mnt_vnodelist);
265: mp->mnt_vfc = vfsp;
266: mp->mnt_op = vfsp->vfc_vfsops;
267: mp->mnt_flag = MNT_RDONLY;
268: mp->mnt_vnodecovered = NULLVP;
269: vfsp->vfc_refcount++;
270: mp->mnt_stat.f_type = vfsp->vfc_typenum;
271: mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
272: strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
273: mp->mnt_stat.f_mntonname[0] = '/';
274: (void) copystr(devname, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 0);
275: *mpp = mp;
276: return (0);
277: }
278:
279: /*
280: * Find an appropriate filesystem to use for the root. If a filesystem
281: * has not been preselected, walk through the list of known filesystems
282: * trying those that have mountroot routines, and try them until one
283: * works or we have tried them all.
284: */
285: int
286: vfs_mountroot()
287: {
288: struct vfsconf *vfsp;
289: extern int (*mountroot)(void);
290: int error;
291:
292: if (mountroot != NULL) {
293: error = (*mountroot)();
294: return (error);
295: }
296:
297: for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {
298: if (vfsp->vfc_mountroot == NULL)
299: continue;
300: if ((error = (*vfsp->vfc_mountroot)()) == 0)
301: return (0);
302: printf("%s_mountroot failed: %d\n", vfsp->vfc_name, error);
303: }
304: return (ENODEV);
305: }
306:
307: /*
308: * Lookup a mount point by filesystem identifier.
309: */
310: struct mount *
311: vfs_getvfs(fsid)
312: fsid_t *fsid;
313: {
314: register struct mount *mp;
315:
316: simple_lock(&mountlist_slock);
317: for (mp = mountlist.cqh_first; mp != (void *)&mountlist;
318: mp = mp->mnt_list.cqe_next) {
319: if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] &&
320: mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) {
321: simple_unlock(&mountlist_slock);
322: return (mp);
323: }
324: }
325: simple_unlock(&mountlist_slock);
326: return ((struct mount *)0);
327: }
328:
329: /*
330: * Get a new unique fsid
331: */
332: void
333: vfs_getnewfsid(mp)
334: struct mount *mp;
335: {
336: static u_short xxxfs_mntid;
337:
338: fsid_t tfsid;
339: int mtype;
340:
341: simple_lock(&mntid_slock);
342: mtype = mp->mnt_vfc->vfc_typenum;
343: mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + mtype, 0);
344: mp->mnt_stat.f_fsid.val[1] = mtype;
345: if (xxxfs_mntid == 0)
346: ++xxxfs_mntid;
347: tfsid.val[0] = makedev(nblkdev + mtype, xxxfs_mntid);
348: tfsid.val[1] = mtype;
349: if (mountlist.cqh_first != (void *)&mountlist) {
350: while (vfs_getvfs(&tfsid)) {
351: tfsid.val[0]++;
352: xxxfs_mntid++;
353: }
354: }
355: mp->mnt_stat.f_fsid.val[0] = tfsid.val[0];
356: simple_unlock(&mntid_slock);
357: }
358:
359: /*
360: * Set vnode attributes to VNOVAL
361: */
362: void
363: vattr_null(vap)
364: register struct vattr *vap;
365: {
366:
367: vap->va_type = VNON;
368: vap->va_size = vap->va_bytes = VNOVAL;
369: vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid =
370: vap->va_fsid = vap->va_fileid =
371: vap->va_blocksize = vap->va_rdev =
372: vap->va_atime.tv_sec = vap->va_atime.tv_nsec =
373: vap->va_mtime.tv_sec = vap->va_mtime.tv_nsec =
374: vap->va_ctime.tv_sec = vap->va_ctime.tv_nsec =
375: vap->va_flags = vap->va_gen = VNOVAL;
376: vap->va_vaflags = 0;
377: }
378:
379: /*
380: * Routines having to do with the management of the vnode table.
381: */
382: extern int (**dead_vnodeop_p)();
383: static void vclean __P((struct vnode *vp, int flag, struct proc *p));
384: extern void vgonel __P((struct vnode *vp, struct proc *p));
385: long numvnodes, freevnodes;
386:
387: extern struct vattr va_null;
388:
389: /*
390: * Return the next vnode from the free list.
391: */
392: int
393: getnewvnode(tag, mp, vops, vpp)
394: enum vtagtype tag;
395: struct mount *mp;
396: int (**vops)();
397: struct vnode **vpp;
398: {
399: struct proc *p = current_proc(); /* XXX */
400: struct vnode *vp;
401: int cnt, didretry = 0;
402: static int reused = 0; /* track the reuse rate */
403:
404: retry:
405: simple_lock(&vnode_free_list_slock);
406: /*
407: * MALLOC a vnode if the number of vnodes is not reached the desired
408: * value. There might be vnodes on the free list, but we do not
409: * reuse from the freelist because reusing a vnode implies reusing
410: * the name cache entry.
411: */
412: if (numvnodes < desiredvnodes) {
413: numvnodes++;
414: simple_unlock(&vnode_free_list_slock);
415: MALLOC_ZONE(vp, struct vnode *, sizeof *vp, M_VNODE, M_WAITOK);
416: bzero((char *)vp, sizeof *vp);
417: simple_lock_init(&vp->v_interlock);
418: } else {
419: /*
420: * Once the desired number of vnodes are allocated, we start reusing
421: * from the freelist.
422: */
423: if (freevnodes < VNODE_FREE_MIN) {
424: /*
425: * if we are low on vnodes on the freelist attempt to get
426: * some back from the VM object cache
427: */
428: simple_unlock(&vnode_free_list_slock);
429: vm_object_cache_steal(vnodetarget);
430: simple_lock(&vnode_free_list_slock);
431: }
432:
433: for (cnt = 0, vp = vnode_free_list.tqh_first;
434: vp != NULLVP; cnt++, vp = vp->v_freelist.tqe_next) {
435: if (simple_lock_try(&vp->v_interlock))
436: break;
437: }
438: /*
439: * Unless this is a bad time of the month, at most
440: * the first NCPUS items on the free list are
441: * locked, so this is close enough to being empty.
442: */
443: if (vp == NULLVP) {
444: simple_unlock(&vnode_free_list_slock);
445: if (!(didretry++) && (vm_object_cache_steal(vnodetarget) > 0))
446: goto retry;
447: tablefull("vnode");
448: log(LOG_EMERG, "%d vnodes locked, %d desired, %d numvnodes\n",
449: cnt, desiredvnodes, numvnodes);
450: *vpp = 0;
451: return (ENFILE);
452: }
453:
454: if (vp->v_usecount)
455: panic("free vnode isn't: v_type = %d, v_usecount = %d?",
456: vp->v_type, vp->v_usecount);
457:
458: if (reused > VNODE_TOOMANY_REUSED) {
459: reused = 0;
460: if (freevnodes < VNODE_FREE_ENOUGH) {
461: simple_unlock(&vnode_free_list_slock);
462: simple_unlock(&vp->v_interlock);
463: vm_object_cache_steal(vnodetarget);
464: /*
465: * The vnode we have right now can potentially have dirty
466: * buffers associated with it. So we do not want to reuse it
467: * given a choice. The vnodes reclimed from VM object cache are
468: * put on the front of the freelist. So retry can potentially
469: * avoid IO, which is a good thing.
470: */
471: goto retry;
472: }
473: }
474:
475: TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
476: /* see comment on why 0xdeadb is set at end of vgone (below) */
477: vp->v_freelist.tqe_prev = (struct vnode **)0xdeadb;
478: freevnodes--;
479: reused++;
480: simple_unlock(&vnode_free_list_slock);
481: vp->v_lease = NULL;
482: if (vp->v_type != VBAD)
483: vgonel(vp, p);
484: else
485: simple_unlock(&vp->v_interlock);
486: #if DIAGNOSTIC
487: if (vp->v_data)
488: panic("cleaned vnode isn't");
489: {
490: int s = splbio();
491: if (vp->v_numoutput)
492: panic("Clean vnode has pending I/O's");
493: splx(s);
494: }
495: #endif
496: vp->v_flag = 0;
497: vp->v_lastr = 0;
498: vp->v_ralen = 0;
499: vp->v_maxra = 0;
500: vp->v_lastw = 0;
501: vp->v_lasta = 0;
502: vp->v_cstart = 0;
503: vp->v_clen = 0;
504: vp->v_socket = 0;
505: vp->v_bread = vp->v_consumed = 0;
506: }
507: vp->v_power = 5; /* 32k speculative reads */
508: vp->v_trigger = 16 * 8;
509: vp->v_type = VNON;
510: cache_purge(vp);
511: vp->v_tag = tag;
512: vp->v_op = vops;
513: insmntque(vp, mp);
514: *vpp = vp;
515: vp->v_usecount = 1;
516: vp->v_data = 0;
517: return (0);
518: }
519:
520: /*
521: * Move a vnode from one mount queue to another.
522: */
523: void
524: insmntque(vp, mp)
525: struct vnode *vp;
526: struct mount *mp;
527: {
528:
529: simple_lock(&mntvnode_slock);
530: /*
531: * Delete from old mount point vnode list, if on one.
532: */
533: if (vp->v_mount != NULL)
534: LIST_REMOVE(vp, v_mntvnodes);
535: /*
536: * Insert into list of vnodes for the new mount point, if available.
537: */
538: if ((vp->v_mount = mp) != NULL)
539: LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes);
540: simple_unlock(&mntvnode_slock);
541: }
542:
543: /*
544: * Update outstanding I/O count and do wakeup if requested.
545: */
546: void
547: vwakeup(bp)
548: register struct buf *bp;
549: {
550: register struct vnode *vp;
551:
552: bp->b_flags &= ~B_WRITEINPROG;
553: if (vp = bp->b_vp) {
554: if (--vp->v_numoutput < 0)
555: panic("vwakeup: neg numoutput");
556: if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {
557: if (vp->v_numoutput < 0)
558: panic("vwakeup: neg numoutput 2");
559: vp->v_flag &= ~VBWAIT;
560: wakeup((caddr_t)&vp->v_numoutput);
561: }
562: }
563: }
564:
565: /*
566: * Flush out and invalidate all buffers associated with a vnode.
567: * Called with the underlying object locked.
568: */
569: int
570: vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)
571: register struct vnode *vp;
572: int flags;
573: struct ucred *cred;
574: struct proc *p;
575: int slpflag, slptimeo;
576: {
577: register struct buf *bp;
578: struct buf *nbp, *blist;
579: int s, error = 0;
580:
581: if (flags & V_SAVE) {
582: #if MACH_NBC
583: if ((vp->v_type == VREG) && (vp->v_vm_info) && (vp->v_vm_info->mapped))
584: if ((error = mapfs_fsync(vp)))
585: return (error);
586: #endif /* MACH_NBC */
587: if (error = VOP_FSYNC(vp, cred, MNT_WAIT, p))
588: return (error);
589: if (vp->v_dirtyblkhd.lh_first != NULL)
590: panic("vinvalbuf: dirty bufs");
591: }
592:
593: /*
594: * make sure we don't have any lingering state
595: * associated with cluster writes
596: */
597: vp->v_cstart = 0;
598: vp->v_clen = 0;
599: vp->v_lasta = 0;
600: vp->v_lastw = 0;
601:
602: #if MACH_NBC
603: if (vp->v_type == VREG) {
604: error = mapfs_invalidate(vp);
605: #if DIAGNOSTIC
606: if (error)
607: kprintf("vinvalbuf: mapfs_invalidate(0x%x) returned %d\n", vp, error);
608: #endif
609: }
610: #endif /* MACH_NBC */
611:
612: for (;;) {
613: if ((blist = vp->v_cleanblkhd.lh_first) && flags & V_SAVEMETA)
614: while (blist && blist->b_lblkno < 0)
615: blist = blist->b_vnbufs.le_next;
616: if (!blist && (blist = vp->v_dirtyblkhd.lh_first) &&
617: (flags & V_SAVEMETA))
618: while (blist && blist->b_lblkno < 0)
619: blist = blist->b_vnbufs.le_next;
620: if (!blist)
621: break;
622:
623: for (bp = blist; bp; bp = nbp) {
624: nbp = bp->b_vnbufs.le_next;
625: if (flags & V_SAVEMETA && bp->b_lblkno < 0)
626: continue;
627: s = splbio();
628: if (bp->b_flags & B_BUSY) {
629: bp->b_flags |= B_WANTED;
630: error = tsleep((caddr_t)bp,
631: slpflag | (PRIBIO + 1), "vinvalbuf",
632: slptimeo);
633: splx(s);
634: if (error)
635: return (error);
636: break;
637: }
638: bremfree(bp);
639: bp->b_flags |= B_BUSY;
640: splx(s);
641: /*
642: * XXX Since there are no node locks for NFS, I believe
643: * there is a slight chance that a delayed write will
644: * occur while sleeping just above, so check for it.
645: */
646: if ((bp->b_flags & B_DELWRI) && (flags & V_SAVE)) {
647: (void) VOP_BWRITE(bp);
648: break;
649: }
650: bp->b_flags |= B_INVAL;
651: brelse(bp);
652: }
653: }
654: if (!(flags & V_SAVEMETA) &&
655: (vp->v_dirtyblkhd.lh_first || vp->v_cleanblkhd.lh_first))
656: panic("vinvalbuf: flush failed");
657: return (0);
658: }
659:
660: /*
661: * Associate a buffer with a vnode.
662: */
663: void
664: bgetvp(vp, bp)
665: register struct vnode *vp;
666: register struct buf *bp;
667: {
668:
669: if (bp->b_vp)
670: panic("bgetvp: not free");
671: VHOLD(vp);
672: bp->b_vp = vp;
673: if (vp->v_type == VBLK || vp->v_type == VCHR)
674: bp->b_dev = vp->v_rdev;
675: else
676: bp->b_dev = NODEV;
677: /*
678: * Insert onto list for new vnode.
679: */
680: bufinsvn(bp, &vp->v_cleanblkhd);
681: }
682:
683: /*
684: * Disassociate a buffer from a vnode.
685: */
686: void
687: brelvp(bp)
688: register struct buf *bp;
689: {
690: struct vnode *vp;
691:
692: if (bp->b_vp == (struct vnode *) 0)
693: panic("brelvp: NULL");
694: /*
695: * Delete from old vnode list, if on one.
696: */
697: if (bp->b_vnbufs.le_next != NOLIST)
698: bufremvn(bp);
699: vp = bp->b_vp;
700: bp->b_vp = (struct vnode *) 0;
701: HOLDRELE(vp);
702: }
703:
704: /*
705: * Reassign a buffer from one vnode to another.
706: * Used to assign file specific control information
707: * (indirect blocks) to the vnode to which they belong.
708: */
709: void
710: reassignbuf(bp, newvp)
711: register struct buf *bp;
712: register struct vnode *newvp;
713: {
714: register struct buflists *listheadp;
715:
716: if (newvp == NULL) {
717: printf("reassignbuf: NULL");
718: return;
719: }
720: /*
721: * Delete from old vnode list, if on one.
722: */
723: if (bp->b_vnbufs.le_next != NOLIST)
724: bufremvn(bp);
725: /*
726: * If dirty, put on list of dirty buffers;
727: * otherwise insert onto list of clean buffers.
728: */
729: if (bp->b_flags & B_DELWRI)
730: listheadp = &newvp->v_dirtyblkhd;
731: else
732: listheadp = &newvp->v_cleanblkhd;
733: bufinsvn(bp, listheadp);
734: }
735:
736: /*
737: * Create a vnode for a block device.
738: * Used for root filesystem, argdev, and swap areas.
739: * Also used for memory file system special devices.
740: */
741: int
742: bdevvp(dev, vpp)
743: dev_t dev;
744: struct vnode **vpp;
745: {
746: register struct vnode *vp;
747: struct vnode *nvp;
748: int error;
749:
750: if (dev == NODEV) {
751: *vpp = NULLVP;
752: return (ENODEV);
753: }
754: error = getnewvnode(VT_NON, (struct mount *)0, spec_vnodeop_p, &nvp);
755: if (error) {
756: *vpp = NULLVP;
757: return (error);
758: }
759: vp = nvp;
760: vp->v_type = VBLK;
761: if (nvp = checkalias(vp, dev, (struct mount *)0)) {
762: vput(vp);
763: vp = nvp;
764: }
765: *vpp = vp;
766: return (0);
767: }
768:
769: /*
770: * Check to see if the new vnode represents a special device
771: * for which we already have a vnode (either because of
772: * bdevvp() or because of a different vnode representing
773: * the same block device). If such an alias exists, deallocate
774: * the existing contents and return the aliased vnode. The
775: * caller is responsible for filling it with its new contents.
776: */
777: struct vnode *
778: checkalias(nvp, nvp_rdev, mp)
779: register struct vnode *nvp;
780: dev_t nvp_rdev;
781: struct mount *mp;
782: {
783: struct proc *p = current_proc(); /* XXX */
784: struct vnode *vp;
785: struct vnode **vpp;
786:
787: if (nvp->v_type != VBLK && nvp->v_type != VCHR)
788: return (NULLVP);
789:
790: vpp = &speclisth[SPECHASH(nvp_rdev)];
791: loop:
792: simple_lock(&spechash_slock);
793: for (vp = *vpp; vp; vp = vp->v_specnext) {
794: if (nvp_rdev != vp->v_rdev || nvp->v_type != vp->v_type)
795: continue;
796: /*
797: * Alias, but not in use, so flush it out.
798: */
799: simple_lock(&vp->v_interlock);
800: if (vp->v_usecount == 0) {
801: simple_unlock(&spechash_slock);
802: vgonel(vp, p);
803: goto loop;
804: }
805: if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
806: simple_unlock(&spechash_slock);
807: goto loop;
808: }
809: break;
810: }
811: if (vp == NULL || vp->v_tag != VT_NON) {
812: MALLOC_ZONE(nvp->v_specinfo, struct specinfo *,
813: sizeof(struct specinfo), M_VNODE, M_WAITOK);
814: bzero(nvp->v_specinfo, sizeof(struct specinfo));
815: nvp->v_rdev = nvp_rdev;
816: nvp->v_hashchain = vpp;
817: nvp->v_specnext = *vpp;
818: nvp->v_specflags = 0;
819: simple_unlock(&spechash_slock);
820: *vpp = nvp;
821: if (vp != NULLVP) {
822: nvp->v_flag |= VALIASED;
823: vp->v_flag |= VALIASED;
824: vput(vp);
825: }
826: return (NULLVP);
827: }
828: simple_unlock(&spechash_slock);
829: VOP_UNLOCK(vp, 0, p);
830: simple_lock(&vp->v_interlock);
831: vclean(vp, 0, p);
832: vp->v_op = nvp->v_op;
833: vp->v_tag = nvp->v_tag;
834: nvp->v_type = VNON;
835: insmntque(vp, mp);
836: return (vp);
837: }
838:
839: /*
840: * Grab a particular vnode from the free list, increment its
841: * reference count and lock it. The vnode lock bit is set the
842: * vnode is being eliminated in vgone. The process is awakened
843: * when the transition is completed, and an error returned to
844: * indicate that the vnode is no longer usable (possibly having
845: * been changed to a new file system type).
846: */
847: int
848: vget(vp, flags, p)
849: struct vnode *vp;
850: int flags;
851: struct proc *p;
852: {
853: int error;
854:
855: /*
856: * If the vnode is in the process of being cleaned out for
857: * another use, we wait for the cleaning to finish and then
858: * return failure. Cleaning is determined by checking that
859: * the VXLOCK flag is set.
860: */
861: if ((flags & LK_INTERLOCK) == 0)
862: simple_lock(&vp->v_interlock);
863: if (vp->v_flag & VXLOCK) {
864: vp->v_flag |= VXWANT;
865: simple_unlock(&vp->v_interlock);
866: tsleep((caddr_t)vp, PINOD, "vget", 0);
867: return (ENOENT);
868: }
869: if (vp->v_usecount == 0) {
870: simple_lock(&vnode_free_list_slock);
871: TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
872: freevnodes--;
873: simple_unlock(&vnode_free_list_slock);
874: }
875: vp->v_usecount++;
876: if (flags & LK_TYPE_MASK) {
877: if (error = vn_lock(vp, flags | LK_INTERLOCK, p))
878: vrele(vp);
879: return (error);
880: }
881: simple_unlock(&vp->v_interlock);
882: return (0);
883: }
884:
885: /*
886: * Stubs to use when there is no locking to be done on the underlying object.
887: * A minimal shared lock is necessary to ensure that the underlying object
888: * is not revoked while an operation is in progress. So, an active shared
889: * count is maintained in an auxillary vnode lock structure.
890: */
891: int
892: vop_nolock(ap)
893: struct vop_lock_args /* {
894: struct vnode *a_vp;
895: int a_flags;
896: struct proc *a_p;
897: } */ *ap;
898: {
899: #ifdef notyet
900: /*
901: * This code cannot be used until all the non-locking filesystems
902: * (notably NFS) are converted to properly lock and release nodes.
903: * Also, certain vnode operations change the locking state within
904: * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
905: * and symlink). Ideally these operations should not change the
906: * lock state, but should be changed to let the caller of the
907: * function unlock them. Otherwise all intermediate vnode layers
908: * (such as union, umapfs, etc) must catch these functions to do
909: * the necessary locking at their layer. Note that the inactive
910: * and lookup operations also change their lock state, but this
911: * cannot be avoided, so these two operations will always need
912: * to be handled in intermediate layers.
913: */
914: struct vnode *vp = ap->a_vp;
915: int vnflags, flags = ap->a_flags;
916:
917: if (vp->v_vnlock == NULL) {
918: if ((flags & LK_TYPE_MASK) == LK_DRAIN)
919: return (0);
920: MALLOC_ZONE(vp->v_vnlock, struct lock__bsd__ *,
921: sizeof(struct lock__bsd__), M_VNODE, M_WAITOK);
922: lockinit(vp->v_vnlock, PVFS, "vnlock", 0, 0);
923: }
924: switch (flags & LK_TYPE_MASK) {
925: case LK_DRAIN:
926: vnflags = LK_DRAIN;
927: break;
928: case LK_EXCLUSIVE:
929: case LK_SHARED:
930: vnflags = LK_SHARED;
931: break;
932: case LK_UPGRADE:
933: case LK_EXCLUPGRADE:
934: case LK_DOWNGRADE:
935: return (0);
936: case LK_RELEASE:
937: default:
938: panic("vop_nolock: bad operation %d", flags & LK_TYPE_MASK);
939: }
940: if (flags & LK_INTERLOCK)
941: vnflags |= LK_INTERLOCK;
942: return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock, ap->a_p));
943: #else /* for now */
944: /*
945: * Since we are not using the lock manager, we must clear
946: * the interlock here.
947: */
948: if (ap->a_flags & LK_INTERLOCK)
949: simple_unlock(&ap->a_vp->v_interlock);
950: return (0);
951: #endif
952: }
953:
954: /*
955: * Decrement the active use count.
956: */
957: int
958: vop_nounlock(ap)
959: struct vop_unlock_args /* {
960: struct vnode *a_vp;
961: int a_flags;
962: struct proc *a_p;
963: } */ *ap;
964: {
965: struct vnode *vp = ap->a_vp;
966:
967: if (vp->v_vnlock == NULL)
968: return (0);
969: return (lockmgr(vp->v_vnlock, LK_RELEASE, NULL, ap->a_p));
970: }
971:
972: /*
973: * Return whether or not the node is in use.
974: */
975: int
976: vop_noislocked(ap)
977: struct vop_islocked_args /* {
978: struct vnode *a_vp;
979: } */ *ap;
980: {
981: struct vnode *vp = ap->a_vp;
982:
983: if (vp->v_vnlock == NULL)
984: return (0);
985: return (lockstatus(vp->v_vnlock));
986: }
987:
988: /*
989: * Vnode reference.
990: */
991: void
992: vref(vp)
993: struct vnode *vp;
994: {
995:
996: simple_lock(&vp->v_interlock);
997: if (vp->v_usecount <= 0)
998: panic("vref used where vget required");
999: vp->v_usecount++;
1000: simple_unlock(&vp->v_interlock);
1001: }
1002:
1003: /*
1004: * vput(), just unlock and vrele()
1005: */
1006: void
1007: vput(vp)
1008: struct vnode *vp;
1009: {
1010: struct proc *p = current_proc(); /* XXX */
1011:
1012: #if DIGANOSTIC
1013: if (vp == NULL)
1014: panic("vput: null vp");
1015: #endif
1016: simple_lock(&vp->v_interlock);
1017: vp->v_usecount--;
1018: if (vp->v_usecount > 0) {
1019: simple_unlock(&vp->v_interlock);
1020: VOP_UNLOCK(vp, 0, p);
1021: return;
1022: }
1023: #if DIAGNOSTIC
1024: if (vp->v_usecount < 0 || vp->v_writecount != 0) {
1025: vprint("vput: bad ref count", vp);
1026: panic("vput: ref cnt");
1027: }
1028: #endif
1029: /*
1030: * insert at tail of LRU list
1031: */
1032: simple_lock(&vnode_free_list_slock);
1033: TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
1034: freevnodes++;
1035: simple_unlock(&vnode_free_list_slock);
1036: simple_unlock(&vp->v_interlock);
1037: VOP_INACTIVE(vp, p);
1038: }
1039:
1040: /*
1041: * Vnode release.
1042: * If count drops to zero, call inactive routine and return to freelist.
1043: */
1044: void
1045: vrele(vp)
1046: struct vnode *vp;
1047: {
1048: struct proc *p = current_proc(); /* XXX */
1049:
1050: #if DIAGNOSTIC
1051: if (vp == NULL)
1052: panic("vrele: null vp");
1053: #endif
1054: simple_lock(&vp->v_interlock);
1055: vp->v_usecount--;
1056: if (vp->v_usecount > 0) {
1057: simple_unlock(&vp->v_interlock);
1058: return;
1059: }
1060: #if DIAGNOSTIC
1061: if (vp->v_usecount < 0 || vp->v_writecount != 0) {
1062: vprint("vrele: bad ref count", vp);
1063: panic("vrele: ref cnt");
1064: }
1065: #endif
1066: /*
1067: * insert at tail of LRU list
1068: */
1069: simple_lock(&vnode_free_list_slock);
1070: if (vp->v_flag & VAGE) {
1071: TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
1072: vp->v_flag &= ~VAGE;
1073: } else
1074: TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
1075: freevnodes++;
1076: simple_unlock(&vnode_free_list_slock);
1077: if ((vp->v_flag & VXLOCK) == 0) {
1078: if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) == 0)
1079: VOP_INACTIVE(vp, p);
1080: #if DIAGNOSTIC
1081: else
1082: kprintf("vrele: vn_lock() failed for vp = 0x%08x\n", vp);
1083: } else {
1084: kprintf("vrele: attempted deadlock!\n");
1085: #endif
1086: simple_unlock(&vp->v_interlock);
1087: }
1088:
1089: }
1090:
1091: /*
1092: * Page or buffer structure gets a reference.
1093: */
1094: void
1095: vhold(vp)
1096: register struct vnode *vp;
1097: {
1098:
1099: simple_lock(&vp->v_interlock);
1100: vp->v_holdcnt++;
1101: simple_unlock(&vp->v_interlock);
1102: }
1103:
1104: /*
1105: * Page or buffer structure frees a reference.
1106: */
1107: void
1108: holdrele(vp)
1109: register struct vnode *vp;
1110: {
1111:
1112: simple_lock(&vp->v_interlock);
1113: if (vp->v_holdcnt <= 0)
1114: panic("holdrele: holdcnt");
1115: vp->v_holdcnt--;
1116: simple_unlock(&vp->v_interlock);
1117: }
1118:
1119: /*
1120: * Remove any vnodes in the vnode table belonging to mount point mp.
1121: *
1122: * If MNT_NOFORCE is specified, there should not be any active ones,
1123: * return error if any are found (nb: this is a user error, not a
1124: * system error). If MNT_FORCE is specified, detach any active vnodes
1125: * that are found.
1126: */
1127: #if DIAGNOSTIC
1128: int busyprt = 0; /* print out busy vnodes */
1129: struct ctldebug debug1 = { "busyprt", &busyprt };
1130: #endif
1131:
1132: int
1133: vflush(mp, skipvp, flags)
1134: struct mount *mp;
1135: struct vnode *skipvp;
1136: int flags;
1137: {
1138: struct proc *p = current_proc(); /* XXX */
1139: struct vnode *vp, *nvp;
1140: int busy = 0;
1141:
1142: simple_lock(&mntvnode_slock);
1143: loop:
1144: for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
1145: if (vp->v_mount != mp)
1146: goto loop;
1147: nvp = vp->v_mntvnodes.le_next;
1148: /*
1149: * Skip over a selected vnode.
1150: */
1151: if (vp == skipvp)
1152: continue;
1153:
1154: simple_lock(&vp->v_interlock);
1155: /*
1156: * Skip over a vnodes marked VSYSTEM.
1157: */
1158: if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) {
1159: simple_unlock(&vp->v_interlock);
1160: continue;
1161: }
1162: /*
1163: * If WRITECLOSE is set, only flush out regular file
1164: * vnodes open for writing.
1165: */
1166: if ((flags & WRITECLOSE) &&
1167: (vp->v_writecount == 0 || vp->v_type != VREG)) {
1168: simple_unlock(&vp->v_interlock);
1169: continue;
1170: }
1171: /*
1172: * With v_usecount == 0, all we need to do is clear
1173: * out the vnode data structures and we are done.
1174: */
1175: if (vp->v_usecount == 0) {
1176: simple_unlock(&mntvnode_slock);
1177: vgonel(vp, p);
1178: simple_lock(&mntvnode_slock);
1179: continue;
1180: }
1181: /*
1182: * If FORCECLOSE is set, forcibly close the vnode.
1183: * For block or character devices, revert to an
1184: * anonymous device. For all other files, just kill them.
1185: */
1186: if (flags & FORCECLOSE) {
1187: simple_unlock(&mntvnode_slock);
1188: if (vp->v_type != VBLK && vp->v_type != VCHR) {
1189: vgonel(vp, p);
1190: } else {
1191: vclean(vp, 0, p);
1192: vp->v_op = spec_vnodeop_p;
1193: insmntque(vp, (struct mount *)0);
1194: }
1195: simple_lock(&mntvnode_slock);
1196: continue;
1197: }
1198: #if DIAGNOSTIC
1199: if (busyprt)
1200: vprint("vflush: busy vnode", vp);
1201: #endif
1202: simple_unlock(&vp->v_interlock);
1203: busy++;
1204: }
1205: simple_unlock(&mntvnode_slock);
1206: if (busy)
1207: return (EBUSY);
1208: return (0);
1209: }
1210:
1211: /*
1212: * Disassociate the underlying file system from a vnode.
1213: * The vnode interlock is held on entry.
1214: */
1215: static void
1216: vclean(vp, flags, p)
1217: struct vnode *vp;
1218: int flags;
1219: struct proc *p;
1220: {
1221: int active;
1222:
1223: /*
1224: * Check to see if the vnode is in use.
1225: * If so we have to reference it before we clean it out
1226: * so that its count cannot fall to zero and generate a
1227: * race against ourselves to recycle it.
1228: */
1229: if (active = vp->v_usecount)
1230: vp->v_usecount++;
1231: /*
1232: * Prevent the vnode from being recycled or
1233: * brought into use while we clean it out.
1234: */
1235: if (vp->v_flag & VXLOCK)
1236: panic("vclean: deadlock");
1237: vp->v_flag |= VXLOCK;
1238: /*
1239: * Even if the count is zero, the VOP_INACTIVE routine may still
1240: * have the object locked while it cleans it out. The VOP_LOCK
1241: * ensures that the VOP_INACTIVE routine is done with its work.
1242: * For active vnodes, it ensures that no other activity can
1243: * occur while the underlying object is being cleaned out.
1244: */
1245: VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, p);
1246: /*
1247: * Clean out any buffers associated with the vnode.
1248: */
1249: if (flags & DOCLOSE)
1250: vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0);
1251:
1252: if ((vp->v_type == VREG) && (vp->v_vm_info != NULL))
1253: {
1254: vm_info_free(vp);
1255: vp->v_vm_info = NULL;
1256: }
1257: /*
1258: * If purging an active vnode, it must be closed and
1259: * deactivated before being reclaimed. Note that the
1260: * VOP_INACTIVE will unlock the vnode.
1261: */
1262: if (active) {
1263: if (flags & DOCLOSE)
1264: VOP_CLOSE(vp, IO_NDELAY, NOCRED, p);
1265: VOP_INACTIVE(vp, p);
1266: } else {
1267: /*
1268: * Any other processes trying to obtain this lock must first
1269: * wait for VXLOCK to clear, then call the new lock operation.
1270: */
1271: VOP_UNLOCK(vp, 0, p);
1272: }
1273: /*
1274: * Reclaim the vnode.
1275: */
1276: if (VOP_RECLAIM(vp, p))
1277: panic("vclean: cannot reclaim");
1278: if (active)
1279: vrele(vp);
1280: cache_purge(vp);
1281: if (vp->v_vnlock) {
1282: if ((vp->v_vnlock->lk_flags & LK_DRAINED) == 0)
1283: vprint("vclean: lock not drained", vp);
1284: FREE_ZONE(vp->v_vnlock, sizeof (struct lock__bsd__), M_VNODE);
1285: vp->v_vnlock = NULL;
1286: }
1287:
1288:
1289: /*
1290: * Done with purge, notify sleepers of the grim news.
1291: */
1292: vp->v_op = dead_vnodeop_p;
1293: vp->v_tag = VT_NON;
1294: vp->v_flag &= ~VXLOCK;
1295: if (vp->v_flag & VXWANT) {
1296: vp->v_flag &= ~VXWANT;
1297: wakeup((caddr_t)vp);
1298: }
1299: }
1300:
1301: /*
1302: * Eliminate all activity associated with the requested vnode
1303: * and with all vnodes aliased to the requested vnode.
1304: */
1305: int
1306: vop_revoke(ap)
1307: struct vop_revoke_args /* {
1308: struct vnode *a_vp;
1309: int a_flags;
1310: } */ *ap;
1311: {
1312: struct vnode *vp, *vq;
1313: struct proc *p = current_proc(); /* XXX */
1314:
1315: #if DIAGNOSTIC
1316: if ((ap->a_flags & REVOKEALL) == 0)
1317: panic("vop_revoke");
1318: #endif
1319:
1320: vp = ap->a_vp;
1321: simple_lock(&vp->v_interlock);
1322:
1323: if (vp->v_flag & VALIASED) {
1324: /*
1325: * If a vgone (or vclean) is already in progress,
1326: * wait until it is done and return.
1327: */
1328: if (vp->v_flag & VXLOCK) {
1329: vp->v_flag |= VXWANT;
1330: simple_unlock(&vp->v_interlock);
1331: tsleep((caddr_t)vp, PINOD, "vop_revokeall", 0);
1332: return (0);
1333: }
1334: /*
1335: * Ensure that vp will not be vgone'd while we
1336: * are eliminating its aliases.
1337: */
1338: vp->v_flag |= VXLOCK;
1339: simple_unlock(&vp->v_interlock);
1340: while (vp->v_flag & VALIASED) {
1341: simple_lock(&spechash_slock);
1342: for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
1343: if (vq->v_rdev != vp->v_rdev ||
1344: vq->v_type != vp->v_type || vp == vq)
1345: continue;
1346: simple_unlock(&spechash_slock);
1347: vgone(vq);
1348: break;
1349: }
1350: if (vq == NULLVP)
1351: simple_unlock(&spechash_slock);
1352: }
1353: /*
1354: * Remove the lock so that vgone below will
1355: * really eliminate the vnode after which time
1356: * vgone will awaken any sleepers.
1357: */
1358: simple_lock(&vp->v_interlock);
1359: vp->v_flag &= ~VXLOCK;
1360: }
1361: vgonel(vp, p);
1362: return (0);
1363: }
1364:
1365: /*
1366: * Recycle an unused vnode to the front of the free list.
1367: * Release the passed interlock if the vnode will be recycled.
1368: */
1369: int
1370: vrecycle(vp, inter_lkp, p)
1371: struct vnode *vp;
1372: struct slock *inter_lkp;
1373: struct proc *p;
1374: {
1375:
1376: simple_lock(&vp->v_interlock);
1377: if (vp->v_usecount == 0) {
1378: if (inter_lkp)
1379: simple_unlock(inter_lkp);
1380: vgonel(vp, p);
1381: return (1);
1382: }
1383: simple_unlock(&vp->v_interlock);
1384: return (0);
1385: }
1386:
1387: /*
1388: * Eliminate all activity associated with a vnode
1389: * in preparation for reuse.
1390: */
1391: void
1392: vgone(vp)
1393: struct vnode *vp;
1394: {
1395: struct proc *p = current_proc(); /* XXX */
1396:
1397: simple_lock(&vp->v_interlock);
1398: vgonel(vp, p);
1399: }
1400:
1401: /*
1402: * vgone, with the vp interlock held.
1403: */
1404: void
1405: vgonel(vp, p)
1406: struct vnode *vp;
1407: struct proc *p;
1408: {
1409: struct vnode *vq;
1410: struct vnode *vx;
1411:
1412: /*
1413: * If a vgone (or vclean) is already in progress,
1414: * wait until it is done and return.
1415: */
1416: if (vp->v_flag & VXLOCK) {
1417: vp->v_flag |= VXWANT;
1418: simple_unlock(&vp->v_interlock);
1419: tsleep((caddr_t)vp, PINOD, "vgone", 0);
1420: return;
1421: }
1422: /*
1423: * Clean out the filesystem specific data.
1424: */
1425: vclean(vp, DOCLOSE, p);
1426: /*
1427: * Delete from old mount point vnode list, if on one.
1428: */
1429: if (vp->v_mount != NULL)
1430: insmntque(vp, (struct mount *)0);
1431: /*
1432: * If special device, remove it from special device alias list
1433: * if it is on one.
1434: */
1435: if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_specinfo != 0) {
1436: simple_lock(&spechash_slock);
1437: if (*vp->v_hashchain == vp) {
1438: *vp->v_hashchain = vp->v_specnext;
1439: } else {
1440: for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
1441: if (vq->v_specnext != vp)
1442: continue;
1443: vq->v_specnext = vp->v_specnext;
1444: break;
1445: }
1446: if (vq == NULL)
1447: panic("missing bdev");
1448: }
1449: if (vp->v_flag & VALIASED) {
1450: vx = NULL;
1451: for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
1452: if (vq->v_rdev != vp->v_rdev ||
1453: vq->v_type != vp->v_type)
1454: continue;
1455: if (vx)
1456: break;
1457: vx = vq;
1458: }
1459: if (vx == NULL)
1460: panic("missing alias");
1461: if (vq == NULL)
1462: vx->v_flag &= ~VALIASED;
1463: vp->v_flag &= ~VALIASED;
1464: }
1465: simple_unlock(&spechash_slock);
1466: FREE_ZONE(vp->v_specinfo, sizeof (struct specinfo), M_VNODE);
1467: vp->v_specinfo = NULL;
1468: }
1469: /*
1470: * If it is on the freelist and not already at the head,
1471: * move it to the head of the list. The test of the back
1472: * pointer and the reference count of zero is because
1473: * it will be removed from the free list by getnewvnode,
1474: * but will not have its reference count incremented until
1475: * after calling vgone. If the reference count were
1476: * incremented first, vgone would (incorrectly) try to
1477: * close the previous instance of the underlying object.
1478: * So, the back pointer is explicitly set to `0xdeadb' in
1479: * getnewvnode after removing it from the freelist to ensure
1480: * that we do not try to move it here.
1481: */
1482: if (vp->v_usecount == 0) {
1483: simple_lock(&vnode_free_list_slock);
1484: if ((vp->v_freelist.tqe_prev != (struct vnode **)0xdeadb) &&
1485: vnode_free_list.tqh_first != vp) {
1486: TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
1487: TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
1488: }
1489: simple_unlock(&vnode_free_list_slock);
1490: }
1491: vp->v_type = VBAD;
1492: }
1493:
1494: /*
1495: * Lookup a vnode by device number.
1496: */
1497: int
1498: vfinddev(dev, type, vpp)
1499: dev_t dev;
1500: enum vtype type;
1501: struct vnode **vpp;
1502: {
1503: struct vnode *vp;
1504: int rc = 0;
1505:
1506: simple_lock(&spechash_slock);
1507: for (vp = speclisth[SPECHASH(dev)]; vp; vp = vp->v_specnext) {
1508: if (dev != vp->v_rdev || type != vp->v_type)
1509: continue;
1510: *vpp = vp;
1511: rc = 1;
1512: break;
1513: }
1514: simple_unlock(&spechash_slock);
1515: return (rc);
1516: }
1517:
1518: /*
1519: * Calculate the total number of references to a special device.
1520: */
1521: int
1522: vcount(vp)
1523: struct vnode *vp;
1524: {
1525: struct vnode *vq, *vnext;
1526: int count;
1527:
1528: loop:
1529: if ((vp->v_flag & VALIASED) == 0)
1530: return (vp->v_usecount);
1531: simple_lock(&spechash_slock);
1532: for (count = 0, vq = *vp->v_hashchain; vq; vq = vnext) {
1533: vnext = vq->v_specnext;
1534: if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type)
1535: continue;
1536: /*
1537: * Alias, but not in use, so flush it out.
1538: */
1539: if (vq->v_usecount == 0 && vq != vp) {
1540: simple_unlock(&spechash_slock);
1541: vgone(vq);
1542: goto loop;
1543: }
1544: count += vq->v_usecount;
1545: }
1546: simple_unlock(&spechash_slock);
1547: return (count);
1548: }
1549:
1550: /*
1551: * Print out a description of a vnode.
1552: */
1553: static char *typename[] =
1554: { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" };
1555:
1556: void
1557: vprint(label, vp)
1558: char *label;
1559: register struct vnode *vp;
1560: {
1561: char buf[64];
1562:
1563: if (label != NULL)
1564: printf("%s: ", label);
1565: printf("type %s, usecount %d, writecount %d, refcount %d,",
1566: typename[vp->v_type], vp->v_usecount, vp->v_writecount,
1567: vp->v_holdcnt);
1568: buf[0] = '\0';
1569: if (vp->v_flag & VROOT)
1570: strcat(buf, "|VROOT");
1571: if (vp->v_flag & VTEXT)
1572: strcat(buf, "|VTEXT");
1573: if (vp->v_flag & VSYSTEM)
1574: strcat(buf, "|VSYSTEM");
1575: if (vp->v_flag & VXLOCK)
1576: strcat(buf, "|VXLOCK");
1577: if (vp->v_flag & VXWANT)
1578: strcat(buf, "|VXWANT");
1579: if (vp->v_flag & VBWAIT)
1580: strcat(buf, "|VBWAIT");
1581: if (vp->v_flag & VALIASED)
1582: strcat(buf, "|VALIASED");
1583: if (buf[0] != '\0')
1584: printf(" flags (%s)", &buf[1]);
1585: if (vp->v_data == NULL) {
1586: printf("\n");
1587: } else {
1588: printf("\n\t");
1589: VOP_PRINT(vp);
1590: }
1591: }
1592:
1593: #ifdef DEBUG
1594: /*
1595: * List all of the locked vnodes in the system.
1596: * Called when debugging the kernel.
1597: */
1598: void
1599: printlockedvnodes()
1600: {
1601: struct proc *p = current_proc(); /* XXX */
1602: struct mount *mp, *nmp;
1603: struct vnode *vp;
1604:
1605: printf("Locked vnodes\n");
1606: simple_lock(&mountlist_slock);
1607: for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
1608: if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
1609: nmp = mp->mnt_list.cqe_next;
1610: continue;
1611: }
1612: for (vp = mp->mnt_vnodelist.lh_first;
1613: vp != NULL;
1614: vp = vp->v_mntvnodes.le_next) {
1615: if (VOP_ISLOCKED(vp))
1616: vprint((char *)0, vp);
1617: }
1618: simple_lock(&mountlist_slock);
1619: nmp = mp->mnt_list.cqe_next;
1620: vfs_unbusy(mp, p);
1621: }
1622: simple_unlock(&mountlist_slock);
1623: }
1624: #endif
1625:
1626: /*
1627: * Top level filesystem related information gathering.
1628: */
1629: int
1630: vfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
1631: int *name;
1632: u_int namelen;
1633: void *oldp;
1634: size_t *oldlenp;
1635: void *newp;
1636: size_t newlen;
1637: struct proc *p;
1638: {
1639: struct ctldebug *cdp;
1640: struct vfsconf *vfsp;
1641:
1642: #ifdef NeXT
1643: if (name[0] == VFS_NUMMNTOPS) {
1644: extern unsigned int vfs_nummntops;
1645: return (sysctl_rdint(oldp, oldlenp, newp, vfs_nummntops));
1646: }
1647: #endif
1648: /* all sysctl names at this level are at least name and field */
1649: if (namelen < 2)
1650: return (ENOTDIR); /* overloaded */
1651: if (name[0] != VFS_GENERIC) {
1652: for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
1653: if (vfsp->vfc_typenum == name[0])
1654: break;
1655: if (vfsp == NULL)
1656: return (EOPNOTSUPP);
1657: return ((*vfsp->vfc_vfsops->vfs_sysctl)(&name[1], namelen - 1,
1658: oldp, oldlenp, newp, newlen, p));
1659: }
1660: switch (name[1]) {
1661: case VFS_MAXTYPENUM:
1662: return (sysctl_rdint(oldp, oldlenp, newp, maxvfsconf));
1663: case VFS_CONF:
1664: if (namelen < 3)
1665: return (ENOTDIR); /* overloaded */
1666: for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
1667: if (vfsp->vfc_typenum == name[2])
1668: break;
1669: if (vfsp == NULL)
1670: return (EOPNOTSUPP);
1671: return (sysctl_rdstruct(oldp, oldlenp, newp, vfsp,
1672: sizeof(struct vfsconf)));
1673: }
1674: return (EOPNOTSUPP);
1675: }
1676:
1677: int kinfo_vdebug = 1;
1678: int kinfo_vgetfailed;
1679: #define KINFO_VNODESLOP 10
1680: /*
1681: * Dump vnode list (via sysctl).
1682: * Copyout address of vnode followed by vnode.
1683: */
1684: /* ARGSUSED */
1685: int
1686: sysctl_vnode(where, sizep, p)
1687: char *where;
1688: size_t *sizep;
1689: struct proc *p;
1690: {
1691: struct mount *mp, *nmp;
1692: struct vnode *nvp, *vp;
1693: char *bp = where, *savebp;
1694: char *ewhere;
1695: int error;
1696:
1697: #define VPTRSZ sizeof (struct vnode *)
1698: #define VNODESZ sizeof (struct vnode)
1699: if (where == NULL) {
1700: *sizep = (numvnodes + KINFO_VNODESLOP) * (VPTRSZ + VNODESZ);
1701: return (0);
1702: }
1703: ewhere = where + *sizep;
1704:
1705: simple_lock(&mountlist_slock);
1706: for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
1707: if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
1708: nmp = mp->mnt_list.cqe_next;
1709: continue;
1710: }
1711: savebp = bp;
1712: again:
1713: simple_lock(&mntvnode_slock);
1714: for (vp = mp->mnt_vnodelist.lh_first;
1715: vp != NULL;
1716: vp = nvp) {
1717: /*
1718: * Check that the vp is still associated with
1719: * this filesystem. RACE: could have been
1720: * recycled onto the same filesystem.
1721: */
1722: if (vp->v_mount != mp) {
1723: simple_unlock(&mntvnode_slock);
1724: if (kinfo_vdebug)
1725: printf("kinfo: vp changed\n");
1726: bp = savebp;
1727: goto again;
1728: }
1729: nvp = vp->v_mntvnodes.le_next;
1730: if (bp + VPTRSZ + VNODESZ > ewhere) {
1731: simple_unlock(&mntvnode_slock);
1732: *sizep = bp - where;
1733: return (ENOMEM);
1734: }
1735: simple_unlock(&mntvnode_slock);
1736: if ((error = copyout((caddr_t)&vp, bp, VPTRSZ)) ||
1737: (error = copyout((caddr_t)vp, bp + VPTRSZ, VNODESZ)))
1738: return (error);
1739: bp += VPTRSZ + VNODESZ;
1740: simple_lock(&mntvnode_slock);
1741: }
1742: simple_unlock(&mntvnode_slock);
1743: simple_lock(&mountlist_slock);
1744: nmp = mp->mnt_list.cqe_next;
1745: vfs_unbusy(mp, p);
1746: }
1747: simple_unlock(&mountlist_slock);
1748:
1749: *sizep = bp - where;
1750: return (0);
1751: }
1752:
1753: /*
1754: * Check to see if a filesystem is mounted on a block device.
1755: */
1756: int
1757: vfs_mountedon(vp)
1758: struct vnode *vp;
1759: {
1760: struct vnode *vq;
1761: int error = 0;
1762:
1763: if (vp->v_specflags & SI_MOUNTEDON)
1764: return (EBUSY);
1765: if (vp->v_flag & VALIASED) {
1766: simple_lock(&spechash_slock);
1767: for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
1768: if (vq->v_rdev != vp->v_rdev ||
1769: vq->v_type != vp->v_type)
1770: continue;
1771: if (vq->v_specflags & SI_MOUNTEDON) {
1772: error = EBUSY;
1773: break;
1774: }
1775: }
1776: simple_unlock(&spechash_slock);
1777: }
1778: return (error);
1779: }
1780:
1781: /*
1782: * Unmount all filesystems. The list is traversed in reverse order
1783: * of mounting to avoid dependencies.
1784: */
1785: void
1786: vfs_unmountall()
1787: {
1788: struct mount *mp, *nmp;
1789: struct proc *p = current_proc(); /* XXX */
1790:
1791: /*
1792: * Since this only runs when rebooting, it is not interlocked.
1793: */
1794: for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
1795: nmp = mp->mnt_list.cqe_prev;
1796: (void) dounmount(mp, MNT_FORCE, p);
1797: }
1798: }
1799:
1800: /*
1801: * Build hash lists of net addresses and hang them off the mount point.
1802: * Called by ufs_mount() to set up the lists of export addresses.
1803: */
1804: static int
1805: vfs_hang_addrlist(mp, nep, argp)
1806: struct mount *mp;
1807: struct netexport *nep;
1808: struct export_args *argp;
1809: {
1810: register struct netcred *np;
1811: register struct radix_node_head *rnh;
1812: register int i;
1813: struct radix_node *rn;
1814: struct sockaddr *saddr, *smask = 0;
1815: struct domain *dom;
1816: int error;
1817:
1818: if (argp->ex_addrlen == 0) {
1819: if (mp->mnt_flag & MNT_DEFEXPORTED)
1820: return (EPERM);
1821: np = &nep->ne_defexported;
1822: np->netc_exflags = argp->ex_flags;
1823: np->netc_anon = argp->ex_anon;
1824: np->netc_anon.cr_ref = 1;
1825: mp->mnt_flag |= MNT_DEFEXPORTED;
1826: return (0);
1827: }
1828: i = sizeof(struct netcred) + argp->ex_addrlen + argp->ex_masklen;
1829: MALLOC(np, struct netcred *, i, M_NETADDR, M_WAITOK);
1830: bzero((caddr_t)np, i);
1831: saddr = (struct sockaddr *)(np + 1);
1832: if (error = copyin(argp->ex_addr, (caddr_t)saddr, argp->ex_addrlen))
1833: goto out;
1834: if (saddr->sa_len > argp->ex_addrlen)
1835: saddr->sa_len = argp->ex_addrlen;
1836: if (argp->ex_masklen) {
1837: smask = (struct sockaddr *)((caddr_t)saddr + argp->ex_addrlen);
1838: error = copyin(argp->ex_addr, (caddr_t)smask, argp->ex_masklen);
1839: if (error)
1840: goto out;
1841: if (smask->sa_len > argp->ex_masklen)
1842: smask->sa_len = argp->ex_masklen;
1843: }
1844: i = saddr->sa_family;
1845: if ((rnh = nep->ne_rtable[i]) == 0) {
1846: /*
1847: * Seems silly to initialize every AF when most are not
1848: * used, do so on demand here
1849: */
1850: for (dom = domains; dom; dom = dom->dom_next)
1851: if (dom->dom_family == i && dom->dom_rtattach) {
1852: dom->dom_rtattach((void **)&nep->ne_rtable[i],
1853: dom->dom_rtoffset);
1854: break;
1855: }
1856: if ((rnh = nep->ne_rtable[i]) == 0) {
1857: error = ENOBUFS;
1858: goto out;
1859: }
1860: }
1861: rn = (*rnh->rnh_addaddr)((caddr_t)saddr, (caddr_t)smask, rnh,
1862: np->netc_rnodes);
1863: if (rn == 0) {
1864: /*
1865: * One of the reasons that rnh_addaddr may fail is that
1866: * the entry already exists. To check for this case, we
1867: * look up the entry to see if it is there. If so, we
1868: * do not need to make a new entry but do return success.
1869: */
1870: _FREE(np, M_NETADDR);
1871: rn = (*rnh->rnh_matchaddr)((caddr_t)saddr, rnh);
1872: if (rn != 0 && (rn->rn_flags & RNF_ROOT) == 0 &&
1873: ((struct netcred *)rn)->netc_exflags == argp->ex_flags &&
1874: !bcmp((caddr_t)&((struct netcred *)rn)->netc_anon,
1875: (caddr_t)&argp->ex_anon, sizeof(struct ucred)))
1876: return (0);
1877: return (EPERM);
1878: }
1879: np->netc_exflags = argp->ex_flags;
1880: np->netc_anon = argp->ex_anon;
1881: np->netc_anon.cr_ref = 1;
1882: return (0);
1883: out:
1884: _FREE(np, M_NETADDR);
1885: return (error);
1886: }
1887:
1888: /* ARGSUSED */
1889: static int
1890: vfs_free_netcred(rn, w)
1891: struct radix_node *rn;
1892: caddr_t w;
1893: {
1894: register struct radix_node_head *rnh = (struct radix_node_head *)w;
1895:
1896: (*rnh->rnh_deladdr)(rn->rn_key, rn->rn_mask, rnh);
1897: _FREE((caddr_t)rn, M_NETADDR);
1898: return (0);
1899: }
1900:
1901: /*
1902: * Free the net address hash lists that are hanging off the mount points.
1903: */
1904: static void
1905: vfs_free_addrlist(nep)
1906: struct netexport *nep;
1907: {
1908: register int i;
1909: register struct radix_node_head *rnh;
1910:
1911: for (i = 0; i <= AF_MAX; i++)
1912: if (rnh = nep->ne_rtable[i]) {
1913: (*rnh->rnh_walktree)(rnh, vfs_free_netcred,
1914: (caddr_t)rnh);
1915: _FREE((caddr_t)rnh, M_RTABLE);
1916: nep->ne_rtable[i] = 0;
1917: }
1918: }
1919:
1920: int
1921: vfs_export(mp, nep, argp)
1922: struct mount *mp;
1923: struct netexport *nep;
1924: struct export_args *argp;
1925: {
1926: int error;
1927:
1928: if (argp->ex_flags & MNT_DELEXPORT) {
1929: vfs_free_addrlist(nep);
1930: mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED);
1931: }
1932: if (argp->ex_flags & MNT_EXPORTED) {
1933: if (error = vfs_hang_addrlist(mp, nep, argp))
1934: return (error);
1935: mp->mnt_flag |= MNT_EXPORTED;
1936: }
1937: return (0);
1938: }
1939:
1940: struct netcred *
1941: vfs_export_lookup(mp, nep, nam)
1942: register struct mount *mp;
1943: struct netexport *nep;
1944: struct mbuf *nam;
1945: {
1946: register struct netcred *np;
1947: register struct radix_node_head *rnh;
1948: struct sockaddr *saddr;
1949:
1950: np = NULL;
1951: if (mp->mnt_flag & MNT_EXPORTED) {
1952: /*
1953: * Lookup in the export list first.
1954: */
1955: if (nam != NULL) {
1956: saddr = mtod(nam, struct sockaddr *);
1957: rnh = nep->ne_rtable[saddr->sa_family];
1958: if (rnh != NULL) {
1959: np = (struct netcred *)
1960: (*rnh->rnh_matchaddr)((caddr_t)saddr,
1961: rnh);
1962: if (np && np->netc_rnodes->rn_flags & RNF_ROOT)
1963: np = NULL;
1964: }
1965: }
1966: /*
1967: * If no address match, use the default if it exists.
1968: */
1969: if (np == NULL && mp->mnt_flag & MNT_DEFEXPORTED)
1970: np = &nep->ne_defexported;
1971: }
1972: return (np);
1973: }
1974:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.