123400Smckusick /* 250264Skarels * Copyright (c) 1989, 1991 The Regents of the University of California. 337737Smckusick * All rights reserved. 423400Smckusick * 544539Sbostic * %sccs.include.redist.c% 637737Smckusick * 7*53913Smckusick * @(#)ffs_vfsops.c 7.66 (Berkeley) 06/04/92 823400Smckusick */ 912795Ssam 1051473Sbostic #include <sys/param.h> 1151473Sbostic #include <sys/systm.h> 1251473Sbostic #include <sys/namei.h> 1351473Sbostic #include <sys/proc.h> 1451473Sbostic #include <sys/kernel.h> 1551473Sbostic #include <sys/vnode.h> 1651473Sbostic #include <sys/specdev.h> 1751473Sbostic #include <sys/mount.h> 1851473Sbostic #include <sys/buf.h> 1951473Sbostic #include <sys/file.h> 2051473Sbostic #include <sys/disklabel.h> 2151473Sbostic #include <sys/ioctl.h> 2251473Sbostic #include <sys/errno.h> 2351473Sbostic #include <sys/malloc.h> 2412795Ssam 2551473Sbostic #include <ufs/ufs/quota.h> 2651473Sbostic #include <ufs/ufs/ufsmount.h> 2751473Sbostic #include <ufs/ufs/inode.h> 2851473Sbostic #include <ufs/ufs/ufs_extern.h> 2947571Skarels 3051473Sbostic #include <ufs/ffs/fs.h> 3151473Sbostic #include <ufs/ffs/ffs_extern.h> 3251473Sbostic 3351942Smckusick int ffs_sbupdate __P((struct ufsmount *, int)); 3451473Sbostic 3537737Smckusick struct vfsops ufs_vfsops = { 3651473Sbostic ffs_mount, 3739043Smckusick ufs_start, 3851473Sbostic ffs_unmount, 3951545Smckusick ffs_root, 4041314Smckusick ufs_quotactl, 4151473Sbostic ffs_statfs, 4251473Sbostic ffs_sync, 4351545Smckusick ffs_fhtovp, 4451545Smckusick ffs_vptofh, 4551473Sbostic ffs_init, 4637737Smckusick }; 4737737Smckusick 4837737Smckusick /* 4953045Sralph * Called by main() when ufs is going to be mounted as root. 5037737Smckusick * 5139336Smckusick * Name is updated by mount(8) after booting. 5237737Smckusick */ 5339297Smckusick #define ROOTNAME "root_device" 5437737Smckusick 5551473Sbostic ffs_mountroot() 5612795Ssam { 5751473Sbostic extern struct vnode *rootvp; 5851473Sbostic register struct fs *fs; 5937737Smckusick register struct mount *mp; 6048036Smckusick struct proc *p = curproc; /* XXX */ 6137737Smckusick struct ufsmount *ump; 6237737Smckusick u_int size; 6337737Smckusick int error; 6412795Ssam 6553045Sralph mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); 6641397Smckusick mp->mnt_op = &ufs_vfsops; 6741397Smckusick mp->mnt_flag = MNT_RDONLY; 6841397Smckusick mp->mnt_mounth = NULLVP; 6951473Sbostic if (error = ffs_mountfs(rootvp, mp, p)) { 7051473Sbostic free(mp, M_MOUNT); 7137737Smckusick return (error); 7212795Ssam } 7339336Smckusick if (error = vfs_lock(mp)) { 7451473Sbostic (void)ffs_unmount(mp, 0, p); 7551473Sbostic free(mp, M_MOUNT); 7637737Smckusick return (error); 7721013Smckusick } 7839336Smckusick rootfs = mp; 7941397Smckusick mp->mnt_next = mp; 8041397Smckusick mp->mnt_prev = mp; 8141397Smckusick mp->mnt_vnodecovered = NULLVP; 8237737Smckusick ump = VFSTOUFS(mp); 8337737Smckusick fs = ump->um_fs; 8440346Smckusick bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 8537737Smckusick fs->fs_fsmnt[0] = '/'; 8641397Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 8741397Smckusick MNAMELEN); 8841397Smckusick (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 8941397Smckusick &size); 9041397Smckusick bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 9151473Sbostic (void)ffs_statfs(mp, &mp->mnt_stat, p); 9237737Smckusick vfs_unlock(mp); 9337737Smckusick inittodr(fs->fs_time); 9437737Smckusick return (0); 9537737Smckusick } 9637737Smckusick 9737737Smckusick /* 9837737Smckusick * VFS Operations. 9937737Smckusick * 10037737Smckusick * mount system call 10137737Smckusick */ 10251942Smckusick int 10351473Sbostic ffs_mount(mp, path, data, ndp, p) 10440346Smckusick register struct mount *mp; 10537737Smckusick char *path; 10637737Smckusick caddr_t data; 10737737Smckusick struct nameidata *ndp; 10848036Smckusick struct proc *p; 10937737Smckusick { 11037737Smckusick struct vnode *devvp; 11137737Smckusick struct ufs_args args; 11237737Smckusick struct ufsmount *ump; 11337737Smckusick register struct fs *fs; 11437737Smckusick u_int size; 11537737Smckusick int error; 11637737Smckusick 11737737Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 11837737Smckusick return (error); 11940371Smckusick /* 12050264Skarels * If updating, check whether changing from read-only to 12150264Skarels * read/write; if there is no device name, that's all we do. 12250264Skarels */ 12350264Skarels if (mp->mnt_flag & MNT_UPDATE) { 12439336Smckusick ump = VFSTOUFS(mp); 12539336Smckusick fs = ump->um_fs; 12641397Smckusick if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 12739336Smckusick fs->fs_ronly = 0; 12852177Smckusick if (args.fspec == 0) { 12952177Smckusick /* 13052177Smckusick * Process export requests. 13152177Smckusick */ 13252177Smckusick if (args.exflags & MNT_EXPORTED) { 13352177Smckusick if (error = hang_addrlist(mp, &args)) 13452177Smckusick return (error); 13552177Smckusick mp->mnt_flag |= MNT_EXPORTED; 13652177Smckusick } 13752177Smckusick if (args.exflags & MNT_DELEXPORT) { 13852177Smckusick free_addrlist(ump); 13952177Smckusick mp->mnt_flag &= 14052177Smckusick ~(MNT_EXPORTED | MNT_DEFEXPORTED); 14152177Smckusick } 14240371Smckusick return (0); 14352177Smckusick } 14450264Skarels } 14550264Skarels /* 14650264Skarels * Not an update, or updating the name: look up the name 14750264Skarels * and verify that it refers to a sensible block device. 14850264Skarels */ 14952332Smckusick NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 15052332Smckusick if (error = namei(ndp)) 15150264Skarels return (error); 15250264Skarels devvp = ndp->ni_vp; 15351473Sbostic 15450264Skarels if (devvp->v_type != VBLK) { 15550264Skarels vrele(devvp); 15650264Skarels return (ENOTBLK); 15750264Skarels } 15850264Skarels if (major(devvp->v_rdev) >= nblkdev) { 15950264Skarels vrele(devvp); 16050264Skarels return (ENXIO); 16150264Skarels } 16250264Skarels if ((mp->mnt_flag & MNT_UPDATE) == 0) 16351473Sbostic error = ffs_mountfs(devvp, mp, p); 16450264Skarels else { 16539336Smckusick if (devvp != ump->um_devvp) 16639336Smckusick error = EINVAL; /* needs translation */ 16742858Smckusick else 16842858Smckusick vrele(devvp); 16939336Smckusick } 17037737Smckusick if (error) { 17137737Smckusick vrele(devvp); 17237737Smckusick return (error); 17332721Smckusick } 17437737Smckusick ump = VFSTOUFS(mp); 17537737Smckusick fs = ump->um_fs; 17637737Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 17737737Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 17841397Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 17941397Smckusick MNAMELEN); 18041397Smckusick (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 18141397Smckusick &size); 18241397Smckusick bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 18351473Sbostic (void)ffs_statfs(mp, &mp->mnt_stat, p); 18437737Smckusick return (0); 18512795Ssam } 18612795Ssam 18737737Smckusick /* 18837737Smckusick * Common code for mount and mountroot 18937737Smckusick */ 19051473Sbostic int 19151473Sbostic ffs_mountfs(devvp, mp, p) 19240376Smckusick register struct vnode *devvp; 19337737Smckusick struct mount *mp; 19448036Smckusick struct proc *p; 19512795Ssam { 19653522Sheideman USES_VOP_CLOSE; 19753522Sheideman USES_VOP_IOCTL; 19853522Sheideman USES_VOP_OPEN; 19941314Smckusick register struct ufsmount *ump = (struct ufsmount *)0; 20037737Smckusick struct buf *bp = NULL; 20112795Ssam register struct fs *fs; 20237737Smckusick dev_t dev = devvp->v_rdev; 20330749Skarels struct partinfo dpart; 20437737Smckusick caddr_t base, space; 20530749Skarels int havepart = 0, blks; 20637737Smckusick int error, i, size; 20721013Smckusick int needclose = 0; 20841397Smckusick int ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 20945652Smckusick extern struct vnode *rootvp; 21012795Ssam 21140376Smckusick /* 21240376Smckusick * Disallow multiple mounts of the same device. 21345652Smckusick * Disallow mounting of a device that is currently in use 21445652Smckusick * (except for root, which might share swap device for miniroot). 21540376Smckusick * Flush out any old buffers remaining from a previous use. 21640376Smckusick */ 21751473Sbostic if (error = ufs_mountedon(devvp)) 21840376Smckusick return (error); 21945652Smckusick if (vcount(devvp) > 1 && devvp != rootvp) 22040376Smckusick return (EBUSY); 22140376Smckusick vinvalbuf(devvp, 1); 22248036Smckusick if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p)) 22337737Smckusick return (error); 22421013Smckusick needclose = 1; 22548036Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 22637737Smckusick size = DEV_BSIZE; 22748036Smckusick else { 22830749Skarels havepart = 1; 22930749Skarels size = dpart.disklab->d_secsize; 23037737Smckusick } 23141314Smckusick if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) 23212795Ssam goto out; 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)) { 23641314Smckusick error = EINVAL; /* XXX needs translation */ 23716639Skarels goto out; 23816639Skarels } 23951473Sbostic ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 24052538Smckusick bzero((caddr_t)ump, sizeof *ump); 24151982Smckusick ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT, 24234473Smckusick M_WAITOK); 24337737Smckusick bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs, 24412795Ssam (u_int)fs->fs_sbsize); 24539675Smckusick if (fs->fs_sbsize < SBSIZE) 24639675Smckusick bp->b_flags |= B_INVAL; 24734421Skarels brelse(bp); 24834421Skarels bp = NULL; 24937737Smckusick fs = ump->um_fs; 25037737Smckusick fs->fs_ronly = ronly; 25112795Ssam if (ronly == 0) 25212795Ssam fs->fs_fmod = 1; 25330749Skarels if (havepart) { 25430749Skarels dpart.part->p_fstype = FS_BSDFFS; 25530749Skarels dpart.part->p_fsize = fs->fs_fsize; 25630749Skarels dpart.part->p_frag = fs->fs_frag; 25731385Skarels dpart.part->p_cpg = fs->fs_cpg; 25830749Skarels } 25912795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 26051982Smckusick base = space = malloc((u_long)fs->fs_cssize, M_UFSMNT, 26134473Smckusick M_WAITOK); 26212795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 26312795Ssam size = fs->fs_bsize; 26412795Ssam if (i + fs->fs_frag > blks) 26512795Ssam size = (blks - i) * fs->fs_fsize; 26638776Smckusick error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 26738776Smckusick NOCRED, &bp); 26837737Smckusick if (error) { 26951982Smckusick free(base, M_UFSMNT); 27012795Ssam goto out; 27112795Ssam } 27234421Skarels bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size); 27317225Smckusick fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 27412795Ssam space += size; 27534421Skarels brelse(bp); 27634421Skarels bp = NULL; 27712795Ssam } 27841397Smckusick mp->mnt_data = (qaddr_t)ump; 27941397Smckusick mp->mnt_stat.f_fsid.val[0] = (long)dev; 28041397Smckusick mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS; 28141397Smckusick mp->mnt_flag |= MNT_LOCAL; 28237737Smckusick ump->um_mountp = mp; 28337737Smckusick ump->um_dev = dev; 28437737Smckusick ump->um_devvp = devvp; 28541314Smckusick for (i = 0; i < MAXQUOTAS; i++) 28641314Smckusick ump->um_quotas[i] = NULLVP; 28740653Smckusick devvp->v_specflags |= SI_MOUNTEDON; 28837737Smckusick 28930383Smckusick /* Sanity checks for old file systems. XXX */ 29030383Smckusick fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */ 29130383Smckusick fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */ 29234145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 29334145Smckusick fs->fs_nrpos = 8; /* XXX */ 294*53913Smckusick if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 295*53913Smckusick quad_t sizepb = fs->fs_bsize; /* XXX */ 296*53913Smckusick /* XXX */ 297*53913Smckusick fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */ 298*53913Smckusick for (i = 0; i < NIADDR; i++) { /* XXX */ 299*53913Smckusick sizepb *= NINDIR(fs); /* XXX */ 300*53913Smckusick fs->fs_maxfilesize += sizepb; /* XXX */ 301*53913Smckusick } /* XXX */ 302*53913Smckusick fs->fs_qbmask = ~fs->fs_bmask; /* XXX */ 303*53913Smckusick fs->fs_qfmask = ~fs->fs_fmask; /* XXX */ 304*53913Smckusick } /* XXX */ 30537737Smckusick return (0); 30612795Ssam out: 30740872Smckusick if (bp) 30840872Smckusick brelse(bp); 30932721Smckusick if (needclose) 31048036Smckusick (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 31141314Smckusick if (ump) { 31251982Smckusick free(ump->um_fs, M_UFSMNT); 31351473Sbostic free(ump, M_UFSMNT); 31441397Smckusick mp->mnt_data = (qaddr_t)0; 31532721Smckusick } 31637737Smckusick return (error); 31712795Ssam } 31812795Ssam 31939043Smckusick /* 32037737Smckusick * unmount system call 32137737Smckusick */ 32251473Sbostic int 32351473Sbostic ffs_unmount(mp, mntflags, p) 32437737Smckusick struct mount *mp; 32541314Smckusick int mntflags; 32648036Smckusick struct proc *p; 32712795Ssam { 32853522Sheideman USES_VOP_CLOSE; 32951473Sbostic extern int doforce; 33037737Smckusick register struct ufsmount *ump; 33137737Smckusick register struct fs *fs; 33241314Smckusick int i, error, ronly, flags = 0; 33312795Ssam 33448065Smckusick if (mntflags & MNT_FORCE) { 33548359Smckusick if (!doforce || mp == rootfs) 33648065Smckusick return (EINVAL); 33741314Smckusick flags |= FORCECLOSE; 33848065Smckusick } 33939675Smckusick mntflushbuf(mp, 0); 34039675Smckusick if (mntinvalbuf(mp)) 34139675Smckusick return (EBUSY); 34237737Smckusick ump = VFSTOUFS(mp); 34312795Ssam #ifdef QUOTA 34441397Smckusick if (mp->mnt_flag & MNT_QUOTA) { 34541314Smckusick if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) 34639898Smckusick return (error); 34741314Smckusick for (i = 0; i < MAXQUOTAS; i++) { 34841314Smckusick if (ump->um_quotas[i] == NULLVP) 34941314Smckusick continue; 35050114Smckusick quotaoff(p, mp, i); 35141314Smckusick } 35239898Smckusick /* 35341314Smckusick * Here we fall through to vflush again to ensure 35441314Smckusick * that we have gotten rid of all the system vnodes. 35539898Smckusick */ 35641314Smckusick } 35712795Ssam #endif 35841314Smckusick if (error = vflush(mp, NULLVP, flags)) 35939898Smckusick return (error); 36037737Smckusick fs = ump->um_fs; 36137737Smckusick ronly = !fs->fs_ronly; 36240653Smckusick ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 36348036Smckusick error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, 36448036Smckusick NOCRED, p); 36537737Smckusick vrele(ump->um_devvp); 36651982Smckusick free(fs->fs_csp[0], M_UFSMNT); 36751982Smckusick free(fs, M_UFSMNT); 36851473Sbostic free(ump, M_UFSMNT); 36941397Smckusick mp->mnt_data = (qaddr_t)0; 37041397Smckusick mp->mnt_flag &= ~MNT_LOCAL; 37130749Skarels return (error); 37212795Ssam } 37312795Ssam 37437737Smckusick /* 37551545Smckusick * Return root of a filesystem 37651545Smckusick */ 37751545Smckusick int 37851545Smckusick ffs_root(mp, vpp) 37951545Smckusick struct mount *mp; 38051545Smckusick struct vnode **vpp; 38151545Smckusick { 38253522Sheideman USES_VOP_VGET; 38351545Smckusick struct vnode *nvp; 38451545Smckusick int error; 38551545Smckusick 38653522Sheideman if (error = FFS_VGET(mp, (ino_t)ROOTINO, &nvp)) 38751545Smckusick return (error); 38851545Smckusick *vpp = nvp; 38951545Smckusick return (0); 39051545Smckusick } 39151545Smckusick 39251545Smckusick /* 39337737Smckusick * Get file system statistics. 39437737Smckusick */ 39551473Sbostic int 39651473Sbostic ffs_statfs(mp, sbp, p) 39737737Smckusick struct mount *mp; 39837737Smckusick register struct statfs *sbp; 39948036Smckusick struct proc *p; 40037737Smckusick { 40137737Smckusick register struct ufsmount *ump; 40237737Smckusick register struct fs *fs; 40337737Smckusick 40437737Smckusick ump = VFSTOUFS(mp); 40537737Smckusick fs = ump->um_fs; 40637737Smckusick if (fs->fs_magic != FS_MAGIC) 40751473Sbostic panic("ffs_statfs"); 40837737Smckusick sbp->f_type = MOUNT_UFS; 40951942Smckusick sbp->f_bsize = fs->fs_fsize; 41051942Smckusick sbp->f_iosize = fs->fs_bsize; 41137737Smckusick sbp->f_blocks = fs->fs_dsize; 41237737Smckusick sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 41337737Smckusick fs->fs_cstotal.cs_nffree; 41437737Smckusick sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 41537737Smckusick (fs->fs_dsize - sbp->f_bfree); 41639350Smckusick sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 41737737Smckusick sbp->f_ffree = fs->fs_cstotal.cs_nifree; 41841397Smckusick if (sbp != &mp->mnt_stat) { 41941397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntonname, 42040346Smckusick (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 42141397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 42240346Smckusick (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 42340346Smckusick } 42437737Smckusick return (0); 42537737Smckusick } 42637737Smckusick 42737737Smckusick /* 42837737Smckusick * Go through the disk queues to initiate sandbagged IO; 42937737Smckusick * go through the inodes to write those that have been modified; 43037737Smckusick * initiate the writing of the super block if it has been modified. 43141314Smckusick * 43241314Smckusick * Note: we are always called with the filesystem marked `MPBUSY'. 43337737Smckusick */ 43451473Sbostic int 43551473Sbostic ffs_sync(mp, waitfor) 43637737Smckusick struct mount *mp; 43737737Smckusick int waitfor; 43837737Smckusick { 43953522Sheideman USES_VOP_ISLOCKED; 44053522Sheideman USES_VOP_UPDATE; 44151473Sbostic extern int syncprt; 44239390Smckusick register struct vnode *vp; 44337737Smckusick register struct inode *ip; 44437737Smckusick register struct ufsmount *ump = VFSTOUFS(mp); 44537737Smckusick register struct fs *fs; 44639596Smckusick int error, allerror = 0; 44737737Smckusick 44837737Smckusick if (syncprt) 44951473Sbostic ufs_bufstats(); 45037737Smckusick fs = ump->um_fs; 45137737Smckusick /* 45237737Smckusick * Write back modified superblock. 45337737Smckusick * Consistency check that the superblock 45437737Smckusick * is still in the buffer cache. 45537737Smckusick */ 45637737Smckusick if (fs->fs_fmod != 0) { 45737737Smckusick if (fs->fs_ronly != 0) { /* XXX */ 45837737Smckusick printf("fs = %s\n", fs->fs_fsmnt); 45937737Smckusick panic("update: rofs mod"); 46037737Smckusick } 46137737Smckusick fs->fs_fmod = 0; 46237737Smckusick fs->fs_time = time.tv_sec; 46351473Sbostic allerror = ffs_sbupdate(ump, waitfor); 46437737Smckusick } 46537737Smckusick /* 46637737Smckusick * Write back each (modified) inode. 46737737Smckusick */ 46839877Smckusick loop: 46941462Smckusick for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) { 47041462Smckusick /* 47141462Smckusick * If the vnode that we are about to sync is no longer 47241462Smckusick * associated with this mount point, start over. 47341462Smckusick */ 47441462Smckusick if (vp->v_mount != mp) 47541462Smckusick goto loop; 47648359Smckusick if (VOP_ISLOCKED(vp)) 47748359Smckusick continue; 47839390Smckusick ip = VTOI(vp); 47939877Smckusick if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 && 48039877Smckusick vp->v_dirtyblkhd == NULL) 48137737Smckusick continue; 48239877Smckusick if (vget(vp)) 48339877Smckusick goto loop; 48439877Smckusick if (vp->v_dirtyblkhd) 48539877Smckusick vflushbuf(vp, 0); 48639877Smckusick if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) && 48753522Sheideman (error = VOP_UPDATE(vp, &time, &time, 0))) 48839596Smckusick allerror = error; 48939596Smckusick vput(vp); 49037737Smckusick } 49137737Smckusick /* 49239675Smckusick * Force stale file system control information to be flushed. 49337737Smckusick */ 49439675Smckusick vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0); 49541314Smckusick #ifdef QUOTA 49641314Smckusick qsync(mp); 49741314Smckusick #endif 49839596Smckusick return (allerror); 49937737Smckusick } 50037737Smckusick 50137737Smckusick /* 50251545Smckusick * File handle to vnode 50351545Smckusick * 50451545Smckusick * Have to be really careful about stale file handles: 50551545Smckusick * - check that the inode number is valid 50651545Smckusick * - call ffs_vget() to get the locked inode 50751545Smckusick * - check for an unallocated inode (i_mode == 0) 50852177Smckusick * - check that the generation number matches unless setgen true 50951545Smckusick */ 51051545Smckusick int 51152177Smckusick ffs_fhtovp(mp, fhp, setgen, vpp) 51251545Smckusick register struct mount *mp; 51351545Smckusick struct fid *fhp; 51452177Smckusick int setgen; 51551545Smckusick struct vnode **vpp; 51651545Smckusick { 51753522Sheideman USES_VOP_VGET; 51851545Smckusick register struct inode *ip; 51951545Smckusick register struct ufid *ufhp; 52051545Smckusick struct fs *fs; 52151545Smckusick struct vnode *nvp; 52251545Smckusick int error; 52351545Smckusick 52451545Smckusick ufhp = (struct ufid *)fhp; 52551545Smckusick fs = VFSTOUFS(mp)->um_fs; 52651545Smckusick if (ufhp->ufid_ino < ROOTINO || 52751545Smckusick ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) 52851545Smckusick return (EINVAL); 52953522Sheideman if (error = FFS_VGET(mp, ufhp->ufid_ino, &nvp)) { 53051545Smckusick *vpp = NULLVP; 53151545Smckusick return (error); 53251545Smckusick } 53351545Smckusick ip = VTOI(nvp); 53451545Smckusick if (ip->i_mode == 0) { 53551545Smckusick ufs_iput(ip); 53651545Smckusick *vpp = NULLVP; 53751545Smckusick return (EINVAL); 53851545Smckusick } 53951545Smckusick if (ip->i_gen != ufhp->ufid_gen) { 54052177Smckusick if (setgen) 54152177Smckusick ufhp->ufid_gen = ip->i_gen; 54252177Smckusick else { 54352177Smckusick ufs_iput(ip); 54452177Smckusick *vpp = NULLVP; 54552177Smckusick return (EINVAL); 54652177Smckusick } 54751545Smckusick } 54851545Smckusick *vpp = nvp; 54951545Smckusick return (0); 55051545Smckusick } 55151545Smckusick 55251545Smckusick /* 55351545Smckusick * Vnode pointer to File handle 55451545Smckusick */ 55551545Smckusick /* ARGSUSED */ 55651545Smckusick ffs_vptofh(vp, fhp) 55751545Smckusick struct vnode *vp; 55851545Smckusick struct fid *fhp; 55951545Smckusick { 56051545Smckusick register struct inode *ip; 56151545Smckusick register struct ufid *ufhp; 56251545Smckusick 56351545Smckusick ip = VTOI(vp); 56451545Smckusick ufhp = (struct ufid *)fhp; 56551545Smckusick ufhp->ufid_len = sizeof(struct ufid); 56651545Smckusick ufhp->ufid_ino = ip->i_number; 56751545Smckusick ufhp->ufid_gen = ip->i_gen; 56851545Smckusick return (0); 56951545Smckusick } 57051545Smckusick 57151545Smckusick /* 57237737Smckusick * Write a superblock and associated information back to disk. 57337737Smckusick */ 57451942Smckusick int 57551473Sbostic ffs_sbupdate(mp, waitfor) 57637737Smckusick struct ufsmount *mp; 57737737Smckusick int waitfor; 57837737Smckusick { 57937737Smckusick register struct fs *fs = mp->um_fs; 58012795Ssam register struct buf *bp; 58112795Ssam int blks; 58212795Ssam caddr_t space; 58337737Smckusick int i, size, error = 0; 58412795Ssam 58537737Smckusick bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize); 58612795Ssam bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); 58734145Smckusick /* Restore compatibility to old file systems. XXX */ 58834145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 58934145Smckusick bp->b_un.b_fs->fs_nrpos = -1; /* XXX */ 59037737Smckusick if (waitfor == MNT_WAIT) 59137737Smckusick error = bwrite(bp); 59237737Smckusick else 59337737Smckusick bawrite(bp); 59412795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 59512795Ssam space = (caddr_t)fs->fs_csp[0]; 59612795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 59712795Ssam size = fs->fs_bsize; 59812795Ssam if (i + fs->fs_frag > blks) 59912795Ssam size = (blks - i) * fs->fs_fsize; 60037737Smckusick bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size); 60112795Ssam bcopy(space, bp->b_un.b_addr, (u_int)size); 60212795Ssam space += size; 60337737Smckusick if (waitfor == MNT_WAIT) 60437737Smckusick error = bwrite(bp); 60537737Smckusick else 60637737Smckusick bawrite(bp); 60712795Ssam } 60837737Smckusick return (error); 60912795Ssam } 610