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*51155Sbostic * @(#)lfs_vfsops.c 7.57 (Berkeley) 09/20/91 823400Smckusick */ 912795Ssam 1017100Sbloom #include "param.h" 1117100Sbloom #include "systm.h" 1247571Skarels #include "namei.h" 1341314Smckusick #include "proc.h" 1437737Smckusick #include "kernel.h" 1537737Smckusick #include "vnode.h" 1640653Smckusick #include "specdev.h" 1737737Smckusick #include "mount.h" 1817100Sbloom #include "buf.h" 1917100Sbloom #include "file.h" 2037737Smckusick #include "disklabel.h" 2130749Skarels #include "ioctl.h" 2237737Smckusick #include "errno.h" 2331660Smckusick #include "malloc.h" 2412795Ssam 25*51155Sbostic #include "../ufs/quota.h" 26*51155Sbostic #include "../ufs/inode.h" 27*51155Sbostic #include "../ufs/ufsmount.h" 28*51155Sbostic #include "lfs.h" 29*51155Sbostic #include "lfs_extern.h" 3047571Skarels 31*51155Sbostic static int lfs_mountfs 32*51155Sbostic __P((struct vnode *, struct mount *, struct proc *)); 33*51155Sbostic static int sbupdate __P((struct ufsmount *, int)); 34*51155Sbostic 35*51155Sbostic struct vfsops lfs_vfsops = { 36*51155Sbostic lfs_mount, 3739043Smckusick ufs_start, 38*51155Sbostic lfs_unmount, 39*51155Sbostic lfs_root, 4041314Smckusick ufs_quotactl, 41*51155Sbostic lfs_statfs, 42*51155Sbostic lfs_sync, 43*51155Sbostic lfs_fhtovp, 4439437Smckusick ufs_vptofh, 45*51155Sbostic lfs_init 4637737Smckusick }; 4737737Smckusick 4837737Smckusick /* 4948359Smckusick * Flag to allow forcible unmounting. 5048359Smckusick */ 51*51155Sbostic extern int doforce; /* LFS */ 5248359Smckusick 53*51155Sbostic lfs_mountroot() 5412795Ssam { 55*51155Sbostic /* LFS IMPLEMENT -- lfs_mountroot */ 56*51155Sbostic panic("lfs_mountroot"); 5737737Smckusick } 5837737Smckusick 5937737Smckusick /* 6037737Smckusick * VFS Operations. 6137737Smckusick * 6237737Smckusick * mount system call 6337737Smckusick */ 64*51155Sbostic lfs_mount(mp, path, data, ndp, p) 6540346Smckusick register struct mount *mp; 6637737Smckusick char *path; 6737737Smckusick caddr_t data; 6837737Smckusick struct nameidata *ndp; 6948036Smckusick struct proc *p; 7037737Smckusick { 7137737Smckusick struct vnode *devvp; 7237737Smckusick struct ufs_args args; 7337737Smckusick struct ufsmount *ump; 74*51155Sbostic register LFS *fs; /* LFS */ 7537737Smckusick u_int size; 7637737Smckusick int error; 7737737Smckusick 78*51155Sbostic printf("lfs_mount\n"); 7937737Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 8037737Smckusick return (error); 8140371Smckusick /* 8240371Smckusick * Process export requests. 8340371Smckusick */ 8441397Smckusick if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) { 8541397Smckusick if (args.exflags & MNT_EXPORTED) 8641397Smckusick mp->mnt_flag |= MNT_EXPORTED; 8740371Smckusick else 8841397Smckusick mp->mnt_flag &= ~MNT_EXPORTED; 8941397Smckusick if (args.exflags & MNT_EXRDONLY) 9041397Smckusick mp->mnt_flag |= MNT_EXRDONLY; 9140371Smckusick else 9241397Smckusick mp->mnt_flag &= ~MNT_EXRDONLY; 9341397Smckusick mp->mnt_exroot = args.exroot; 9440371Smckusick } 9550264Skarels /* 9650264Skarels * If updating, check whether changing from read-only to 9750264Skarels * read/write; if there is no device name, that's all we do. 9850264Skarels */ 9950264Skarels if (mp->mnt_flag & MNT_UPDATE) { 10039336Smckusick ump = VFSTOUFS(mp); 101*51155Sbostic #ifdef NOTLFS /* LFS */ 10239336Smckusick fs = ump->um_fs; 10341397Smckusick if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 10439336Smckusick fs->fs_ronly = 0; 105*51155Sbostic #else 106*51155Sbostic fs = ump->um_lfs; 107*51155Sbostic if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 108*51155Sbostic fs->lfs_ronly = 0; 109*51155Sbostic #endif 11040371Smckusick if (args.fspec == 0) 11140371Smckusick return (0); 11250264Skarels } 11350264Skarels /* 11450264Skarels * Not an update, or updating the name: look up the name 11550264Skarels * and verify that it refers to a sensible block device. 11650264Skarels */ 11750264Skarels ndp->ni_nameiop = LOOKUP | FOLLOW; 11850264Skarels ndp->ni_segflg = UIO_USERSPACE; 11950264Skarels ndp->ni_dirp = args.fspec; 12050264Skarels if (error = namei(ndp, p)) 12150264Skarels return (error); 12250264Skarels devvp = ndp->ni_vp; 12350264Skarels if (devvp->v_type != VBLK) { 12450264Skarels vrele(devvp); 12550264Skarels return (ENOTBLK); 12650264Skarels } 12750264Skarels if (major(devvp->v_rdev) >= nblkdev) { 12850264Skarels vrele(devvp); 12950264Skarels return (ENXIO); 13050264Skarels } 13150264Skarels if ((mp->mnt_flag & MNT_UPDATE) == 0) 132*51155Sbostic error = lfs_mountfs(devvp, mp, p); /* LFS */ 13350264Skarels else { 13439336Smckusick if (devvp != ump->um_devvp) 13539336Smckusick error = EINVAL; /* needs translation */ 13642858Smckusick else 13742858Smckusick vrele(devvp); 13839336Smckusick } 13937737Smckusick if (error) { 14037737Smckusick vrele(devvp); 14137737Smckusick return (error); 14232721Smckusick } 14337737Smckusick ump = VFSTOUFS(mp); 144*51155Sbostic fs = ump->um_lfs; /* LFS */ 145*51155Sbostic #ifdef NOTLFS /* LFS */ 14637737Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 14737737Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 14841397Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 14941397Smckusick MNAMELEN); 15041397Smckusick (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 15141397Smckusick &size); 15241397Smckusick bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 15348036Smckusick (void) ufs_statfs(mp, &mp->mnt_stat, p); 154*51155Sbostic #else 155*51155Sbostic (void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size); 156*51155Sbostic bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size); 157*51155Sbostic bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 158*51155Sbostic MNAMELEN); 159*51155Sbostic (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 160*51155Sbostic &size); 161*51155Sbostic bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 162*51155Sbostic (void) lfs_statfs(mp, &mp->mnt_stat, p); 163*51155Sbostic #endif 16437737Smckusick return (0); 16512795Ssam } 16612795Ssam 16737737Smckusick /* 16837737Smckusick * Common code for mount and mountroot 169*51155Sbostic * LFS specific 17037737Smckusick */ 171*51155Sbostic static int 172*51155Sbostic lfs_mountfs(devvp, mp, p) 17340376Smckusick register struct vnode *devvp; 17437737Smckusick struct mount *mp; 17548036Smckusick struct proc *p; 17612795Ssam { 177*51155Sbostic extern struct vnode *rootvp; 178*51155Sbostic register LFS *fs; 179*51155Sbostic register struct ufsmount *ump; 180*51155Sbostic struct inode *ip; 181*51155Sbostic struct vnode *vp; 182*51155Sbostic struct buf *bp; 18330749Skarels struct partinfo dpart; 184*51155Sbostic daddr_t seg_addr; 185*51155Sbostic dev_t dev; 186*51155Sbostic int error, i, ronly, size; 18712795Ssam 18840376Smckusick /* 189*51155Sbostic printf("lfs_mountfs\n"); 19040376Smckusick * Disallow multiple mounts of the same device. 19145652Smckusick * Disallow mounting of a device that is currently in use 19245652Smckusick * (except for root, which might share swap device for miniroot). 19340376Smckusick * Flush out any old buffers remaining from a previous use. 19440376Smckusick */ 19540376Smckusick if (error = mountedon(devvp)) 19640376Smckusick return (error); 19745652Smckusick if (vcount(devvp) > 1 && devvp != rootvp) 19840376Smckusick return (EBUSY); 19940376Smckusick vinvalbuf(devvp, 1); 200*51155Sbostic 201*51155Sbostic ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 20248036Smckusick if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p)) 20337737Smckusick return (error); 204*51155Sbostic 20548036Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 20637737Smckusick size = DEV_BSIZE; 20748036Smckusick else { 20830749Skarels size = dpart.disklab->d_secsize; 209*51155Sbostic #ifdef NEVER_USED 210*51155Sbostic dpart.part->p_fstype = FS_LFS; 211*51155Sbostic dpart.part->p_fsize = fs->lfs_fsize; /* frag size */ 212*51155Sbostic dpart.part->p_frag = fs->lfs_frag; /* frags per block */ 213*51155Sbostic dpart.part->p_cpg = fs->lfs_segshift; /* segment shift */ 214*51155Sbostic #endif 21537737Smckusick } 216*51155Sbostic 217*51155Sbostic /* Don't free random space on error. */ 218*51155Sbostic bp = NULL; 219*51155Sbostic ump = NULL; 220*51155Sbostic 221*51155Sbostic /* Read in the superblock. */ 222*51155Sbostic if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp)) 22312795Ssam goto out; 224*51155Sbostic fs = bp->b_un.b_lfs; 225*51155Sbostic 226*51155Sbostic /* Check the basics. */ 227*51155Sbostic if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE || 228*51155Sbostic fs->lfs_bsize < sizeof(LFS)) { 22941314Smckusick error = EINVAL; /* XXX needs translation */ 23016639Skarels goto out; 23116639Skarels } 232*51155Sbostic #ifdef DEBUG 233*51155Sbostic dump_super(fs); 234*51155Sbostic #endif 235*51155Sbostic 236*51155Sbostic /* Allocate the mount structure, copy the superblock into it. */ 23741314Smckusick ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 238*51155Sbostic ump->um_lfs = malloc(sizeof(LFS), M_SUPERBLK, M_WAITOK); 239*51155Sbostic bcopy(bp->b_un.b_addr, ump->um_lfs, sizeof(LFS)); 240*51155Sbostic if (sizeof(LFS) < LFS_SBPAD) /* XXX why? */ 24139675Smckusick bp->b_flags |= B_INVAL; 24234421Skarels brelse(bp); 24334421Skarels bp = NULL; 244*51155Sbostic 245*51155Sbostic /* Set the file system readonly/modify bits. */ 246*51155Sbostic fs = ump->um_lfs; 247*51155Sbostic fs->lfs_ronly = ronly; 24812795Ssam if (ronly == 0) 249*51155Sbostic fs->lfs_fmod = 1; 250*51155Sbostic 251*51155Sbostic /* Initialize the mount structure. */ 252*51155Sbostic dev = devvp->v_rdev; 25341397Smckusick mp->mnt_data = (qaddr_t)ump; 25441397Smckusick mp->mnt_stat.f_fsid.val[0] = (long)dev; 255*51155Sbostic mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS; 25641397Smckusick mp->mnt_flag |= MNT_LOCAL; 25737737Smckusick ump->um_mountp = mp; 25837737Smckusick ump->um_dev = dev; 25937737Smckusick ump->um_devvp = devvp; 26041314Smckusick for (i = 0; i < MAXQUOTAS; i++) 26141314Smckusick ump->um_quotas[i] = NULLVP; 262*51155Sbostic 263*51155Sbostic /* Read the ifile disk inode and store it in a vnode. */ 264*51155Sbostic error = bread(devvp, fs->lfs_idaddr, fs->lfs_bsize, NOCRED, &bp); 265*51155Sbostic if (error) 266*51155Sbostic goto out; 267*51155Sbostic error = lfs_vcreate(mp, LFS_IFILE_INUM, &vp); 268*51155Sbostic if (error) 269*51155Sbostic goto out; 270*51155Sbostic ip = VTOI(vp); 271*51155Sbostic 272*51155Sbostic /* The ifile inode is stored in the superblock. */ 273*51155Sbostic fs->lfs_ivnode = vp; 274*51155Sbostic 275*51155Sbostic /* Copy the on-disk inode into place. */ 276*51155Sbostic ip->i_din = *lfs_ifind(fs, LFS_IFILE_INUM, bp->b_un.b_dino); 277*51155Sbostic brelse(bp); 278*51155Sbostic 279*51155Sbostic /* Initialize the associated vnode */ 280*51155Sbostic vp->v_type = IFTOVT(ip->i_mode); 281*51155Sbostic 282*51155Sbostic /* 283*51155Sbostic * Read in the segusage table. 284*51155Sbostic * 285*51155Sbostic * Since we always explicitly write the segusage table at a checkpoint, 286*51155Sbostic * we're assuming that it is continguous on disk. 287*51155Sbostic */ 288*51155Sbostic seg_addr = ip->i_din.di_db[0]; 289*51155Sbostic size = fs->lfs_segtabsz << fs->lfs_bshift; 290*51155Sbostic fs->lfs_segtab = malloc(size, M_SUPERBLK, M_WAITOK); 291*51155Sbostic error = bread(devvp, seg_addr, size, NOCRED, &bp); 292*51155Sbostic if (error) { 293*51155Sbostic free(fs->lfs_segtab, M_SUPERBLK); 294*51155Sbostic goto out; 295*51155Sbostic } 296*51155Sbostic bcopy((caddr_t)bp->b_un.b_addr, fs->lfs_segtab, size); 297*51155Sbostic brelse(bp); 29840653Smckusick devvp->v_specflags |= SI_MOUNTEDON; 299*51155Sbostic VREF(ip->i_devvp); 30037737Smckusick return (0); 30112795Ssam out: 30240872Smckusick if (bp) 30340872Smckusick brelse(bp); 304*51155Sbostic (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 30541314Smckusick if (ump) { 306*51155Sbostic free((caddr_t)ump->um_lfs, M_SUPERBLK); 30741314Smckusick free((caddr_t)ump, M_UFSMNT); 30841397Smckusick mp->mnt_data = (qaddr_t)0; 30932721Smckusick } 31037737Smckusick return (error); 31112795Ssam } 31212795Ssam 31339043Smckusick /* 31437737Smckusick * unmount system call 31537737Smckusick */ 316*51155Sbostic lfs_unmount(mp, mntflags, p) 31737737Smckusick struct mount *mp; 31841314Smckusick int mntflags; 31948036Smckusick struct proc *p; 32012795Ssam { 32137737Smckusick register struct ufsmount *ump; 322*51155Sbostic register struct lfs *fs; /* LFS */ 32341314Smckusick int i, error, ronly, flags = 0; 32412795Ssam 325*51155Sbostic printf("lfs_unmount\n"); 32648065Smckusick if (mntflags & MNT_FORCE) { 32748359Smckusick if (!doforce || mp == rootfs) 32848065Smckusick return (EINVAL); 32941314Smckusick flags |= FORCECLOSE; 33048065Smckusick } 33139675Smckusick mntflushbuf(mp, 0); 33239675Smckusick if (mntinvalbuf(mp)) 33339675Smckusick return (EBUSY); 33437737Smckusick ump = VFSTOUFS(mp); 33512795Ssam #ifdef QUOTA 33641397Smckusick if (mp->mnt_flag & MNT_QUOTA) { 33741314Smckusick if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) 33839898Smckusick return (error); 33941314Smckusick for (i = 0; i < MAXQUOTAS; i++) { 34041314Smckusick if (ump->um_quotas[i] == NULLVP) 34141314Smckusick continue; 34250114Smckusick quotaoff(p, mp, i); 34341314Smckusick } 34439898Smckusick /* 34541314Smckusick * Here we fall through to vflush again to ensure 34641314Smckusick * that we have gotten rid of all the system vnodes. 34739898Smckusick */ 34841314Smckusick } 34912795Ssam #endif 35041314Smckusick if (error = vflush(mp, NULLVP, flags)) 35139898Smckusick return (error); 352*51155Sbostic #ifdef NOTLFS /* LFS */ 35337737Smckusick fs = ump->um_fs; 35437737Smckusick ronly = !fs->fs_ronly; 355*51155Sbostic #else 356*51155Sbostic fs = ump->um_lfs; 357*51155Sbostic ronly = !fs->lfs_ronly; 358*51155Sbostic #endif 35940653Smckusick ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 36048036Smckusick error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, 36148036Smckusick NOCRED, p); 36237737Smckusick vrele(ump->um_devvp); 363*51155Sbostic #ifdef NOTLFS /* LFS */ 36441314Smckusick free((caddr_t)fs->fs_csp[0], M_SUPERBLK); 365*51155Sbostic #else 366*51155Sbostic free(fs->lfs_segtab, M_SUPERBLK); 367*51155Sbostic iput(VTOI(fs->lfs_ivnode)); 368*51155Sbostic #endif 36941314Smckusick free((caddr_t)fs, M_SUPERBLK); 37041314Smckusick free((caddr_t)ump, M_UFSMNT); 37141397Smckusick mp->mnt_data = (qaddr_t)0; 37241397Smckusick mp->mnt_flag &= ~MNT_LOCAL; 37330749Skarels return (error); 37412795Ssam } 37512795Ssam 37637737Smckusick /* 37737737Smckusick * Return root of a filesystem 37837737Smckusick */ 379*51155Sbostic lfs_root(mp, vpp) 38012795Ssam struct mount *mp; 38137737Smckusick struct vnode **vpp; 38212795Ssam { 38339390Smckusick register struct inode *ip; 38439390Smckusick struct inode *nip; 38539390Smckusick struct vnode tvp; 38637737Smckusick int error; 38737737Smckusick 388*51155Sbostic printf("lfs_root\n"); 38939390Smckusick tvp.v_mount = mp; 39039390Smckusick ip = VTOI(&tvp); 39139390Smckusick ip->i_vnode = &tvp; 39239390Smckusick ip->i_dev = VFSTOUFS(mp)->um_dev; 393*51155Sbostic error = lfs_iget(ip, (ino_t)ROOTINO, &nip); /* LFS */ 39437737Smckusick if (error) 39537737Smckusick return (error); 39639390Smckusick *vpp = ITOV(nip); 39737737Smckusick return (0); 39837737Smckusick } 39937737Smckusick 40037737Smckusick /* 40137737Smckusick * Get file system statistics. 40237737Smckusick */ 403*51155Sbostic lfs_statfs(mp, sbp, p) 40437737Smckusick struct mount *mp; 40537737Smckusick register struct statfs *sbp; 40648036Smckusick struct proc *p; 40737737Smckusick { 408*51155Sbostic register LFS *fs; 40937737Smckusick register struct ufsmount *ump; 41037737Smckusick 411*51155Sbostic printf("lfs_statfs\n"); 41237737Smckusick ump = VFSTOUFS(mp); 413*51155Sbostic #ifdef NOTLFS /* LFS */ 41437737Smckusick fs = ump->um_fs; 41537737Smckusick if (fs->fs_magic != FS_MAGIC) 41637737Smckusick panic("ufs_statfs"); 41737737Smckusick sbp->f_type = MOUNT_UFS; 41837737Smckusick sbp->f_fsize = fs->fs_fsize; 41937737Smckusick sbp->f_bsize = fs->fs_bsize; 42037737Smckusick sbp->f_blocks = fs->fs_dsize; 42137737Smckusick sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 42237737Smckusick fs->fs_cstotal.cs_nffree; 42337737Smckusick sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 42437737Smckusick (fs->fs_dsize - sbp->f_bfree); 42539350Smckusick sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 42637737Smckusick sbp->f_ffree = fs->fs_cstotal.cs_nifree; 427*51155Sbostic #else 428*51155Sbostic fs = ump->um_lfs; 429*51155Sbostic if (fs->lfs_magic != LFS_MAGIC) 430*51155Sbostic panic("lfs_statfs: magic"); 431*51155Sbostic sbp->f_type = MOUNT_LFS; 432*51155Sbostic sbp->f_fsize = fs->lfs_bsize; 433*51155Sbostic sbp->f_bsize = fs->lfs_bsize; 434*51155Sbostic sbp->f_blocks = fs->lfs_dsize; 435*51155Sbostic sbp->f_bfree = fs->lfs_bfree; 436*51155Sbostic sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) - 437*51155Sbostic (fs->lfs_dsize - sbp->f_bfree); 438*51155Sbostic sbp->f_files = fs->lfs_nfiles; 439*51155Sbostic sbp->f_ffree = fs->lfs_bfree * INOPB(fs); 440*51155Sbostic #endif 44141397Smckusick if (sbp != &mp->mnt_stat) { 44241397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntonname, 44340346Smckusick (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 44441397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 44540346Smckusick (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 44640346Smckusick } 44737737Smckusick return (0); 44837737Smckusick } 44937737Smckusick 450*51155Sbostic extern int syncprt; /* LFS */ 45137737Smckusick 45237737Smckusick /* 45337737Smckusick * Go through the disk queues to initiate sandbagged IO; 45437737Smckusick * go through the inodes to write those that have been modified; 45537737Smckusick * initiate the writing of the super block if it has been modified. 45641314Smckusick * 45741314Smckusick * Note: we are always called with the filesystem marked `MPBUSY'. 45837737Smckusick */ 459*51155Sbostic lfs_sync(mp, waitfor) 46037737Smckusick struct mount *mp; 46137737Smckusick int waitfor; 46237737Smckusick { 46339390Smckusick register struct vnode *vp; 46437737Smckusick register struct inode *ip; 46537737Smckusick register struct ufsmount *ump = VFSTOUFS(mp); 46637737Smckusick register struct fs *fs; 46739596Smckusick int error, allerror = 0; 46837737Smckusick 469*51155Sbostic printf("lfs_sync\n"); 47037737Smckusick if (syncprt) 47137737Smckusick bufstats(); 472*51155Sbostic #ifdef NOTLFS /* LFS */ 47337737Smckusick fs = ump->um_fs; 47437737Smckusick /* 47537737Smckusick * Write back modified superblock. 47637737Smckusick * Consistency check that the superblock 47737737Smckusick * is still in the buffer cache. 47837737Smckusick */ 47937737Smckusick if (fs->fs_fmod != 0) { 48037737Smckusick if (fs->fs_ronly != 0) { /* XXX */ 48137737Smckusick printf("fs = %s\n", fs->fs_fsmnt); 48237737Smckusick panic("update: rofs mod"); 48337737Smckusick } 48437737Smckusick fs->fs_fmod = 0; 48537737Smckusick fs->fs_time = time.tv_sec; 48641510Smckusick allerror = sbupdate(ump, waitfor); 48737737Smckusick } 488*51155Sbostic #else 489*51155Sbostic #ifdef DEBUG 490*51155Sbostic return (0); 491*51155Sbostic #else 492*51155Sbostic /* LFS IMPLEMENT -- read only access, super-block update */ 493*51155Sbostic panic("lfs_sync not implemented"); */ 494*51155Sbostic #endif 495*51155Sbostic #endif 49637737Smckusick /* 49737737Smckusick * Write back each (modified) inode. 49837737Smckusick */ 49939877Smckusick loop: 50041462Smckusick for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) { 50141462Smckusick /* 50241462Smckusick * If the vnode that we are about to sync is no longer 50341462Smckusick * associated with this mount point, start over. 50441462Smckusick */ 50541462Smckusick if (vp->v_mount != mp) 50641462Smckusick goto loop; 50748359Smckusick if (VOP_ISLOCKED(vp)) 50848359Smckusick continue; 50939390Smckusick ip = VTOI(vp); 51039877Smckusick if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 && 51139877Smckusick vp->v_dirtyblkhd == NULL) 51237737Smckusick continue; 51339877Smckusick if (vget(vp)) 51439877Smckusick goto loop; 51539877Smckusick if (vp->v_dirtyblkhd) 51639877Smckusick vflushbuf(vp, 0); 51739877Smckusick if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) && 518*51155Sbostic (error = lfs_iupdat(ip, &time, &time, 0))) /* LFS */ 51939596Smckusick allerror = error; 52039596Smckusick vput(vp); 52137737Smckusick } 52237737Smckusick /* 52339675Smckusick * Force stale file system control information to be flushed. 52437737Smckusick */ 52539675Smckusick vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0); 52641314Smckusick #ifdef QUOTA 52741314Smckusick qsync(mp); 52841314Smckusick #endif 52939596Smckusick return (allerror); 53037737Smckusick } 53137737Smckusick 532*51155Sbostic static int 53337737Smckusick sbupdate(mp, waitfor) 53437737Smckusick struct ufsmount *mp; 53537737Smckusick int waitfor; 53637737Smckusick { 537*51155Sbostic /* LFS IMPLEMENT -- sbupdate */ 538*51155Sbostic panic("sbupdate not implemented"); 53912795Ssam } 54012795Ssam 54112795Ssam /* 54237737Smckusick * File handle to vnode 54338453Smckusick * 54438453Smckusick * Have to be really careful about stale file handles: 54538453Smckusick * - check that the inode number is in range 54638453Smckusick * - call iget() to get the locked inode 54738453Smckusick * - check for an unallocated inode (i_mode == 0) 54838453Smckusick * - check that the generation number matches 54937737Smckusick */ 550*51155Sbostic lfs_fhtovp(mp, fhp, vpp) 55138453Smckusick register struct mount *mp; 55237737Smckusick struct fid *fhp; 55337737Smckusick struct vnode **vpp; 55437737Smckusick { 55537737Smckusick register struct ufid *ufhp; 556*51155Sbostic register struct lfs *fs; /* LFS */ 55739390Smckusick register struct inode *ip; 558*51155Sbostic IFILE *ifp; 559*51155Sbostic struct buf *bp; 56039390Smckusick struct inode *nip; 56139390Smckusick struct vnode tvp; 56237737Smckusick int error; 56337737Smckusick 56437737Smckusick ufhp = (struct ufid *)fhp; 565*51155Sbostic #ifdef NOTLFS /* LFS */ 56638453Smckusick fs = VFSTOUFS(mp)->um_fs; 56738453Smckusick if (ufhp->ufid_ino < ROOTINO || 56838453Smckusick ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) { 56941397Smckusick *vpp = NULLVP; 57038453Smckusick return (EINVAL); 57138453Smckusick } 572*51155Sbostic #else 573*51155Sbostic fs = VFSTOUFS(mp)->um_lfs; 574*51155Sbostic if (ufhp->ufid_ino < ROOTINO) { 575*51155Sbostic *vpp = NULLVP; 576*51155Sbostic return (EINVAL); 577*51155Sbostic } 578*51155Sbostic #endif 57939390Smckusick tvp.v_mount = mp; 58039390Smckusick ip = VTOI(&tvp); 58139390Smckusick ip->i_vnode = &tvp; 58239390Smckusick ip->i_dev = VFSTOUFS(mp)->um_dev; 583*51155Sbostic if (error = lfs_iget(ip, ufhp->ufid_ino, &nip)) { /* LFS */ 58441397Smckusick *vpp = NULLVP; 58537737Smckusick return (error); 58637737Smckusick } 58739390Smckusick ip = nip; 58838453Smckusick if (ip->i_mode == 0) { 58938453Smckusick iput(ip); 59041397Smckusick *vpp = NULLVP; 59138453Smckusick return (EINVAL); 59238453Smckusick } 59337737Smckusick if (ip->i_gen != ufhp->ufid_gen) { 59437737Smckusick iput(ip); 59541397Smckusick *vpp = NULLVP; 59637737Smckusick return (EINVAL); 59737737Smckusick } 59837737Smckusick *vpp = ITOV(ip); 59937737Smckusick return (0); 60037737Smckusick } 601