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