xref: /original-bsd/sys/ufs/lfs/lfs_subr.c (revision 9640b10a)
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