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*40346Smckusick * @(#)lfs_vfsops.c 7.35 (Berkeley) 03/06/90 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(); 4939437Smckusick int ufs_init(); 5037737Smckusick 5137737Smckusick struct vfsops ufs_vfsops = { 5237737Smckusick ufs_mount, 5339043Smckusick ufs_start, 5437737Smckusick ufs_unmount, 5537737Smckusick ufs_root, 5637737Smckusick ufs_statfs, 5737737Smckusick ufs_sync, 5837737Smckusick ufs_fhtovp, 5939437Smckusick ufs_vptofh, 6039437Smckusick ufs_init 6137737Smckusick }; 6237737Smckusick 6337737Smckusick /* 6437737Smckusick * ufs mount table. 6537737Smckusick */ 6637737Smckusick struct ufsmount mounttab[NMOUNT]; 6737737Smckusick 6837737Smckusick /* 6939336Smckusick * Called by vfs_mountroot when ufs is going to be mounted as root. 7037737Smckusick * 7139336Smckusick * Name is updated by mount(8) after booting. 7237737Smckusick */ 7339297Smckusick #define ROOTNAME "root_device" 7437737Smckusick 7537737Smckusick ufs_mountroot() 7612795Ssam { 7737737Smckusick register struct mount *mp; 7837737Smckusick extern struct vnode *rootvp; 7937737Smckusick struct ufsmount *ump; 8012795Ssam register struct fs *fs; 8137737Smckusick u_int size; 8237737Smckusick int error; 8312795Ssam 8437737Smckusick mp = (struct mount *)malloc((u_long)sizeof(struct mount), 8537737Smckusick M_MOUNT, M_WAITOK); 8637737Smckusick mp->m_op = &ufs_vfsops; 8739675Smckusick mp->m_flag = M_RDONLY; 8837737Smckusick mp->m_exroot = 0; 8939390Smckusick mp->m_mounth = (struct vnode *)0; 9037737Smckusick error = mountfs(rootvp, mp); 9137737Smckusick if (error) { 9237737Smckusick free((caddr_t)mp, M_MOUNT); 9337737Smckusick return (error); 9412795Ssam } 9539336Smckusick if (error = vfs_lock(mp)) { 9637737Smckusick (void)ufs_unmount(mp, 0); 9737737Smckusick free((caddr_t)mp, M_MOUNT); 9837737Smckusick return (error); 9921013Smckusick } 10039336Smckusick rootfs = mp; 10139336Smckusick mp->m_next = mp; 10239336Smckusick mp->m_prev = mp; 10339336Smckusick mp->m_vnodecovered = (struct vnode *)0; 10437737Smckusick ump = VFSTOUFS(mp); 10537737Smckusick fs = ump->um_fs; 106*40346Smckusick bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 10737737Smckusick fs->fs_fsmnt[0] = '/'; 108*40346Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->m_stat.f_mntonname, MNAMELEN); 109*40346Smckusick (void) copystr(ROOTNAME, mp->m_stat.f_mntfromname, MNAMELEN - 1, &size); 110*40346Smckusick bzero(mp->m_stat.f_mntfromname + size, MNAMELEN - size); 111*40346Smckusick (void) ufs_statfs(mp, &mp->m_stat); 11237737Smckusick vfs_unlock(mp); 11337737Smckusick inittodr(fs->fs_time); 11437737Smckusick return (0); 11537737Smckusick } 11637737Smckusick 11737737Smckusick /* 11837737Smckusick * VFS Operations. 11937737Smckusick * 12037737Smckusick * mount system call 12137737Smckusick */ 12237737Smckusick ufs_mount(mp, path, data, ndp) 123*40346Smckusick register struct mount *mp; 12437737Smckusick char *path; 12537737Smckusick caddr_t data; 12637737Smckusick struct nameidata *ndp; 12737737Smckusick { 12837737Smckusick struct vnode *devvp; 12937737Smckusick struct ufs_args args; 13037737Smckusick struct ufsmount *ump; 13137737Smckusick register struct fs *fs; 13237737Smckusick u_int size; 13337737Smckusick int error; 13437737Smckusick 13537737Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 13637737Smckusick return (error); 13737737Smckusick if ((error = getmdev(&devvp, args.fspec, ndp)) != 0) 13837737Smckusick return (error); 13939336Smckusick if ((mp->m_flag & M_UPDATE) == 0) { 14039336Smckusick error = mountfs(devvp, mp); 14139336Smckusick } else { 14239336Smckusick ump = VFSTOUFS(mp); 14339336Smckusick fs = ump->um_fs; 14439336Smckusick if (fs->fs_ronly && (mp->m_flag & M_RDONLY) == 0) 14539336Smckusick fs->fs_ronly = 0; 14639336Smckusick /* 14739336Smckusick * Verify that the specified device is the one that 14839336Smckusick * is really being used for the root file system. 14939336Smckusick */ 15039336Smckusick if (devvp != ump->um_devvp) 15139336Smckusick error = EINVAL; /* needs translation */ 15239336Smckusick } 15337737Smckusick if (error) { 15437737Smckusick vrele(devvp); 15537737Smckusick return (error); 15632721Smckusick } 15737737Smckusick ump = VFSTOUFS(mp); 15837737Smckusick fs = ump->um_fs; 15937737Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 16037737Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 161*40346Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->m_stat.f_mntonname, MNAMELEN); 162*40346Smckusick (void) copyinstr(args.fspec, mp->m_stat.f_mntfromname, MNAMELEN - 1, 163*40346Smckusick &size); 164*40346Smckusick bzero(mp->m_stat.f_mntfromname + size, MNAMELEN - size); 165*40346Smckusick (void) ufs_statfs(mp, &mp->m_stat); 16637737Smckusick return (0); 16712795Ssam } 16812795Ssam 16937737Smckusick /* 17037737Smckusick * Common code for mount and mountroot 17137737Smckusick */ 17237737Smckusick mountfs(devvp, mp) 17337737Smckusick struct vnode *devvp; 17437737Smckusick struct mount *mp; 17512795Ssam { 17637737Smckusick register struct ufsmount *ump; 17737737Smckusick struct ufsmount *fmp = NULL; 17837737Smckusick struct buf *bp = NULL; 17912795Ssam register struct fs *fs; 18037737Smckusick dev_t dev = devvp->v_rdev; 18130749Skarels struct partinfo dpart; 18237737Smckusick caddr_t base, space; 18330749Skarels int havepart = 0, blks; 18437737Smckusick int error, i, size; 18521013Smckusick int needclose = 0; 18637737Smckusick int ronly = (mp->m_flag & M_RDONLY) != 0; 18712795Ssam 18837737Smckusick for (ump = &mounttab[0]; ump < &mounttab[NMOUNT]; ump++) { 18937737Smckusick if (ump->um_fs == NULL) { 19032721Smckusick if (fmp == NULL) 19137737Smckusick fmp = ump; 19237737Smckusick } else if (dev == ump->um_dev) { 19337737Smckusick return (EBUSY); /* needs translation */ 19432721Smckusick } 19532721Smckusick } 19637737Smckusick if ((ump = fmp) == NULL) 19737737Smckusick return (EMFILE); /* needs translation */ 19837737Smckusick ump->um_fs = (struct fs *)1; /* just to reserve this slot */ 19938776Smckusick error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 20032721Smckusick if (error) { 20137737Smckusick ump->um_fs = NULL; 20237737Smckusick return (error); 20332721Smckusick } 20421013Smckusick needclose = 1; 20538776Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED) != 0) 20637737Smckusick size = DEV_BSIZE; 20737737Smckusick else { 20830749Skarels havepart = 1; 20930749Skarels size = dpart.disklab->d_secsize; 21037737Smckusick } 21138776Smckusick if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) { 21237737Smckusick ump->um_fs = NULL; 21312795Ssam goto out; 21432721Smckusick } 21534421Skarels fs = bp->b_un.b_fs; 21630749Skarels if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 21730749Skarels fs->fs_bsize < sizeof(struct fs)) { 21837737Smckusick ump->um_fs = NULL; 21937737Smckusick error = EINVAL; /* XXX also needs translation */ 22016639Skarels goto out; 22116639Skarels } 22237737Smckusick ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK, 22334473Smckusick M_WAITOK); 22437737Smckusick bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs, 22512795Ssam (u_int)fs->fs_sbsize); 22639675Smckusick if (fs->fs_sbsize < SBSIZE) 22739675Smckusick bp->b_flags |= B_INVAL; 22834421Skarels brelse(bp); 22934421Skarels bp = NULL; 23037737Smckusick fs = ump->um_fs; 23137737Smckusick fs->fs_ronly = ronly; 23212795Ssam if (ronly == 0) 23312795Ssam fs->fs_fmod = 1; 23430749Skarels if (havepart) { 23530749Skarels dpart.part->p_fstype = FS_BSDFFS; 23630749Skarels dpart.part->p_fsize = fs->fs_fsize; 23730749Skarels dpart.part->p_frag = fs->fs_frag; 23831385Skarels dpart.part->p_cpg = fs->fs_cpg; 23930749Skarels } 24012795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 24134473Smckusick base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK, 24234473Smckusick M_WAITOK); 24312795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 24412795Ssam size = fs->fs_bsize; 24512795Ssam if (i + fs->fs_frag > blks) 24612795Ssam size = (blks - i) * fs->fs_fsize; 24738776Smckusick error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 24838776Smckusick NOCRED, &bp); 24937737Smckusick if (error) { 25034473Smckusick free((caddr_t)base, M_SUPERBLK); 25112795Ssam goto out; 25212795Ssam } 25334421Skarels bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size); 25417225Smckusick fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 25512795Ssam space += size; 25634421Skarels brelse(bp); 25734421Skarels bp = NULL; 25812795Ssam } 25937737Smckusick mp->m_data = (qaddr_t)ump; 260*40346Smckusick mp->m_stat.f_fsid.val[0] = (long)dev; 261*40346Smckusick mp->m_stat.f_fsid.val[1] = MOUNT_UFS; 26237737Smckusick ump->um_mountp = mp; 26337737Smckusick ump->um_dev = dev; 26437737Smckusick ump->um_devvp = devvp; 26537737Smckusick ump->um_qinod = NULL; 26637737Smckusick 26730383Smckusick /* Sanity checks for old file systems. XXX */ 26830383Smckusick fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */ 26930383Smckusick fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */ 27034145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 27134145Smckusick fs->fs_nrpos = 8; /* XXX */ 27237737Smckusick return (0); 27312795Ssam out: 27432721Smckusick if (needclose) 27538776Smckusick (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 27637737Smckusick if (ump->um_fs) { 27737737Smckusick free((caddr_t)ump->um_fs, M_SUPERBLK); 27837737Smckusick ump->um_fs = NULL; 27932721Smckusick } 28034421Skarels if (bp) 28134421Skarels brelse(bp); 28237737Smckusick return (error); 28312795Ssam } 28412795Ssam 28539043Smckusick /* 28639043Smckusick * Make a filesystem operational. 28739043Smckusick * Nothing to do at the moment. 28839043Smckusick */ 28939390Smckusick /* ARGSUSED */ 29039043Smckusick ufs_start(mp, flags) 29139043Smckusick struct mount *mp; 29239043Smckusick int flags; 29339043Smckusick { 29412795Ssam 29539043Smckusick return (0); 29639043Smckusick } 29739043Smckusick 29837737Smckusick /* 29937737Smckusick * unmount system call 30037737Smckusick */ 30137737Smckusick ufs_unmount(mp, flags) 30237737Smckusick struct mount *mp; 30337737Smckusick int flags; 30412795Ssam { 30537737Smckusick register struct ufsmount *ump; 30637737Smckusick register struct fs *fs; 30737737Smckusick int error, ronly; 30812795Ssam 30937737Smckusick if (flags & MNT_FORCE) 31037737Smckusick return (EINVAL); 31139675Smckusick mntflushbuf(mp, 0); 31239675Smckusick if (mntinvalbuf(mp)) 31339675Smckusick return (EBUSY); 31437737Smckusick ump = VFSTOUFS(mp); 31512795Ssam #ifdef QUOTA 31639898Smckusick if (ump->um_qinod) { 31739898Smckusick if (error = vflush(mp, ITOV(ump->um_qinod), flags)) 31839898Smckusick return (error); 31939898Smckusick (void) closedq(ump); 32039898Smckusick /* 32139898Smckusick * Here we have to vflush again to get rid of the quota inode. 32239898Smckusick * A drag, but it would be ugly to cheat, and this system 32339898Smckusick * call does not happen often. 32439898Smckusick */ 32539898Smckusick if (vflush(mp, (struct vnode *)NULL, MNT_NOFORCE)) 32639898Smckusick panic("ufs_unmount: quota"); 32739898Smckusick } else 32812795Ssam #endif 32939898Smckusick if (error = vflush(mp, (struct vnode *)NULL, flags)) 33039898Smckusick return (error); 33137737Smckusick fs = ump->um_fs; 33237737Smckusick ronly = !fs->fs_ronly; 33331660Smckusick free((caddr_t)fs->fs_csp[0], M_SUPERBLK); 33437737Smckusick free((caddr_t)fs, M_SUPERBLK); 33537737Smckusick ump->um_fs = NULL; 33637737Smckusick ump->um_dev = NODEV; 33738776Smckusick error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 33837737Smckusick vrele(ump->um_devvp); 33937737Smckusick ump->um_devvp = (struct vnode *)0; 34030749Skarels return (error); 34112795Ssam } 34212795Ssam 34337737Smckusick /* 34437737Smckusick * Return root of a filesystem 34537737Smckusick */ 34637737Smckusick ufs_root(mp, vpp) 34712795Ssam struct mount *mp; 34837737Smckusick struct vnode **vpp; 34912795Ssam { 35039390Smckusick register struct inode *ip; 35139390Smckusick struct inode *nip; 35239390Smckusick struct vnode tvp; 35337737Smckusick int error; 35437737Smckusick 35539390Smckusick tvp.v_mount = mp; 35639390Smckusick ip = VTOI(&tvp); 35739390Smckusick ip->i_vnode = &tvp; 35839390Smckusick ip->i_dev = VFSTOUFS(mp)->um_dev; 35939390Smckusick error = iget(ip, (ino_t)ROOTINO, &nip); 36037737Smckusick if (error) 36137737Smckusick return (error); 36239390Smckusick *vpp = ITOV(nip); 36337737Smckusick return (0); 36437737Smckusick } 36537737Smckusick 36637737Smckusick /* 36737737Smckusick * Get file system statistics. 36837737Smckusick */ 36937737Smckusick ufs_statfs(mp, sbp) 37037737Smckusick struct mount *mp; 37137737Smckusick register struct statfs *sbp; 37237737Smckusick { 37337737Smckusick register struct ufsmount *ump; 37437737Smckusick register struct fs *fs; 37537737Smckusick 37637737Smckusick ump = VFSTOUFS(mp); 37737737Smckusick fs = ump->um_fs; 37837737Smckusick if (fs->fs_magic != FS_MAGIC) 37937737Smckusick panic("ufs_statfs"); 38037737Smckusick sbp->f_type = MOUNT_UFS; 38137737Smckusick sbp->f_fsize = fs->fs_fsize; 38237737Smckusick sbp->f_bsize = fs->fs_bsize; 38337737Smckusick sbp->f_blocks = fs->fs_dsize; 38437737Smckusick sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 38537737Smckusick fs->fs_cstotal.cs_nffree; 38637737Smckusick sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 38737737Smckusick (fs->fs_dsize - sbp->f_bfree); 38839350Smckusick sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 38937737Smckusick sbp->f_ffree = fs->fs_cstotal.cs_nifree; 390*40346Smckusick if (sbp != &mp->m_stat) { 391*40346Smckusick bcopy((caddr_t)mp->m_stat.f_mntonname, 392*40346Smckusick (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 393*40346Smckusick bcopy((caddr_t)mp->m_stat.f_mntfromname, 394*40346Smckusick (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 395*40346Smckusick } 39637737Smckusick return (0); 39737737Smckusick } 39837737Smckusick 39937737Smckusick int syncprt = 0; 40037737Smckusick 40137737Smckusick /* 40237737Smckusick * Go through the disk queues to initiate sandbagged IO; 40337737Smckusick * go through the inodes to write those that have been modified; 40437737Smckusick * initiate the writing of the super block if it has been modified. 40537737Smckusick */ 40637737Smckusick ufs_sync(mp, waitfor) 40737737Smckusick struct mount *mp; 40837737Smckusick int waitfor; 40937737Smckusick { 41039390Smckusick register struct vnode *vp; 41137737Smckusick register struct inode *ip; 41237737Smckusick register struct ufsmount *ump = VFSTOUFS(mp); 41337737Smckusick register struct fs *fs; 41439877Smckusick struct vnode *nvp; 41539596Smckusick int error, allerror = 0; 41637737Smckusick static int updlock = 0; 41737737Smckusick 41837737Smckusick if (syncprt) 41937737Smckusick bufstats(); 42037737Smckusick if (updlock) 42137737Smckusick return (EBUSY); 42237737Smckusick fs = ump->um_fs; 42337737Smckusick if (fs == (struct fs *)1) 42437737Smckusick return (0); 42537737Smckusick updlock++; 42637737Smckusick /* 42737737Smckusick * Write back modified superblock. 42837737Smckusick * Consistency check that the superblock 42937737Smckusick * is still in the buffer cache. 43037737Smckusick */ 43137737Smckusick if (fs->fs_fmod != 0) { 43237737Smckusick if (fs->fs_ronly != 0) { /* XXX */ 43337737Smckusick printf("fs = %s\n", fs->fs_fsmnt); 43437737Smckusick panic("update: rofs mod"); 43537737Smckusick } 43637737Smckusick fs->fs_fmod = 0; 43737737Smckusick fs->fs_time = time.tv_sec; 43837737Smckusick error = sbupdate(ump, waitfor); 43937737Smckusick } 44037737Smckusick /* 44137737Smckusick * Write back each (modified) inode. 44237737Smckusick */ 44339877Smckusick loop: 44439877Smckusick for (vp = mp->m_mounth; vp; vp = nvp) { 44539877Smckusick nvp = vp->v_mountf; 44639390Smckusick ip = VTOI(vp); 44739877Smckusick if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 && 44839877Smckusick vp->v_dirtyblkhd == NULL) 44937737Smckusick continue; 45039877Smckusick if (vget(vp)) 45139877Smckusick goto loop; 45239877Smckusick if (vp->v_dirtyblkhd) 45339877Smckusick vflushbuf(vp, 0); 45439877Smckusick if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) && 45539877Smckusick (error = iupdat(ip, &time, &time, 0))) 45639596Smckusick allerror = error; 45739596Smckusick vput(vp); 45837737Smckusick } 45937737Smckusick updlock = 0; 46037737Smckusick /* 46139675Smckusick * Force stale file system control information to be flushed. 46237737Smckusick */ 46339675Smckusick vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0); 46439596Smckusick return (allerror); 46537737Smckusick } 46637737Smckusick 46737737Smckusick /* 46837737Smckusick * Write a superblock and associated information back to disk. 46937737Smckusick */ 47037737Smckusick sbupdate(mp, waitfor) 47137737Smckusick struct ufsmount *mp; 47237737Smckusick int waitfor; 47337737Smckusick { 47437737Smckusick register struct fs *fs = mp->um_fs; 47512795Ssam register struct buf *bp; 47612795Ssam int blks; 47712795Ssam caddr_t space; 47837737Smckusick int i, size, error = 0; 47912795Ssam 48037737Smckusick bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize); 48112795Ssam bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); 48234145Smckusick /* Restore compatibility to old file systems. XXX */ 48334145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 48434145Smckusick bp->b_un.b_fs->fs_nrpos = -1; /* XXX */ 48537737Smckusick if (waitfor == MNT_WAIT) 48637737Smckusick error = bwrite(bp); 48737737Smckusick else 48837737Smckusick bawrite(bp); 48912795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 49012795Ssam space = (caddr_t)fs->fs_csp[0]; 49112795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 49212795Ssam size = fs->fs_bsize; 49312795Ssam if (i + fs->fs_frag > blks) 49412795Ssam size = (blks - i) * fs->fs_fsize; 49537737Smckusick bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size); 49612795Ssam bcopy(space, bp->b_un.b_addr, (u_int)size); 49712795Ssam space += size; 49837737Smckusick if (waitfor == MNT_WAIT) 49937737Smckusick error = bwrite(bp); 50037737Smckusick else 50137737Smckusick bawrite(bp); 50212795Ssam } 50337737Smckusick return (error); 50412795Ssam } 50512795Ssam 50612795Ssam /* 50737737Smckusick * Print out statistics on the current allocation of the buffer pool. 50837737Smckusick * Can be enabled to print out on every ``sync'' by setting "syncprt" 50937737Smckusick * above. 51037737Smckusick */ 51137737Smckusick bufstats() 51237737Smckusick { 51337737Smckusick int s, i, j, count; 51437737Smckusick register struct buf *bp, *dp; 51537737Smckusick int counts[MAXBSIZE/CLBYTES+1]; 51637737Smckusick static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; 51737737Smckusick 51837737Smckusick for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { 51937737Smckusick count = 0; 52037737Smckusick for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 52137737Smckusick counts[j] = 0; 52237737Smckusick s = splbio(); 52337737Smckusick for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { 52437737Smckusick counts[dp->b_bufsize/CLBYTES]++; 52537737Smckusick count++; 52637737Smckusick } 52737737Smckusick splx(s); 52837737Smckusick printf("%s: total-%d", bname[i], count); 52937737Smckusick for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 53037737Smckusick if (counts[j] != 0) 53137737Smckusick printf(", %d-%d", j * CLBYTES, counts[j]); 53237737Smckusick printf("\n"); 53337737Smckusick } 53437737Smckusick } 53537737Smckusick 53637737Smckusick /* 53737737Smckusick * File handle to vnode 53838453Smckusick * 53938453Smckusick * Have to be really careful about stale file handles: 54038453Smckusick * - check that the inode number is in range 54138453Smckusick * - call iget() to get the locked inode 54238453Smckusick * - check for an unallocated inode (i_mode == 0) 54338453Smckusick * - check that the generation number matches 54437737Smckusick */ 54537737Smckusick ufs_fhtovp(mp, fhp, vpp) 54638453Smckusick register struct mount *mp; 54737737Smckusick struct fid *fhp; 54837737Smckusick struct vnode **vpp; 54937737Smckusick { 55037737Smckusick register struct ufid *ufhp; 55138453Smckusick register struct fs *fs; 55239390Smckusick register struct inode *ip; 55339390Smckusick struct inode *nip; 55439390Smckusick struct vnode tvp; 55537737Smckusick int error; 55637737Smckusick 55737737Smckusick ufhp = (struct ufid *)fhp; 55838453Smckusick fs = VFSTOUFS(mp)->um_fs; 55938453Smckusick if (ufhp->ufid_ino < ROOTINO || 56038453Smckusick ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) { 56138453Smckusick *vpp = (struct vnode *)0; 56238453Smckusick return (EINVAL); 56338453Smckusick } 56439390Smckusick tvp.v_mount = mp; 56539390Smckusick ip = VTOI(&tvp); 56639390Smckusick ip->i_vnode = &tvp; 56739390Smckusick ip->i_dev = VFSTOUFS(mp)->um_dev; 56839390Smckusick if (error = iget(ip, ufhp->ufid_ino, &nip)) { 56938453Smckusick *vpp = (struct vnode *)0; 57037737Smckusick return (error); 57137737Smckusick } 57239390Smckusick ip = nip; 57338453Smckusick if (ip->i_mode == 0) { 57438453Smckusick iput(ip); 57538453Smckusick *vpp = (struct vnode *)0; 57638453Smckusick return (EINVAL); 57738453Smckusick } 57837737Smckusick if (ip->i_gen != ufhp->ufid_gen) { 57937737Smckusick iput(ip); 58038453Smckusick *vpp = (struct vnode *)0; 58137737Smckusick return (EINVAL); 58237737Smckusick } 58337737Smckusick *vpp = ITOV(ip); 58437737Smckusick return (0); 58537737Smckusick } 58637737Smckusick 58737737Smckusick /* 58838355Smckusick * Vnode pointer to File handle 58937737Smckusick */ 59037737Smckusick /* ARGSUSED */ 59138143Smckusick ufs_vptofh(vp, fhp) 59238143Smckusick struct vnode *vp; 59337737Smckusick struct fid *fhp; 59437737Smckusick { 59538143Smckusick register struct inode *ip = VTOI(vp); 59638143Smckusick register struct ufid *ufhp; 59737737Smckusick 59838143Smckusick ufhp = (struct ufid *)fhp; 59938143Smckusick ufhp->ufid_len = sizeof(struct ufid); 60038143Smckusick ufhp->ufid_ino = ip->i_number; 60138143Smckusick ufhp->ufid_gen = ip->i_gen; 60238143Smckusick return (0); 60337737Smckusick } 60437737Smckusick 60537737Smckusick /* 60637737Smckusick * Common code for mount and quota. 60712795Ssam * Check that the user's argument is a reasonable 60812795Ssam * thing on which to mount, and return the device number if so. 60912795Ssam */ 61037737Smckusick getmdev(devvpp, fname, ndp) 61137737Smckusick struct vnode **devvpp; 61216697Smckusick caddr_t fname; 61337737Smckusick register struct nameidata *ndp; 61412795Ssam { 61537737Smckusick register struct vnode *vp; 61637737Smckusick int error; 61712795Ssam 61837737Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 61916697Smckusick ndp->ni_segflg = UIO_USERSPACE; 62016697Smckusick ndp->ni_dirp = fname; 62137737Smckusick if (error = namei(ndp)) { 62237737Smckusick if (error == ENOENT) 62337737Smckusick return (ENODEV); /* needs translation */ 62437737Smckusick return (error); 62521013Smckusick } 62637737Smckusick vp = ndp->ni_vp; 62737737Smckusick if (vp->v_type != VBLK) { 62837737Smckusick vput(vp); 62912795Ssam return (ENOTBLK); 63015956Skarels } 63139532Smckusick if (major(vp->v_rdev) >= nblkdev) { 63239532Smckusick vput(vp); 63312795Ssam return (ENXIO); 63439532Smckusick } 63537737Smckusick iunlock(VTOI(vp)); 63637737Smckusick *devvpp = vp; 63712795Ssam return (0); 63812795Ssam } 639