123400Smckusick /* 237737Smckusick * Copyright (c) 1989 The Regents of the University of California. 337737Smckusick * All rights reserved. 423400Smckusick * 537737Smckusick * Redistribution and use in source and binary forms are permitted 637737Smckusick * provided that the above copyright notice and this paragraph are 737737Smckusick * duplicated in all such forms and that any documentation, 837737Smckusick * advertising materials, and other materials related to such 937737Smckusick * distribution and use acknowledge that the software was developed 1037737Smckusick * by the University of California, Berkeley. The name of the 1137737Smckusick * University may not be used to endorse or promote products derived 1237737Smckusick * from this software without specific prior written permission. 1337737Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437737Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537737Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637737Smckusick * 17*39336Smckusick * @(#)ffs_vfsops.c 7.22 (Berkeley) 10/19/89 1823400Smckusick */ 1912795Ssam 2017100Sbloom #include "param.h" 2117100Sbloom #include "systm.h" 2237737Smckusick #include "time.h" 2337737Smckusick #include "kernel.h" 2437737Smckusick #include "namei.h" 2537737Smckusick #include "vnode.h" 2637737Smckusick #include "mount.h" 2717100Sbloom #include "buf.h" 2838776Smckusick #include "ucred.h" 2917100Sbloom #include "file.h" 3037737Smckusick #include "disklabel.h" 3130749Skarels #include "ioctl.h" 3237737Smckusick #include "errno.h" 3331660Smckusick #include "malloc.h" 3437737Smckusick #include "../ufs/fs.h" 3537737Smckusick #include "../ufs/ufsmount.h" 3637737Smckusick #include "../ufs/inode.h" 3712795Ssam 3837737Smckusick /* 3937737Smckusick * ufs vfs operations. 4037737Smckusick */ 4137737Smckusick int ufs_mount(); 4239043Smckusick int ufs_start(); 4337737Smckusick int ufs_unmount(); 4437737Smckusick int ufs_root(); 4537737Smckusick int ufs_statfs(); 4637737Smckusick int ufs_sync(); 4737737Smckusick int ufs_fhtovp(); 4837737Smckusick int ufs_vptofh(); 4937737Smckusick 5037737Smckusick struct vfsops ufs_vfsops = { 5137737Smckusick ufs_mount, 5239043Smckusick ufs_start, 5337737Smckusick ufs_unmount, 5437737Smckusick ufs_root, 5537737Smckusick ufs_statfs, 5637737Smckusick ufs_sync, 5737737Smckusick ufs_fhtovp, 5837737Smckusick ufs_vptofh 5937737Smckusick }; 6037737Smckusick 6137737Smckusick /* 6237737Smckusick * ufs mount table. 6337737Smckusick */ 6437737Smckusick struct ufsmount mounttab[NMOUNT]; 6537737Smckusick 6637737Smckusick /* 67*39336Smckusick * Called by vfs_mountroot when ufs is going to be mounted as root. 6837737Smckusick * 69*39336Smckusick * Name is updated by mount(8) after booting. 7037737Smckusick */ 7139297Smckusick #define ROOTNAME "root_device" 7237737Smckusick 7337737Smckusick ufs_mountroot() 7412795Ssam { 7537737Smckusick register struct mount *mp; 7637737Smckusick extern struct vnode *rootvp; 7737737Smckusick struct ufsmount *ump; 7812795Ssam register struct fs *fs; 7937737Smckusick u_int size; 8037737Smckusick int error; 8112795Ssam 8237737Smckusick mp = (struct mount *)malloc((u_long)sizeof(struct mount), 8337737Smckusick M_MOUNT, M_WAITOK); 8437737Smckusick mp->m_op = &ufs_vfsops; 8537737Smckusick mp->m_flag = 0; 8637737Smckusick mp->m_exroot = 0; 8737737Smckusick error = mountfs(rootvp, mp); 8837737Smckusick if (error) { 8937737Smckusick free((caddr_t)mp, M_MOUNT); 9037737Smckusick return (error); 9112795Ssam } 92*39336Smckusick if (error = vfs_lock(mp)) { 9337737Smckusick (void)ufs_unmount(mp, 0); 9437737Smckusick free((caddr_t)mp, M_MOUNT); 9537737Smckusick return (error); 9621013Smckusick } 97*39336Smckusick rootfs = mp; 98*39336Smckusick mp->m_next = mp; 99*39336Smckusick mp->m_prev = mp; 100*39336Smckusick mp->m_vnodecovered = (struct vnode *)0; 10137737Smckusick ump = VFSTOUFS(mp); 10237737Smckusick fs = ump->um_fs; 10337737Smckusick fs->fs_fsmnt[0] = '/'; 10437737Smckusick bzero(fs->fs_fsmnt + 1, sizeof(fs->fs_fsmnt) - 1); 10537737Smckusick (void) copystr(ROOTNAME, ump->um_mntname, MNAMELEN - 1, &size); 10637737Smckusick bzero(ump->um_mntname + size, MNAMELEN - size); 10737737Smckusick vfs_unlock(mp); 10837737Smckusick inittodr(fs->fs_time); 10937737Smckusick return (0); 11037737Smckusick } 11137737Smckusick 11237737Smckusick /* 11337737Smckusick * VFS Operations. 11437737Smckusick * 11537737Smckusick * mount system call 11637737Smckusick */ 11737737Smckusick ufs_mount(mp, path, data, ndp) 11837737Smckusick struct mount *mp; 11937737Smckusick char *path; 12037737Smckusick caddr_t data; 12137737Smckusick struct nameidata *ndp; 12237737Smckusick { 12337737Smckusick struct vnode *devvp; 12437737Smckusick struct ufs_args args; 12537737Smckusick struct ufsmount *ump; 12637737Smckusick register struct fs *fs; 12737737Smckusick u_int size; 12837737Smckusick int error; 12937737Smckusick 13037737Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 13137737Smckusick return (error); 13237737Smckusick if ((error = getmdev(&devvp, args.fspec, ndp)) != 0) 13337737Smckusick return (error); 134*39336Smckusick if ((mp->m_flag & M_UPDATE) == 0) { 135*39336Smckusick error = mountfs(devvp, mp); 136*39336Smckusick } else { 137*39336Smckusick ump = VFSTOUFS(mp); 138*39336Smckusick fs = ump->um_fs; 139*39336Smckusick if (fs->fs_ronly && (mp->m_flag & M_RDONLY) == 0) 140*39336Smckusick fs->fs_ronly = 0; 141*39336Smckusick /* 142*39336Smckusick * Verify that the specified device is the one that 143*39336Smckusick * is really being used for the root file system. 144*39336Smckusick */ 145*39336Smckusick if (devvp != ump->um_devvp) 146*39336Smckusick error = EINVAL; /* needs translation */ 147*39336Smckusick } 14837737Smckusick if (error) { 14937737Smckusick vrele(devvp); 15037737Smckusick return (error); 15132721Smckusick } 15237737Smckusick ump = VFSTOUFS(mp); 15337737Smckusick fs = ump->um_fs; 15437737Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 15537737Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 15637737Smckusick (void) copyinstr(args.fspec, ump->um_mntname, MNAMELEN - 1, &size); 15737737Smckusick bzero(ump->um_mntname + size, MNAMELEN - size); 15837737Smckusick return (0); 15912795Ssam } 16012795Ssam 16137737Smckusick /* 16237737Smckusick * Common code for mount and mountroot 16337737Smckusick */ 16437737Smckusick mountfs(devvp, mp) 16537737Smckusick struct vnode *devvp; 16637737Smckusick struct mount *mp; 16712795Ssam { 16837737Smckusick register struct ufsmount *ump; 16937737Smckusick struct ufsmount *fmp = NULL; 17037737Smckusick struct buf *bp = NULL; 17112795Ssam register struct fs *fs; 17237737Smckusick dev_t dev = devvp->v_rdev; 17330749Skarels struct partinfo dpart; 17437737Smckusick caddr_t base, space; 17530749Skarels int havepart = 0, blks; 17637737Smckusick int error, i, size; 17721013Smckusick int needclose = 0; 17837737Smckusick int ronly = (mp->m_flag & M_RDONLY) != 0; 17912795Ssam 18037737Smckusick for (ump = &mounttab[0]; ump < &mounttab[NMOUNT]; ump++) { 18137737Smckusick if (ump->um_fs == NULL) { 18232721Smckusick if (fmp == NULL) 18337737Smckusick fmp = ump; 18437737Smckusick } else if (dev == ump->um_dev) { 18537737Smckusick return (EBUSY); /* needs translation */ 18632721Smckusick } 18732721Smckusick } 18837737Smckusick if ((ump = fmp) == NULL) 18937737Smckusick return (EMFILE); /* needs translation */ 19037737Smckusick ump->um_fs = (struct fs *)1; /* just to reserve this slot */ 19138776Smckusick error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 19232721Smckusick if (error) { 19337737Smckusick ump->um_fs = NULL; 19437737Smckusick return (error); 19532721Smckusick } 19621013Smckusick needclose = 1; 19738776Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED) != 0) 19837737Smckusick size = DEV_BSIZE; 19937737Smckusick else { 20030749Skarels havepart = 1; 20130749Skarels size = dpart.disklab->d_secsize; 20237737Smckusick } 20338776Smckusick if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) { 20437737Smckusick ump->um_fs = NULL; 20512795Ssam goto out; 20632721Smckusick } 20734421Skarels fs = bp->b_un.b_fs; 20830749Skarels if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 20930749Skarels fs->fs_bsize < sizeof(struct fs)) { 21037737Smckusick ump->um_fs = NULL; 21137737Smckusick error = EINVAL; /* XXX also needs translation */ 21216639Skarels goto out; 21316639Skarels } 21437737Smckusick ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK, 21534473Smckusick M_WAITOK); 21637737Smckusick bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs, 21712795Ssam (u_int)fs->fs_sbsize); 21834421Skarels brelse(bp); 21934421Skarels bp = NULL; 22037737Smckusick fs = ump->um_fs; 22137737Smckusick fs->fs_ronly = ronly; 22212795Ssam if (ronly == 0) 22312795Ssam fs->fs_fmod = 1; 22430749Skarels if (havepart) { 22530749Skarels dpart.part->p_fstype = FS_BSDFFS; 22630749Skarels dpart.part->p_fsize = fs->fs_fsize; 22730749Skarels dpart.part->p_frag = fs->fs_frag; 22831385Skarels dpart.part->p_cpg = fs->fs_cpg; 22930749Skarels } 23012795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 23134473Smckusick base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK, 23234473Smckusick M_WAITOK); 23312795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 23412795Ssam size = fs->fs_bsize; 23512795Ssam if (i + fs->fs_frag > blks) 23612795Ssam size = (blks - i) * fs->fs_fsize; 23738776Smckusick error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 23838776Smckusick NOCRED, &bp); 23937737Smckusick if (error) { 24034473Smckusick free((caddr_t)base, M_SUPERBLK); 24112795Ssam goto out; 24212795Ssam } 24334421Skarels bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size); 24417225Smckusick fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 24512795Ssam space += size; 24634421Skarels brelse(bp); 24734421Skarels bp = NULL; 24812795Ssam } 24937737Smckusick mp->m_data = (qaddr_t)ump; 25037737Smckusick mp->m_bsize = fs->fs_bsize; 25137737Smckusick mp->m_fsize = fs->fs_fsize; 25237737Smckusick mp->m_fsid.val[0] = (long)dev; 25337737Smckusick mp->m_fsid.val[1] = MOUNT_UFS; 25437737Smckusick ump->um_mountp = mp; 25537737Smckusick ump->um_dev = dev; 25637737Smckusick ump->um_devvp = devvp; 25737737Smckusick ump->um_qinod = NULL; 25838776Smckusick devvp->v_mount = mp; 25937737Smckusick 26030383Smckusick /* Sanity checks for old file systems. XXX */ 26130383Smckusick fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */ 26230383Smckusick fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */ 26334145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 26434145Smckusick fs->fs_nrpos = 8; /* XXX */ 26537737Smckusick return (0); 26612795Ssam out: 26732721Smckusick if (needclose) 26838776Smckusick (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 26937737Smckusick if (ump->um_fs) { 27037737Smckusick free((caddr_t)ump->um_fs, M_SUPERBLK); 27137737Smckusick ump->um_fs = NULL; 27232721Smckusick } 27334421Skarels if (bp) 27434421Skarels brelse(bp); 27537737Smckusick return (error); 27612795Ssam } 27712795Ssam 27839043Smckusick /* 27939043Smckusick * Make a filesystem operational. 28039043Smckusick * Nothing to do at the moment. 28139043Smckusick */ 28239043Smckusick ufs_start(mp, flags) 28339043Smckusick struct mount *mp; 28439043Smckusick int flags; 28539043Smckusick { 28612795Ssam 28739043Smckusick return (0); 28839043Smckusick } 28939043Smckusick 29037737Smckusick /* 29137737Smckusick * unmount system call 29237737Smckusick */ 29337737Smckusick ufs_unmount(mp, flags) 29437737Smckusick struct mount *mp; 29537737Smckusick int flags; 29612795Ssam { 29737737Smckusick register struct ufsmount *ump; 29837737Smckusick register struct fs *fs; 29912795Ssam dev_t dev; 30037737Smckusick int error, ronly; 30112795Ssam 30237737Smckusick if (flags & MNT_FORCE) 30337737Smckusick return (EINVAL); 30437737Smckusick ump = VFSTOUFS(mp); 30537737Smckusick dev = ump->um_dev; 30612795Ssam #ifdef QUOTA 30737737Smckusick if (error = iflush(dev, ump->um_qinod)) 30812795Ssam #else 30937737Smckusick if (error = iflush(dev)) 31012795Ssam #endif 31130749Skarels return (error); 31212795Ssam #ifdef QUOTA 31337737Smckusick (void)closedq(ump); 31412795Ssam /* 31512795Ssam * Here we have to iflush again to get rid of the quota inode. 31637737Smckusick * A drag, but it would be ugly to cheat, & this doesn't happen often 31712795Ssam */ 31812795Ssam (void)iflush(dev, (struct inode *)NULL); 31912795Ssam #endif 32037737Smckusick fs = ump->um_fs; 32137737Smckusick ronly = !fs->fs_ronly; 32231660Smckusick free((caddr_t)fs->fs_csp[0], M_SUPERBLK); 32337737Smckusick free((caddr_t)fs, M_SUPERBLK); 32437737Smckusick ump->um_fs = NULL; 32537737Smckusick ump->um_dev = NODEV; 32638776Smckusick error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 32738776Smckusick ump->um_devvp->v_mount = (struct mount *)0; 32837737Smckusick vrele(ump->um_devvp); 32937737Smckusick ump->um_devvp = (struct vnode *)0; 33030749Skarels return (error); 33112795Ssam } 33212795Ssam 33337737Smckusick /* 33437737Smckusick * Return root of a filesystem 33537737Smckusick */ 33637737Smckusick ufs_root(mp, vpp) 33712795Ssam struct mount *mp; 33837737Smckusick struct vnode **vpp; 33912795Ssam { 34037737Smckusick struct inode tip, *ip; 34137737Smckusick int error; 34237737Smckusick 34337737Smckusick tip.i_dev = VFSTOUFS(mp)->um_dev; 34437737Smckusick tip.i_vnode.v_mount = mp; 34537737Smckusick error = iget(&tip, (ino_t)ROOTINO, &ip); 34637737Smckusick if (error) 34737737Smckusick return (error); 34837737Smckusick *vpp = ITOV(ip); 34937737Smckusick return (0); 35037737Smckusick } 35137737Smckusick 35237737Smckusick /* 35337737Smckusick * Get file system statistics. 35437737Smckusick */ 35537737Smckusick ufs_statfs(mp, sbp) 35637737Smckusick struct mount *mp; 35737737Smckusick register struct statfs *sbp; 35837737Smckusick { 35937737Smckusick register struct ufsmount *ump; 36037737Smckusick register struct fs *fs; 36137737Smckusick 36237737Smckusick ump = VFSTOUFS(mp); 36337737Smckusick fs = ump->um_fs; 36437737Smckusick if (fs->fs_magic != FS_MAGIC) 36537737Smckusick panic("ufs_statfs"); 36637737Smckusick sbp->f_type = MOUNT_UFS; 36737737Smckusick sbp->f_flags = mp->m_flag &~ (M_MLOCK|M_MWAIT); 36837737Smckusick sbp->f_fsize = fs->fs_fsize; 36937737Smckusick sbp->f_bsize = fs->fs_bsize; 37037737Smckusick sbp->f_blocks = fs->fs_dsize; 37137737Smckusick sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 37237737Smckusick fs->fs_cstotal.cs_nffree; 37337737Smckusick sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 37437737Smckusick (fs->fs_dsize - sbp->f_bfree); 37537737Smckusick if (sbp->f_bavail < 0) 37637737Smckusick sbp->f_bavail = 0; 37737737Smckusick sbp->f_files = fs->fs_ncg * fs->fs_ipg; 37837737Smckusick sbp->f_ffree = fs->fs_cstotal.cs_nifree; 37937737Smckusick sbp->f_fsid = mp->m_fsid; 38037737Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 38137737Smckusick bcopy((caddr_t)ump->um_mntname, (caddr_t)&sbp->f_mntfromname[0], 38237737Smckusick MNAMELEN); 38337737Smckusick return (0); 38437737Smckusick } 38537737Smckusick 38637737Smckusick int syncprt = 0; 38737737Smckusick 38837737Smckusick /* 38937737Smckusick * Go through the disk queues to initiate sandbagged IO; 39037737Smckusick * go through the inodes to write those that have been modified; 39137737Smckusick * initiate the writing of the super block if it has been modified. 39237737Smckusick */ 39337737Smckusick ufs_sync(mp, waitfor) 39437737Smckusick struct mount *mp; 39537737Smckusick int waitfor; 39637737Smckusick { 39737737Smckusick register struct inode *ip; 39837737Smckusick register struct ufsmount *ump = VFSTOUFS(mp); 39937737Smckusick register struct fs *fs; 40037737Smckusick int error = 0; 40137737Smckusick static int updlock = 0; 40237737Smckusick 40337737Smckusick if (syncprt) 40437737Smckusick bufstats(); 40537737Smckusick if (updlock) 40637737Smckusick return (EBUSY); 40737737Smckusick fs = ump->um_fs; 40837737Smckusick if (fs == (struct fs *)1) 40937737Smckusick return (0); 41037737Smckusick updlock++; 41137737Smckusick /* 41237737Smckusick * Write back modified superblock. 41337737Smckusick * Consistency check that the superblock 41437737Smckusick * is still in the buffer cache. 41537737Smckusick */ 41637737Smckusick if (fs->fs_fmod != 0) { 41737737Smckusick if (fs->fs_ronly != 0) { /* XXX */ 41837737Smckusick printf("fs = %s\n", fs->fs_fsmnt); 41937737Smckusick panic("update: rofs mod"); 42037737Smckusick } 42137737Smckusick fs->fs_fmod = 0; 42237737Smckusick fs->fs_time = time.tv_sec; 42337737Smckusick error = sbupdate(ump, waitfor); 42437737Smckusick } 42537737Smckusick /* 42637737Smckusick * Write back each (modified) inode. 42737737Smckusick */ 42837737Smckusick for (ip = inode; ip < inodeNINODE; ip++) { 42937737Smckusick if (ip->i_devvp != ump->um_devvp || 43037737Smckusick (ip->i_flag & ILOCKED) != 0 || ITOV(ip)->v_count == 0 || 43137737Smckusick (ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0) 43237737Smckusick continue; 43338227Smckusick ILOCK(ip); 43438346Smckusick VREF(ITOV(ip)); 43537737Smckusick error = iupdat(ip, &time, &time, waitfor == MNT_WAIT); 43637737Smckusick iput(ip); 43737737Smckusick } 43837737Smckusick updlock = 0; 43937737Smckusick /* 44037737Smckusick * Force stale buffer cache information to be flushed. 44137737Smckusick */ 44238776Smckusick bflush(ump->um_devvp->v_mount); 44337737Smckusick return (error); 44437737Smckusick } 44537737Smckusick 44637737Smckusick /* 44737737Smckusick * Write a superblock and associated information back to disk. 44837737Smckusick */ 44937737Smckusick sbupdate(mp, waitfor) 45037737Smckusick struct ufsmount *mp; 45137737Smckusick int waitfor; 45237737Smckusick { 45337737Smckusick register struct fs *fs = mp->um_fs; 45412795Ssam register struct buf *bp; 45512795Ssam int blks; 45612795Ssam caddr_t space; 45737737Smckusick int i, size, error = 0; 45812795Ssam 45937737Smckusick bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize); 46012795Ssam bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); 46134145Smckusick /* Restore compatibility to old file systems. XXX */ 46234145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 46334145Smckusick bp->b_un.b_fs->fs_nrpos = -1; /* XXX */ 46437737Smckusick if (waitfor == MNT_WAIT) 46537737Smckusick error = bwrite(bp); 46637737Smckusick else 46737737Smckusick bawrite(bp); 46812795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 46912795Ssam space = (caddr_t)fs->fs_csp[0]; 47012795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 47112795Ssam size = fs->fs_bsize; 47212795Ssam if (i + fs->fs_frag > blks) 47312795Ssam size = (blks - i) * fs->fs_fsize; 47437737Smckusick bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size); 47512795Ssam bcopy(space, bp->b_un.b_addr, (u_int)size); 47612795Ssam space += size; 47737737Smckusick if (waitfor == MNT_WAIT) 47837737Smckusick error = bwrite(bp); 47937737Smckusick else 48037737Smckusick bawrite(bp); 48112795Ssam } 48237737Smckusick return (error); 48312795Ssam } 48412795Ssam 48512795Ssam /* 48637737Smckusick * Print out statistics on the current allocation of the buffer pool. 48737737Smckusick * Can be enabled to print out on every ``sync'' by setting "syncprt" 48837737Smckusick * above. 48937737Smckusick */ 49037737Smckusick bufstats() 49137737Smckusick { 49237737Smckusick int s, i, j, count; 49337737Smckusick register struct buf *bp, *dp; 49437737Smckusick int counts[MAXBSIZE/CLBYTES+1]; 49537737Smckusick static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; 49637737Smckusick 49737737Smckusick for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { 49837737Smckusick count = 0; 49937737Smckusick for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 50037737Smckusick counts[j] = 0; 50137737Smckusick s = splbio(); 50237737Smckusick for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { 50337737Smckusick counts[dp->b_bufsize/CLBYTES]++; 50437737Smckusick count++; 50537737Smckusick } 50637737Smckusick splx(s); 50737737Smckusick printf("%s: total-%d", bname[i], count); 50837737Smckusick for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 50937737Smckusick if (counts[j] != 0) 51037737Smckusick printf(", %d-%d", j * CLBYTES, counts[j]); 51137737Smckusick printf("\n"); 51237737Smckusick } 51337737Smckusick } 51437737Smckusick 51537737Smckusick /* 51637737Smckusick * File handle to vnode 51738453Smckusick * 51838453Smckusick * Have to be really careful about stale file handles: 51938453Smckusick * - check that the inode number is in range 52038453Smckusick * - call iget() to get the locked inode 52138453Smckusick * - check for an unallocated inode (i_mode == 0) 52238453Smckusick * - check that the generation number matches 52337737Smckusick */ 52437737Smckusick ufs_fhtovp(mp, fhp, vpp) 52538453Smckusick register struct mount *mp; 52637737Smckusick struct fid *fhp; 52737737Smckusick struct vnode **vpp; 52837737Smckusick { 52937737Smckusick register struct ufid *ufhp; 53038453Smckusick register struct fs *fs; 53137737Smckusick struct inode tip, *ip; 53237737Smckusick int error; 53337737Smckusick 53437737Smckusick ufhp = (struct ufid *)fhp; 53538453Smckusick fs = VFSTOUFS(mp)->um_fs; 53638453Smckusick if (ufhp->ufid_ino < ROOTINO || 53738453Smckusick ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) { 53838453Smckusick *vpp = (struct vnode *)0; 53938453Smckusick return (EINVAL); 54038453Smckusick } 54137737Smckusick tip.i_dev = VFSTOUFS(mp)->um_dev; 54237737Smckusick tip.i_vnode.v_mount = mp; 54337737Smckusick if (error = iget(&tip, ufhp->ufid_ino, &ip)) { 54438453Smckusick *vpp = (struct vnode *)0; 54537737Smckusick return (error); 54637737Smckusick } 54738453Smckusick if (ip->i_mode == 0) { 54838453Smckusick iput(ip); 54938453Smckusick *vpp = (struct vnode *)0; 55038453Smckusick return (EINVAL); 55138453Smckusick } 55237737Smckusick if (ip->i_gen != ufhp->ufid_gen) { 55337737Smckusick iput(ip); 55438453Smckusick *vpp = (struct vnode *)0; 55537737Smckusick return (EINVAL); 55637737Smckusick } 55737737Smckusick *vpp = ITOV(ip); 55837737Smckusick return (0); 55937737Smckusick } 56037737Smckusick 56137737Smckusick /* 56238355Smckusick * Vnode pointer to File handle 56337737Smckusick */ 56437737Smckusick /* ARGSUSED */ 56538143Smckusick ufs_vptofh(vp, fhp) 56638143Smckusick struct vnode *vp; 56737737Smckusick struct fid *fhp; 56837737Smckusick { 56938143Smckusick register struct inode *ip = VTOI(vp); 57038143Smckusick register struct ufid *ufhp; 57137737Smckusick 57238143Smckusick ufhp = (struct ufid *)fhp; 57338143Smckusick ufhp->ufid_len = sizeof(struct ufid); 57438143Smckusick ufhp->ufid_ino = ip->i_number; 57538143Smckusick ufhp->ufid_gen = ip->i_gen; 57638143Smckusick return (0); 57737737Smckusick } 57837737Smckusick 57937737Smckusick /* 58037737Smckusick * Common code for mount and quota. 58112795Ssam * Check that the user's argument is a reasonable 58212795Ssam * thing on which to mount, and return the device number if so. 58312795Ssam */ 58437737Smckusick getmdev(devvpp, fname, ndp) 58537737Smckusick struct vnode **devvpp; 58616697Smckusick caddr_t fname; 58737737Smckusick register struct nameidata *ndp; 58812795Ssam { 58937737Smckusick register struct vnode *vp; 59037737Smckusick int error; 59112795Ssam 59237737Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 59316697Smckusick ndp->ni_segflg = UIO_USERSPACE; 59416697Smckusick ndp->ni_dirp = fname; 59537737Smckusick if (error = namei(ndp)) { 59637737Smckusick if (error == ENOENT) 59737737Smckusick return (ENODEV); /* needs translation */ 59837737Smckusick return (error); 59921013Smckusick } 60037737Smckusick vp = ndp->ni_vp; 60137737Smckusick if (vp->v_type != VBLK) { 60237737Smckusick vput(vp); 60312795Ssam return (ENOTBLK); 60415956Skarels } 60537737Smckusick if (major(vp->v_rdev) >= nblkdev) 60612795Ssam return (ENXIO); 60737737Smckusick iunlock(VTOI(vp)); 60837737Smckusick *devvpp = vp; 60912795Ssam return (0); 61012795Ssam } 611