1 /* 2 * Copyright (c) 1991 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)lfs_subr.c 7.12 (Berkeley) 06/23/92 8 */ 9 10 #include <sys/param.h> 11 #include <sys/namei.h> 12 #include <sys/vnode.h> 13 #include <sys/buf.h> 14 #include <sys/mount.h> 15 16 #include <ufs/ufs/quota.h> 17 #include <ufs/ufs/inode.h> 18 #include <ufs/lfs/lfs.h> 19 #include <ufs/lfs/lfs_extern.h> 20 21 /* 22 * Return buffer with the contents of block "offset" from the beginning of 23 * directory "ip". If "res" is non-zero, fill it in with a pointer to the 24 * remaining space in the directory. 25 */ 26 int 27 lfs_blkatoff (ap) 28 struct vop_blkatoff_args *ap; 29 { 30 register struct lfs *fs; 31 struct inode *ip; 32 struct buf *bp; 33 daddr_t lbn; 34 int bsize, error; 35 36 ip = VTOI(ap->a_vp); 37 fs = ip->i_lfs; 38 lbn = lblkno(fs, ap->a_offset); 39 bsize = blksize(fs); 40 41 *ap->a_bpp = NULL; 42 if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) { 43 brelse(bp); 44 return (error); 45 } 46 if (ap->a_res) 47 *ap->a_res = bp->b_un.b_addr + blkoff(fs, ap->a_offset); 48 *ap->a_bpp = bp; 49 return (0); 50 } 51 52 int 53 lfs_mntinvalbuf(mp) 54 struct mount *mp; 55 { 56 struct vnode *vp; 57 int dirty; 58 59 dirty = 0; 60 if ((mp->mnt_flag & MNT_MPBUSY) == 0) 61 panic("lfs_mntinvalbuf: not busy"); 62 loop: 63 for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) { 64 if (VTOI(vp)->i_number == LFS_IFILE_INUM) 65 continue; 66 if (vget(vp)) 67 goto loop; 68 dirty += lfs_vinvalbuf(vp); 69 vput(vp); 70 if (vp->v_mount != mp) 71 goto loop; 72 } 73 return (dirty); 74 } 75 76 /* 77 * For LFS, we need to do two passes. First we need to wait on any dirty and 78 * busy buffers. Once we've guaranteed that all the buffers are unbusy, we 79 * can do the segment write. Then we need to go through and invalidate all 80 * the buffers on the clean list. 81 */ 82 int 83 lfs_vinvalbuf(vp) 84 register struct vnode *vp; 85 { 86 register struct buf *bp; 87 struct buf *nbp, *blist; 88 int s, dirty = 0; 89 90 loop: for (bp = vp->v_dirtyblkhd; bp; bp = nbp) { 91 nbp = bp->b_blockf; 92 s = splbio(); 93 if (bp->b_flags & B_BUSY) { 94 bp->b_flags |= B_WANTED; 95 sleep((caddr_t)bp, PRIBIO + 1); 96 splx(s); 97 goto loop; 98 } 99 bremfree(bp); 100 splx(s); 101 dirty++; 102 brelse(bp); 103 } 104 if (dirty) 105 lfs_segwrite(vp->v_mount, 0); 106 107 /* Remove blocks from the clean list. */ 108 for (bp = vp->v_cleanblkhd; bp; bp = nbp) { 109 nbp = bp->b_blockf; 110 bremfree(bp); 111 bp->b_flags |= B_INVAL; 112 brelse(bp); 113 } 114 115 if (vp->v_dirtyblkhd || vp->v_cleanblkhd) 116 panic("lfs_vinvalbuf: flush failed"); 117 return (dirty); 118 } 119