xref: /csrg-svn/sys/ufs/lfs/lfs_subr.c (revision 54264)
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