xref: /original-bsd/sys/ufs/ffs/ffs_subr.c (revision 5f5c18da)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)ffs_subr.c	7.8 (Berkeley) 05/09/89
18  */
19 
20 #ifdef KERNEL
21 #include "param.h"
22 #include "systm.h"
23 #include "buf.h"
24 #include "time.h"
25 #include "kernel.h"
26 #include "file.h"
27 #include "mount.h"
28 #include "vnode.h"
29 #include "../ufs/inode.h"
30 #include "../ufs/ufsmount.h"
31 #include "../ufs/fs.h"
32 #include "../ufs/quota.h"
33 #else
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/buf.h>
37 #include <sys/time.h>
38 #include <sys/file.h>
39 #include <sys/mount.h>
40 #include <sys/vnode.h>
41 #include <ufs/inode.h>
42 #include <ufs/ufsmount.h>
43 #include <ufs/fs.h>
44 #include <ufs/quota.h>
45 #endif
46 
47 #ifdef KERNEL
48 /*
49  * Flush all the blocks associated with an inode.
50  * There are two strategies based on the size of the file;
51  * large files are those with more than (nbuf / 2) blocks.
52  * Large files
53  * 	Walk through the buffer pool and push any dirty pages
54  *	associated with the device on which the file resides.
55  * Small files
56  *	Look up each block in the file to see if it is in the
57  *	buffer pool writing any that are found to disk.
58  *	Note that we make a more stringent check of
59  *	writing out any block in the buffer pool that may
60  *	overlap the inode. This brings the inode up to
61  *	date with recent mods to the cooked device.
62  */
63 syncip(ip)
64 	register struct inode *ip;
65 {
66 	register struct fs *fs;
67 	register struct buf *bp;
68 	struct buf *lastbufp;
69 	long lbn, lastlbn;
70 	int s, error, allerror = 0;
71 	daddr_t blkno;
72 
73 	fs = ip->i_fs;
74 	lastlbn = howmany(ip->i_size, fs->fs_bsize);
75 	if (lastlbn < nbuf / 2) {
76 		for (lbn = 0; lbn < lastlbn; lbn++) {
77 			error = bmap(ip, lbn, &blkno, (daddr_t *)0, (int *)0);
78 			if (error)
79 				allerror = error;
80 			if (error = blkflush(ip->i_devvp, blkno,
81 			    blksize(fs, ip, lbn)))
82 				allerror = error;
83 		}
84 	} else {
85 		lastbufp = &buf[nbuf];
86 		for (bp = buf; bp < lastbufp; bp++) {
87 			if (bp->b_dev != ip->i_dev ||
88 			    (bp->b_flags & B_DELWRI) == 0)
89 				continue;
90 			s = splbio();
91 			if (bp->b_flags & B_BUSY) {
92 				bp->b_flags |= B_WANTED;
93 				sleep((caddr_t)bp, PRIBIO+1);
94 				splx(s);
95 				bp--;
96 				continue;
97 			}
98 			splx(s);
99 			notavail(bp);
100 			if (error = bwrite(bp))
101 				allerror = error;
102 		}
103 	}
104 	if (error = iupdat(ip, &time, &time, 1))
105 		allerror = error;
106 	return (allerror);
107 }
108 #endif KERNEL
109 
110 extern	int around[9];
111 extern	int inside[9];
112 extern	u_char *fragtbl[];
113 
114 /*
115  * Update the frsum fields to reflect addition or deletion
116  * of some frags.
117  */
118 fragacct(fs, fragmap, fraglist, cnt)
119 	struct fs *fs;
120 	int fragmap;
121 	long fraglist[];
122 	int cnt;
123 {
124 	int inblk;
125 	register int field, subfield;
126 	register int siz, pos;
127 
128 	inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
129 	fragmap <<= 1;
130 	for (siz = 1; siz < fs->fs_frag; siz++) {
131 		if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
132 			continue;
133 		field = around[siz];
134 		subfield = inside[siz];
135 		for (pos = siz; pos <= fs->fs_frag; pos++) {
136 			if ((fragmap & field) == subfield) {
137 				fraglist[siz] += cnt;
138 				pos += siz;
139 				field <<= siz;
140 				subfield <<= siz;
141 			}
142 			field <<= 1;
143 			subfield <<= 1;
144 		}
145 	}
146 }
147 
148 #ifdef KERNEL
149 /*
150  * Check that a specified block number is in range.
151  */
152 badblock(fs, bn)
153 	register struct fs *fs;
154 	daddr_t bn;
155 {
156 
157 	if ((unsigned)bn >= fs->fs_size) {
158 		printf("bad block %d, ", bn);
159 		fserr(fs, "bad block");
160 		return (1);
161 	}
162 	return (0);
163 }
164 #endif
165 
166 /*
167  * block operations
168  *
169  * check if a block is available
170  */
171 isblock(fs, cp, h)
172 	struct fs *fs;
173 	unsigned char *cp;
174 	daddr_t h;
175 {
176 	unsigned char mask;
177 
178 	switch ((int)fs->fs_frag) {
179 	case 8:
180 		return (cp[h] == 0xff);
181 	case 4:
182 		mask = 0x0f << ((h & 0x1) << 2);
183 		return ((cp[h >> 1] & mask) == mask);
184 	case 2:
185 		mask = 0x03 << ((h & 0x3) << 1);
186 		return ((cp[h >> 2] & mask) == mask);
187 	case 1:
188 		mask = 0x01 << (h & 0x7);
189 		return ((cp[h >> 3] & mask) == mask);
190 	default:
191 		panic("isblock");
192 		return (NULL);
193 	}
194 }
195 
196 /*
197  * take a block out of the map
198  */
199 clrblock(fs, cp, h)
200 	struct fs *fs;
201 	u_char *cp;
202 	daddr_t h;
203 {
204 
205 	switch ((int)fs->fs_frag) {
206 	case 8:
207 		cp[h] = 0;
208 		return;
209 	case 4:
210 		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
211 		return;
212 	case 2:
213 		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
214 		return;
215 	case 1:
216 		cp[h >> 3] &= ~(0x01 << (h & 0x7));
217 		return;
218 	default:
219 		panic("clrblock");
220 	}
221 }
222 
223 /*
224  * put a block into the map
225  */
226 setblock(fs, cp, h)
227 	struct fs *fs;
228 	unsigned char *cp;
229 	daddr_t h;
230 {
231 
232 	switch ((int)fs->fs_frag) {
233 
234 	case 8:
235 		cp[h] = 0xff;
236 		return;
237 	case 4:
238 		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
239 		return;
240 	case 2:
241 		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
242 		return;
243 	case 1:
244 		cp[h >> 3] |= (0x01 << (h & 0x7));
245 		return;
246 	default:
247 		panic("setblock");
248 	}
249 }
250 
251 #ifdef KERNEL
252 /*
253  * Getfs maps a device number into a pointer to the incore super block.
254  *
255  * The algorithm is a linear search through the mount table. A
256  * consistency check of the super block magic number is performed.
257  * Filesystems still working on a mount are skipped.
258  *
259  * panic: no fs -- the device is not mounted.
260  *	this "cannot happen"
261  */
262 struct fs *
263 getfs(dev)
264 	dev_t dev;
265 {
266 	register struct ufsmount *mp;
267 	register struct fs *fs;
268 
269 	for (mp = &mounttab[0]; mp < &mounttab[NMOUNT]; mp++) {
270 		if (mp->um_fs == NULL || mp->um_dev != dev ||
271 		    mp->um_fs == (struct fs *)1)		/* XXX */
272 			continue;
273 		fs = mp->um_fs;
274 		if (fs->fs_magic != FS_MAGIC) {
275 			printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt);
276 			panic("getfs: bad magic");
277 		}
278 		return (fs);
279 	}
280 	printf("dev = 0x%x\n", dev);
281 	panic("getfs: no fs");
282 	return (NULL);
283 }
284 
285 /*
286  * Getfsx returns the index in the file system
287  * table of the specified device.  The swap device
288  * is also assigned a pseudo-index.  The index may
289  * be used as a compressed indication of the location
290  * of a block, recording
291  *	<getfsx(dev),blkno>
292  * rather than
293  *	<dev, blkno>
294  * provided the information need remain valid only
295  * as long as the file system is mounted.
296  */
297 getfsx(dev)
298 	dev_t dev;
299 {
300 	register struct ufsmount *mp;
301 
302 	if (dev == swapdev)
303 		return (MSWAPX);
304 	for(mp = &mounttab[0]; mp < &mounttab[NMOUNT]; mp++)
305 		if (mp->um_dev == dev)
306 			return (mp - &mounttab[0]);
307 	return (-1);
308 }
309 #endif
310 
311 #if (!defined(vax) && !defined(tahoe)) || defined(VAX630) || defined(VAX650)
312 /*
313  * C definitions of special instructions.
314  * Normally expanded with inline.
315  */
316 scanc(size, cp, table, mask)
317 	u_int size;
318 	register u_char *cp, table[];
319 	register u_char mask;
320 {
321 	register u_char *end = &cp[size];
322 
323 	while (cp < end && (table[*cp] & mask) == 0)
324 		cp++;
325 	return (end - cp);
326 }
327 #endif
328 
329 #if !defined(vax) && !defined(tahoe)
330 skpc(mask, size, cp)
331 	register u_char mask;
332 	u_int size;
333 	register u_char *cp;
334 {
335 	register u_char *end = &cp[size];
336 
337 	while (cp < end && *cp == mask)
338 		cp++;
339 	return (end - cp);
340 }
341 
342 locc(mask, size, cp)
343 	register u_char mask;
344 	u_int size;
345 	register u_char *cp;
346 {
347 	register u_char *end = &cp[size];
348 
349 	while (cp < end && *cp != mask)
350 		cp++;
351 	return (end - cp);
352 }
353 #endif
354