151500Sbostic /* 251503Sbostic * Copyright (c) 1991 Regents of the University of California. 351500Sbostic * All rights reserved. 451500Sbostic * 551500Sbostic * %sccs.include.redist.c% 651500Sbostic * 7*54264Sbostic * @(#)lfs_subr.c 7.12 (Berkeley) 06/23/92 851500Sbostic */ 951500Sbostic 1051500Sbostic #include <sys/param.h> 1151500Sbostic #include <sys/namei.h> 1251500Sbostic #include <sys/vnode.h> 1351500Sbostic #include <sys/buf.h> 14*54264Sbostic #include <sys/mount.h> 1551500Sbostic 1651500Sbostic #include <ufs/ufs/quota.h> 1751500Sbostic #include <ufs/ufs/inode.h> 1851500Sbostic #include <ufs/lfs/lfs.h> 1951500Sbostic #include <ufs/lfs/lfs_extern.h> 2051500Sbostic 2151500Sbostic /* 2251500Sbostic * Return buffer with the contents of block "offset" from the beginning of 2351500Sbostic * directory "ip". If "res" is non-zero, fill it in with a pointer to the 2451500Sbostic * remaining space in the directory. 2551500Sbostic */ 2651500Sbostic int 2753530Sheideman lfs_blkatoff (ap) 2853530Sheideman struct vop_blkatoff_args *ap; 2951500Sbostic { 3051500Sbostic register struct lfs *fs; 3151557Smckusick struct inode *ip; 3251500Sbostic struct buf *bp; 3351500Sbostic daddr_t lbn; 3451500Sbostic int bsize, error; 3551500Sbostic 3653592Sheideman ip = VTOI(ap->a_vp); 3751500Sbostic fs = ip->i_lfs; 3853592Sheideman lbn = lblkno(fs, ap->a_offset); 3951500Sbostic bsize = blksize(fs); 4051500Sbostic 4153592Sheideman *ap->a_bpp = NULL; 4253592Sheideman if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) { 4351500Sbostic brelse(bp); 4451500Sbostic return (error); 4551500Sbostic } 4653592Sheideman if (ap->a_res) 4753592Sheideman *ap->a_res = bp->b_un.b_addr + blkoff(fs, ap->a_offset); 4853592Sheideman *ap->a_bpp = bp; 4951500Sbostic return (0); 5051500Sbostic } 51*54264Sbostic 52*54264Sbostic int 53*54264Sbostic lfs_mntinvalbuf(mp) 54*54264Sbostic struct mount *mp; 55*54264Sbostic { 56*54264Sbostic struct vnode *vp; 57*54264Sbostic int dirty; 58*54264Sbostic 59*54264Sbostic dirty = 0; 60*54264Sbostic if ((mp->mnt_flag & MNT_MPBUSY) == 0) 61*54264Sbostic panic("lfs_mntinvalbuf: not busy"); 62*54264Sbostic loop: 63*54264Sbostic for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) { 64*54264Sbostic if (VTOI(vp)->i_number == LFS_IFILE_INUM) 65*54264Sbostic continue; 66*54264Sbostic if (vget(vp)) 67*54264Sbostic goto loop; 68*54264Sbostic dirty += lfs_vinvalbuf(vp); 69*54264Sbostic vput(vp); 70*54264Sbostic if (vp->v_mount != mp) 71*54264Sbostic goto loop; 72*54264Sbostic } 73*54264Sbostic return (dirty); 74*54264Sbostic } 75*54264Sbostic 76*54264Sbostic /* 77*54264Sbostic * For LFS, we need to do two passes. First we need to wait on any dirty and 78*54264Sbostic * busy buffers. Once we've guaranteed that all the buffers are unbusy, we 79*54264Sbostic * can do the segment write. Then we need to go through and invalidate all 80*54264Sbostic * the buffers on the clean list. 81*54264Sbostic */ 82*54264Sbostic int 83*54264Sbostic lfs_vinvalbuf(vp) 84*54264Sbostic register struct vnode *vp; 85*54264Sbostic { 86*54264Sbostic register struct buf *bp; 87*54264Sbostic struct buf *nbp, *blist; 88*54264Sbostic int s, dirty = 0; 89*54264Sbostic 90*54264Sbostic loop: for (bp = vp->v_dirtyblkhd; bp; bp = nbp) { 91*54264Sbostic nbp = bp->b_blockf; 92*54264Sbostic s = splbio(); 93*54264Sbostic if (bp->b_flags & B_BUSY) { 94*54264Sbostic bp->b_flags |= B_WANTED; 95*54264Sbostic sleep((caddr_t)bp, PRIBIO + 1); 96*54264Sbostic splx(s); 97*54264Sbostic goto loop; 98*54264Sbostic } 99*54264Sbostic bremfree(bp); 100*54264Sbostic splx(s); 101*54264Sbostic dirty++; 102*54264Sbostic brelse(bp); 103*54264Sbostic } 104*54264Sbostic if (dirty) 105*54264Sbostic lfs_segwrite(vp->v_mount, 0); 106*54264Sbostic 107*54264Sbostic /* Remove blocks from the clean list. */ 108*54264Sbostic for (bp = vp->v_cleanblkhd; bp; bp = nbp) { 109*54264Sbostic nbp = bp->b_blockf; 110*54264Sbostic bremfree(bp); 111*54264Sbostic bp->b_flags |= B_INVAL; 112*54264Sbostic brelse(bp); 113*54264Sbostic } 114*54264Sbostic 115*54264Sbostic if (vp->v_dirtyblkhd || vp->v_cleanblkhd) 116*54264Sbostic panic("lfs_vinvalbuf: flush failed"); 117*54264Sbostic return (dirty); 118*54264Sbostic } 119