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*51942Smckusick * @(#)ffs_vfsops.c 7.59 (Berkeley) 12/14/91 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 33*51942Smckusick 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 /* 4939336Smckusick * Called by vfs_mountroot 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 6551473Sbostic mp = malloc((u_long)sizeof(struct mount), 6637737Smckusick M_MOUNT, M_WAITOK); 6741397Smckusick mp->mnt_op = &ufs_vfsops; 6841397Smckusick mp->mnt_flag = MNT_RDONLY; 6941397Smckusick mp->mnt_exroot = 0; 7041397Smckusick mp->mnt_mounth = NULLVP; 7151473Sbostic if (error = ffs_mountfs(rootvp, mp, p)) { 7251473Sbostic free(mp, M_MOUNT); 7337737Smckusick return (error); 7412795Ssam } 7539336Smckusick if (error = vfs_lock(mp)) { 7651473Sbostic (void)ffs_unmount(mp, 0, p); 7751473Sbostic free(mp, M_MOUNT); 7837737Smckusick return (error); 7921013Smckusick } 8039336Smckusick rootfs = mp; 8141397Smckusick mp->mnt_next = mp; 8241397Smckusick mp->mnt_prev = mp; 8341397Smckusick mp->mnt_vnodecovered = NULLVP; 8437737Smckusick ump = VFSTOUFS(mp); 8537737Smckusick fs = ump->um_fs; 8640346Smckusick bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 8737737Smckusick fs->fs_fsmnt[0] = '/'; 8841397Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 8941397Smckusick MNAMELEN); 9041397Smckusick (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 9141397Smckusick &size); 9241397Smckusick bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 9351473Sbostic (void)ffs_statfs(mp, &mp->mnt_stat, p); 9437737Smckusick vfs_unlock(mp); 9537737Smckusick inittodr(fs->fs_time); 9637737Smckusick return (0); 9737737Smckusick } 9837737Smckusick 9937737Smckusick /* 10037737Smckusick * VFS Operations. 10137737Smckusick * 10237737Smckusick * mount system call 10337737Smckusick */ 104*51942Smckusick int 10551473Sbostic ffs_mount(mp, path, data, ndp, p) 10640346Smckusick register struct mount *mp; 10737737Smckusick char *path; 10837737Smckusick caddr_t data; 10937737Smckusick struct nameidata *ndp; 11048036Smckusick struct proc *p; 11137737Smckusick { 11237737Smckusick struct vnode *devvp; 11337737Smckusick struct ufs_args args; 11437737Smckusick struct ufsmount *ump; 11537737Smckusick register struct fs *fs; 11637737Smckusick u_int size; 11737737Smckusick int error; 11837737Smckusick 11937737Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 12037737Smckusick return (error); 12140371Smckusick /* 12240371Smckusick * Process export requests. 12340371Smckusick */ 12441397Smckusick if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) { 12541397Smckusick if (args.exflags & MNT_EXPORTED) 12641397Smckusick mp->mnt_flag |= MNT_EXPORTED; 12740371Smckusick else 12841397Smckusick mp->mnt_flag &= ~MNT_EXPORTED; 12941397Smckusick if (args.exflags & MNT_EXRDONLY) 13041397Smckusick mp->mnt_flag |= MNT_EXRDONLY; 13140371Smckusick else 13241397Smckusick mp->mnt_flag &= ~MNT_EXRDONLY; 13341397Smckusick mp->mnt_exroot = args.exroot; 13440371Smckusick } 13550264Skarels /* 13650264Skarels * If updating, check whether changing from read-only to 13750264Skarels * read/write; if there is no device name, that's all we do. 13850264Skarels */ 13950264Skarels if (mp->mnt_flag & MNT_UPDATE) { 14039336Smckusick ump = VFSTOUFS(mp); 14139336Smckusick fs = ump->um_fs; 14241397Smckusick if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 14339336Smckusick fs->fs_ronly = 0; 14440371Smckusick if (args.fspec == 0) 14540371Smckusick return (0); 14650264Skarels } 14750264Skarels /* 14850264Skarels * Not an update, or updating the name: look up the name 14950264Skarels * and verify that it refers to a sensible block device. 15050264Skarels */ 15150264Skarels ndp->ni_nameiop = LOOKUP | FOLLOW; 15250264Skarels ndp->ni_segflg = UIO_USERSPACE; 15350264Skarels ndp->ni_dirp = args.fspec; 15450264Skarels if (error = namei(ndp, p)) 15550264Skarels return (error); 15650264Skarels devvp = ndp->ni_vp; 15751473Sbostic 15850264Skarels if (devvp->v_type != VBLK) { 15950264Skarels vrele(devvp); 16050264Skarels return (ENOTBLK); 16150264Skarels } 16250264Skarels if (major(devvp->v_rdev) >= nblkdev) { 16350264Skarels vrele(devvp); 16450264Skarels return (ENXIO); 16550264Skarels } 16650264Skarels if ((mp->mnt_flag & MNT_UPDATE) == 0) 16751473Sbostic error = ffs_mountfs(devvp, mp, p); 16850264Skarels else { 16939336Smckusick if (devvp != ump->um_devvp) 17039336Smckusick error = EINVAL; /* needs translation */ 17142858Smckusick else 17242858Smckusick vrele(devvp); 17339336Smckusick } 17437737Smckusick if (error) { 17537737Smckusick vrele(devvp); 17637737Smckusick return (error); 17732721Smckusick } 17837737Smckusick ump = VFSTOUFS(mp); 17937737Smckusick fs = ump->um_fs; 18037737Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 18137737Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 18241397Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 18341397Smckusick MNAMELEN); 18441397Smckusick (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 18541397Smckusick &size); 18641397Smckusick bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 18751473Sbostic (void)ffs_statfs(mp, &mp->mnt_stat, p); 18837737Smckusick return (0); 18912795Ssam } 19012795Ssam 19137737Smckusick /* 19237737Smckusick * Common code for mount and mountroot 19337737Smckusick */ 19451473Sbostic int 19551473Sbostic ffs_mountfs(devvp, mp, p) 19640376Smckusick register struct vnode *devvp; 19737737Smckusick struct mount *mp; 19848036Smckusick struct proc *p; 19912795Ssam { 20041314Smckusick register struct ufsmount *ump = (struct ufsmount *)0; 20137737Smckusick struct buf *bp = NULL; 20212795Ssam register struct fs *fs; 20337737Smckusick dev_t dev = devvp->v_rdev; 20430749Skarels struct partinfo dpart; 20537737Smckusick caddr_t base, space; 20630749Skarels int havepart = 0, blks; 20737737Smckusick int error, i, size; 20821013Smckusick int needclose = 0; 20941397Smckusick int ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 21045652Smckusick extern struct vnode *rootvp; 21112795Ssam 21240376Smckusick /* 21340376Smckusick * Disallow multiple mounts of the same device. 21445652Smckusick * Disallow mounting of a device that is currently in use 21545652Smckusick * (except for root, which might share swap device for miniroot). 21640376Smckusick * Flush out any old buffers remaining from a previous use. 21740376Smckusick */ 21851473Sbostic if (error = ufs_mountedon(devvp)) 21940376Smckusick return (error); 22045652Smckusick if (vcount(devvp) > 1 && devvp != rootvp) 22140376Smckusick return (EBUSY); 22240376Smckusick vinvalbuf(devvp, 1); 22348036Smckusick if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p)) 22437737Smckusick return (error); 22521013Smckusick needclose = 1; 22648036Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 22737737Smckusick size = DEV_BSIZE; 22848036Smckusick else { 22930749Skarels havepart = 1; 23030749Skarels size = dpart.disklab->d_secsize; 23137737Smckusick } 23241314Smckusick if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) 23312795Ssam goto out; 23434421Skarels fs = bp->b_un.b_fs; 23530749Skarels if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 23630749Skarels fs->fs_bsize < sizeof(struct fs)) { 23741314Smckusick error = EINVAL; /* XXX needs translation */ 23816639Skarels goto out; 23916639Skarels } 24051473Sbostic ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 24151473Sbostic ump->um_fs = malloc((u_long)fs->fs_sbsize, M_SUPERBLK, 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); 26051473Sbostic base = space = malloc((u_long)fs->fs_cssize, M_SUPERBLK, 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) { 26951473Sbostic free(base, M_SUPERBLK); 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 */ 29437737Smckusick return (0); 29512795Ssam out: 29640872Smckusick if (bp) 29740872Smckusick brelse(bp); 29832721Smckusick if (needclose) 29948036Smckusick (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 30041314Smckusick if (ump) { 30151473Sbostic free(ump->um_fs, M_SUPERBLK); 30251473Sbostic free(ump, M_UFSMNT); 30341397Smckusick mp->mnt_data = (qaddr_t)0; 30432721Smckusick } 30537737Smckusick return (error); 30612795Ssam } 30712795Ssam 30839043Smckusick /* 30937737Smckusick * unmount system call 31037737Smckusick */ 31151473Sbostic int 31251473Sbostic ffs_unmount(mp, mntflags, p) 31337737Smckusick struct mount *mp; 31441314Smckusick int mntflags; 31548036Smckusick struct proc *p; 31612795Ssam { 31751473Sbostic extern int doforce; 31837737Smckusick register struct ufsmount *ump; 31937737Smckusick register struct fs *fs; 32041314Smckusick int i, error, ronly, flags = 0; 32112795Ssam 32248065Smckusick if (mntflags & MNT_FORCE) { 32348359Smckusick if (!doforce || mp == rootfs) 32448065Smckusick return (EINVAL); 32541314Smckusick flags |= FORCECLOSE; 32648065Smckusick } 32739675Smckusick mntflushbuf(mp, 0); 32839675Smckusick if (mntinvalbuf(mp)) 32939675Smckusick return (EBUSY); 33037737Smckusick ump = VFSTOUFS(mp); 33112795Ssam #ifdef QUOTA 33241397Smckusick if (mp->mnt_flag & MNT_QUOTA) { 33341314Smckusick if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) 33439898Smckusick return (error); 33541314Smckusick for (i = 0; i < MAXQUOTAS; i++) { 33641314Smckusick if (ump->um_quotas[i] == NULLVP) 33741314Smckusick continue; 33850114Smckusick quotaoff(p, mp, i); 33941314Smckusick } 34039898Smckusick /* 34141314Smckusick * Here we fall through to vflush again to ensure 34241314Smckusick * that we have gotten rid of all the system vnodes. 34339898Smckusick */ 34441314Smckusick } 34512795Ssam #endif 34641314Smckusick if (error = vflush(mp, NULLVP, flags)) 34739898Smckusick return (error); 34837737Smckusick fs = ump->um_fs; 34937737Smckusick ronly = !fs->fs_ronly; 35040653Smckusick ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 35148036Smckusick error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, 35248036Smckusick NOCRED, p); 35337737Smckusick vrele(ump->um_devvp); 35451473Sbostic free(fs->fs_csp[0], M_SUPERBLK); 35551473Sbostic free(fs, M_SUPERBLK); 35651473Sbostic free(ump, M_UFSMNT); 35741397Smckusick mp->mnt_data = (qaddr_t)0; 35841397Smckusick mp->mnt_flag &= ~MNT_LOCAL; 35930749Skarels return (error); 36012795Ssam } 36112795Ssam 36237737Smckusick /* 36351545Smckusick * Return root of a filesystem 36451545Smckusick */ 36551545Smckusick int 36651545Smckusick ffs_root(mp, vpp) 36751545Smckusick struct mount *mp; 36851545Smckusick struct vnode **vpp; 36951545Smckusick { 37051545Smckusick struct vnode *nvp; 37151545Smckusick int error; 37251545Smckusick 37351545Smckusick if (error = ffs_vget(mp, (ino_t)ROOTINO, &nvp)) 37451545Smckusick return (error); 37551545Smckusick *vpp = nvp; 37651545Smckusick return (0); 37751545Smckusick } 37851545Smckusick 37951545Smckusick /* 38037737Smckusick * Get file system statistics. 38137737Smckusick */ 38251473Sbostic int 38351473Sbostic ffs_statfs(mp, sbp, p) 38437737Smckusick struct mount *mp; 38537737Smckusick register struct statfs *sbp; 38648036Smckusick struct proc *p; 38737737Smckusick { 38837737Smckusick register struct ufsmount *ump; 38937737Smckusick register struct fs *fs; 39037737Smckusick 39137737Smckusick ump = VFSTOUFS(mp); 39237737Smckusick fs = ump->um_fs; 39337737Smckusick if (fs->fs_magic != FS_MAGIC) 39451473Sbostic panic("ffs_statfs"); 39537737Smckusick sbp->f_type = MOUNT_UFS; 396*51942Smckusick sbp->f_bsize = fs->fs_fsize; 397*51942Smckusick sbp->f_iosize = fs->fs_bsize; 39837737Smckusick sbp->f_blocks = fs->fs_dsize; 39937737Smckusick sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 40037737Smckusick fs->fs_cstotal.cs_nffree; 40137737Smckusick sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 40237737Smckusick (fs->fs_dsize - sbp->f_bfree); 40339350Smckusick sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 40437737Smckusick sbp->f_ffree = fs->fs_cstotal.cs_nifree; 40541397Smckusick if (sbp != &mp->mnt_stat) { 40641397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntonname, 40740346Smckusick (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 40841397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 40940346Smckusick (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 41040346Smckusick } 41137737Smckusick return (0); 41237737Smckusick } 41337737Smckusick 41437737Smckusick /* 41537737Smckusick * Go through the disk queues to initiate sandbagged IO; 41637737Smckusick * go through the inodes to write those that have been modified; 41737737Smckusick * initiate the writing of the super block if it has been modified. 41841314Smckusick * 41941314Smckusick * Note: we are always called with the filesystem marked `MPBUSY'. 42037737Smckusick */ 42151473Sbostic int 42251473Sbostic ffs_sync(mp, waitfor) 42337737Smckusick struct mount *mp; 42437737Smckusick int waitfor; 42537737Smckusick { 42651473Sbostic extern int syncprt; 42739390Smckusick register struct vnode *vp; 42837737Smckusick register struct inode *ip; 42937737Smckusick register struct ufsmount *ump = VFSTOUFS(mp); 43037737Smckusick register struct fs *fs; 43139596Smckusick int error, allerror = 0; 43237737Smckusick 43337737Smckusick if (syncprt) 43451473Sbostic ufs_bufstats(); 43537737Smckusick fs = ump->um_fs; 43637737Smckusick /* 43737737Smckusick * Write back modified superblock. 43837737Smckusick * Consistency check that the superblock 43937737Smckusick * is still in the buffer cache. 44037737Smckusick */ 44137737Smckusick if (fs->fs_fmod != 0) { 44237737Smckusick if (fs->fs_ronly != 0) { /* XXX */ 44337737Smckusick printf("fs = %s\n", fs->fs_fsmnt); 44437737Smckusick panic("update: rofs mod"); 44537737Smckusick } 44637737Smckusick fs->fs_fmod = 0; 44737737Smckusick fs->fs_time = time.tv_sec; 44851473Sbostic allerror = ffs_sbupdate(ump, waitfor); 44937737Smckusick } 45037737Smckusick /* 45137737Smckusick * Write back each (modified) inode. 45237737Smckusick */ 45339877Smckusick loop: 45441462Smckusick for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) { 45541462Smckusick /* 45641462Smckusick * If the vnode that we are about to sync is no longer 45741462Smckusick * associated with this mount point, start over. 45841462Smckusick */ 45941462Smckusick if (vp->v_mount != mp) 46041462Smckusick goto loop; 46148359Smckusick if (VOP_ISLOCKED(vp)) 46248359Smckusick continue; 46339390Smckusick ip = VTOI(vp); 46439877Smckusick if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 && 46539877Smckusick vp->v_dirtyblkhd == NULL) 46637737Smckusick continue; 46739877Smckusick if (vget(vp)) 46839877Smckusick goto loop; 46939877Smckusick if (vp->v_dirtyblkhd) 47039877Smckusick vflushbuf(vp, 0); 47139877Smckusick if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) && 47251545Smckusick (error = ffs_update(vp, &time, &time, 0))) 47339596Smckusick allerror = error; 47439596Smckusick vput(vp); 47537737Smckusick } 47637737Smckusick /* 47739675Smckusick * Force stale file system control information to be flushed. 47837737Smckusick */ 47939675Smckusick vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0); 48041314Smckusick #ifdef QUOTA 48141314Smckusick qsync(mp); 48241314Smckusick #endif 48339596Smckusick return (allerror); 48437737Smckusick } 48537737Smckusick 48637737Smckusick /* 48751545Smckusick * File handle to vnode 48851545Smckusick * 48951545Smckusick * Have to be really careful about stale file handles: 49051545Smckusick * - check that the inode number is valid 49151545Smckusick * - call ffs_vget() to get the locked inode 49251545Smckusick * - check for an unallocated inode (i_mode == 0) 49351545Smckusick * - check that the generation number matches 49451545Smckusick */ 49551545Smckusick int 49651545Smckusick ffs_fhtovp(mp, fhp, vpp) 49751545Smckusick register struct mount *mp; 49851545Smckusick struct fid *fhp; 49951545Smckusick struct vnode **vpp; 50051545Smckusick { 50151545Smckusick register struct inode *ip; 50251545Smckusick register struct ufid *ufhp; 50351545Smckusick struct fs *fs; 50451545Smckusick struct vnode *nvp; 50551545Smckusick int error; 50651545Smckusick 50751545Smckusick ufhp = (struct ufid *)fhp; 50851545Smckusick fs = VFSTOUFS(mp)->um_fs; 50951545Smckusick if (ufhp->ufid_ino < ROOTINO || 51051545Smckusick ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) 51151545Smckusick return (EINVAL); 51251545Smckusick if (error = ffs_vget(mp, ufhp->ufid_ino, &nvp)) { 51351545Smckusick *vpp = NULLVP; 51451545Smckusick return (error); 51551545Smckusick } 51651545Smckusick ip = VTOI(nvp); 51751545Smckusick if (ip->i_mode == 0) { 51851545Smckusick ufs_iput(ip); 51951545Smckusick *vpp = NULLVP; 52051545Smckusick return (EINVAL); 52151545Smckusick } 52251545Smckusick if (ip->i_gen != ufhp->ufid_gen) { 52351545Smckusick ufs_iput(ip); 52451545Smckusick *vpp = NULLVP; 52551545Smckusick return (EINVAL); 52651545Smckusick } 52751545Smckusick *vpp = nvp; 52851545Smckusick return (0); 52951545Smckusick } 53051545Smckusick 53151545Smckusick /* 53251545Smckusick * Vnode pointer to File handle 53351545Smckusick */ 53451545Smckusick /* ARGSUSED */ 53551545Smckusick ffs_vptofh(vp, fhp) 53651545Smckusick struct vnode *vp; 53751545Smckusick struct fid *fhp; 53851545Smckusick { 53951545Smckusick register struct inode *ip; 54051545Smckusick register struct ufid *ufhp; 54151545Smckusick 54251545Smckusick ip = VTOI(vp); 54351545Smckusick ufhp = (struct ufid *)fhp; 54451545Smckusick ufhp->ufid_len = sizeof(struct ufid); 54551545Smckusick ufhp->ufid_ino = ip->i_number; 54651545Smckusick ufhp->ufid_gen = ip->i_gen; 54751545Smckusick return (0); 54851545Smckusick } 54951545Smckusick 55051545Smckusick /* 55137737Smckusick * Write a superblock and associated information back to disk. 55237737Smckusick */ 553*51942Smckusick int 55451473Sbostic ffs_sbupdate(mp, waitfor) 55537737Smckusick struct ufsmount *mp; 55637737Smckusick int waitfor; 55737737Smckusick { 55837737Smckusick register struct fs *fs = mp->um_fs; 55912795Ssam register struct buf *bp; 56012795Ssam int blks; 56112795Ssam caddr_t space; 56237737Smckusick int i, size, error = 0; 56312795Ssam 56437737Smckusick bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize); 56512795Ssam bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); 56634145Smckusick /* Restore compatibility to old file systems. XXX */ 56734145Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 56834145Smckusick bp->b_un.b_fs->fs_nrpos = -1; /* XXX */ 56937737Smckusick if (waitfor == MNT_WAIT) 57037737Smckusick error = bwrite(bp); 57137737Smckusick else 57237737Smckusick bawrite(bp); 57312795Ssam blks = howmany(fs->fs_cssize, fs->fs_fsize); 57412795Ssam space = (caddr_t)fs->fs_csp[0]; 57512795Ssam for (i = 0; i < blks; i += fs->fs_frag) { 57612795Ssam size = fs->fs_bsize; 57712795Ssam if (i + fs->fs_frag > blks) 57812795Ssam size = (blks - i) * fs->fs_fsize; 57937737Smckusick bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size); 58012795Ssam bcopy(space, bp->b_un.b_addr, (u_int)size); 58112795Ssam space += size; 58237737Smckusick if (waitfor == MNT_WAIT) 58337737Smckusick error = bwrite(bp); 58437737Smckusick else 58537737Smckusick bawrite(bp); 58612795Ssam } 58737737Smckusick return (error); 58812795Ssam } 589