|
|
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: }
1.1.1.2 ! root 875: if (++vp->v_usecount <= 0)
! 876: panic("vget: v_usecount");
1.1 root 877: if (flags & LK_TYPE_MASK) {
878: if (error = vn_lock(vp, flags | LK_INTERLOCK, p))
879: vrele(vp);
880: return (error);
881: }
882: simple_unlock(&vp->v_interlock);
883: return (0);
884: }
885:
886: /*
887: * Stubs to use when there is no locking to be done on the underlying object.
888: * A minimal shared lock is necessary to ensure that the underlying object
889: * is not revoked while an operation is in progress. So, an active shared
890: * count is maintained in an auxillary vnode lock structure.
891: */
892: int
893: vop_nolock(ap)
894: struct vop_lock_args /* {
895: struct vnode *a_vp;
896: int a_flags;
897: struct proc *a_p;
898: } */ *ap;
899: {
900: #ifdef notyet
901: /*
902: * This code cannot be used until all the non-locking filesystems
903: * (notably NFS) are converted to properly lock and release nodes.
904: * Also, certain vnode operations change the locking state within
905: * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
906: * and symlink). Ideally these operations should not change the
907: * lock state, but should be changed to let the caller of the
908: * function unlock them. Otherwise all intermediate vnode layers
909: * (such as union, umapfs, etc) must catch these functions to do
910: * the necessary locking at their layer. Note that the inactive
911: * and lookup operations also change their lock state, but this
912: * cannot be avoided, so these two operations will always need
913: * to be handled in intermediate layers.
914: */
915: struct vnode *vp = ap->a_vp;
916: int vnflags, flags = ap->a_flags;
917:
918: if (vp->v_vnlock == NULL) {
919: if ((flags & LK_TYPE_MASK) == LK_DRAIN)
920: return (0);
921: MALLOC_ZONE(vp->v_vnlock, struct lock__bsd__ *,
922: sizeof(struct lock__bsd__), M_VNODE, M_WAITOK);
923: lockinit(vp->v_vnlock, PVFS, "vnlock", 0, 0);
924: }
925: switch (flags & LK_TYPE_MASK) {
926: case LK_DRAIN:
927: vnflags = LK_DRAIN;
928: break;
929: case LK_EXCLUSIVE:
930: case LK_SHARED:
931: vnflags = LK_SHARED;
932: break;
933: case LK_UPGRADE:
934: case LK_EXCLUPGRADE:
935: case LK_DOWNGRADE:
936: return (0);
937: case LK_RELEASE:
938: default:
939: panic("vop_nolock: bad operation %d", flags & LK_TYPE_MASK);
940: }
941: if (flags & LK_INTERLOCK)
942: vnflags |= LK_INTERLOCK;
943: return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock, ap->a_p));
944: #else /* for now */
945: /*
946: * Since we are not using the lock manager, we must clear
947: * the interlock here.
948: */
949: if (ap->a_flags & LK_INTERLOCK)
950: simple_unlock(&ap->a_vp->v_interlock);
951: return (0);
952: #endif
953: }
954:
955: /*
956: * Decrement the active use count.
957: */
958: int
959: vop_nounlock(ap)
960: struct vop_unlock_args /* {
961: struct vnode *a_vp;
962: int a_flags;
963: struct proc *a_p;
964: } */ *ap;
965: {
966: struct vnode *vp = ap->a_vp;
967:
968: if (vp->v_vnlock == NULL)
969: return (0);
970: return (lockmgr(vp->v_vnlock, LK_RELEASE, NULL, ap->a_p));
971: }
972:
973: /*
974: * Return whether or not the node is in use.
975: */
976: int
977: vop_noislocked(ap)
978: struct vop_islocked_args /* {
979: struct vnode *a_vp;
980: } */ *ap;
981: {
982: struct vnode *vp = ap->a_vp;
983:
984: if (vp->v_vnlock == NULL)
985: return (0);
986: return (lockstatus(vp->v_vnlock));
987: }
988:
989: /*
990: * Vnode reference.
991: */
992: void
993: vref(vp)
994: struct vnode *vp;
995: {
996: simple_lock(&vp->v_interlock);
997: if (vp->v_usecount <= 0)
998: panic("vref used where vget required");
1.1.1.2 ! root 999: if (++vp->v_usecount <= 0)
! 1000: panic("vref v_usecount");
1.1 root 1001: simple_unlock(&vp->v_interlock);
1002: }
1003:
1004: /*
1005: * vput(), just unlock and vrele()
1006: */
1007: void
1008: vput(vp)
1009: struct vnode *vp;
1010: {
1011: struct proc *p = current_proc(); /* XXX */
1012:
1.1.1.2 ! root 1013: #if DIAGNOSTIC
1.1 root 1014: if (vp == NULL)
1015: panic("vput: null vp");
1016: #endif
1017: simple_lock(&vp->v_interlock);
1018: vp->v_usecount--;
1019: if (vp->v_usecount > 0) {
1020: simple_unlock(&vp->v_interlock);
1021: VOP_UNLOCK(vp, 0, p);
1022: return;
1023: }
1024: #if DIAGNOSTIC
1025: if (vp->v_usecount < 0 || vp->v_writecount != 0) {
1026: vprint("vput: bad ref count", vp);
1027: panic("vput: ref cnt");
1028: }
1029: #endif
1030: /*
1031: * insert at tail of LRU list
1032: */
1033: simple_lock(&vnode_free_list_slock);
1034: TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
1035: freevnodes++;
1036: simple_unlock(&vnode_free_list_slock);
1037: simple_unlock(&vp->v_interlock);
1038: VOP_INACTIVE(vp, p);
1039: }
1040:
1041: /*
1042: * Vnode release.
1043: * If count drops to zero, call inactive routine and return to freelist.
1044: */
1045: void
1046: vrele(vp)
1047: struct vnode *vp;
1048: {
1049: struct proc *p = current_proc(); /* XXX */
1050:
1051: #if DIAGNOSTIC
1052: if (vp == NULL)
1053: panic("vrele: null vp");
1054: #endif
1055: simple_lock(&vp->v_interlock);
1056: vp->v_usecount--;
1057: if (vp->v_usecount > 0) {
1058: simple_unlock(&vp->v_interlock);
1059: return;
1060: }
1061: #if DIAGNOSTIC
1062: if (vp->v_usecount < 0 || vp->v_writecount != 0) {
1063: vprint("vrele: bad ref count", vp);
1064: panic("vrele: ref cnt");
1065: }
1066: #endif
1067: /*
1068: * insert at tail of LRU list
1069: */
1070: simple_lock(&vnode_free_list_slock);
1071: if (vp->v_flag & VAGE) {
1072: TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
1073: vp->v_flag &= ~VAGE;
1074: } else
1075: TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
1076: freevnodes++;
1077: simple_unlock(&vnode_free_list_slock);
1078: if ((vp->v_flag & VXLOCK) == 0) {
1079: if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) == 0)
1080: VOP_INACTIVE(vp, p);
1081: #if DIAGNOSTIC
1082: else
1083: kprintf("vrele: vn_lock() failed for vp = 0x%08x\n", vp);
1084: } else {
1085: kprintf("vrele: attempted deadlock!\n");
1086: #endif
1087: simple_unlock(&vp->v_interlock);
1088: }
1089:
1090: }
1091:
1092: /*
1093: * Page or buffer structure gets a reference.
1094: */
1095: void
1096: vhold(vp)
1097: register struct vnode *vp;
1098: {
1099:
1100: simple_lock(&vp->v_interlock);
1101: vp->v_holdcnt++;
1102: simple_unlock(&vp->v_interlock);
1103: }
1104:
1105: /*
1106: * Page or buffer structure frees a reference.
1107: */
1108: void
1109: holdrele(vp)
1110: register struct vnode *vp;
1111: {
1112:
1113: simple_lock(&vp->v_interlock);
1114: if (vp->v_holdcnt <= 0)
1115: panic("holdrele: holdcnt");
1116: vp->v_holdcnt--;
1117: simple_unlock(&vp->v_interlock);
1118: }
1119:
1120: /*
1121: * Remove any vnodes in the vnode table belonging to mount point mp.
1122: *
1123: * If MNT_NOFORCE is specified, there should not be any active ones,
1124: * return error if any are found (nb: this is a user error, not a
1125: * system error). If MNT_FORCE is specified, detach any active vnodes
1126: * that are found.
1127: */
1128: #if DIAGNOSTIC
1129: int busyprt = 0; /* print out busy vnodes */
1130: struct ctldebug debug1 = { "busyprt", &busyprt };
1131: #endif
1132:
1133: int
1134: vflush(mp, skipvp, flags)
1135: struct mount *mp;
1136: struct vnode *skipvp;
1137: int flags;
1138: {
1139: struct proc *p = current_proc(); /* XXX */
1140: struct vnode *vp, *nvp;
1141: int busy = 0;
1142:
1143: simple_lock(&mntvnode_slock);
1144: loop:
1145: for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
1146: if (vp->v_mount != mp)
1147: goto loop;
1148: nvp = vp->v_mntvnodes.le_next;
1149: /*
1150: * Skip over a selected vnode.
1151: */
1152: if (vp == skipvp)
1153: continue;
1154:
1155: simple_lock(&vp->v_interlock);
1156: /*
1157: * Skip over a vnodes marked VSYSTEM.
1158: */
1159: if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) {
1160: simple_unlock(&vp->v_interlock);
1161: continue;
1162: }
1163: /*
1164: * If WRITECLOSE is set, only flush out regular file
1165: * vnodes open for writing.
1166: */
1167: if ((flags & WRITECLOSE) &&
1168: (vp->v_writecount == 0 || vp->v_type != VREG)) {
1169: simple_unlock(&vp->v_interlock);
1170: continue;
1171: }
1172: /*
1173: * With v_usecount == 0, all we need to do is clear
1174: * out the vnode data structures and we are done.
1175: */
1176: if (vp->v_usecount == 0) {
1177: simple_unlock(&mntvnode_slock);
1178: vgonel(vp, p);
1179: simple_lock(&mntvnode_slock);
1180: continue;
1181: }
1182: /*
1183: * If FORCECLOSE is set, forcibly close the vnode.
1184: * For block or character devices, revert to an
1185: * anonymous device. For all other files, just kill them.
1186: */
1187: if (flags & FORCECLOSE) {
1188: simple_unlock(&mntvnode_slock);
1189: if (vp->v_type != VBLK && vp->v_type != VCHR) {
1190: vgonel(vp, p);
1191: } else {
1192: vclean(vp, 0, p);
1193: vp->v_op = spec_vnodeop_p;
1194: insmntque(vp, (struct mount *)0);
1195: }
1196: simple_lock(&mntvnode_slock);
1197: continue;
1198: }
1199: #if DIAGNOSTIC
1200: if (busyprt)
1201: vprint("vflush: busy vnode", vp);
1202: #endif
1203: simple_unlock(&vp->v_interlock);
1204: busy++;
1205: }
1206: simple_unlock(&mntvnode_slock);
1207: if (busy)
1208: return (EBUSY);
1209: return (0);
1210: }
1211:
1212: /*
1213: * Disassociate the underlying file system from a vnode.
1214: * The vnode interlock is held on entry.
1215: */
1216: static void
1217: vclean(vp, flags, p)
1218: struct vnode *vp;
1219: int flags;
1220: struct proc *p;
1221: {
1222: int active;
1223:
1224: /*
1225: * Check to see if the vnode is in use.
1226: * If so we have to reference it before we clean it out
1227: * so that its count cannot fall to zero and generate a
1228: * race against ourselves to recycle it.
1229: */
1230: if (active = vp->v_usecount)
1.1.1.2 ! root 1231: if (++vp->v_usecount <= 0)
! 1232: panic("vclean: v_usecount");
1.1 root 1233: /*
1234: * Prevent the vnode from being recycled or
1235: * brought into use while we clean it out.
1236: */
1237: if (vp->v_flag & VXLOCK)
1238: panic("vclean: deadlock");
1239: vp->v_flag |= VXLOCK;
1240: /*
1241: * Even if the count is zero, the VOP_INACTIVE routine may still
1242: * have the object locked while it cleans it out. The VOP_LOCK
1243: * ensures that the VOP_INACTIVE routine is done with its work.
1244: * For active vnodes, it ensures that no other activity can
1245: * occur while the underlying object is being cleaned out.
1246: */
1247: VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, p);
1248: /*
1249: * Clean out any buffers associated with the vnode.
1250: */
1251: if (flags & DOCLOSE)
1252: vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0);
1253:
1254: if ((vp->v_type == VREG) && (vp->v_vm_info != NULL))
1255: {
1256: vm_info_free(vp);
1257: vp->v_vm_info = NULL;
1258: }
1259: /*
1260: * If purging an active vnode, it must be closed and
1261: * deactivated before being reclaimed. Note that the
1262: * VOP_INACTIVE will unlock the vnode.
1263: */
1264: if (active) {
1265: if (flags & DOCLOSE)
1266: VOP_CLOSE(vp, IO_NDELAY, NOCRED, p);
1267: VOP_INACTIVE(vp, p);
1268: } else {
1269: /*
1270: * Any other processes trying to obtain this lock must first
1271: * wait for VXLOCK to clear, then call the new lock operation.
1272: */
1273: VOP_UNLOCK(vp, 0, p);
1274: }
1275: /*
1276: * Reclaim the vnode.
1277: */
1278: if (VOP_RECLAIM(vp, p))
1279: panic("vclean: cannot reclaim");
1280: if (active)
1281: vrele(vp);
1282: cache_purge(vp);
1283: if (vp->v_vnlock) {
1284: if ((vp->v_vnlock->lk_flags & LK_DRAINED) == 0)
1285: vprint("vclean: lock not drained", vp);
1286: FREE_ZONE(vp->v_vnlock, sizeof (struct lock__bsd__), M_VNODE);
1287: vp->v_vnlock = NULL;
1288: }
1289:
1290:
1291: /*
1292: * Done with purge, notify sleepers of the grim news.
1293: */
1294: vp->v_op = dead_vnodeop_p;
1295: vp->v_tag = VT_NON;
1296: vp->v_flag &= ~VXLOCK;
1297: if (vp->v_flag & VXWANT) {
1298: vp->v_flag &= ~VXWANT;
1299: wakeup((caddr_t)vp);
1300: }
1301: }
1302:
1303: /*
1304: * Eliminate all activity associated with the requested vnode
1305: * and with all vnodes aliased to the requested vnode.
1306: */
1307: int
1308: vop_revoke(ap)
1309: struct vop_revoke_args /* {
1310: struct vnode *a_vp;
1311: int a_flags;
1312: } */ *ap;
1313: {
1314: struct vnode *vp, *vq;
1315: struct proc *p = current_proc(); /* XXX */
1316:
1317: #if DIAGNOSTIC
1318: if ((ap->a_flags & REVOKEALL) == 0)
1319: panic("vop_revoke");
1320: #endif
1321:
1322: vp = ap->a_vp;
1323: simple_lock(&vp->v_interlock);
1324:
1325: if (vp->v_flag & VALIASED) {
1326: /*
1327: * If a vgone (or vclean) is already in progress,
1328: * wait until it is done and return.
1329: */
1330: if (vp->v_flag & VXLOCK) {
1331: vp->v_flag |= VXWANT;
1332: simple_unlock(&vp->v_interlock);
1333: tsleep((caddr_t)vp, PINOD, "vop_revokeall", 0);
1334: return (0);
1335: }
1336: /*
1337: * Ensure that vp will not be vgone'd while we
1338: * are eliminating its aliases.
1339: */
1340: vp->v_flag |= VXLOCK;
1341: simple_unlock(&vp->v_interlock);
1342: while (vp->v_flag & VALIASED) {
1343: simple_lock(&spechash_slock);
1344: for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
1345: if (vq->v_rdev != vp->v_rdev ||
1346: vq->v_type != vp->v_type || vp == vq)
1347: continue;
1348: simple_unlock(&spechash_slock);
1349: vgone(vq);
1350: break;
1351: }
1352: if (vq == NULLVP)
1353: simple_unlock(&spechash_slock);
1354: }
1355: /*
1356: * Remove the lock so that vgone below will
1357: * really eliminate the vnode after which time
1358: * vgone will awaken any sleepers.
1359: */
1360: simple_lock(&vp->v_interlock);
1361: vp->v_flag &= ~VXLOCK;
1362: }
1363: vgonel(vp, p);
1364: return (0);
1365: }
1366:
1367: /*
1368: * Recycle an unused vnode to the front of the free list.
1369: * Release the passed interlock if the vnode will be recycled.
1370: */
1371: int
1372: vrecycle(vp, inter_lkp, p)
1373: struct vnode *vp;
1374: struct slock *inter_lkp;
1375: struct proc *p;
1376: {
1377:
1378: simple_lock(&vp->v_interlock);
1379: if (vp->v_usecount == 0) {
1380: if (inter_lkp)
1381: simple_unlock(inter_lkp);
1382: vgonel(vp, p);
1383: return (1);
1384: }
1385: simple_unlock(&vp->v_interlock);
1386: return (0);
1387: }
1388:
1389: /*
1390: * Eliminate all activity associated with a vnode
1391: * in preparation for reuse.
1392: */
1393: void
1394: vgone(vp)
1395: struct vnode *vp;
1396: {
1397: struct proc *p = current_proc(); /* XXX */
1398:
1399: simple_lock(&vp->v_interlock);
1400: vgonel(vp, p);
1401: }
1402:
1403: /*
1404: * vgone, with the vp interlock held.
1405: */
1406: void
1407: vgonel(vp, p)
1408: struct vnode *vp;
1409: struct proc *p;
1410: {
1411: struct vnode *vq;
1412: struct vnode *vx;
1413:
1414: /*
1415: * If a vgone (or vclean) is already in progress,
1416: * wait until it is done and return.
1417: */
1418: if (vp->v_flag & VXLOCK) {
1419: vp->v_flag |= VXWANT;
1420: simple_unlock(&vp->v_interlock);
1421: tsleep((caddr_t)vp, PINOD, "vgone", 0);
1422: return;
1423: }
1424: /*
1425: * Clean out the filesystem specific data.
1426: */
1427: vclean(vp, DOCLOSE, p);
1428: /*
1429: * Delete from old mount point vnode list, if on one.
1430: */
1431: if (vp->v_mount != NULL)
1432: insmntque(vp, (struct mount *)0);
1433: /*
1434: * If special device, remove it from special device alias list
1435: * if it is on one.
1436: */
1437: if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_specinfo != 0) {
1438: simple_lock(&spechash_slock);
1439: if (*vp->v_hashchain == vp) {
1440: *vp->v_hashchain = vp->v_specnext;
1441: } else {
1442: for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
1443: if (vq->v_specnext != vp)
1444: continue;
1445: vq->v_specnext = vp->v_specnext;
1446: break;
1447: }
1448: if (vq == NULL)
1449: panic("missing bdev");
1450: }
1451: if (vp->v_flag & VALIASED) {
1452: vx = NULL;
1453: for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
1454: if (vq->v_rdev != vp->v_rdev ||
1455: vq->v_type != vp->v_type)
1456: continue;
1457: if (vx)
1458: break;
1459: vx = vq;
1460: }
1461: if (vx == NULL)
1462: panic("missing alias");
1463: if (vq == NULL)
1464: vx->v_flag &= ~VALIASED;
1465: vp->v_flag &= ~VALIASED;
1466: }
1467: simple_unlock(&spechash_slock);
1468: FREE_ZONE(vp->v_specinfo, sizeof (struct specinfo), M_VNODE);
1469: vp->v_specinfo = NULL;
1470: }
1471: /*
1472: * If it is on the freelist and not already at the head,
1473: * move it to the head of the list. The test of the back
1474: * pointer and the reference count of zero is because
1475: * it will be removed from the free list by getnewvnode,
1476: * but will not have its reference count incremented until
1477: * after calling vgone. If the reference count were
1478: * incremented first, vgone would (incorrectly) try to
1479: * close the previous instance of the underlying object.
1480: * So, the back pointer is explicitly set to `0xdeadb' in
1481: * getnewvnode after removing it from the freelist to ensure
1482: * that we do not try to move it here.
1483: */
1484: if (vp->v_usecount == 0) {
1485: simple_lock(&vnode_free_list_slock);
1486: if ((vp->v_freelist.tqe_prev != (struct vnode **)0xdeadb) &&
1487: vnode_free_list.tqh_first != vp) {
1488: TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
1489: TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
1490: }
1491: simple_unlock(&vnode_free_list_slock);
1492: }
1493: vp->v_type = VBAD;
1494: }
1495:
1496: /*
1497: * Lookup a vnode by device number.
1498: */
1499: int
1500: vfinddev(dev, type, vpp)
1501: dev_t dev;
1502: enum vtype type;
1503: struct vnode **vpp;
1504: {
1505: struct vnode *vp;
1506: int rc = 0;
1507:
1508: simple_lock(&spechash_slock);
1509: for (vp = speclisth[SPECHASH(dev)]; vp; vp = vp->v_specnext) {
1510: if (dev != vp->v_rdev || type != vp->v_type)
1511: continue;
1512: *vpp = vp;
1513: rc = 1;
1514: break;
1515: }
1516: simple_unlock(&spechash_slock);
1517: return (rc);
1518: }
1519:
1520: /*
1521: * Calculate the total number of references to a special device.
1522: */
1523: int
1524: vcount(vp)
1525: struct vnode *vp;
1526: {
1527: struct vnode *vq, *vnext;
1528: int count;
1529:
1530: loop:
1531: if ((vp->v_flag & VALIASED) == 0)
1532: return (vp->v_usecount);
1533: simple_lock(&spechash_slock);
1534: for (count = 0, vq = *vp->v_hashchain; vq; vq = vnext) {
1535: vnext = vq->v_specnext;
1536: if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type)
1537: continue;
1538: /*
1539: * Alias, but not in use, so flush it out.
1540: */
1541: if (vq->v_usecount == 0 && vq != vp) {
1542: simple_unlock(&spechash_slock);
1543: vgone(vq);
1544: goto loop;
1545: }
1546: count += vq->v_usecount;
1547: }
1548: simple_unlock(&spechash_slock);
1549: return (count);
1550: }
1551:
1552: /*
1553: * Print out a description of a vnode.
1554: */
1555: static char *typename[] =
1556: { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" };
1557:
1558: void
1559: vprint(label, vp)
1560: char *label;
1561: register struct vnode *vp;
1562: {
1563: char buf[64];
1564:
1565: if (label != NULL)
1566: printf("%s: ", label);
1567: printf("type %s, usecount %d, writecount %d, refcount %d,",
1568: typename[vp->v_type], vp->v_usecount, vp->v_writecount,
1569: vp->v_holdcnt);
1570: buf[0] = '\0';
1571: if (vp->v_flag & VROOT)
1572: strcat(buf, "|VROOT");
1573: if (vp->v_flag & VTEXT)
1574: strcat(buf, "|VTEXT");
1575: if (vp->v_flag & VSYSTEM)
1576: strcat(buf, "|VSYSTEM");
1577: if (vp->v_flag & VXLOCK)
1578: strcat(buf, "|VXLOCK");
1579: if (vp->v_flag & VXWANT)
1580: strcat(buf, "|VXWANT");
1581: if (vp->v_flag & VBWAIT)
1582: strcat(buf, "|VBWAIT");
1583: if (vp->v_flag & VALIASED)
1584: strcat(buf, "|VALIASED");
1585: if (buf[0] != '\0')
1586: printf(" flags (%s)", &buf[1]);
1587: if (vp->v_data == NULL) {
1588: printf("\n");
1589: } else {
1590: printf("\n\t");
1591: VOP_PRINT(vp);
1592: }
1593: }
1594:
1595: #ifdef DEBUG
1596: /*
1597: * List all of the locked vnodes in the system.
1598: * Called when debugging the kernel.
1599: */
1600: void
1601: printlockedvnodes()
1602: {
1603: struct proc *p = current_proc(); /* XXX */
1604: struct mount *mp, *nmp;
1605: struct vnode *vp;
1606:
1607: printf("Locked vnodes\n");
1608: simple_lock(&mountlist_slock);
1609: for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
1610: if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
1611: nmp = mp->mnt_list.cqe_next;
1612: continue;
1613: }
1614: for (vp = mp->mnt_vnodelist.lh_first;
1615: vp != NULL;
1616: vp = vp->v_mntvnodes.le_next) {
1617: if (VOP_ISLOCKED(vp))
1618: vprint((char *)0, vp);
1619: }
1620: simple_lock(&mountlist_slock);
1621: nmp = mp->mnt_list.cqe_next;
1622: vfs_unbusy(mp, p);
1623: }
1624: simple_unlock(&mountlist_slock);
1625: }
1626: #endif
1627:
1628: /*
1629: * Top level filesystem related information gathering.
1630: */
1631: int
1632: vfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
1633: int *name;
1634: u_int namelen;
1635: void *oldp;
1636: size_t *oldlenp;
1637: void *newp;
1638: size_t newlen;
1639: struct proc *p;
1640: {
1641: struct ctldebug *cdp;
1642: struct vfsconf *vfsp;
1643:
1644: #ifdef NeXT
1645: if (name[0] == VFS_NUMMNTOPS) {
1646: extern unsigned int vfs_nummntops;
1647: return (sysctl_rdint(oldp, oldlenp, newp, vfs_nummntops));
1648: }
1649: #endif
1650: /* all sysctl names at this level are at least name and field */
1651: if (namelen < 2)
1652: return (ENOTDIR); /* overloaded */
1653: if (name[0] != VFS_GENERIC) {
1654: for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
1655: if (vfsp->vfc_typenum == name[0])
1656: break;
1657: if (vfsp == NULL)
1658: return (EOPNOTSUPP);
1659: return ((*vfsp->vfc_vfsops->vfs_sysctl)(&name[1], namelen - 1,
1660: oldp, oldlenp, newp, newlen, p));
1661: }
1662: switch (name[1]) {
1663: case VFS_MAXTYPENUM:
1664: return (sysctl_rdint(oldp, oldlenp, newp, maxvfsconf));
1665: case VFS_CONF:
1666: if (namelen < 3)
1667: return (ENOTDIR); /* overloaded */
1668: for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
1669: if (vfsp->vfc_typenum == name[2])
1670: break;
1671: if (vfsp == NULL)
1672: return (EOPNOTSUPP);
1673: return (sysctl_rdstruct(oldp, oldlenp, newp, vfsp,
1674: sizeof(struct vfsconf)));
1675: }
1676: return (EOPNOTSUPP);
1677: }
1678:
1679: int kinfo_vdebug = 1;
1680: int kinfo_vgetfailed;
1681: #define KINFO_VNODESLOP 10
1682: /*
1683: * Dump vnode list (via sysctl).
1684: * Copyout address of vnode followed by vnode.
1685: */
1686: /* ARGSUSED */
1687: int
1688: sysctl_vnode(where, sizep, p)
1689: char *where;
1690: size_t *sizep;
1691: struct proc *p;
1692: {
1693: struct mount *mp, *nmp;
1694: struct vnode *nvp, *vp;
1695: char *bp = where, *savebp;
1696: char *ewhere;
1697: int error;
1698:
1699: #define VPTRSZ sizeof (struct vnode *)
1700: #define VNODESZ sizeof (struct vnode)
1701: if (where == NULL) {
1702: *sizep = (numvnodes + KINFO_VNODESLOP) * (VPTRSZ + VNODESZ);
1703: return (0);
1704: }
1705: ewhere = where + *sizep;
1706:
1707: simple_lock(&mountlist_slock);
1708: for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
1709: if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
1710: nmp = mp->mnt_list.cqe_next;
1711: continue;
1712: }
1713: savebp = bp;
1714: again:
1715: simple_lock(&mntvnode_slock);
1716: for (vp = mp->mnt_vnodelist.lh_first;
1717: vp != NULL;
1718: vp = nvp) {
1719: /*
1720: * Check that the vp is still associated with
1721: * this filesystem. RACE: could have been
1722: * recycled onto the same filesystem.
1723: */
1724: if (vp->v_mount != mp) {
1725: simple_unlock(&mntvnode_slock);
1726: if (kinfo_vdebug)
1727: printf("kinfo: vp changed\n");
1728: bp = savebp;
1729: goto again;
1730: }
1731: nvp = vp->v_mntvnodes.le_next;
1732: if (bp + VPTRSZ + VNODESZ > ewhere) {
1733: simple_unlock(&mntvnode_slock);
1734: *sizep = bp - where;
1735: return (ENOMEM);
1736: }
1737: simple_unlock(&mntvnode_slock);
1738: if ((error = copyout((caddr_t)&vp, bp, VPTRSZ)) ||
1739: (error = copyout((caddr_t)vp, bp + VPTRSZ, VNODESZ)))
1740: return (error);
1741: bp += VPTRSZ + VNODESZ;
1742: simple_lock(&mntvnode_slock);
1743: }
1744: simple_unlock(&mntvnode_slock);
1745: simple_lock(&mountlist_slock);
1746: nmp = mp->mnt_list.cqe_next;
1747: vfs_unbusy(mp, p);
1748: }
1749: simple_unlock(&mountlist_slock);
1750:
1751: *sizep = bp - where;
1752: return (0);
1753: }
1754:
1755: /*
1756: * Check to see if a filesystem is mounted on a block device.
1757: */
1758: int
1759: vfs_mountedon(vp)
1760: struct vnode *vp;
1761: {
1762: struct vnode *vq;
1763: int error = 0;
1764:
1765: if (vp->v_specflags & SI_MOUNTEDON)
1766: return (EBUSY);
1767: if (vp->v_flag & VALIASED) {
1768: simple_lock(&spechash_slock);
1769: for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
1770: if (vq->v_rdev != vp->v_rdev ||
1771: vq->v_type != vp->v_type)
1772: continue;
1773: if (vq->v_specflags & SI_MOUNTEDON) {
1774: error = EBUSY;
1775: break;
1776: }
1777: }
1778: simple_unlock(&spechash_slock);
1779: }
1780: return (error);
1781: }
1782:
1783: /*
1784: * Unmount all filesystems. The list is traversed in reverse order
1785: * of mounting to avoid dependencies.
1786: */
1787: void
1788: vfs_unmountall()
1789: {
1790: struct mount *mp, *nmp;
1791: struct proc *p = current_proc(); /* XXX */
1792:
1793: /*
1794: * Since this only runs when rebooting, it is not interlocked.
1795: */
1796: for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
1797: nmp = mp->mnt_list.cqe_prev;
1798: (void) dounmount(mp, MNT_FORCE, p);
1799: }
1800: }
1801:
1802: /*
1803: * Build hash lists of net addresses and hang them off the mount point.
1804: * Called by ufs_mount() to set up the lists of export addresses.
1805: */
1806: static int
1807: vfs_hang_addrlist(mp, nep, argp)
1808: struct mount *mp;
1809: struct netexport *nep;
1810: struct export_args *argp;
1811: {
1812: register struct netcred *np;
1813: register struct radix_node_head *rnh;
1814: register int i;
1815: struct radix_node *rn;
1816: struct sockaddr *saddr, *smask = 0;
1817: struct domain *dom;
1818: int error;
1819:
1820: if (argp->ex_addrlen == 0) {
1821: if (mp->mnt_flag & MNT_DEFEXPORTED)
1822: return (EPERM);
1823: np = &nep->ne_defexported;
1824: np->netc_exflags = argp->ex_flags;
1825: np->netc_anon = argp->ex_anon;
1826: np->netc_anon.cr_ref = 1;
1827: mp->mnt_flag |= MNT_DEFEXPORTED;
1828: return (0);
1829: }
1830: i = sizeof(struct netcred) + argp->ex_addrlen + argp->ex_masklen;
1831: MALLOC(np, struct netcred *, i, M_NETADDR, M_WAITOK);
1832: bzero((caddr_t)np, i);
1833: saddr = (struct sockaddr *)(np + 1);
1834: if (error = copyin(argp->ex_addr, (caddr_t)saddr, argp->ex_addrlen))
1835: goto out;
1836: if (saddr->sa_len > argp->ex_addrlen)
1837: saddr->sa_len = argp->ex_addrlen;
1838: if (argp->ex_masklen) {
1839: smask = (struct sockaddr *)((caddr_t)saddr + argp->ex_addrlen);
1840: error = copyin(argp->ex_addr, (caddr_t)smask, argp->ex_masklen);
1841: if (error)
1842: goto out;
1843: if (smask->sa_len > argp->ex_masklen)
1844: smask->sa_len = argp->ex_masklen;
1845: }
1846: i = saddr->sa_family;
1847: if ((rnh = nep->ne_rtable[i]) == 0) {
1848: /*
1849: * Seems silly to initialize every AF when most are not
1850: * used, do so on demand here
1851: */
1852: for (dom = domains; dom; dom = dom->dom_next)
1853: if (dom->dom_family == i && dom->dom_rtattach) {
1854: dom->dom_rtattach((void **)&nep->ne_rtable[i],
1855: dom->dom_rtoffset);
1856: break;
1857: }
1858: if ((rnh = nep->ne_rtable[i]) == 0) {
1859: error = ENOBUFS;
1860: goto out;
1861: }
1862: }
1863: rn = (*rnh->rnh_addaddr)((caddr_t)saddr, (caddr_t)smask, rnh,
1864: np->netc_rnodes);
1865: if (rn == 0) {
1866: /*
1867: * One of the reasons that rnh_addaddr may fail is that
1868: * the entry already exists. To check for this case, we
1869: * look up the entry to see if it is there. If so, we
1870: * do not need to make a new entry but do return success.
1871: */
1872: _FREE(np, M_NETADDR);
1873: rn = (*rnh->rnh_matchaddr)((caddr_t)saddr, rnh);
1874: if (rn != 0 && (rn->rn_flags & RNF_ROOT) == 0 &&
1875: ((struct netcred *)rn)->netc_exflags == argp->ex_flags &&
1876: !bcmp((caddr_t)&((struct netcred *)rn)->netc_anon,
1877: (caddr_t)&argp->ex_anon, sizeof(struct ucred)))
1878: return (0);
1879: return (EPERM);
1880: }
1881: np->netc_exflags = argp->ex_flags;
1882: np->netc_anon = argp->ex_anon;
1883: np->netc_anon.cr_ref = 1;
1884: return (0);
1885: out:
1886: _FREE(np, M_NETADDR);
1887: return (error);
1888: }
1889:
1890: /* ARGSUSED */
1891: static int
1892: vfs_free_netcred(rn, w)
1893: struct radix_node *rn;
1894: caddr_t w;
1895: {
1896: register struct radix_node_head *rnh = (struct radix_node_head *)w;
1897:
1898: (*rnh->rnh_deladdr)(rn->rn_key, rn->rn_mask, rnh);
1899: _FREE((caddr_t)rn, M_NETADDR);
1900: return (0);
1901: }
1902:
1903: /*
1904: * Free the net address hash lists that are hanging off the mount points.
1905: */
1906: static void
1907: vfs_free_addrlist(nep)
1908: struct netexport *nep;
1909: {
1910: register int i;
1911: register struct radix_node_head *rnh;
1912:
1913: for (i = 0; i <= AF_MAX; i++)
1914: if (rnh = nep->ne_rtable[i]) {
1915: (*rnh->rnh_walktree)(rnh, vfs_free_netcred,
1916: (caddr_t)rnh);
1917: _FREE((caddr_t)rnh, M_RTABLE);
1918: nep->ne_rtable[i] = 0;
1919: }
1920: }
1921:
1922: int
1923: vfs_export(mp, nep, argp)
1924: struct mount *mp;
1925: struct netexport *nep;
1926: struct export_args *argp;
1927: {
1928: int error;
1929:
1930: if (argp->ex_flags & MNT_DELEXPORT) {
1931: vfs_free_addrlist(nep);
1932: mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED);
1933: }
1934: if (argp->ex_flags & MNT_EXPORTED) {
1935: if (error = vfs_hang_addrlist(mp, nep, argp))
1936: return (error);
1937: mp->mnt_flag |= MNT_EXPORTED;
1938: }
1939: return (0);
1940: }
1941:
1942: struct netcred *
1943: vfs_export_lookup(mp, nep, nam)
1944: register struct mount *mp;
1945: struct netexport *nep;
1946: struct mbuf *nam;
1947: {
1948: register struct netcred *np;
1949: register struct radix_node_head *rnh;
1950: struct sockaddr *saddr;
1951:
1952: np = NULL;
1953: if (mp->mnt_flag & MNT_EXPORTED) {
1954: /*
1955: * Lookup in the export list first.
1956: */
1957: if (nam != NULL) {
1958: saddr = mtod(nam, struct sockaddr *);
1959: rnh = nep->ne_rtable[saddr->sa_family];
1960: if (rnh != NULL) {
1961: np = (struct netcred *)
1962: (*rnh->rnh_matchaddr)((caddr_t)saddr,
1963: rnh);
1964: if (np && np->netc_rnodes->rn_flags & RNF_ROOT)
1965: np = NULL;
1966: }
1967: }
1968: /*
1969: * If no address match, use the default if it exists.
1970: */
1971: if (np == NULL && mp->mnt_flag & MNT_DEFEXPORTED)
1972: np = &nep->ne_defexported;
1973: }
1974: return (np);
1975: }
1976:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.