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*40371Smckusick * @(#)lfs_vfsops.c 7.36 (Berkeley) 03/08/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; 10640346Smckusick bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 10737737Smckusick fs->fs_fsmnt[0] = '/'; 10840346Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->m_stat.f_mntonname, MNAMELEN); 10940346Smckusick (void) copystr(ROOTNAME, mp->m_stat.f_mntfromname, MNAMELEN - 1, &size); 11040346Smckusick bzero(mp->m_stat.f_mntfromname + size, MNAMELEN - size); 11140346Smckusick (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) 12340346Smckusick 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); 137*40371Smckusick /* 138*40371Smckusick * Process export requests. 139*40371Smckusick */ 140*40371Smckusick if ((args.exflags & M_EXPORTED) || (mp->m_flag & M_EXPORTED)) { 141*40371Smckusick if (args.exflags & M_EXPORTED) 142*40371Smckusick mp->m_flag |= M_EXPORTED; 143*40371Smckusick else 144*40371Smckusick mp->m_flag &= ~M_EXPORTED; 145*40371Smckusick if (args.exflags & M_EXRDONLY) 146*40371Smckusick mp->m_flag |= M_EXRDONLY; 147*40371Smckusick else 148*40371Smckusick mp->m_flag &= ~M_EXRDONLY; 149*40371Smckusick mp->m_exroot = args.exroot; 150*40371Smckusick } 15139336Smckusick if ((mp->m_flag & M_UPDATE) == 0) { 152*40371Smckusick if ((error = getmdev(&devvp, args.fspec, ndp)) != 0) 153*40371Smckusick return (error); 15439336Smckusick error = mountfs(devvp, mp); 15539336Smckusick } else { 15639336Smckusick ump = VFSTOUFS(mp); 15739336Smckusick fs = ump->um_fs; 15839336Smckusick if (fs->fs_ronly && (mp->m_flag & M_RDONLY) == 0) 15939336Smckusick fs->fs_ronly = 0; 16039336Smckusick /* 16139336Smckusick * Verify that the specified device is the one that 16239336Smckusick * is really being used for the root file system. 16339336Smckusick */ 164*40371Smckusick if (args.fspec == 0) 165*40371Smckusick return (0); 166*40371Smckusick if ((error = getmdev(&devvp, args.fspec, ndp)) != 0) 167*40371Smckusick return (error); 16839336Smckusick if (devvp != ump->um_devvp) 16939336Smckusick error = EINVAL; /* needs translation */ 17039336Smckusick } 17137737Smckusick if (error) { 17237737Smckusick vrele(devvp); 17337737Smckusick return (error); 17432721Smckusick } 17537737Smckusick ump = VFSTOUFS(mp); 17637737Smckusick fs = ump->um_fs; 17737737Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 17837737Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 17940346Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->m_stat.f_mntonname, MNAMELEN); 18040346Smckusick (void) copyinstr(args.fspec, mp->m_stat.f_mntfromname, MNAMELEN - 1, 18140346Smckusick &size); 18240346Smckusick bzero(mp->m_stat.f_mntfromname + size, MNAMELEN - size); 18340346Smckusick (void) ufs_statfs(mp, &mp->m_stat); 18437737Smckusick return (0); 18512795Ssam } 18612795Ssam 18737737Smckusick /* 18837737Smckusick * Common code for mount and mountroot 18937737Smckusick */ 19037737Smckusick mountfs(devvp, mp) 19137737Smckusick struct vnode *devvp; 19237737Smckusick struct mount *mp; 19312795Ssam { 19437737Smckusick register struct ufsmount *ump; 19537737Smckusick struct ufsmount *fmp = NULL; 19637737Smckusick struct buf *bp = NULL; 19712795Ssam register struct fs *fs; 19837737Smckusick dev_t dev = devvp->v_rdev; 19930749Skarels struct partinfo dpart; 20037737Smckusick caddr_t base, space; 20130749Skarels int havepart = 0, blks; 20237737Smckusick int error, i, size; 20321013Smckusick int needclose = 0; 20437737Smckusick int ronly = (mp->m_flag & M_RDONLY) != 0; 20512795Ssam 20637737Smckusick for (ump = &mounttab[0]; ump < &mounttab[NMOUNT]; ump++) { 20737737Smckusick if (ump->um_fs == NULL) { 20832721Smckusick if (fmp == NULL) 20937737Smckusick fmp = ump; 21037737Smckusick } else if (dev == ump->um_dev) { 21137737Smckusick return (EBUSY); /* needs translation */ 21232721Smckusick } 21332721Smckusick } 21437737Smckusick if ((ump = fmp) == NULL) 21537737Smckusick return (EMFILE); /* needs translation */ 21637737Smckusick ump->um_fs = (struct fs *)1; /* just to reserve this slot */ 21738776Smckusick error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 21832721Smckusick if (error) { 21937737Smckusick ump->um_fs = NULL; 22037737Smckusick return (error); 22132721Smckusick } 22221013Smckusick needclose = 1; 22338776Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED) != 0) 22437737Smckusick size = DEV_BSIZE; 22537737Smckusick else { 22630749Skarels havepart = 1; 22730749Skarels size = dpart.disklab->d_secsize; 22837737Smckusick } 22938776Smckusick if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) { 23037737Smckusick ump->um_fs = NULL; 23112795Ssam goto out; 23232721Smckusick } 23334421Skarels fs = bp->b_un.b_fs; 23430749Skarels if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 23530749Skarels fs->fs_bsize < sizeof(struct fs)) { 23637737Smckusick ump->um_fs = NULL; 23737737Smckusick error = EINVAL; /* XXX also needs translation */ 23816639Skarels goto out; 23916639Skarels } 24037737Smckusick ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK, 24134473Smckusick M_WAITOK); 24237737Smckusick bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs, 24312795Ssam (u_int)fs->fs_sbsize); 24439675Smckusick if (fs->fs_sbsize < SBSIZE) 24539675Smckusick bp->b_flags |= B_INVAL; 24634421Skarels brelse(bp); 24734421Skarels bp = NULL; 24837737Smckusick fs = ump->um_fs; 24937737Smckusick fs->fs_ronly = ronly; 25012795Ssam if (ronly == 0) 25112795Ssam fs->fs_fmod = 1; 25230749Skarels if (havepart) { 25330749Skarels dpart.part->p_fstype = FS_BSDFFS; 25430749Skarels dpart.part->p_fsize = fs->fs_fsize; 25530749Skarels dpart.part->p_frag = fs->fs_frag; 25631385Skarels dpart.part->p_cpg = fs->fs_cpg; 25730749Skarels } 25812795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 25934473Smckusick base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK, 26034473Smckusick M_WAITOK); 26112795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 26212795Ssam size = fs->fs_bsize; 26312795Ssam if (i + fs->fs_frag > blks) 26412795Ssam size = (blks - i) * fs->fs_fsize; 26538776Smckusick error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 26638776Smckusick NOCRED, &bp); 26737737Smckusick if (error) { 26834473Smckusick free((caddr_t)base, M_SUPERBLK); 26912795Ssam goto out; 27012795Ssam } 27134421Skarels bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size); 27217225Smckusick fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 27312795Ssam space += size; 27434421Skarels brelse(bp); 27534421Skarels bp = NULL; 27612795Ssam } 27737737Smckusick mp->m_data = (qaddr_t)ump; 27840346Smckusick mp->m_stat.f_fsid.val[0] = (long)dev; 27940346Smckusick mp->m_stat.f_fsid.val[1] = MOUNT_UFS; 28037737Smckusick ump->um_mountp = mp; 28137737Smckusick ump->um_dev = dev; 28237737Smckusick ump->um_devvp = devvp; 28337737Smckusick ump->um_qinod = NULL; 28437737Smckusick 28530383Smckusick /* Sanity checks for old file systems. XXX */ 28630383Smckusick fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */ 28730383Smckusick fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */ 28834145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 28934145Smckusick fs->fs_nrpos = 8; /* XXX */ 29037737Smckusick return (0); 29112795Ssam out: 29232721Smckusick if (needclose) 29338776Smckusick (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 29437737Smckusick if (ump->um_fs) { 29537737Smckusick free((caddr_t)ump->um_fs, M_SUPERBLK); 29637737Smckusick ump->um_fs = NULL; 29732721Smckusick } 29834421Skarels if (bp) 29934421Skarels brelse(bp); 30037737Smckusick return (error); 30112795Ssam } 30212795Ssam 30339043Smckusick /* 30439043Smckusick * Make a filesystem operational. 30539043Smckusick * Nothing to do at the moment. 30639043Smckusick */ 30739390Smckusick /* ARGSUSED */ 30839043Smckusick ufs_start(mp, flags) 30939043Smckusick struct mount *mp; 31039043Smckusick int flags; 31139043Smckusick { 31212795Ssam 31339043Smckusick return (0); 31439043Smckusick } 31539043Smckusick 31637737Smckusick /* 31737737Smckusick * unmount system call 31837737Smckusick */ 31937737Smckusick ufs_unmount(mp, flags) 32037737Smckusick struct mount *mp; 32137737Smckusick int flags; 32212795Ssam { 32337737Smckusick register struct ufsmount *ump; 32437737Smckusick register struct fs *fs; 32537737Smckusick int error, ronly; 32612795Ssam 32737737Smckusick if (flags & MNT_FORCE) 32837737Smckusick return (EINVAL); 32939675Smckusick mntflushbuf(mp, 0); 33039675Smckusick if (mntinvalbuf(mp)) 33139675Smckusick return (EBUSY); 33237737Smckusick ump = VFSTOUFS(mp); 33312795Ssam #ifdef QUOTA 33439898Smckusick if (ump->um_qinod) { 33539898Smckusick if (error = vflush(mp, ITOV(ump->um_qinod), flags)) 33639898Smckusick return (error); 33739898Smckusick (void) closedq(ump); 33839898Smckusick /* 33939898Smckusick * Here we have to vflush again to get rid of the quota inode. 34039898Smckusick * A drag, but it would be ugly to cheat, and this system 34139898Smckusick * call does not happen often. 34239898Smckusick */ 34339898Smckusick if (vflush(mp, (struct vnode *)NULL, MNT_NOFORCE)) 34439898Smckusick panic("ufs_unmount: quota"); 34539898Smckusick } else 34612795Ssam #endif 34739898Smckusick if (error = vflush(mp, (struct vnode *)NULL, flags)) 34839898Smckusick return (error); 34937737Smckusick fs = ump->um_fs; 35037737Smckusick ronly = !fs->fs_ronly; 35131660Smckusick free((caddr_t)fs->fs_csp[0], M_SUPERBLK); 35237737Smckusick free((caddr_t)fs, M_SUPERBLK); 35337737Smckusick ump->um_fs = NULL; 35437737Smckusick ump->um_dev = NODEV; 35538776Smckusick error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 35637737Smckusick vrele(ump->um_devvp); 35737737Smckusick ump->um_devvp = (struct vnode *)0; 35830749Skarels return (error); 35912795Ssam } 36012795Ssam 36137737Smckusick /* 36237737Smckusick * Return root of a filesystem 36337737Smckusick */ 36437737Smckusick ufs_root(mp, vpp) 36512795Ssam struct mount *mp; 36637737Smckusick struct vnode **vpp; 36712795Ssam { 36839390Smckusick register struct inode *ip; 36939390Smckusick struct inode *nip; 37039390Smckusick struct vnode tvp; 37137737Smckusick int error; 37237737Smckusick 37339390Smckusick tvp.v_mount = mp; 37439390Smckusick ip = VTOI(&tvp); 37539390Smckusick ip->i_vnode = &tvp; 37639390Smckusick ip->i_dev = VFSTOUFS(mp)->um_dev; 37739390Smckusick error = iget(ip, (ino_t)ROOTINO, &nip); 37837737Smckusick if (error) 37937737Smckusick return (error); 38039390Smckusick *vpp = ITOV(nip); 38137737Smckusick return (0); 38237737Smckusick } 38337737Smckusick 38437737Smckusick /* 38537737Smckusick * Get file system statistics. 38637737Smckusick */ 38737737Smckusick ufs_statfs(mp, sbp) 38837737Smckusick struct mount *mp; 38937737Smckusick register struct statfs *sbp; 39037737Smckusick { 39137737Smckusick register struct ufsmount *ump; 39237737Smckusick register struct fs *fs; 39337737Smckusick 39437737Smckusick ump = VFSTOUFS(mp); 39537737Smckusick fs = ump->um_fs; 39637737Smckusick if (fs->fs_magic != FS_MAGIC) 39737737Smckusick panic("ufs_statfs"); 39837737Smckusick sbp->f_type = MOUNT_UFS; 39937737Smckusick sbp->f_fsize = fs->fs_fsize; 40037737Smckusick sbp->f_bsize = fs->fs_bsize; 40137737Smckusick sbp->f_blocks = fs->fs_dsize; 40237737Smckusick sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 40337737Smckusick fs->fs_cstotal.cs_nffree; 40437737Smckusick sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 40537737Smckusick (fs->fs_dsize - sbp->f_bfree); 40639350Smckusick sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 40737737Smckusick sbp->f_ffree = fs->fs_cstotal.cs_nifree; 40840346Smckusick if (sbp != &mp->m_stat) { 40940346Smckusick bcopy((caddr_t)mp->m_stat.f_mntonname, 41040346Smckusick (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 41140346Smckusick bcopy((caddr_t)mp->m_stat.f_mntfromname, 41240346Smckusick (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 41340346Smckusick } 41437737Smckusick return (0); 41537737Smckusick } 41637737Smckusick 41737737Smckusick int syncprt = 0; 41837737Smckusick 41937737Smckusick /* 42037737Smckusick * Go through the disk queues to initiate sandbagged IO; 42137737Smckusick * go through the inodes to write those that have been modified; 42237737Smckusick * initiate the writing of the super block if it has been modified. 42337737Smckusick */ 42437737Smckusick ufs_sync(mp, waitfor) 42537737Smckusick struct mount *mp; 42637737Smckusick int waitfor; 42737737Smckusick { 42839390Smckusick register struct vnode *vp; 42937737Smckusick register struct inode *ip; 43037737Smckusick register struct ufsmount *ump = VFSTOUFS(mp); 43137737Smckusick register struct fs *fs; 43239877Smckusick struct vnode *nvp; 43339596Smckusick int error, allerror = 0; 43437737Smckusick static int updlock = 0; 43537737Smckusick 43637737Smckusick if (syncprt) 43737737Smckusick bufstats(); 43837737Smckusick if (updlock) 43937737Smckusick return (EBUSY); 44037737Smckusick fs = ump->um_fs; 44137737Smckusick if (fs == (struct fs *)1) 44237737Smckusick return (0); 44337737Smckusick updlock++; 44437737Smckusick /* 44537737Smckusick * Write back modified superblock. 44637737Smckusick * Consistency check that the superblock 44737737Smckusick * is still in the buffer cache. 44837737Smckusick */ 44937737Smckusick if (fs->fs_fmod != 0) { 45037737Smckusick if (fs->fs_ronly != 0) { /* XXX */ 45137737Smckusick printf("fs = %s\n", fs->fs_fsmnt); 45237737Smckusick panic("update: rofs mod"); 45337737Smckusick } 45437737Smckusick fs->fs_fmod = 0; 45537737Smckusick fs->fs_time = time.tv_sec; 45637737Smckusick error = sbupdate(ump, waitfor); 45737737Smckusick } 45837737Smckusick /* 45937737Smckusick * Write back each (modified) inode. 46037737Smckusick */ 46139877Smckusick loop: 46239877Smckusick for (vp = mp->m_mounth; vp; vp = nvp) { 46339877Smckusick nvp = vp->v_mountf; 46439390Smckusick ip = VTOI(vp); 46539877Smckusick if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 && 46639877Smckusick vp->v_dirtyblkhd == NULL) 46737737Smckusick continue; 46839877Smckusick if (vget(vp)) 46939877Smckusick goto loop; 47039877Smckusick if (vp->v_dirtyblkhd) 47139877Smckusick vflushbuf(vp, 0); 47239877Smckusick if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) && 47339877Smckusick (error = iupdat(ip, &time, &time, 0))) 47439596Smckusick allerror = error; 47539596Smckusick vput(vp); 47637737Smckusick } 47737737Smckusick updlock = 0; 47837737Smckusick /* 47939675Smckusick * Force stale file system control information to be flushed. 48037737Smckusick */ 48139675Smckusick vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0); 48239596Smckusick return (allerror); 48337737Smckusick } 48437737Smckusick 48537737Smckusick /* 48637737Smckusick * Write a superblock and associated information back to disk. 48737737Smckusick */ 48837737Smckusick sbupdate(mp, waitfor) 48937737Smckusick struct ufsmount *mp; 49037737Smckusick int waitfor; 49137737Smckusick { 49237737Smckusick register struct fs *fs = mp->um_fs; 49312795Ssam register struct buf *bp; 49412795Ssam int blks; 49512795Ssam caddr_t space; 49637737Smckusick int i, size, error = 0; 49712795Ssam 49837737Smckusick bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize); 49912795Ssam bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); 50034145Smckusick /* Restore compatibility to old file systems. XXX */ 50134145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 50234145Smckusick bp->b_un.b_fs->fs_nrpos = -1; /* XXX */ 50337737Smckusick if (waitfor == MNT_WAIT) 50437737Smckusick error = bwrite(bp); 50537737Smckusick else 50637737Smckusick bawrite(bp); 50712795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 50812795Ssam space = (caddr_t)fs->fs_csp[0]; 50912795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 51012795Ssam size = fs->fs_bsize; 51112795Ssam if (i + fs->fs_frag > blks) 51212795Ssam size = (blks - i) * fs->fs_fsize; 51337737Smckusick bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size); 51412795Ssam bcopy(space, bp->b_un.b_addr, (u_int)size); 51512795Ssam space += size; 51637737Smckusick if (waitfor == MNT_WAIT) 51737737Smckusick error = bwrite(bp); 51837737Smckusick else 51937737Smckusick bawrite(bp); 52012795Ssam } 52137737Smckusick return (error); 52212795Ssam } 52312795Ssam 52412795Ssam /* 52537737Smckusick * Print out statistics on the current allocation of the buffer pool. 52637737Smckusick * Can be enabled to print out on every ``sync'' by setting "syncprt" 52737737Smckusick * above. 52837737Smckusick */ 52937737Smckusick bufstats() 53037737Smckusick { 53137737Smckusick int s, i, j, count; 53237737Smckusick register struct buf *bp, *dp; 53337737Smckusick int counts[MAXBSIZE/CLBYTES+1]; 53437737Smckusick static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; 53537737Smckusick 53637737Smckusick for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { 53737737Smckusick count = 0; 53837737Smckusick for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 53937737Smckusick counts[j] = 0; 54037737Smckusick s = splbio(); 54137737Smckusick for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { 54237737Smckusick counts[dp->b_bufsize/CLBYTES]++; 54337737Smckusick count++; 54437737Smckusick } 54537737Smckusick splx(s); 54637737Smckusick printf("%s: total-%d", bname[i], count); 54737737Smckusick for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 54837737Smckusick if (counts[j] != 0) 54937737Smckusick printf(", %d-%d", j * CLBYTES, counts[j]); 55037737Smckusick printf("\n"); 55137737Smckusick } 55237737Smckusick } 55337737Smckusick 55437737Smckusick /* 55537737Smckusick * File handle to vnode 55638453Smckusick * 55738453Smckusick * Have to be really careful about stale file handles: 55838453Smckusick * - check that the inode number is in range 55938453Smckusick * - call iget() to get the locked inode 56038453Smckusick * - check for an unallocated inode (i_mode == 0) 56138453Smckusick * - check that the generation number matches 56237737Smckusick */ 56337737Smckusick ufs_fhtovp(mp, fhp, vpp) 56438453Smckusick register struct mount *mp; 56537737Smckusick struct fid *fhp; 56637737Smckusick struct vnode **vpp; 56737737Smckusick { 56837737Smckusick register struct ufid *ufhp; 56938453Smckusick register struct fs *fs; 57039390Smckusick register struct inode *ip; 57139390Smckusick struct inode *nip; 57239390Smckusick struct vnode tvp; 57337737Smckusick int error; 57437737Smckusick 57537737Smckusick ufhp = (struct ufid *)fhp; 57638453Smckusick fs = VFSTOUFS(mp)->um_fs; 57738453Smckusick if (ufhp->ufid_ino < ROOTINO || 57838453Smckusick ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) { 57938453Smckusick *vpp = (struct vnode *)0; 58038453Smckusick return (EINVAL); 58138453Smckusick } 58239390Smckusick tvp.v_mount = mp; 58339390Smckusick ip = VTOI(&tvp); 58439390Smckusick ip->i_vnode = &tvp; 58539390Smckusick ip->i_dev = VFSTOUFS(mp)->um_dev; 58639390Smckusick if (error = iget(ip, ufhp->ufid_ino, &nip)) { 58738453Smckusick *vpp = (struct vnode *)0; 58837737Smckusick return (error); 58937737Smckusick } 59039390Smckusick ip = nip; 59138453Smckusick if (ip->i_mode == 0) { 59238453Smckusick iput(ip); 59338453Smckusick *vpp = (struct vnode *)0; 59438453Smckusick return (EINVAL); 59538453Smckusick } 59637737Smckusick if (ip->i_gen != ufhp->ufid_gen) { 59737737Smckusick iput(ip); 59838453Smckusick *vpp = (struct vnode *)0; 59937737Smckusick return (EINVAL); 60037737Smckusick } 60137737Smckusick *vpp = ITOV(ip); 60237737Smckusick return (0); 60337737Smckusick } 60437737Smckusick 60537737Smckusick /* 60638355Smckusick * Vnode pointer to File handle 60737737Smckusick */ 60837737Smckusick /* ARGSUSED */ 60938143Smckusick ufs_vptofh(vp, fhp) 61038143Smckusick struct vnode *vp; 61137737Smckusick struct fid *fhp; 61237737Smckusick { 61338143Smckusick register struct inode *ip = VTOI(vp); 61438143Smckusick register struct ufid *ufhp; 61537737Smckusick 61638143Smckusick ufhp = (struct ufid *)fhp; 61738143Smckusick ufhp->ufid_len = sizeof(struct ufid); 61838143Smckusick ufhp->ufid_ino = ip->i_number; 61938143Smckusick ufhp->ufid_gen = ip->i_gen; 62038143Smckusick return (0); 62137737Smckusick } 62237737Smckusick 62337737Smckusick /* 62437737Smckusick * Common code for mount and quota. 62512795Ssam * Check that the user's argument is a reasonable 62612795Ssam * thing on which to mount, and return the device number if so. 62712795Ssam */ 62837737Smckusick getmdev(devvpp, fname, ndp) 62937737Smckusick struct vnode **devvpp; 63016697Smckusick caddr_t fname; 63137737Smckusick register struct nameidata *ndp; 63212795Ssam { 63337737Smckusick register struct vnode *vp; 63437737Smckusick int error; 63512795Ssam 63637737Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 63716697Smckusick ndp->ni_segflg = UIO_USERSPACE; 63816697Smckusick ndp->ni_dirp = fname; 63937737Smckusick if (error = namei(ndp)) { 64037737Smckusick if (error == ENOENT) 64137737Smckusick return (ENODEV); /* needs translation */ 64237737Smckusick return (error); 64321013Smckusick } 64437737Smckusick vp = ndp->ni_vp; 64537737Smckusick if (vp->v_type != VBLK) { 64637737Smckusick vput(vp); 64712795Ssam return (ENOTBLK); 64815956Skarels } 64939532Smckusick if (major(vp->v_rdev) >= nblkdev) { 65039532Smckusick vput(vp); 65112795Ssam return (ENXIO); 65239532Smckusick } 65337737Smckusick iunlock(VTOI(vp)); 65437737Smckusick *devvpp = vp; 65512795Ssam return (0); 65612795Ssam } 657