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