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*39898Smckusick * @(#)lfs_vfsops.c 7.34 (Berkeley) 01/13/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; 10637737Smckusick fs->fs_fsmnt[0] = '/'; 10737737Smckusick bzero(fs->fs_fsmnt + 1, sizeof(fs->fs_fsmnt) - 1); 10837737Smckusick (void) copystr(ROOTNAME, ump->um_mntname, MNAMELEN - 1, &size); 10937737Smckusick bzero(ump->um_mntname + size, MNAMELEN - size); 11037737Smckusick vfs_unlock(mp); 11137737Smckusick inittodr(fs->fs_time); 11237737Smckusick return (0); 11337737Smckusick } 11437737Smckusick 11537737Smckusick /* 11637737Smckusick * VFS Operations. 11737737Smckusick * 11837737Smckusick * mount system call 11937737Smckusick */ 12037737Smckusick ufs_mount(mp, path, data, ndp) 12137737Smckusick struct mount *mp; 12237737Smckusick char *path; 12337737Smckusick caddr_t data; 12437737Smckusick struct nameidata *ndp; 12537737Smckusick { 12637737Smckusick struct vnode *devvp; 12737737Smckusick struct ufs_args args; 12837737Smckusick struct ufsmount *ump; 12937737Smckusick register struct fs *fs; 13037737Smckusick u_int size; 13137737Smckusick int error; 13237737Smckusick 13337737Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 13437737Smckusick return (error); 13537737Smckusick if ((error = getmdev(&devvp, args.fspec, ndp)) != 0) 13637737Smckusick return (error); 13739336Smckusick if ((mp->m_flag & M_UPDATE) == 0) { 13839336Smckusick error = mountfs(devvp, mp); 13939336Smckusick } else { 14039336Smckusick ump = VFSTOUFS(mp); 14139336Smckusick fs = ump->um_fs; 14239336Smckusick if (fs->fs_ronly && (mp->m_flag & M_RDONLY) == 0) 14339336Smckusick fs->fs_ronly = 0; 14439336Smckusick /* 14539336Smckusick * Verify that the specified device is the one that 14639336Smckusick * is really being used for the root file system. 14739336Smckusick */ 14839336Smckusick if (devvp != ump->um_devvp) 14939336Smckusick error = EINVAL; /* needs translation */ 15039336Smckusick } 15137737Smckusick if (error) { 15237737Smckusick vrele(devvp); 15337737Smckusick return (error); 15432721Smckusick } 15537737Smckusick ump = VFSTOUFS(mp); 15637737Smckusick fs = ump->um_fs; 15737737Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 15837737Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 15937737Smckusick (void) copyinstr(args.fspec, ump->um_mntname, MNAMELEN - 1, &size); 16037737Smckusick bzero(ump->um_mntname + size, MNAMELEN - size); 16137737Smckusick return (0); 16212795Ssam } 16312795Ssam 16437737Smckusick /* 16537737Smckusick * Common code for mount and mountroot 16637737Smckusick */ 16737737Smckusick mountfs(devvp, mp) 16837737Smckusick struct vnode *devvp; 16937737Smckusick struct mount *mp; 17012795Ssam { 17137737Smckusick register struct ufsmount *ump; 17237737Smckusick struct ufsmount *fmp = NULL; 17337737Smckusick struct buf *bp = NULL; 17412795Ssam register struct fs *fs; 17537737Smckusick dev_t dev = devvp->v_rdev; 17630749Skarels struct partinfo dpart; 17737737Smckusick caddr_t base, space; 17830749Skarels int havepart = 0, blks; 17937737Smckusick int error, i, size; 18021013Smckusick int needclose = 0; 18137737Smckusick int ronly = (mp->m_flag & M_RDONLY) != 0; 18212795Ssam 18337737Smckusick for (ump = &mounttab[0]; ump < &mounttab[NMOUNT]; ump++) { 18437737Smckusick if (ump->um_fs == NULL) { 18532721Smckusick if (fmp == NULL) 18637737Smckusick fmp = ump; 18737737Smckusick } else if (dev == ump->um_dev) { 18837737Smckusick return (EBUSY); /* needs translation */ 18932721Smckusick } 19032721Smckusick } 19137737Smckusick if ((ump = fmp) == NULL) 19237737Smckusick return (EMFILE); /* needs translation */ 19337737Smckusick ump->um_fs = (struct fs *)1; /* just to reserve this slot */ 19438776Smckusick error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 19532721Smckusick if (error) { 19637737Smckusick ump->um_fs = NULL; 19737737Smckusick return (error); 19832721Smckusick } 19921013Smckusick needclose = 1; 20038776Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED) != 0) 20137737Smckusick size = DEV_BSIZE; 20237737Smckusick else { 20330749Skarels havepart = 1; 20430749Skarels size = dpart.disklab->d_secsize; 20537737Smckusick } 20638776Smckusick if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) { 20737737Smckusick ump->um_fs = NULL; 20812795Ssam goto out; 20932721Smckusick } 21034421Skarels fs = bp->b_un.b_fs; 21130749Skarels if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 21230749Skarels fs->fs_bsize < sizeof(struct fs)) { 21337737Smckusick ump->um_fs = NULL; 21437737Smckusick error = EINVAL; /* XXX also needs translation */ 21516639Skarels goto out; 21616639Skarels } 21737737Smckusick ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK, 21834473Smckusick M_WAITOK); 21937737Smckusick bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs, 22012795Ssam (u_int)fs->fs_sbsize); 22139675Smckusick if (fs->fs_sbsize < SBSIZE) 22239675Smckusick bp->b_flags |= B_INVAL; 22334421Skarels brelse(bp); 22434421Skarels bp = NULL; 22537737Smckusick fs = ump->um_fs; 22637737Smckusick fs->fs_ronly = ronly; 22712795Ssam if (ronly == 0) 22812795Ssam fs->fs_fmod = 1; 22930749Skarels if (havepart) { 23030749Skarels dpart.part->p_fstype = FS_BSDFFS; 23130749Skarels dpart.part->p_fsize = fs->fs_fsize; 23230749Skarels dpart.part->p_frag = fs->fs_frag; 23331385Skarels dpart.part->p_cpg = fs->fs_cpg; 23430749Skarels } 23512795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 23634473Smckusick base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK, 23734473Smckusick M_WAITOK); 23812795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 23912795Ssam size = fs->fs_bsize; 24012795Ssam if (i + fs->fs_frag > blks) 24112795Ssam size = (blks - i) * fs->fs_fsize; 24238776Smckusick error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 24338776Smckusick NOCRED, &bp); 24437737Smckusick if (error) { 24534473Smckusick free((caddr_t)base, M_SUPERBLK); 24612795Ssam goto out; 24712795Ssam } 24834421Skarels bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size); 24917225Smckusick fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 25012795Ssam space += size; 25134421Skarels brelse(bp); 25234421Skarels bp = NULL; 25312795Ssam } 25437737Smckusick mp->m_data = (qaddr_t)ump; 25537737Smckusick mp->m_bsize = fs->fs_bsize; 25637737Smckusick mp->m_fsize = fs->fs_fsize; 25737737Smckusick mp->m_fsid.val[0] = (long)dev; 25837737Smckusick mp->m_fsid.val[1] = MOUNT_UFS; 25937737Smckusick ump->um_mountp = mp; 26037737Smckusick ump->um_dev = dev; 26137737Smckusick ump->um_devvp = devvp; 26237737Smckusick ump->um_qinod = NULL; 26337737Smckusick 26430383Smckusick /* Sanity checks for old file systems. XXX */ 26530383Smckusick fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */ 26630383Smckusick fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */ 26734145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 26834145Smckusick fs->fs_nrpos = 8; /* XXX */ 26937737Smckusick return (0); 27012795Ssam out: 27132721Smckusick if (needclose) 27238776Smckusick (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 27337737Smckusick if (ump->um_fs) { 27437737Smckusick free((caddr_t)ump->um_fs, M_SUPERBLK); 27537737Smckusick ump->um_fs = NULL; 27632721Smckusick } 27734421Skarels if (bp) 27834421Skarels brelse(bp); 27937737Smckusick return (error); 28012795Ssam } 28112795Ssam 28239043Smckusick /* 28339043Smckusick * Make a filesystem operational. 28439043Smckusick * Nothing to do at the moment. 28539043Smckusick */ 28639390Smckusick /* ARGSUSED */ 28739043Smckusick ufs_start(mp, flags) 28839043Smckusick struct mount *mp; 28939043Smckusick int flags; 29039043Smckusick { 29112795Ssam 29239043Smckusick return (0); 29339043Smckusick } 29439043Smckusick 29537737Smckusick /* 29637737Smckusick * unmount system call 29737737Smckusick */ 29837737Smckusick ufs_unmount(mp, flags) 29937737Smckusick struct mount *mp; 30037737Smckusick int flags; 30112795Ssam { 30237737Smckusick register struct ufsmount *ump; 30337737Smckusick register struct fs *fs; 30437737Smckusick int error, ronly; 30512795Ssam 30637737Smckusick if (flags & MNT_FORCE) 30737737Smckusick return (EINVAL); 30839675Smckusick mntflushbuf(mp, 0); 30939675Smckusick if (mntinvalbuf(mp)) 31039675Smckusick return (EBUSY); 31137737Smckusick ump = VFSTOUFS(mp); 31212795Ssam #ifdef QUOTA 313*39898Smckusick if (ump->um_qinod) { 314*39898Smckusick if (error = vflush(mp, ITOV(ump->um_qinod), flags)) 315*39898Smckusick return (error); 316*39898Smckusick (void) closedq(ump); 317*39898Smckusick /* 318*39898Smckusick * Here we have to vflush again to get rid of the quota inode. 319*39898Smckusick * A drag, but it would be ugly to cheat, and this system 320*39898Smckusick * call does not happen often. 321*39898Smckusick */ 322*39898Smckusick if (vflush(mp, (struct vnode *)NULL, MNT_NOFORCE)) 323*39898Smckusick panic("ufs_unmount: quota"); 324*39898Smckusick } else 32512795Ssam #endif 326*39898Smckusick if (error = vflush(mp, (struct vnode *)NULL, flags)) 327*39898Smckusick return (error); 32837737Smckusick fs = ump->um_fs; 32937737Smckusick ronly = !fs->fs_ronly; 33031660Smckusick free((caddr_t)fs->fs_csp[0], M_SUPERBLK); 33137737Smckusick free((caddr_t)fs, M_SUPERBLK); 33237737Smckusick ump->um_fs = NULL; 33337737Smckusick ump->um_dev = NODEV; 33438776Smckusick error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 33537737Smckusick vrele(ump->um_devvp); 33637737Smckusick ump->um_devvp = (struct vnode *)0; 33730749Skarels return (error); 33812795Ssam } 33912795Ssam 34037737Smckusick /* 34137737Smckusick * Return root of a filesystem 34237737Smckusick */ 34337737Smckusick ufs_root(mp, vpp) 34412795Ssam struct mount *mp; 34537737Smckusick struct vnode **vpp; 34612795Ssam { 34739390Smckusick register struct inode *ip; 34839390Smckusick struct inode *nip; 34939390Smckusick struct vnode tvp; 35037737Smckusick int error; 35137737Smckusick 35239390Smckusick tvp.v_mount = mp; 35339390Smckusick ip = VTOI(&tvp); 35439390Smckusick ip->i_vnode = &tvp; 35539390Smckusick ip->i_dev = VFSTOUFS(mp)->um_dev; 35639390Smckusick error = iget(ip, (ino_t)ROOTINO, &nip); 35737737Smckusick if (error) 35837737Smckusick return (error); 35939390Smckusick *vpp = ITOV(nip); 36037737Smckusick return (0); 36137737Smckusick } 36237737Smckusick 36337737Smckusick /* 36437737Smckusick * Get file system statistics. 36537737Smckusick */ 36637737Smckusick ufs_statfs(mp, sbp) 36737737Smckusick struct mount *mp; 36837737Smckusick register struct statfs *sbp; 36937737Smckusick { 37037737Smckusick register struct ufsmount *ump; 37137737Smckusick register struct fs *fs; 37237737Smckusick 37337737Smckusick ump = VFSTOUFS(mp); 37437737Smckusick fs = ump->um_fs; 37537737Smckusick if (fs->fs_magic != FS_MAGIC) 37637737Smckusick panic("ufs_statfs"); 37737737Smckusick sbp->f_type = MOUNT_UFS; 37837737Smckusick sbp->f_fsize = fs->fs_fsize; 37937737Smckusick sbp->f_bsize = fs->fs_bsize; 38037737Smckusick sbp->f_blocks = fs->fs_dsize; 38137737Smckusick sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 38237737Smckusick fs->fs_cstotal.cs_nffree; 38337737Smckusick sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 38437737Smckusick (fs->fs_dsize - sbp->f_bfree); 38539350Smckusick sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 38637737Smckusick sbp->f_ffree = fs->fs_cstotal.cs_nifree; 38737737Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 38837737Smckusick bcopy((caddr_t)ump->um_mntname, (caddr_t)&sbp->f_mntfromname[0], 38937737Smckusick MNAMELEN); 39037737Smckusick return (0); 39137737Smckusick } 39237737Smckusick 39337737Smckusick int syncprt = 0; 39437737Smckusick 39537737Smckusick /* 39637737Smckusick * Go through the disk queues to initiate sandbagged IO; 39737737Smckusick * go through the inodes to write those that have been modified; 39837737Smckusick * initiate the writing of the super block if it has been modified. 39937737Smckusick */ 40037737Smckusick ufs_sync(mp, waitfor) 40137737Smckusick struct mount *mp; 40237737Smckusick int waitfor; 40337737Smckusick { 40439390Smckusick register struct vnode *vp; 40537737Smckusick register struct inode *ip; 40637737Smckusick register struct ufsmount *ump = VFSTOUFS(mp); 40737737Smckusick register struct fs *fs; 40839877Smckusick struct vnode *nvp; 40939596Smckusick int error, allerror = 0; 41037737Smckusick static int updlock = 0; 41137737Smckusick 41237737Smckusick if (syncprt) 41337737Smckusick bufstats(); 41437737Smckusick if (updlock) 41537737Smckusick return (EBUSY); 41637737Smckusick fs = ump->um_fs; 41737737Smckusick if (fs == (struct fs *)1) 41837737Smckusick return (0); 41937737Smckusick updlock++; 42037737Smckusick /* 42137737Smckusick * Write back modified superblock. 42237737Smckusick * Consistency check that the superblock 42337737Smckusick * is still in the buffer cache. 42437737Smckusick */ 42537737Smckusick if (fs->fs_fmod != 0) { 42637737Smckusick if (fs->fs_ronly != 0) { /* XXX */ 42737737Smckusick printf("fs = %s\n", fs->fs_fsmnt); 42837737Smckusick panic("update: rofs mod"); 42937737Smckusick } 43037737Smckusick fs->fs_fmod = 0; 43137737Smckusick fs->fs_time = time.tv_sec; 43237737Smckusick error = sbupdate(ump, waitfor); 43337737Smckusick } 43437737Smckusick /* 43537737Smckusick * Write back each (modified) inode. 43637737Smckusick */ 43739877Smckusick loop: 43839877Smckusick for (vp = mp->m_mounth; vp; vp = nvp) { 43939877Smckusick nvp = vp->v_mountf; 44039390Smckusick ip = VTOI(vp); 44139877Smckusick if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 && 44239877Smckusick vp->v_dirtyblkhd == NULL) 44337737Smckusick continue; 44439877Smckusick if (vget(vp)) 44539877Smckusick goto loop; 44639877Smckusick if (vp->v_dirtyblkhd) 44739877Smckusick vflushbuf(vp, 0); 44839877Smckusick if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) && 44939877Smckusick (error = iupdat(ip, &time, &time, 0))) 45039596Smckusick allerror = error; 45139596Smckusick vput(vp); 45237737Smckusick } 45337737Smckusick updlock = 0; 45437737Smckusick /* 45539675Smckusick * Force stale file system control information to be flushed. 45637737Smckusick */ 45739675Smckusick vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0); 45839596Smckusick return (allerror); 45937737Smckusick } 46037737Smckusick 46137737Smckusick /* 46237737Smckusick * Write a superblock and associated information back to disk. 46337737Smckusick */ 46437737Smckusick sbupdate(mp, waitfor) 46537737Smckusick struct ufsmount *mp; 46637737Smckusick int waitfor; 46737737Smckusick { 46837737Smckusick register struct fs *fs = mp->um_fs; 46912795Ssam register struct buf *bp; 47012795Ssam int blks; 47112795Ssam caddr_t space; 47237737Smckusick int i, size, error = 0; 47312795Ssam 47437737Smckusick bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize); 47512795Ssam bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); 47634145Smckusick /* Restore compatibility to old file systems. XXX */ 47734145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 47834145Smckusick bp->b_un.b_fs->fs_nrpos = -1; /* XXX */ 47937737Smckusick if (waitfor == MNT_WAIT) 48037737Smckusick error = bwrite(bp); 48137737Smckusick else 48237737Smckusick bawrite(bp); 48312795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 48412795Ssam space = (caddr_t)fs->fs_csp[0]; 48512795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 48612795Ssam size = fs->fs_bsize; 48712795Ssam if (i + fs->fs_frag > blks) 48812795Ssam size = (blks - i) * fs->fs_fsize; 48937737Smckusick bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size); 49012795Ssam bcopy(space, bp->b_un.b_addr, (u_int)size); 49112795Ssam space += size; 49237737Smckusick if (waitfor == MNT_WAIT) 49337737Smckusick error = bwrite(bp); 49437737Smckusick else 49537737Smckusick bawrite(bp); 49612795Ssam } 49737737Smckusick return (error); 49812795Ssam } 49912795Ssam 50012795Ssam /* 50137737Smckusick * Print out statistics on the current allocation of the buffer pool. 50237737Smckusick * Can be enabled to print out on every ``sync'' by setting "syncprt" 50337737Smckusick * above. 50437737Smckusick */ 50537737Smckusick bufstats() 50637737Smckusick { 50737737Smckusick int s, i, j, count; 50837737Smckusick register struct buf *bp, *dp; 50937737Smckusick int counts[MAXBSIZE/CLBYTES+1]; 51037737Smckusick static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; 51137737Smckusick 51237737Smckusick for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { 51337737Smckusick count = 0; 51437737Smckusick for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 51537737Smckusick counts[j] = 0; 51637737Smckusick s = splbio(); 51737737Smckusick for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { 51837737Smckusick counts[dp->b_bufsize/CLBYTES]++; 51937737Smckusick count++; 52037737Smckusick } 52137737Smckusick splx(s); 52237737Smckusick printf("%s: total-%d", bname[i], count); 52337737Smckusick for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 52437737Smckusick if (counts[j] != 0) 52537737Smckusick printf(", %d-%d", j * CLBYTES, counts[j]); 52637737Smckusick printf("\n"); 52737737Smckusick } 52837737Smckusick } 52937737Smckusick 53037737Smckusick /* 53137737Smckusick * File handle to vnode 53238453Smckusick * 53338453Smckusick * Have to be really careful about stale file handles: 53438453Smckusick * - check that the inode number is in range 53538453Smckusick * - call iget() to get the locked inode 53638453Smckusick * - check for an unallocated inode (i_mode == 0) 53738453Smckusick * - check that the generation number matches 53837737Smckusick */ 53937737Smckusick ufs_fhtovp(mp, fhp, vpp) 54038453Smckusick register struct mount *mp; 54137737Smckusick struct fid *fhp; 54237737Smckusick struct vnode **vpp; 54337737Smckusick { 54437737Smckusick register struct ufid *ufhp; 54538453Smckusick register struct fs *fs; 54639390Smckusick register struct inode *ip; 54739390Smckusick struct inode *nip; 54839390Smckusick struct vnode tvp; 54937737Smckusick int error; 55037737Smckusick 55137737Smckusick ufhp = (struct ufid *)fhp; 55238453Smckusick fs = VFSTOUFS(mp)->um_fs; 55338453Smckusick if (ufhp->ufid_ino < ROOTINO || 55438453Smckusick ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) { 55538453Smckusick *vpp = (struct vnode *)0; 55638453Smckusick return (EINVAL); 55738453Smckusick } 55839390Smckusick tvp.v_mount = mp; 55939390Smckusick ip = VTOI(&tvp); 56039390Smckusick ip->i_vnode = &tvp; 56139390Smckusick ip->i_dev = VFSTOUFS(mp)->um_dev; 56239390Smckusick if (error = iget(ip, ufhp->ufid_ino, &nip)) { 56338453Smckusick *vpp = (struct vnode *)0; 56437737Smckusick return (error); 56537737Smckusick } 56639390Smckusick ip = nip; 56738453Smckusick if (ip->i_mode == 0) { 56838453Smckusick iput(ip); 56938453Smckusick *vpp = (struct vnode *)0; 57038453Smckusick return (EINVAL); 57138453Smckusick } 57237737Smckusick if (ip->i_gen != ufhp->ufid_gen) { 57337737Smckusick iput(ip); 57438453Smckusick *vpp = (struct vnode *)0; 57537737Smckusick return (EINVAL); 57637737Smckusick } 57737737Smckusick *vpp = ITOV(ip); 57837737Smckusick return (0); 57937737Smckusick } 58037737Smckusick 58137737Smckusick /* 58238355Smckusick * Vnode pointer to File handle 58337737Smckusick */ 58437737Smckusick /* ARGSUSED */ 58538143Smckusick ufs_vptofh(vp, fhp) 58638143Smckusick struct vnode *vp; 58737737Smckusick struct fid *fhp; 58837737Smckusick { 58938143Smckusick register struct inode *ip = VTOI(vp); 59038143Smckusick register struct ufid *ufhp; 59137737Smckusick 59238143Smckusick ufhp = (struct ufid *)fhp; 59338143Smckusick ufhp->ufid_len = sizeof(struct ufid); 59438143Smckusick ufhp->ufid_ino = ip->i_number; 59538143Smckusick ufhp->ufid_gen = ip->i_gen; 59638143Smckusick return (0); 59737737Smckusick } 59837737Smckusick 59937737Smckusick /* 60037737Smckusick * Common code for mount and quota. 60112795Ssam * Check that the user's argument is a reasonable 60212795Ssam * thing on which to mount, and return the device number if so. 60312795Ssam */ 60437737Smckusick getmdev(devvpp, fname, ndp) 60537737Smckusick struct vnode **devvpp; 60616697Smckusick caddr_t fname; 60737737Smckusick register struct nameidata *ndp; 60812795Ssam { 60937737Smckusick register struct vnode *vp; 61037737Smckusick int error; 61112795Ssam 61237737Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 61316697Smckusick ndp->ni_segflg = UIO_USERSPACE; 61416697Smckusick ndp->ni_dirp = fname; 61537737Smckusick if (error = namei(ndp)) { 61637737Smckusick if (error == ENOENT) 61737737Smckusick return (ENODEV); /* needs translation */ 61837737Smckusick return (error); 61921013Smckusick } 62037737Smckusick vp = ndp->ni_vp; 62137737Smckusick if (vp->v_type != VBLK) { 62237737Smckusick vput(vp); 62312795Ssam return (ENOTBLK); 62415956Skarels } 62539532Smckusick if (major(vp->v_rdev) >= nblkdev) { 62639532Smckusick vput(vp); 62712795Ssam return (ENXIO); 62839532Smckusick } 62937737Smckusick iunlock(VTOI(vp)); 63037737Smckusick *devvpp = vp; 63112795Ssam return (0); 63212795Ssam } 633