|
|
1.1 root 1: /*
2: * Copyright (c) 1989, 1991 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)ufs_vfsops.c 7.56 (Berkeley) 6/28/91
34: */
35:
36: #include "param.h"
37: #include "systm.h"
38: #include "namei.h"
39: #include "proc.h"
40: #include "kernel.h"
41: #include "vnode.h"
42: #include "specdev.h"
43: #include "mount.h"
44: #include "buf.h"
45: #include "file.h"
46: #include "disklabel.h"
47: #include "ioctl.h"
48: #include "errno.h"
49: #include "malloc.h"
50:
51: #include "quota.h"
52: #include "fs.h"
53: #include "ufsmount.h"
54: #include "inode.h"
55:
56: struct vfsops ufs_vfsops = {
57: ufs_mount,
58: ufs_start,
59: ufs_unmount,
60: ufs_root,
61: ufs_quotactl,
62: ufs_statfs,
63: ufs_sync,
64: ufs_fhtovp,
65: ufs_vptofh,
66: ufs_init
67: };
68:
69: /*
70: * Flag to allow forcible unmounting.
71: */
72: int doforce = 1;
73:
74: /*
75: * Called by vfs_mountroot when ufs is going to be mounted as root.
76: *
77: * Name is updated by mount(8) after booting.
78: */
79: #define ROOTNAME "root_device"
80:
81: ufs_mountroot()
82: {
83: register struct mount *mp;
84: extern struct vnode *rootvp;
85: struct proc *p = curproc; /* XXX */
86: struct ufsmount *ump;
87: register struct fs *fs;
88: u_int size;
89: int error;
90:
91: mp = (struct mount *)malloc((u_long)sizeof(struct mount),
92: M_MOUNT, M_WAITOK);
93: mp->mnt_op = &ufs_vfsops;
94: mp->mnt_flag = MNT_RDONLY;
95: mp->mnt_exroot = 0;
96: mp->mnt_mounth = NULLVP;
97: error = mountfs(rootvp, mp, p);
98: if (error) {
99: free((caddr_t)mp, M_MOUNT);
100: return (error);
101: }
102: if (error = vfs_lock(mp)) {
103: (void)ufs_unmount(mp, 0, p);
104: free((caddr_t)mp, M_MOUNT);
105: return (error);
106: }
107: rootfs = mp;
108: mp->mnt_next = mp;
109: mp->mnt_prev = mp;
110: mp->mnt_vnodecovered = NULLVP;
111: ump = VFSTOUFS(mp);
112: fs = ump->um_fs;
113: bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
114: fs->fs_fsmnt[0] = '/';
115: bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
116: MNAMELEN);
117: (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
118: &size);
119: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
120: (void) ufs_statfs(mp, &mp->mnt_stat, p);
121: vfs_unlock(mp);
122: inittodr(fs->fs_time);
123: return (0);
124: }
125:
126: /*
127: * VFS Operations.
128: *
129: * mount system call
130: */
131: ufs_mount(mp, path, data, ndp, p)
132: register struct mount *mp;
133: char *path;
134: caddr_t data;
135: struct nameidata *ndp;
136: struct proc *p;
137: {
138: struct vnode *devvp;
139: struct ufs_args args;
140: struct ufsmount *ump;
141: register struct fs *fs;
142: u_int size;
143: int error;
144:
145: if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
146: return (error);
147: /*
148: * Process export requests.
149: */
150: if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) {
151: if (args.exflags & MNT_EXPORTED)
152: mp->mnt_flag |= MNT_EXPORTED;
153: else
154: mp->mnt_flag &= ~MNT_EXPORTED;
155: if (args.exflags & MNT_EXRDONLY)
156: mp->mnt_flag |= MNT_EXRDONLY;
157: else
158: mp->mnt_flag &= ~MNT_EXRDONLY;
159: mp->mnt_exroot = args.exroot;
160: }
161: /*
162: * If updating, check whether changing from read-only to
163: * read/write; if there is no device name, that's all we do.
164: */
165: if (mp->mnt_flag & MNT_UPDATE) {
166: ump = VFSTOUFS(mp);
167: fs = ump->um_fs;
168: if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
169: fs->fs_ronly = 0;
170: if (args.fspec == 0)
171: return (0);
172: }
173: /*
174: * Not an update, or updating the name: look up the name
175: * and verify that it refers to a sensible block device.
176: */
177: ndp->ni_nameiop = LOOKUP | FOLLOW;
178: ndp->ni_segflg = UIO_USERSPACE;
179: ndp->ni_dirp = args.fspec;
180: if (error = namei(ndp, p))
181: return (error);
182: devvp = ndp->ni_vp;
183: if (devvp->v_type != VBLK) {
184: vrele(devvp);
185: return (ENOTBLK);
186: }
187: if (major(devvp->v_rdev) >= nblkdev) {
188: vrele(devvp);
189: return (ENXIO);
190: }
191: if ((mp->mnt_flag & MNT_UPDATE) == 0)
192: error = mountfs(devvp, mp, p);
193: else {
194: if (devvp != ump->um_devvp)
195: error = EINVAL; /* needs translation */
196: else
197: vrele(devvp);
198: }
199: if (error) {
200: vrele(devvp);
201: return (error);
202: }
203: ump = VFSTOUFS(mp);
204: fs = ump->um_fs;
205: (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
206: bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
207: bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
208: MNAMELEN);
209: (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
210: &size);
211: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
212: (void) ufs_statfs(mp, &mp->mnt_stat, p);
213: return (0);
214: }
215:
216: /*
217: * Common code for mount and mountroot
218: */
219: mountfs(devvp, mp, p)
220: register struct vnode *devvp;
221: struct mount *mp;
222: struct proc *p;
223: {
224: register struct ufsmount *ump = (struct ufsmount *)0;
225: struct buf *bp = NULL;
226: register struct fs *fs;
227: dev_t dev = devvp->v_rdev;
228: struct partinfo dpart;
229: caddr_t base, space;
230: int havepart = 0, blks;
231: int error, i, size;
232: int needclose = 0;
233: int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
234: extern struct vnode *rootvp;
235:
236: /*
237: * Disallow multiple mounts of the same device.
238: * Disallow mounting of a device that is currently in use
239: * (except for root, which might share swap device for miniroot).
240: * Flush out any old buffers remaining from a previous use.
241: */
242: if (error = mountedon(devvp))
243: return (error);
244: if (vcount(devvp) > 1 && devvp != rootvp)
245: return (EBUSY);
246: vinvalbuf(devvp, 1);
247: if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p))
248: return (error);
249: needclose = 1;
250: if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
251: size = DEV_BSIZE;
252: else {
253: havepart = 1;
254: size = dpart.disklab->d_secsize;
255: }
256: if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp))
257: goto out;
258: fs = bp->b_un.b_fs;
259: if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
260: fs->fs_bsize < sizeof(struct fs)) {
261: error = EINVAL; /* XXX needs translation */
262: goto out;
263: }
264: ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
265: ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK,
266: M_WAITOK);
267: bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs,
268: (u_int)fs->fs_sbsize);
269: if (fs->fs_sbsize < SBSIZE)
270: bp->b_flags |= B_INVAL;
271: brelse(bp);
272: bp = NULL;
273: fs = ump->um_fs;
274: fs->fs_ronly = ronly;
275: if (ronly == 0)
276: fs->fs_fmod = 1;
277: if (havepart) {
278: dpart.part->p_fstype = FS_BSDFFS;
279: dpart.part->p_fsize = fs->fs_fsize;
280: dpart.part->p_frag = fs->fs_frag;
281: dpart.part->p_cpg = fs->fs_cpg;
282: }
283: blks = howmany(fs->fs_cssize, fs->fs_fsize);
284: base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK,
285: M_WAITOK);
286: for (i = 0; i < blks; i += fs->fs_frag) {
287: size = fs->fs_bsize;
288: if (i + fs->fs_frag > blks)
289: size = (blks - i) * fs->fs_fsize;
290: error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
291: NOCRED, &bp);
292: if (error) {
293: free((caddr_t)base, M_SUPERBLK);
294: goto out;
295: }
296: bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size);
297: fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
298: space += size;
299: brelse(bp);
300: bp = NULL;
301: }
302: mp->mnt_data = (qaddr_t)ump;
303: mp->mnt_stat.f_fsid.val[0] = (long)dev;
304: mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS;
305: mp->mnt_flag |= MNT_LOCAL;
306: ump->um_mountp = mp;
307: ump->um_dev = dev;
308: ump->um_devvp = devvp;
309: for (i = 0; i < MAXQUOTAS; i++)
310: ump->um_quotas[i] = NULLVP;
311: devvp->v_specflags |= SI_MOUNTEDON;
312:
313: /* Sanity checks for old file systems. XXX */
314: fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */
315: fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */
316: if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
317: fs->fs_nrpos = 8; /* XXX */
318: return (0);
319: out:
320: if (bp)
321: brelse(bp);
322: if (needclose)
323: (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
324: if (ump) {
325: free((caddr_t)ump->um_fs, M_SUPERBLK);
326: free((caddr_t)ump, M_UFSMNT);
327: mp->mnt_data = (qaddr_t)0;
328: }
329: return (error);
330: }
331:
332: /*
333: * Make a filesystem operational.
334: * Nothing to do at the moment.
335: */
336: /* ARGSUSED */
337: ufs_start(mp, flags, p)
338: struct mount *mp;
339: int flags;
340: struct proc *p;
341: {
342:
343: return (0);
344: }
345:
346: /*
347: * unmount system call
348: */
349: ufs_unmount(mp, mntflags, p)
350: struct mount *mp;
351: int mntflags;
352: struct proc *p;
353: {
354: register struct ufsmount *ump;
355: register struct fs *fs;
356: int i, error, ronly, flags = 0;
357:
358: if (mntflags & MNT_FORCE) {
359: if (!doforce || mp == rootfs)
360: return (EINVAL);
361: flags |= FORCECLOSE;
362: }
363: mntflushbuf(mp, 0);
364: if (mntinvalbuf(mp))
365: return (EBUSY);
366: ump = VFSTOUFS(mp);
367: #ifdef QUOTA
368: if (mp->mnt_flag & MNT_QUOTA) {
369: if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
370: return (error);
371: for (i = 0; i < MAXQUOTAS; i++) {
372: if (ump->um_quotas[i] == NULLVP)
373: continue;
374: quotaoff(p, mp, i);
375: }
376: /*
377: * Here we fall through to vflush again to ensure
378: * that we have gotten rid of all the system vnodes.
379: */
380: }
381: #endif
382: if (error = vflush(mp, NULLVP, flags))
383: return (error);
384: fs = ump->um_fs;
385: ronly = !fs->fs_ronly;
386: ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
387: error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
388: NOCRED, p);
389: vrele(ump->um_devvp);
390: free((caddr_t)fs->fs_csp[0], M_SUPERBLK);
391: free((caddr_t)fs, M_SUPERBLK);
392: free((caddr_t)ump, M_UFSMNT);
393: mp->mnt_data = (qaddr_t)0;
394: mp->mnt_flag &= ~MNT_LOCAL;
395: return (error);
396: }
397:
398: /*
399: * Check to see if a filesystem is mounted on a block device.
400: */
401: mountedon(vp)
402: register struct vnode *vp;
403: {
404: register struct vnode *vq;
405:
406: if (vp->v_specflags & SI_MOUNTEDON)
407: return (EBUSY);
408: if (vp->v_flag & VALIASED) {
409: for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
410: if (vq->v_rdev != vp->v_rdev ||
411: vq->v_type != vp->v_type)
412: continue;
413: if (vq->v_specflags & SI_MOUNTEDON)
414: return (EBUSY);
415: }
416: }
417: return (0);
418: }
419:
420: /*
421: * Return root of a filesystem
422: */
423: ufs_root(mp, vpp)
424: struct mount *mp;
425: struct vnode **vpp;
426: {
427: register struct inode *ip;
428: struct inode *nip;
429: struct vnode tvp;
430: int error;
431:
432: tvp.v_mount = mp;
433: ip = VTOI(&tvp);
434: ip->i_vnode = &tvp;
435: ip->i_dev = VFSTOUFS(mp)->um_dev;
436: error = iget(ip, (ino_t)ROOTINO, &nip);
437: if (error)
438: return (error);
439: *vpp = ITOV(nip);
440: return (0);
441: }
442:
443: /*
444: * Do operations associated with quotas
445: */
446: ufs_quotactl(mp, cmds, uid, arg, p)
447: struct mount *mp;
448: int cmds;
449: uid_t uid;
450: caddr_t arg;
451: struct proc *p;
452: {
453: struct ufsmount *ump = VFSTOUFS(mp);
454: int cmd, type, error;
455:
456: #ifndef QUOTA
457: return (EOPNOTSUPP);
458: #else
459: if (uid == -1)
460: uid = p->p_cred->p_ruid;
461: cmd = cmds >> SUBCMDSHIFT;
462:
463: switch (cmd) {
464: case Q_GETQUOTA:
465: case Q_SYNC:
466: if (uid == p->p_cred->p_ruid)
467: break;
468: /* fall through */
469: default:
470: if (error = suser(p->p_ucred, &p->p_acflag))
471: return (error);
472: }
473:
474: type = cmd & SUBCMDMASK;
475: if ((u_int)type >= MAXQUOTAS)
476: return (EINVAL);
477:
478: switch (cmd) {
479:
480: case Q_QUOTAON:
481: return (quotaon(p, mp, type, arg));
482:
483: case Q_QUOTAOFF:
484: if (vfs_busy(mp))
485: return (0);
486: error = quotaoff(p, mp, type);
487: vfs_unbusy(mp);
488: return (error);
489:
490: case Q_SETQUOTA:
491: return (setquota(mp, uid, type, arg));
492:
493: case Q_SETUSE:
494: return (setuse(mp, uid, type, arg));
495:
496: case Q_GETQUOTA:
497: return (getquota(mp, uid, type, arg));
498:
499: case Q_SYNC:
500: if (vfs_busy(mp))
501: return (0);
502: error = qsync(mp);
503: vfs_unbusy(mp);
504: return (error);
505:
506: default:
507: return (EINVAL);
508: }
509: /* NOTREACHED */
510: #endif
511: }
512:
513: /*
514: * Get file system statistics.
515: */
516: ufs_statfs(mp, sbp, p)
517: struct mount *mp;
518: register struct statfs *sbp;
519: struct proc *p;
520: {
521: register struct ufsmount *ump;
522: register struct fs *fs;
523:
524: ump = VFSTOUFS(mp);
525: fs = ump->um_fs;
526: if (fs->fs_magic != FS_MAGIC)
527: panic("ufs_statfs");
528: sbp->f_type = MOUNT_UFS;
529: sbp->f_fsize = fs->fs_fsize;
530: sbp->f_bsize = fs->fs_bsize;
531: sbp->f_blocks = fs->fs_dsize;
532: sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
533: fs->fs_cstotal.cs_nffree;
534: sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
535: (fs->fs_dsize - sbp->f_bfree);
536: sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
537: sbp->f_ffree = fs->fs_cstotal.cs_nifree;
538: if (sbp != &mp->mnt_stat) {
539: bcopy((caddr_t)mp->mnt_stat.f_mntonname,
540: (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
541: bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
542: (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
543: }
544: return (0);
545: }
546:
547: int syncprt = 0;
548:
549: /*
550: * Go through the disk queues to initiate sandbagged IO;
551: * go through the inodes to write those that have been modified;
552: * initiate the writing of the super block if it has been modified.
553: *
554: * Note: we are always called with the filesystem marked `MPBUSY'.
555: */
556: ufs_sync(mp, waitfor)
557: struct mount *mp;
558: int waitfor;
559: {
560: register struct vnode *vp;
561: register struct inode *ip;
562: register struct ufsmount *ump = VFSTOUFS(mp);
563: register struct fs *fs;
564: int error, allerror = 0;
565:
566: if (syncprt)
567: bufstats();
568: fs = ump->um_fs;
569: /*
570: * Write back modified superblock.
571: * Consistency check that the superblock
572: * is still in the buffer cache.
573: */
574: if (fs->fs_fmod != 0) {
575: if (fs->fs_ronly != 0) { /* XXX */
576: printf("fs = %s\n", fs->fs_fsmnt);
577: panic("update: rofs mod");
578: }
579: fs->fs_fmod = 0;
580: fs->fs_time = time.tv_sec;
581: allerror = sbupdate(ump, waitfor);
582: }
583: /*
584: * Write back each (modified) inode.
585: */
586: loop:
587: for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) {
588: /*
589: * If the vnode that we are about to sync is no longer
590: * associated with this mount point, start over.
591: */
592: if (vp->v_mount != mp)
593: goto loop;
594: if (VOP_ISLOCKED(vp))
595: continue;
596: ip = VTOI(vp);
597: if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 &&
598: vp->v_dirtyblkhd == NULL)
599: continue;
600: if (vget(vp))
601: goto loop;
602: if (vp->v_dirtyblkhd)
603: vflushbuf(vp, 0);
604: if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) &&
605: (error = iupdat(ip, &time, &time, 0)))
606: allerror = error;
607: vput(vp);
608: }
609: /*
610: * Force stale file system control information to be flushed.
611: */
612: vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0);
613: #ifdef QUOTA
614: qsync(mp);
615: #endif
616: return (allerror);
617: }
618:
619: /*
620: * Write a superblock and associated information back to disk.
621: */
622: sbupdate(mp, waitfor)
623: struct ufsmount *mp;
624: int waitfor;
625: {
626: register struct fs *fs = mp->um_fs;
627: register struct buf *bp;
628: int blks;
629: caddr_t space;
630: int i, size, error = 0;
631:
632: bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize);
633: bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize);
634: /* Restore compatibility to old file systems. XXX */
635: if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
636: bp->b_un.b_fs->fs_nrpos = -1; /* XXX */
637: if (waitfor == MNT_WAIT)
638: error = bwrite(bp);
639: else
640: bawrite(bp);
641: blks = howmany(fs->fs_cssize, fs->fs_fsize);
642: space = (caddr_t)fs->fs_csp[0];
643: for (i = 0; i < blks; i += fs->fs_frag) {
644: size = fs->fs_bsize;
645: if (i + fs->fs_frag > blks)
646: size = (blks - i) * fs->fs_fsize;
647: bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size);
648: bcopy(space, bp->b_un.b_addr, (u_int)size);
649: space += size;
650: if (waitfor == MNT_WAIT)
651: error = bwrite(bp);
652: else
653: bawrite(bp);
654: }
655: return (error);
656: }
657:
658: /*
659: * Print out statistics on the current allocation of the buffer pool.
660: * Can be enabled to print out on every ``sync'' by setting "syncprt"
661: * above.
662: */
663: bufstats()
664: {
665: int s, i, j, count;
666: register struct buf *bp, *dp;
667: int counts[MAXBSIZE/CLBYTES+1];
668: static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
669:
670: for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) {
671: count = 0;
672: for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
673: counts[j] = 0;
674: s = splbio();
675: for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) {
676: counts[dp->b_bufsize/CLBYTES]++;
677: count++;
678: }
679: splx(s);
680: printf("%s: total-%d", bname[i], count);
681: for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
682: if (counts[j] != 0)
683: printf(", %d-%d", j * CLBYTES, counts[j]);
684: printf("\n");
685: }
686: }
687:
688: /*
689: * File handle to vnode
690: *
691: * Have to be really careful about stale file handles:
692: * - check that the inode number is in range
693: * - call iget() to get the locked inode
694: * - check for an unallocated inode (i_mode == 0)
695: * - check that the generation number matches
696: */
697: ufs_fhtovp(mp, fhp, vpp)
698: register struct mount *mp;
699: struct fid *fhp;
700: struct vnode **vpp;
701: {
702: register struct ufid *ufhp;
703: register struct fs *fs;
704: register struct inode *ip;
705: struct inode *nip;
706: struct vnode tvp;
707: int error;
708:
709: ufhp = (struct ufid *)fhp;
710: fs = VFSTOUFS(mp)->um_fs;
711: if (ufhp->ufid_ino < ROOTINO ||
712: ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) {
713: *vpp = NULLVP;
714: return (EINVAL);
715: }
716: tvp.v_mount = mp;
717: ip = VTOI(&tvp);
718: ip->i_vnode = &tvp;
719: ip->i_dev = VFSTOUFS(mp)->um_dev;
720: if (error = iget(ip, ufhp->ufid_ino, &nip)) {
721: *vpp = NULLVP;
722: return (error);
723: }
724: ip = nip;
725: if (ip->i_mode == 0) {
726: iput(ip);
727: *vpp = NULLVP;
728: return (EINVAL);
729: }
730: if (ip->i_gen != ufhp->ufid_gen) {
731: iput(ip);
732: *vpp = NULLVP;
733: return (EINVAL);
734: }
735: *vpp = ITOV(ip);
736: return (0);
737: }
738:
739: /*
740: * Vnode pointer to File handle
741: */
742: /* ARGSUSED */
743: ufs_vptofh(vp, fhp)
744: struct vnode *vp;
745: struct fid *fhp;
746: {
747: register struct inode *ip = VTOI(vp);
748: register struct ufid *ufhp;
749:
750: ufhp = (struct ufid *)fhp;
751: ufhp->ufid_len = sizeof(struct ufid);
752: ufhp->ufid_ino = ip->i_number;
753: ufhp->ufid_gen = ip->i_gen;
754: return (0);
755: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.