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*51310Sbostic * @(#)lfs_vfsops.c 7.60 (Berkeley) 10/03/91 823400Smckusick */ 912795Ssam 1051215Sbostic #ifdef LOGFS 1117100Sbloom #include "param.h" 1217100Sbloom #include "systm.h" 1347571Skarels #include "namei.h" 1441314Smckusick #include "proc.h" 1537737Smckusick #include "kernel.h" 1637737Smckusick #include "vnode.h" 1740653Smckusick #include "specdev.h" 1837737Smckusick #include "mount.h" 1917100Sbloom #include "buf.h" 2017100Sbloom #include "file.h" 2137737Smckusick #include "disklabel.h" 2230749Skarels #include "ioctl.h" 2337737Smckusick #include "errno.h" 2431660Smckusick #include "malloc.h" 2512795Ssam 2651155Sbostic #include "../ufs/quota.h" 2751155Sbostic #include "../ufs/inode.h" 2851155Sbostic #include "../ufs/ufsmount.h" 2951155Sbostic #include "lfs.h" 3051155Sbostic #include "lfs_extern.h" 3147571Skarels 3251155Sbostic static int lfs_mountfs 3351155Sbostic __P((struct vnode *, struct mount *, struct proc *)); 3451155Sbostic 3551215Sbostic static int lfs_umountdebug __P((struct mount *)); 3651215Sbostic static int lfs_vinvalbuf __P((register struct vnode *)); 3751215Sbostic 3851155Sbostic struct vfsops lfs_vfsops = { 3951155Sbostic lfs_mount, 4039043Smckusick ufs_start, 4151155Sbostic lfs_unmount, 4251155Sbostic lfs_root, 4341314Smckusick ufs_quotactl, 4451155Sbostic lfs_statfs, 4551155Sbostic lfs_sync, 4651155Sbostic lfs_fhtovp, 4739437Smckusick ufs_vptofh, 4851155Sbostic lfs_init 4937737Smckusick }; 5037737Smckusick 5137737Smckusick /* 5248359Smckusick * Flag to allow forcible unmounting. 5348359Smckusick */ 5451155Sbostic extern int doforce; /* LFS */ 5548359Smckusick 5651155Sbostic lfs_mountroot() 5712795Ssam { 5851155Sbostic /* LFS IMPLEMENT -- lfs_mountroot */ 5951155Sbostic panic("lfs_mountroot"); 6037737Smckusick } 6137737Smckusick 6237737Smckusick /* 6337737Smckusick * VFS Operations. 6437737Smckusick * 6537737Smckusick * mount system call 6637737Smckusick */ 6751155Sbostic lfs_mount(mp, path, data, ndp, p) 6840346Smckusick register struct mount *mp; 6937737Smckusick char *path; 7037737Smckusick caddr_t data; 7137737Smckusick struct nameidata *ndp; 7248036Smckusick struct proc *p; 7337737Smckusick { 7437737Smckusick struct vnode *devvp; 7537737Smckusick struct ufs_args args; 7637737Smckusick struct ufsmount *ump; 7751155Sbostic register LFS *fs; /* LFS */ 7837737Smckusick u_int size; 7937737Smckusick int error; 8037737Smckusick 8137737Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 8237737Smckusick return (error); 8340371Smckusick /* 8440371Smckusick * Process export requests. 8540371Smckusick */ 8641397Smckusick if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) { 8741397Smckusick if (args.exflags & MNT_EXPORTED) 8841397Smckusick mp->mnt_flag |= MNT_EXPORTED; 8940371Smckusick else 9041397Smckusick mp->mnt_flag &= ~MNT_EXPORTED; 9141397Smckusick if (args.exflags & MNT_EXRDONLY) 9241397Smckusick mp->mnt_flag |= MNT_EXRDONLY; 9340371Smckusick else 9441397Smckusick mp->mnt_flag &= ~MNT_EXRDONLY; 9541397Smckusick mp->mnt_exroot = args.exroot; 9640371Smckusick } 9750264Skarels /* 9850264Skarels * If updating, check whether changing from read-only to 9950264Skarels * read/write; if there is no device name, that's all we do. 10050264Skarels */ 10150264Skarels if (mp->mnt_flag & MNT_UPDATE) { 10239336Smckusick ump = VFSTOUFS(mp); 10351155Sbostic #ifdef NOTLFS /* LFS */ 10439336Smckusick fs = ump->um_fs; 10541397Smckusick if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 10639336Smckusick fs->fs_ronly = 0; 10751155Sbostic #else 10851155Sbostic fs = ump->um_lfs; 10951155Sbostic if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 11051155Sbostic fs->lfs_ronly = 0; 11151155Sbostic #endif 11240371Smckusick if (args.fspec == 0) 11340371Smckusick return (0); 11450264Skarels } 11550264Skarels /* 11650264Skarels * Not an update, or updating the name: look up the name 11750264Skarels * and verify that it refers to a sensible block device. 11850264Skarels */ 11950264Skarels ndp->ni_nameiop = LOOKUP | FOLLOW; 12050264Skarels ndp->ni_segflg = UIO_USERSPACE; 12150264Skarels ndp->ni_dirp = args.fspec; 12250264Skarels if (error = namei(ndp, p)) 12350264Skarels return (error); 12450264Skarels devvp = ndp->ni_vp; 12550264Skarels if (devvp->v_type != VBLK) { 12650264Skarels vrele(devvp); 12750264Skarels return (ENOTBLK); 12850264Skarels } 12950264Skarels if (major(devvp->v_rdev) >= nblkdev) { 13050264Skarels vrele(devvp); 13150264Skarels return (ENXIO); 13250264Skarels } 13350264Skarels if ((mp->mnt_flag & MNT_UPDATE) == 0) 13451155Sbostic error = lfs_mountfs(devvp, mp, p); /* LFS */ 13550264Skarels else { 13639336Smckusick if (devvp != ump->um_devvp) 13739336Smckusick error = EINVAL; /* needs translation */ 13842858Smckusick else 13942858Smckusick vrele(devvp); 14039336Smckusick } 14137737Smckusick if (error) { 14237737Smckusick vrele(devvp); 14337737Smckusick return (error); 14432721Smckusick } 14537737Smckusick ump = VFSTOUFS(mp); 14651155Sbostic fs = ump->um_lfs; /* LFS */ 14751155Sbostic #ifdef NOTLFS /* LFS */ 14837737Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 14937737Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 15041397Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 15141397Smckusick MNAMELEN); 15241397Smckusick (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 15341397Smckusick &size); 15441397Smckusick bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 15548036Smckusick (void) ufs_statfs(mp, &mp->mnt_stat, p); 15651155Sbostic #else 15751155Sbostic (void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size); 15851155Sbostic bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size); 15951155Sbostic bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 16051155Sbostic MNAMELEN); 16151155Sbostic (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 16251155Sbostic &size); 16351155Sbostic bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 16451155Sbostic (void) lfs_statfs(mp, &mp->mnt_stat, p); 16551155Sbostic #endif 16637737Smckusick return (0); 16712795Ssam } 16812795Ssam 16937737Smckusick /* 17037737Smckusick * Common code for mount and mountroot 17151155Sbostic * LFS specific 17237737Smckusick */ 17351155Sbostic static int 17451155Sbostic lfs_mountfs(devvp, mp, p) 17540376Smckusick register struct vnode *devvp; 17637737Smckusick struct mount *mp; 17748036Smckusick struct proc *p; 17812795Ssam { 17951155Sbostic extern struct vnode *rootvp; 18051155Sbostic register LFS *fs; 18151155Sbostic register struct ufsmount *ump; 18251155Sbostic struct inode *ip; 18351155Sbostic struct vnode *vp; 18451155Sbostic struct buf *bp; 18530749Skarels struct partinfo dpart; 18651155Sbostic daddr_t seg_addr; 18751155Sbostic dev_t dev; 18851155Sbostic int error, i, ronly, size; 18912795Ssam 19040376Smckusick /* 19140376Smckusick * Disallow multiple mounts of the same device. 19245652Smckusick * Disallow mounting of a device that is currently in use 19345652Smckusick * (except for root, which might share swap device for miniroot). 19440376Smckusick * Flush out any old buffers remaining from a previous use. 19540376Smckusick */ 19640376Smckusick if (error = mountedon(devvp)) 19740376Smckusick return (error); 19845652Smckusick if (vcount(devvp) > 1 && devvp != rootvp) 19940376Smckusick return (EBUSY); 20040376Smckusick vinvalbuf(devvp, 1); 20151155Sbostic 20251155Sbostic ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 20348036Smckusick if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p)) 20437737Smckusick return (error); 20551155Sbostic 20648036Smckusick if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 20737737Smckusick size = DEV_BSIZE; 20848036Smckusick else { 20930749Skarels size = dpart.disklab->d_secsize; 21051155Sbostic #ifdef NEVER_USED 21151155Sbostic dpart.part->p_fstype = FS_LFS; 21251155Sbostic dpart.part->p_fsize = fs->lfs_fsize; /* frag size */ 21351155Sbostic dpart.part->p_frag = fs->lfs_frag; /* frags per block */ 21451155Sbostic dpart.part->p_cpg = fs->lfs_segshift; /* segment shift */ 21551155Sbostic #endif 21637737Smckusick } 21751155Sbostic 21851155Sbostic /* Don't free random space on error. */ 21951155Sbostic bp = NULL; 22051155Sbostic ump = NULL; 22151155Sbostic 22251155Sbostic /* Read in the superblock. */ 22351155Sbostic if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp)) 22412795Ssam goto out; 22551155Sbostic fs = bp->b_un.b_lfs; 22651155Sbostic 22751155Sbostic /* Check the basics. */ 22851155Sbostic if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE || 22951155Sbostic fs->lfs_bsize < sizeof(LFS)) { 23041314Smckusick error = EINVAL; /* XXX needs translation */ 23116639Skarels goto out; 23216639Skarels } 23351155Sbostic #ifdef DEBUG 23451155Sbostic dump_super(fs); 23551155Sbostic #endif 23651155Sbostic 23751155Sbostic /* Allocate the mount structure, copy the superblock into it. */ 23841314Smckusick ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 23951155Sbostic ump->um_lfs = malloc(sizeof(LFS), M_SUPERBLK, M_WAITOK); 24051155Sbostic bcopy(bp->b_un.b_addr, ump->um_lfs, sizeof(LFS)); 24151155Sbostic if (sizeof(LFS) < LFS_SBPAD) /* XXX why? */ 24239675Smckusick bp->b_flags |= B_INVAL; 24334421Skarels brelse(bp); 24434421Skarels bp = NULL; 24551155Sbostic 24651183Sbostic /* Set up the I/O information */ 24751183Sbostic fs->lfs_iocount = 0; 24851183Sbostic fs->lfs_seglist = NULL; 24951183Sbostic 25051155Sbostic /* Set the file system readonly/modify bits. */ 25151155Sbostic fs = ump->um_lfs; 25251155Sbostic fs->lfs_ronly = ronly; 25312795Ssam if (ronly == 0) 25451155Sbostic fs->lfs_fmod = 1; 25551155Sbostic 25651155Sbostic /* Initialize the mount structure. */ 25751155Sbostic dev = devvp->v_rdev; 25841397Smckusick mp->mnt_data = (qaddr_t)ump; 25941397Smckusick mp->mnt_stat.f_fsid.val[0] = (long)dev; 26051155Sbostic mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS; 26141397Smckusick mp->mnt_flag |= MNT_LOCAL; 26237737Smckusick ump->um_mountp = mp; 26337737Smckusick ump->um_dev = dev; 26437737Smckusick ump->um_devvp = devvp; 26541314Smckusick for (i = 0; i < MAXQUOTAS; i++) 26641314Smckusick ump->um_quotas[i] = NULLVP; 26751155Sbostic 26851155Sbostic /* Read the ifile disk inode and store it in a vnode. */ 26951155Sbostic error = bread(devvp, fs->lfs_idaddr, fs->lfs_bsize, NOCRED, &bp); 27051155Sbostic if (error) 27151155Sbostic goto out; 27251155Sbostic error = lfs_vcreate(mp, LFS_IFILE_INUM, &vp); 27351155Sbostic if (error) 27451155Sbostic goto out; 27551155Sbostic ip = VTOI(vp); 27651155Sbostic 27751155Sbostic /* The ifile inode is stored in the superblock. */ 27851155Sbostic fs->lfs_ivnode = vp; 27951155Sbostic 28051155Sbostic /* Copy the on-disk inode into place. */ 28151155Sbostic ip->i_din = *lfs_ifind(fs, LFS_IFILE_INUM, bp->b_un.b_dino); 28251155Sbostic brelse(bp); 28351155Sbostic 28451155Sbostic /* Initialize the associated vnode */ 28551155Sbostic vp->v_type = IFTOVT(ip->i_mode); 28651155Sbostic 28751155Sbostic /* 28851155Sbostic * Read in the segusage table. 28951155Sbostic * 29051155Sbostic * Since we always explicitly write the segusage table at a checkpoint, 29151155Sbostic * we're assuming that it is continguous on disk. 29251155Sbostic */ 29351155Sbostic seg_addr = ip->i_din.di_db[0]; 29451155Sbostic size = fs->lfs_segtabsz << fs->lfs_bshift; 29551155Sbostic fs->lfs_segtab = malloc(size, M_SUPERBLK, M_WAITOK); 29651155Sbostic error = bread(devvp, seg_addr, size, NOCRED, &bp); 29751155Sbostic if (error) { 29851155Sbostic free(fs->lfs_segtab, M_SUPERBLK); 29951155Sbostic goto out; 30051155Sbostic } 30151155Sbostic bcopy((caddr_t)bp->b_un.b_addr, fs->lfs_segtab, size); 30251155Sbostic brelse(bp); 30340653Smckusick devvp->v_specflags |= SI_MOUNTEDON; 30451155Sbostic VREF(ip->i_devvp); 30537737Smckusick return (0); 30612795Ssam out: 30740872Smckusick if (bp) 30840872Smckusick brelse(bp); 30951155Sbostic (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 31041314Smckusick if (ump) { 31151155Sbostic free((caddr_t)ump->um_lfs, M_SUPERBLK); 31241314Smckusick free((caddr_t)ump, M_UFSMNT); 31341397Smckusick mp->mnt_data = (qaddr_t)0; 31432721Smckusick } 31537737Smckusick return (error); 31612795Ssam } 31712795Ssam 31839043Smckusick /* 31937737Smckusick * unmount system call 32037737Smckusick */ 32151155Sbostic lfs_unmount(mp, mntflags, p) 32237737Smckusick struct mount *mp; 32341314Smckusick int mntflags; 32448036Smckusick struct proc *p; 32512795Ssam { 32637737Smckusick register struct ufsmount *ump; 32751183Sbostic register LFS *fs; /* LFS */ 32841314Smckusick int i, error, ronly, flags = 0; 32951215Sbostic int ndirty; /* LFS */ 33012795Ssam 33151155Sbostic printf("lfs_unmount\n"); 33248065Smckusick if (mntflags & MNT_FORCE) { 33348359Smckusick if (!doforce || mp == rootfs) 33448065Smckusick return (EINVAL); 33541314Smckusick flags |= FORCECLOSE; 33648065Smckusick } 33751215Sbostic if (error = lfs_segwrite(mp, 1)) 33851215Sbostic return(error); 33951215Sbostic 34051215Sbostic ndirty = lfs_umountdebug(mp); 34151215Sbostic printf("lfs_umountdebug: returned %d dirty\n", ndirty); 34251215Sbostic return(0); 34339675Smckusick if (mntinvalbuf(mp)) 34439675Smckusick return (EBUSY); 34537737Smckusick ump = VFSTOUFS(mp); 34612795Ssam #ifdef QUOTA 34741397Smckusick if (mp->mnt_flag & MNT_QUOTA) { 34841314Smckusick if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) 34939898Smckusick return (error); 35041314Smckusick for (i = 0; i < MAXQUOTAS; i++) { 35141314Smckusick if (ump->um_quotas[i] == NULLVP) 35241314Smckusick continue; 35350114Smckusick quotaoff(p, mp, i); 35441314Smckusick } 35539898Smckusick /* 35641314Smckusick * Here we fall through to vflush again to ensure 35741314Smckusick * that we have gotten rid of all the system vnodes. 35839898Smckusick */ 35941314Smckusick } 36012795Ssam #endif 36141314Smckusick if (error = vflush(mp, NULLVP, flags)) 36239898Smckusick return (error); 36351155Sbostic #ifdef NOTLFS /* LFS */ 36437737Smckusick fs = ump->um_fs; 36537737Smckusick ronly = !fs->fs_ronly; 36651155Sbostic #else 36751155Sbostic fs = ump->um_lfs; 36851155Sbostic ronly = !fs->lfs_ronly; 36951155Sbostic #endif 37040653Smckusick ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 37148036Smckusick error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, 37248036Smckusick NOCRED, p); 37337737Smckusick vrele(ump->um_devvp); 37451155Sbostic #ifdef NOTLFS /* LFS */ 37541314Smckusick free((caddr_t)fs->fs_csp[0], M_SUPERBLK); 37651155Sbostic #else 37751155Sbostic free(fs->lfs_segtab, M_SUPERBLK); 37851155Sbostic iput(VTOI(fs->lfs_ivnode)); 37951155Sbostic #endif 38041314Smckusick free((caddr_t)fs, M_SUPERBLK); 38141314Smckusick free((caddr_t)ump, M_UFSMNT); 38241397Smckusick mp->mnt_data = (qaddr_t)0; 38341397Smckusick mp->mnt_flag &= ~MNT_LOCAL; 38430749Skarels return (error); 38512795Ssam } 38612795Ssam 38737737Smckusick /* 38837737Smckusick * Return root of a filesystem 38937737Smckusick */ 39051155Sbostic lfs_root(mp, vpp) 39112795Ssam struct mount *mp; 39237737Smckusick struct vnode **vpp; 39312795Ssam { 39439390Smckusick register struct inode *ip; 39539390Smckusick struct inode *nip; 39639390Smckusick struct vnode tvp; 39737737Smckusick int error; 39837737Smckusick 39939390Smckusick tvp.v_mount = mp; 40039390Smckusick ip = VTOI(&tvp); 40139390Smckusick ip->i_vnode = &tvp; 40239390Smckusick ip->i_dev = VFSTOUFS(mp)->um_dev; 40351155Sbostic error = lfs_iget(ip, (ino_t)ROOTINO, &nip); /* LFS */ 40437737Smckusick if (error) 40537737Smckusick return (error); 40639390Smckusick *vpp = ITOV(nip); 40737737Smckusick return (0); 40837737Smckusick } 40937737Smckusick 41037737Smckusick /* 41137737Smckusick * Get file system statistics. 41237737Smckusick */ 41351155Sbostic lfs_statfs(mp, sbp, p) 41437737Smckusick struct mount *mp; 41537737Smckusick register struct statfs *sbp; 41648036Smckusick struct proc *p; 41737737Smckusick { 41851155Sbostic register LFS *fs; 41937737Smckusick register struct ufsmount *ump; 42037737Smckusick 42137737Smckusick ump = VFSTOUFS(mp); 42251155Sbostic #ifdef NOTLFS /* LFS */ 42337737Smckusick fs = ump->um_fs; 42437737Smckusick if (fs->fs_magic != FS_MAGIC) 42537737Smckusick panic("ufs_statfs"); 42637737Smckusick sbp->f_type = MOUNT_UFS; 42737737Smckusick sbp->f_fsize = fs->fs_fsize; 42837737Smckusick sbp->f_bsize = fs->fs_bsize; 42937737Smckusick sbp->f_blocks = fs->fs_dsize; 43037737Smckusick sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 43137737Smckusick fs->fs_cstotal.cs_nffree; 43237737Smckusick sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 43337737Smckusick (fs->fs_dsize - sbp->f_bfree); 43439350Smckusick sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 43537737Smckusick sbp->f_ffree = fs->fs_cstotal.cs_nifree; 43651155Sbostic #else 43751155Sbostic fs = ump->um_lfs; 43851155Sbostic if (fs->lfs_magic != LFS_MAGIC) 43951155Sbostic panic("lfs_statfs: magic"); 44051155Sbostic sbp->f_type = MOUNT_LFS; 44151155Sbostic sbp->f_fsize = fs->lfs_bsize; 44251155Sbostic sbp->f_bsize = fs->lfs_bsize; 44351155Sbostic sbp->f_blocks = fs->lfs_dsize; 44451155Sbostic sbp->f_bfree = fs->lfs_bfree; 44551155Sbostic sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) - 44651155Sbostic (fs->lfs_dsize - sbp->f_bfree); 44751155Sbostic sbp->f_files = fs->lfs_nfiles; 44851155Sbostic sbp->f_ffree = fs->lfs_bfree * INOPB(fs); 44951155Sbostic #endif 45041397Smckusick if (sbp != &mp->mnt_stat) { 45141397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntonname, 45240346Smckusick (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 45341397Smckusick bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 45440346Smckusick (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 45540346Smckusick } 45637737Smckusick return (0); 45737737Smckusick } 45837737Smckusick 45951155Sbostic extern int syncprt; /* LFS */ 46037737Smckusick 46137737Smckusick /* 46237737Smckusick * Go through the disk queues to initiate sandbagged IO; 46337737Smckusick * go through the inodes to write those that have been modified; 46437737Smckusick * initiate the writing of the super block if it has been modified. 46541314Smckusick * 46641314Smckusick * Note: we are always called with the filesystem marked `MPBUSY'. 46737737Smckusick */ 46851215Sbostic int STOPNOW; 46951155Sbostic lfs_sync(mp, waitfor) 47037737Smckusick struct mount *mp; 47137737Smckusick int waitfor; 47237737Smckusick { 473*51310Sbostic static int sync_lock, sync_want; 47451215Sbostic int error; 47537737Smckusick 47651155Sbostic printf("lfs_sync\n"); 47751215Sbostic 47851215Sbostic /* 479*51310Sbostic * Meta data blocks are only marked dirty, not busy, so LFS syncs 480*51310Sbostic * must be single threaded. 48151215Sbostic */ 482*51310Sbostic while (sync_lock) { 483*51310Sbostic sync_want = 1; 484*51310Sbostic if (error = tsleep(&sync_lock, PLOCK | PCATCH, "lfs sync", 0)) 485*51310Sbostic return (error); 486*51310Sbostic } 487*51310Sbostic sync_lock = 1; 48851215Sbostic 48937737Smckusick if (syncprt) 49037737Smckusick bufstats(); 491*51310Sbostic 492*51310Sbostic /* All syncs must be checkpoints until roll-forward is implemented. */ 493*51310Sbostic STOPNOW = 1; 49451215Sbostic error = lfs_segwrite(mp, 1); 49541314Smckusick #ifdef QUOTA 49641314Smckusick qsync(mp); 49741314Smckusick #endif 498*51310Sbostic sync_lock = 0; 499*51310Sbostic if (sync_want) { 500*51310Sbostic sync_want = 0; 501*51310Sbostic wakeup(&sync_lock); 502*51310Sbostic } 50351215Sbostic return (error); 50437737Smckusick } 50537737Smckusick 50612795Ssam /* 50737737Smckusick * File handle to vnode 50838453Smckusick * 50938453Smckusick * Have to be really careful about stale file handles: 51038453Smckusick * - check that the inode number is in range 51138453Smckusick * - call iget() to get the locked inode 51238453Smckusick * - check for an unallocated inode (i_mode == 0) 51338453Smckusick * - check that the generation number matches 51437737Smckusick */ 51551155Sbostic lfs_fhtovp(mp, fhp, vpp) 51638453Smckusick register struct mount *mp; 51737737Smckusick struct fid *fhp; 51837737Smckusick struct vnode **vpp; 51937737Smckusick { 52037737Smckusick register struct ufid *ufhp; 52151183Sbostic register LFS *fs; /* LFS */ 52239390Smckusick register struct inode *ip; 52351155Sbostic IFILE *ifp; 52451155Sbostic struct buf *bp; 52539390Smckusick struct inode *nip; 52639390Smckusick struct vnode tvp; 52737737Smckusick int error; 52837737Smckusick 52937737Smckusick ufhp = (struct ufid *)fhp; 53051155Sbostic #ifdef NOTLFS /* LFS */ 53138453Smckusick fs = VFSTOUFS(mp)->um_fs; 53238453Smckusick if (ufhp->ufid_ino < ROOTINO || 53338453Smckusick ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) { 53441397Smckusick *vpp = NULLVP; 53538453Smckusick return (EINVAL); 53638453Smckusick } 53751155Sbostic #else 53851155Sbostic fs = VFSTOUFS(mp)->um_lfs; 53951155Sbostic if (ufhp->ufid_ino < ROOTINO) { 54051155Sbostic *vpp = NULLVP; 54151155Sbostic return (EINVAL); 54251155Sbostic } 54351155Sbostic #endif 54439390Smckusick tvp.v_mount = mp; 54539390Smckusick ip = VTOI(&tvp); 54639390Smckusick ip->i_vnode = &tvp; 54739390Smckusick ip->i_dev = VFSTOUFS(mp)->um_dev; 54851155Sbostic if (error = lfs_iget(ip, ufhp->ufid_ino, &nip)) { /* LFS */ 54941397Smckusick *vpp = NULLVP; 55037737Smckusick return (error); 55137737Smckusick } 55239390Smckusick ip = nip; 55338453Smckusick if (ip->i_mode == 0) { 55438453Smckusick iput(ip); 55541397Smckusick *vpp = NULLVP; 55638453Smckusick return (EINVAL); 55738453Smckusick } 55837737Smckusick if (ip->i_gen != ufhp->ufid_gen) { 55937737Smckusick iput(ip); 56041397Smckusick *vpp = NULLVP; 56137737Smckusick return (EINVAL); 56237737Smckusick } 56337737Smckusick *vpp = ITOV(ip); 56437737Smckusick return (0); 56537737Smckusick } 56651215Sbostic 56751215Sbostic static int 56851215Sbostic lfs_umountdebug(mp) 56951215Sbostic struct mount *mp; 57051215Sbostic { 57151215Sbostic struct vnode *vp; 57251215Sbostic int dirty; 57351215Sbostic 57451215Sbostic dirty = 0; 57551215Sbostic if ((mp->mnt_flag & MNT_MPBUSY) == 0) 57651215Sbostic panic("umountdebug: not busy"); 57751215Sbostic loop: 57851215Sbostic for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) { 57951215Sbostic if (vget(vp)) 58051215Sbostic goto loop; 58151215Sbostic dirty += lfs_vinvalbuf(vp); 58251215Sbostic vput(vp); 58351215Sbostic if (vp->v_mount != mp) 58451215Sbostic goto loop; 58551215Sbostic } 58651215Sbostic return (dirty); 58751215Sbostic } 58851215Sbostic static int 58951215Sbostic lfs_vinvalbuf(vp) 59051215Sbostic register struct vnode *vp; 59151215Sbostic { 59251215Sbostic register struct buf *bp; 59351215Sbostic struct buf *nbp, *blist; 59451215Sbostic int s, dirty = 0; 59551215Sbostic 59651215Sbostic for (;;) { 59751215Sbostic if (blist = vp->v_dirtyblkhd) 59851215Sbostic /* void */; 59951215Sbostic else if (blist = vp->v_cleanblkhd) 60051215Sbostic /* void */; 60151215Sbostic else 60251215Sbostic break; 60351215Sbostic for (bp = blist; bp; bp = nbp) { 60451215Sbostic printf("lfs_vinvalbuf: ino %d, lblkno %d, blkno %lx flags %xl\n", 60551215Sbostic VTOI(vp)->i_number, bp->b_lblkno, bp->b_blkno, bp->b_flags); 60651215Sbostic nbp = bp->b_blockf; 60751215Sbostic s = splbio(); 60851215Sbostic if (bp->b_flags & B_BUSY) { 60951215Sbostic printf("lfs_vinvalbuf: buffer busy, would normally sleep\n"); 61051215Sbostic /* 61151215Sbostic bp->b_flags |= B_WANTED; 61251215Sbostic sleep((caddr_t)bp, PRIBIO + 1); 61351215Sbostic */ 61451215Sbostic splx(s); 61551215Sbostic break; 61651215Sbostic } 61751215Sbostic bremfree(bp); 61851215Sbostic bp->b_flags |= B_BUSY; 61951215Sbostic splx(s); 62051215Sbostic if (bp->b_flags & B_DELWRI) { 62151215Sbostic dirty++; /* XXX */ 62251215Sbostic printf("lfs_vinvalbuf: buffer dirty (DELWRI). would normally write\n"); 62351215Sbostic break; 62451215Sbostic } 62551215Sbostic if (bp->b_vp != vp) 62651215Sbostic reassignbuf(bp, bp->b_vp); 62751215Sbostic else 62851215Sbostic bp->b_flags |= B_INVAL; 62951215Sbostic brelse(bp); 63051215Sbostic } 63151215Sbostic } 63251215Sbostic if (vp->v_dirtyblkhd || vp->v_cleanblkhd) 63351215Sbostic panic("lfs_vinvalbuf: flush failed"); 63451215Sbostic return (dirty); 63551215Sbostic } 63651215Sbostic #endif /* LOGFS */ 637