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*40376Smckusick * @(#)lfs_vfsops.c 7.37 (Berkeley) 03/09/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); 13740371Smckusick /* 13840371Smckusick * Process export requests. 13940371Smckusick */ 14040371Smckusick if ((args.exflags & M_EXPORTED) || (mp->m_flag & M_EXPORTED)) { 14140371Smckusick if (args.exflags & M_EXPORTED) 14240371Smckusick mp->m_flag |= M_EXPORTED; 14340371Smckusick else 14440371Smckusick mp->m_flag &= ~M_EXPORTED; 14540371Smckusick if (args.exflags & M_EXRDONLY) 14640371Smckusick mp->m_flag |= M_EXRDONLY; 14740371Smckusick else 14840371Smckusick mp->m_flag &= ~M_EXRDONLY; 14940371Smckusick mp->m_exroot = args.exroot; 15040371Smckusick } 15139336Smckusick if ((mp->m_flag & M_UPDATE) == 0) { 15240371Smckusick if ((error = getmdev(&devvp, args.fspec, ndp)) != 0) 15340371Smckusick 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 */ 16440371Smckusick if (args.fspec == 0) 16540371Smckusick return (0); 16640371Smckusick if ((error = getmdev(&devvp, args.fspec, ndp)) != 0) 16740371Smckusick 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) 191*40376Smckusick register struct vnode *devvp; 19237737Smckusick struct mount *mp; 19312795Ssam { 19437737Smckusick register struct ufsmount *ump; 19537737Smckusick struct buf *bp = NULL; 19612795Ssam register struct fs *fs; 19737737Smckusick dev_t dev = devvp->v_rdev; 19830749Skarels struct partinfo dpart; 19937737Smckusick caddr_t base, space; 20030749Skarels int havepart = 0, blks; 20137737Smckusick int error, i, size; 20221013Smckusick int needclose = 0; 20337737Smckusick int ronly = (mp->m_flag & M_RDONLY) != 0; 20412795Ssam 205*40376Smckusick /* 206*40376Smckusick * Disallow multiple mounts of the same device. 207*40376Smckusick * Disallow mounting of a device that is currently in use. 208*40376Smckusick * Flush out any old buffers remaining from a previous use. 209*40376Smckusick */ 210*40376Smckusick if (error = mountedon(devvp)) 211*40376Smckusick return (error); 212*40376Smckusick if (vcount(devvp) > 1) 213*40376Smckusick return (EBUSY); 214*40376Smckusick vinvalbuf(devvp, 1); 215*40376Smckusick for (ump = &mounttab[0]; ump < &mounttab[NMOUNT]; ump++) 216*40376Smckusick if (ump->um_fs == NULL) 217*40376Smckusick break; 218*40376Smckusick if (ump >= &mounttab[NMOUNT]) 21937737Smckusick return (EMFILE); /* needs translation */ 22037737Smckusick ump->um_fs = (struct fs *)1; /* just to reserve this slot */ 22138776Smckusick error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 22232721Smckusick if (error) { 22337737Smckusick ump->um_fs = NULL; 22437737Smckusick return (error); 22532721Smckusick } 22621013Smckusick needclose = 1; 22738776Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED) != 0) 22837737Smckusick size = DEV_BSIZE; 22937737Smckusick else { 23030749Skarels havepart = 1; 23130749Skarels size = dpart.disklab->d_secsize; 23237737Smckusick } 23338776Smckusick if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) { 23437737Smckusick ump->um_fs = NULL; 23512795Ssam goto out; 23632721Smckusick } 23734421Skarels fs = bp->b_un.b_fs; 23830749Skarels if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 23930749Skarels fs->fs_bsize < sizeof(struct fs)) { 24037737Smckusick ump->um_fs = NULL; 24137737Smckusick error = EINVAL; /* XXX also needs translation */ 24216639Skarels goto out; 24316639Skarels } 24437737Smckusick ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK, 24534473Smckusick M_WAITOK); 24637737Smckusick bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs, 24712795Ssam (u_int)fs->fs_sbsize); 24839675Smckusick if (fs->fs_sbsize < SBSIZE) 24939675Smckusick bp->b_flags |= B_INVAL; 25034421Skarels brelse(bp); 25134421Skarels bp = NULL; 25237737Smckusick fs = ump->um_fs; 25337737Smckusick fs->fs_ronly = ronly; 25412795Ssam if (ronly == 0) 25512795Ssam fs->fs_fmod = 1; 25630749Skarels if (havepart) { 25730749Skarels dpart.part->p_fstype = FS_BSDFFS; 25830749Skarels dpart.part->p_fsize = fs->fs_fsize; 25930749Skarels dpart.part->p_frag = fs->fs_frag; 26031385Skarels dpart.part->p_cpg = fs->fs_cpg; 26130749Skarels } 26212795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 26334473Smckusick base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK, 26434473Smckusick M_WAITOK); 26512795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 26612795Ssam size = fs->fs_bsize; 26712795Ssam if (i + fs->fs_frag > blks) 26812795Ssam size = (blks - i) * fs->fs_fsize; 26938776Smckusick error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 27038776Smckusick NOCRED, &bp); 27137737Smckusick if (error) { 27234473Smckusick free((caddr_t)base, M_SUPERBLK); 27312795Ssam goto out; 27412795Ssam } 27534421Skarels bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size); 27617225Smckusick fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 27712795Ssam space += size; 27834421Skarels brelse(bp); 27934421Skarels bp = NULL; 28012795Ssam } 28137737Smckusick mp->m_data = (qaddr_t)ump; 28240346Smckusick mp->m_stat.f_fsid.val[0] = (long)dev; 28340346Smckusick mp->m_stat.f_fsid.val[1] = MOUNT_UFS; 28437737Smckusick ump->um_mountp = mp; 28537737Smckusick ump->um_dev = dev; 28637737Smckusick ump->um_devvp = devvp; 28737737Smckusick ump->um_qinod = NULL; 288*40376Smckusick devvp->v_specinfo->si_flags |= SI_MOUNTEDON; 28937737Smckusick 29030383Smckusick /* Sanity checks for old file systems. XXX */ 29130383Smckusick fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */ 29230383Smckusick fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */ 29334145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 29434145Smckusick fs->fs_nrpos = 8; /* XXX */ 29537737Smckusick return (0); 29612795Ssam out: 29732721Smckusick if (needclose) 29838776Smckusick (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 29937737Smckusick if (ump->um_fs) { 30037737Smckusick free((caddr_t)ump->um_fs, M_SUPERBLK); 30137737Smckusick ump->um_fs = NULL; 30232721Smckusick } 30334421Skarels if (bp) 30434421Skarels brelse(bp); 30537737Smckusick return (error); 30612795Ssam } 30712795Ssam 30839043Smckusick /* 30939043Smckusick * Make a filesystem operational. 31039043Smckusick * Nothing to do at the moment. 31139043Smckusick */ 31239390Smckusick /* ARGSUSED */ 31339043Smckusick ufs_start(mp, flags) 31439043Smckusick struct mount *mp; 31539043Smckusick int flags; 31639043Smckusick { 31712795Ssam 31839043Smckusick return (0); 31939043Smckusick } 32039043Smckusick 32137737Smckusick /* 32237737Smckusick * unmount system call 32337737Smckusick */ 32437737Smckusick ufs_unmount(mp, flags) 32537737Smckusick struct mount *mp; 32637737Smckusick int flags; 32712795Ssam { 32837737Smckusick register struct ufsmount *ump; 32937737Smckusick register struct fs *fs; 33037737Smckusick int error, ronly; 33112795Ssam 33237737Smckusick if (flags & MNT_FORCE) 33337737Smckusick return (EINVAL); 33439675Smckusick mntflushbuf(mp, 0); 33539675Smckusick if (mntinvalbuf(mp)) 33639675Smckusick return (EBUSY); 33737737Smckusick ump = VFSTOUFS(mp); 33812795Ssam #ifdef QUOTA 33939898Smckusick if (ump->um_qinod) { 34039898Smckusick if (error = vflush(mp, ITOV(ump->um_qinod), flags)) 34139898Smckusick return (error); 34239898Smckusick (void) closedq(ump); 34339898Smckusick /* 34439898Smckusick * Here we have to vflush again to get rid of the quota inode. 34539898Smckusick * A drag, but it would be ugly to cheat, and this system 34639898Smckusick * call does not happen often. 34739898Smckusick */ 34839898Smckusick if (vflush(mp, (struct vnode *)NULL, MNT_NOFORCE)) 34939898Smckusick panic("ufs_unmount: quota"); 35039898Smckusick } else 35112795Ssam #endif 35239898Smckusick if (error = vflush(mp, (struct vnode *)NULL, flags)) 35339898Smckusick return (error); 35437737Smckusick fs = ump->um_fs; 35537737Smckusick ronly = !fs->fs_ronly; 35631660Smckusick free((caddr_t)fs->fs_csp[0], M_SUPERBLK); 35737737Smckusick free((caddr_t)fs, M_SUPERBLK); 35837737Smckusick ump->um_fs = NULL; 35937737Smckusick ump->um_dev = NODEV; 360*40376Smckusick ump->um_devvp->v_specinfo->si_flags &= ~SI_MOUNTEDON; 36138776Smckusick error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 36237737Smckusick vrele(ump->um_devvp); 36337737Smckusick ump->um_devvp = (struct vnode *)0; 36430749Skarels return (error); 36512795Ssam } 36612795Ssam 36737737Smckusick /* 368*40376Smckusick * Check to see if a filesystem is mounted on a block device. 369*40376Smckusick */ 370*40376Smckusick mountedon(vp) 371*40376Smckusick register struct vnode *vp; 372*40376Smckusick { 373*40376Smckusick register struct vnode *vq; 374*40376Smckusick 375*40376Smckusick if (vp->v_specinfo->si_flags & SI_MOUNTEDON) 376*40376Smckusick return (EBUSY); 377*40376Smckusick if (vp->v_flag & VALIASED) { 378*40376Smckusick for (vq = *vp->v_specinfo->si_hashchain; vq; 379*40376Smckusick vq = vq->v_specinfo->si_specnext) { 380*40376Smckusick if (vq->v_rdev != vp->v_rdev || 381*40376Smckusick vq->v_type != vp->v_type) 382*40376Smckusick continue; 383*40376Smckusick if (vq->v_specinfo->si_flags & SI_MOUNTEDON) 384*40376Smckusick return (EBUSY); 385*40376Smckusick } 386*40376Smckusick } 387*40376Smckusick return (0); 388*40376Smckusick } 389*40376Smckusick 390*40376Smckusick /* 39137737Smckusick * Return root of a filesystem 39237737Smckusick */ 39337737Smckusick ufs_root(mp, vpp) 39412795Ssam struct mount *mp; 39537737Smckusick struct vnode **vpp; 39612795Ssam { 39739390Smckusick register struct inode *ip; 39839390Smckusick struct inode *nip; 39939390Smckusick struct vnode tvp; 40037737Smckusick int error; 40137737Smckusick 40239390Smckusick tvp.v_mount = mp; 40339390Smckusick ip = VTOI(&tvp); 40439390Smckusick ip->i_vnode = &tvp; 40539390Smckusick ip->i_dev = VFSTOUFS(mp)->um_dev; 40639390Smckusick error = iget(ip, (ino_t)ROOTINO, &nip); 40737737Smckusick if (error) 40837737Smckusick return (error); 40939390Smckusick *vpp = ITOV(nip); 41037737Smckusick return (0); 41137737Smckusick } 41237737Smckusick 41337737Smckusick /* 41437737Smckusick * Get file system statistics. 41537737Smckusick */ 41637737Smckusick ufs_statfs(mp, sbp) 41737737Smckusick struct mount *mp; 41837737Smckusick register struct statfs *sbp; 41937737Smckusick { 42037737Smckusick register struct ufsmount *ump; 42137737Smckusick register struct fs *fs; 42237737Smckusick 42337737Smckusick ump = VFSTOUFS(mp); 42437737Smckusick fs = ump->um_fs; 42537737Smckusick if (fs->fs_magic != FS_MAGIC) 42637737Smckusick panic("ufs_statfs"); 42737737Smckusick sbp->f_type = MOUNT_UFS; 42837737Smckusick sbp->f_fsize = fs->fs_fsize; 42937737Smckusick sbp->f_bsize = fs->fs_bsize; 43037737Smckusick sbp->f_blocks = fs->fs_dsize; 43137737Smckusick sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 43237737Smckusick fs->fs_cstotal.cs_nffree; 43337737Smckusick sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 43437737Smckusick (fs->fs_dsize - sbp->f_bfree); 43539350Smckusick sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 43637737Smckusick sbp->f_ffree = fs->fs_cstotal.cs_nifree; 43740346Smckusick if (sbp != &mp->m_stat) { 43840346Smckusick bcopy((caddr_t)mp->m_stat.f_mntonname, 43940346Smckusick (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 44040346Smckusick bcopy((caddr_t)mp->m_stat.f_mntfromname, 44140346Smckusick (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 44240346Smckusick } 44337737Smckusick return (0); 44437737Smckusick } 44537737Smckusick 44637737Smckusick int syncprt = 0; 44737737Smckusick 44837737Smckusick /* 44937737Smckusick * Go through the disk queues to initiate sandbagged IO; 45037737Smckusick * go through the inodes to write those that have been modified; 45137737Smckusick * initiate the writing of the super block if it has been modified. 45237737Smckusick */ 45337737Smckusick ufs_sync(mp, waitfor) 45437737Smckusick struct mount *mp; 45537737Smckusick int waitfor; 45637737Smckusick { 45739390Smckusick register struct vnode *vp; 45837737Smckusick register struct inode *ip; 45937737Smckusick register struct ufsmount *ump = VFSTOUFS(mp); 46037737Smckusick register struct fs *fs; 46139877Smckusick struct vnode *nvp; 46239596Smckusick int error, allerror = 0; 46337737Smckusick static int updlock = 0; 46437737Smckusick 46537737Smckusick if (syncprt) 46637737Smckusick bufstats(); 46737737Smckusick if (updlock) 46837737Smckusick return (EBUSY); 46937737Smckusick fs = ump->um_fs; 47037737Smckusick if (fs == (struct fs *)1) 47137737Smckusick return (0); 47237737Smckusick updlock++; 47337737Smckusick /* 47437737Smckusick * Write back modified superblock. 47537737Smckusick * Consistency check that the superblock 47637737Smckusick * is still in the buffer cache. 47737737Smckusick */ 47837737Smckusick if (fs->fs_fmod != 0) { 47937737Smckusick if (fs->fs_ronly != 0) { /* XXX */ 48037737Smckusick printf("fs = %s\n", fs->fs_fsmnt); 48137737Smckusick panic("update: rofs mod"); 48237737Smckusick } 48337737Smckusick fs->fs_fmod = 0; 48437737Smckusick fs->fs_time = time.tv_sec; 48537737Smckusick error = sbupdate(ump, waitfor); 48637737Smckusick } 48737737Smckusick /* 48837737Smckusick * Write back each (modified) inode. 48937737Smckusick */ 49039877Smckusick loop: 49139877Smckusick for (vp = mp->m_mounth; vp; vp = nvp) { 49239877Smckusick nvp = vp->v_mountf; 49339390Smckusick ip = VTOI(vp); 49439877Smckusick if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 && 49539877Smckusick vp->v_dirtyblkhd == NULL) 49637737Smckusick continue; 49739877Smckusick if (vget(vp)) 49839877Smckusick goto loop; 49939877Smckusick if (vp->v_dirtyblkhd) 50039877Smckusick vflushbuf(vp, 0); 50139877Smckusick if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) && 50239877Smckusick (error = iupdat(ip, &time, &time, 0))) 50339596Smckusick allerror = error; 50439596Smckusick vput(vp); 50537737Smckusick } 50637737Smckusick updlock = 0; 50737737Smckusick /* 50839675Smckusick * Force stale file system control information to be flushed. 50937737Smckusick */ 51039675Smckusick vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0); 51139596Smckusick return (allerror); 51237737Smckusick } 51337737Smckusick 51437737Smckusick /* 51537737Smckusick * Write a superblock and associated information back to disk. 51637737Smckusick */ 51737737Smckusick sbupdate(mp, waitfor) 51837737Smckusick struct ufsmount *mp; 51937737Smckusick int waitfor; 52037737Smckusick { 52137737Smckusick register struct fs *fs = mp->um_fs; 52212795Ssam register struct buf *bp; 52312795Ssam int blks; 52412795Ssam caddr_t space; 52537737Smckusick int i, size, error = 0; 52612795Ssam 52737737Smckusick bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize); 52812795Ssam bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); 52934145Smckusick /* Restore compatibility to old file systems. XXX */ 53034145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 53134145Smckusick bp->b_un.b_fs->fs_nrpos = -1; /* XXX */ 53237737Smckusick if (waitfor == MNT_WAIT) 53337737Smckusick error = bwrite(bp); 53437737Smckusick else 53537737Smckusick bawrite(bp); 53612795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 53712795Ssam space = (caddr_t)fs->fs_csp[0]; 53812795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 53912795Ssam size = fs->fs_bsize; 54012795Ssam if (i + fs->fs_frag > blks) 54112795Ssam size = (blks - i) * fs->fs_fsize; 54237737Smckusick bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size); 54312795Ssam bcopy(space, bp->b_un.b_addr, (u_int)size); 54412795Ssam space += size; 54537737Smckusick if (waitfor == MNT_WAIT) 54637737Smckusick error = bwrite(bp); 54737737Smckusick else 54837737Smckusick bawrite(bp); 54912795Ssam } 55037737Smckusick return (error); 55112795Ssam } 55212795Ssam 55312795Ssam /* 55437737Smckusick * Print out statistics on the current allocation of the buffer pool. 55537737Smckusick * Can be enabled to print out on every ``sync'' by setting "syncprt" 55637737Smckusick * above. 55737737Smckusick */ 55837737Smckusick bufstats() 55937737Smckusick { 56037737Smckusick int s, i, j, count; 56137737Smckusick register struct buf *bp, *dp; 56237737Smckusick int counts[MAXBSIZE/CLBYTES+1]; 56337737Smckusick static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; 56437737Smckusick 56537737Smckusick for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { 56637737Smckusick count = 0; 56737737Smckusick for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 56837737Smckusick counts[j] = 0; 56937737Smckusick s = splbio(); 57037737Smckusick for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { 57137737Smckusick counts[dp->b_bufsize/CLBYTES]++; 57237737Smckusick count++; 57337737Smckusick } 57437737Smckusick splx(s); 57537737Smckusick printf("%s: total-%d", bname[i], count); 57637737Smckusick for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 57737737Smckusick if (counts[j] != 0) 57837737Smckusick printf(", %d-%d", j * CLBYTES, counts[j]); 57937737Smckusick printf("\n"); 58037737Smckusick } 58137737Smckusick } 58237737Smckusick 58337737Smckusick /* 58437737Smckusick * File handle to vnode 58538453Smckusick * 58638453Smckusick * Have to be really careful about stale file handles: 58738453Smckusick * - check that the inode number is in range 58838453Smckusick * - call iget() to get the locked inode 58938453Smckusick * - check for an unallocated inode (i_mode == 0) 59038453Smckusick * - check that the generation number matches 59137737Smckusick */ 59237737Smckusick ufs_fhtovp(mp, fhp, vpp) 59338453Smckusick register struct mount *mp; 59437737Smckusick struct fid *fhp; 59537737Smckusick struct vnode **vpp; 59637737Smckusick { 59737737Smckusick register struct ufid *ufhp; 59838453Smckusick register struct fs *fs; 59939390Smckusick register struct inode *ip; 60039390Smckusick struct inode *nip; 60139390Smckusick struct vnode tvp; 60237737Smckusick int error; 60337737Smckusick 60437737Smckusick ufhp = (struct ufid *)fhp; 60538453Smckusick fs = VFSTOUFS(mp)->um_fs; 60638453Smckusick if (ufhp->ufid_ino < ROOTINO || 60738453Smckusick ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) { 60838453Smckusick *vpp = (struct vnode *)0; 60938453Smckusick return (EINVAL); 61038453Smckusick } 61139390Smckusick tvp.v_mount = mp; 61239390Smckusick ip = VTOI(&tvp); 61339390Smckusick ip->i_vnode = &tvp; 61439390Smckusick ip->i_dev = VFSTOUFS(mp)->um_dev; 61539390Smckusick if (error = iget(ip, ufhp->ufid_ino, &nip)) { 61638453Smckusick *vpp = (struct vnode *)0; 61737737Smckusick return (error); 61837737Smckusick } 61939390Smckusick ip = nip; 62038453Smckusick if (ip->i_mode == 0) { 62138453Smckusick iput(ip); 62238453Smckusick *vpp = (struct vnode *)0; 62338453Smckusick return (EINVAL); 62438453Smckusick } 62537737Smckusick if (ip->i_gen != ufhp->ufid_gen) { 62637737Smckusick iput(ip); 62738453Smckusick *vpp = (struct vnode *)0; 62837737Smckusick return (EINVAL); 62937737Smckusick } 63037737Smckusick *vpp = ITOV(ip); 63137737Smckusick return (0); 63237737Smckusick } 63337737Smckusick 63437737Smckusick /* 63538355Smckusick * Vnode pointer to File handle 63637737Smckusick */ 63737737Smckusick /* ARGSUSED */ 63838143Smckusick ufs_vptofh(vp, fhp) 63938143Smckusick struct vnode *vp; 64037737Smckusick struct fid *fhp; 64137737Smckusick { 64238143Smckusick register struct inode *ip = VTOI(vp); 64338143Smckusick register struct ufid *ufhp; 64437737Smckusick 64538143Smckusick ufhp = (struct ufid *)fhp; 64638143Smckusick ufhp->ufid_len = sizeof(struct ufid); 64738143Smckusick ufhp->ufid_ino = ip->i_number; 64838143Smckusick ufhp->ufid_gen = ip->i_gen; 64938143Smckusick return (0); 65037737Smckusick } 65137737Smckusick 65237737Smckusick /* 65337737Smckusick * Common code for mount and quota. 65412795Ssam * Check that the user's argument is a reasonable 65512795Ssam * thing on which to mount, and return the device number if so. 65612795Ssam */ 65737737Smckusick getmdev(devvpp, fname, ndp) 65837737Smckusick struct vnode **devvpp; 65916697Smckusick caddr_t fname; 66037737Smckusick register struct nameidata *ndp; 66112795Ssam { 66237737Smckusick register struct vnode *vp; 66337737Smckusick int error; 66412795Ssam 66537737Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 66616697Smckusick ndp->ni_segflg = UIO_USERSPACE; 66716697Smckusick ndp->ni_dirp = fname; 66837737Smckusick if (error = namei(ndp)) { 66937737Smckusick if (error == ENOENT) 67037737Smckusick return (ENODEV); /* needs translation */ 67137737Smckusick return (error); 67221013Smckusick } 67337737Smckusick vp = ndp->ni_vp; 67437737Smckusick if (vp->v_type != VBLK) { 67537737Smckusick vput(vp); 67612795Ssam return (ENOTBLK); 67715956Skarels } 67839532Smckusick if (major(vp->v_rdev) >= nblkdev) { 67939532Smckusick vput(vp); 68012795Ssam return (ENXIO); 68139532Smckusick } 68237737Smckusick iunlock(VTOI(vp)); 68337737Smckusick *devvpp = vp; 68412795Ssam return (0); 68512795Ssam } 686