xref: /csrg-svn/sys/ufs/ffs/ffs_subr.c (revision 53521)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)ffs_subr.c	7.19 (Berkeley) 05/14/92
8  */
9 
10 #include <sys/param.h>
11 #include <sys/vnode.h>
12 #include <ufs/ffs/fs.h>
13 #include <ufs/ffs/ffs_extern.h>
14 
15 #ifdef KERNEL
16 #include <sys/buf.h>
17 #include <ufs/ufs/quota.h>
18 #include <ufs/ufs/inode.h>
19 
20 /*
21  * Return buffer with the contents of block "offset" from the beginning of
22  * directory "ip".  If "res" is non-zero, fill it in with a pointer to the
23  * remaining space in the directory.
24  */
25 int
26 ffs_blkatoff (ap)
27 	struct vop_blkatoff_args *ap;
28 #define vp (ap->a_vp)
29 #define offset (ap->a_offset)
30 #define res (ap->a_res)
31 #define bpp (ap->a_bpp)
32 {
33 	struct inode *ip;
34 	register struct fs *fs;
35 	struct buf *bp;
36 	daddr_t lbn;
37 	int bsize, error;
38 
39 	ip = VTOI(vp);
40 	fs = ip->i_fs;
41 	lbn = lblkno(fs, offset);
42 	bsize = blksize(fs, ip, lbn);
43 
44 	*bpp = NULL;
45 	if (error = bread(vp, lbn, bsize, NOCRED, &bp)) {
46 		brelse(bp);
47 		return (error);
48 	}
49 	if (res)
50 		*res = bp->b_un.b_addr + blkoff(fs, offset);
51 	*bpp = bp;
52 	return (0);
53 }
54 #undef vp
55 #undef offset
56 #undef res
57 #undef bpp
58 #endif
59 
60 /*
61  * Update the frsum fields to reflect addition or deletion
62  * of some frags.
63  */
64 void
65 ffs_fragacct(fs, fragmap, fraglist, cnt)
66 	struct fs *fs;
67 	int fragmap;
68 	long fraglist[];
69 	int cnt;
70 {
71 	int inblk;
72 	register int field, subfield;
73 	register int siz, pos;
74 
75 	inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
76 	fragmap <<= 1;
77 	for (siz = 1; siz < fs->fs_frag; siz++) {
78 		if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
79 			continue;
80 		field = around[siz];
81 		subfield = inside[siz];
82 		for (pos = siz; pos <= fs->fs_frag; pos++) {
83 			if ((fragmap & field) == subfield) {
84 				fraglist[siz] += cnt;
85 				pos += siz;
86 				field <<= siz;
87 				subfield <<= siz;
88 			}
89 			field <<= 1;
90 			subfield <<= 1;
91 		}
92 	}
93 }
94 
95 #if defined(KERNEL) && defined(DIAGNOSTIC)
96 void
97 ffs_checkoverlap(bp, ip)
98 	struct buf *bp;
99 	struct inode *ip;
100 {
101 	USES_VOP_BMAP;
102 	register struct buf *ebp, *ep;
103 	register daddr_t start, last;
104 	struct vnode *vp;
105 
106 	ebp = &buf[nbuf];
107 	start = bp->b_blkno;
108 	last = start + btodb(bp->b_bcount) - 1;
109 	for (ep = buf; ep < ebp; ep++) {
110 		if (ep == bp || (ep->b_flags & B_INVAL) ||
111 		    ep->b_vp == NULLVP)
112 			continue;
113 		if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0))
114 			continue;
115 		if (vp != ip->i_devvp)
116 			continue;
117 		/* look for overlap */
118 		if (ep->b_bcount == 0 || ep->b_blkno > last ||
119 		    ep->b_blkno + btodb(ep->b_bcount) <= start)
120 			continue;
121 		vprint("Disk overlap", vp);
122 		(void)printf("\tstart %d, end %d overlap start %d, end %d\n",
123 			start, last, ep->b_blkno,
124 			ep->b_blkno + btodb(ep->b_bcount) - 1);
125 		panic("Disk buffer overlap");
126 	}
127 }
128 #endif /* DIAGNOSTIC */
129 
130 /*
131  * block operations
132  *
133  * check if a block is available
134  */
135 int
136 ffs_isblock(fs, cp, h)
137 	struct fs *fs;
138 	unsigned char *cp;
139 	daddr_t h;
140 {
141 	unsigned char mask;
142 
143 	switch ((int)fs->fs_frag) {
144 	case 8:
145 		return (cp[h] == 0xff);
146 	case 4:
147 		mask = 0x0f << ((h & 0x1) << 2);
148 		return ((cp[h >> 1] & mask) == mask);
149 	case 2:
150 		mask = 0x03 << ((h & 0x3) << 1);
151 		return ((cp[h >> 2] & mask) == mask);
152 	case 1:
153 		mask = 0x01 << (h & 0x7);
154 		return ((cp[h >> 3] & mask) == mask);
155 	default:
156 		panic("ffs_isblock");
157 	}
158 }
159 
160 /*
161  * take a block out of the map
162  */
163 void
164 ffs_clrblock(fs, cp, h)
165 	struct fs *fs;
166 	u_char *cp;
167 	daddr_t h;
168 {
169 
170 	switch ((int)fs->fs_frag) {
171 	case 8:
172 		cp[h] = 0;
173 		return;
174 	case 4:
175 		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
176 		return;
177 	case 2:
178 		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
179 		return;
180 	case 1:
181 		cp[h >> 3] &= ~(0x01 << (h & 0x7));
182 		return;
183 	default:
184 		panic("ffs_clrblock");
185 	}
186 }
187 
188 /*
189  * put a block into the map
190  */
191 void
192 ffs_setblock(fs, cp, h)
193 	struct fs *fs;
194 	unsigned char *cp;
195 	daddr_t h;
196 {
197 
198 	switch ((int)fs->fs_frag) {
199 
200 	case 8:
201 		cp[h] = 0xff;
202 		return;
203 	case 4:
204 		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
205 		return;
206 	case 2:
207 		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
208 		return;
209 	case 1:
210 		cp[h >> 3] |= (0x01 << (h & 0x7));
211 		return;
212 	default:
213 		panic("ffs_setblock");
214 	}
215 }
216 
217 #if (!defined(vax) && !defined(tahoe) && !defined(hp300)) \
218 	|| defined(VAX630) || defined(VAX650)
219 /*
220  * C definitions of special instructions.
221  * Normally expanded with inline.
222  */
223 int
224 scanc(size, cp, table, mask)
225 	u_int size;
226 	register u_char *cp, table[];
227 	register u_char mask;
228 {
229 	register u_char *end = &cp[size];
230 
231 	while (cp < end && (table[*cp] & mask) == 0)
232 		cp++;
233 	return (end - cp);
234 }
235 #endif
236 
237 #if !defined(vax) && !defined(tahoe) && !defined(hp300)
238 int
239 skpc(mask, size, cp)
240 	register u_char mask;
241 	u_int size;
242 	register u_char *cp;
243 {
244 	register u_char *end = &cp[size];
245 
246 	while (cp < end && *cp == mask)
247 		cp++;
248 	return (end - cp);
249 }
250 
251 int
252 locc(mask, size, cp)
253 	register u_char mask;
254 	u_int size;
255 	register u_char *cp;
256 {
257 	register u_char *end = &cp[size];
258 
259 	while (cp < end && *cp != mask)
260 		cp++;
261 	return (end - cp);
262 }
263 #endif
264