xref: /original-bsd/sys/ufs/ffs/ffs_subr.c (revision c43e4352)
1 /*	ffs_subr.c	6.1	83/07/29	*/
2 
3 #ifdef KERNEL
4 #include "../h/param.h"
5 #include "../h/systm.h"
6 #include "../h/mount.h"
7 #include "../h/fs.h"
8 #include "../h/conf.h"
9 #include "../h/buf.h"
10 #include "../h/inode.h"
11 #include "../h/dir.h"
12 #include "../h/user.h"
13 #include "../h/quota.h"
14 #include "../h/kernel.h"
15 #else
16 #include <sys/param.h>
17 #include <sys/systm.h>
18 #include <sys/mount.h>
19 #include <sys/fs.h>
20 #include <sys/conf.h>
21 #include <sys/buf.h>
22 #include <sys/inode.h>
23 #include <sys/dir.h>
24 #include <sys/user.h>
25 #include <sys/quota.h>
26 #endif
27 
28 #ifdef KERNEL
29 int	syncprt = 0;
30 
31 /*
32  * Update is the internal name of 'sync'.  It goes through the disk
33  * queues to initiate sandbagged IO; goes through the inodes to write
34  * modified nodes; and it goes through the mount table to initiate
35  * the writing of the modified super blocks.
36  */
37 update()
38 {
39 	register struct inode *ip;
40 	register struct mount *mp;
41 	struct fs *fs;
42 
43 	if (syncprt)
44 		bufstats();
45 	if (updlock)
46 		return;
47 	updlock++;
48 	/*
49 	 * Write back modified superblocks.
50 	 * Consistency check that the superblock
51 	 * of each file system is still in the buffer cache.
52 	 */
53 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
54 		if (mp->m_bufp == NULL || mp->m_dev == NODEV)
55 			continue;
56 		fs = mp->m_bufp->b_un.b_fs;
57 		if (fs->fs_fmod == 0)
58 			continue;
59 		if (fs->fs_ronly != 0) {		/* XXX */
60 			printf("fs = %s\n", fs->fs_fsmnt);
61 			panic("update: rofs mod");
62 		}
63 		fs->fs_fmod = 0;
64 		fs->fs_time = time.tv_sec;
65 		sbupdate(mp);
66 	}
67 	/*
68 	 * Write back each (modified) inode.
69 	 */
70 	for (ip = inode; ip < inodeNINODE; ip++) {
71 		if ((ip->i_flag & ILOCKED) != 0 || ip->i_count == 0)
72 			continue;
73 		ip->i_flag |= ILOCKED;
74 		ip->i_count++;
75 		iupdat(ip, &time, &time, 0);
76 		iput(ip);
77 	}
78 	updlock = 0;
79 	/*
80 	 * Force stale buffer cache information to be flushed,
81 	 * for all devices.
82 	 */
83 	bflush(NODEV);
84 }
85 
86 /*
87  * Flush all the blocks associated with an inode.
88  * Note that we make a more stringent check of
89  * writing out any block in the buffer pool that may
90  * overlap the inode. This brings the inode up to
91  * date with recent mods to the cooked device.
92  */
93 syncip(ip)
94 	register struct inode *ip;
95 {
96 	register struct fs *fs;
97 	long lbn, lastlbn;
98 	daddr_t blkno;
99 
100 	fs = ip->i_fs;
101 	lastlbn = howmany(ip->i_size, fs->fs_bsize);
102 	for (lbn = 0; lbn < lastlbn; lbn++) {
103 		blkno = fsbtodb(fs, bmap(ip, lbn, B_READ));
104 		blkflush(ip->i_dev, blkno, blksize(fs, ip, lbn));
105 	}
106 	ip->i_flag |= ICHG;
107 	iupdat(ip, &time, &time, 1);
108 }
109 #endif
110 
111 extern	int around[9];
112 extern	int inside[9];
113 extern	u_char *fragtbl[];
114 
115 /*
116  * Update the frsum fields to reflect addition or deletion
117  * of some frags.
118  */
119 fragacct(fs, fragmap, fraglist, cnt)
120 	struct fs *fs;
121 	int fragmap;
122 	long fraglist[];
123 	int cnt;
124 {
125 	int inblk;
126 	register int field, subfield;
127 	register int siz, pos;
128 
129 	inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
130 	fragmap <<= 1;
131 	for (siz = 1; siz < fs->fs_frag; siz++) {
132 		if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
133 			continue;
134 		field = around[siz];
135 		subfield = inside[siz];
136 		for (pos = siz; pos <= fs->fs_frag; pos++) {
137 			if ((fragmap & field) == subfield) {
138 				fraglist[siz] += cnt;
139 				pos += siz;
140 				field <<= siz;
141 				subfield <<= siz;
142 			}
143 			field <<= 1;
144 			subfield <<= 1;
145 		}
146 	}
147 }
148 
149 #ifdef KERNEL
150 /*
151  * Check that a specified block number is in range.
152  */
153 badblock(fs, bn)
154 	register struct fs *fs;
155 	daddr_t bn;
156 {
157 
158 	if ((unsigned)bn >= fs->fs_size) {
159 		printf("bad block %d, ", bn);
160 		fserr(fs, "bad block");
161 		return (1);
162 	}
163 	return (0);
164 }
165 #endif
166 
167 /*
168  * block operations
169  *
170  * check if a block is available
171  */
172 isblock(fs, cp, h)
173 	struct fs *fs;
174 	unsigned char *cp;
175 	daddr_t h;
176 {
177 	unsigned char mask;
178 
179 	switch (fs->fs_frag) {
180 	case 8:
181 		return (cp[h] == 0xff);
182 	case 4:
183 		mask = 0x0f << ((h & 0x1) << 2);
184 		return ((cp[h >> 1] & mask) == mask);
185 	case 2:
186 		mask = 0x03 << ((h & 0x3) << 1);
187 		return ((cp[h >> 2] & mask) == mask);
188 	case 1:
189 		mask = 0x01 << (h & 0x7);
190 		return ((cp[h >> 3] & mask) == mask);
191 	default:
192 		panic("isblock");
193 		return (NULL);
194 	}
195 }
196 
197 /*
198  * take a block out of the map
199  */
200 clrblock(fs, cp, h)
201 	struct fs *fs;
202 	u_char *cp;
203 	daddr_t h;
204 {
205 
206 	switch ((fs)->fs_frag) {
207 	case 8:
208 		cp[h] = 0;
209 		return;
210 	case 4:
211 		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
212 		return;
213 	case 2:
214 		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
215 		return;
216 	case 1:
217 		cp[h >> 3] &= ~(0x01 << (h & 0x7));
218 		return;
219 	default:
220 		panic("clrblock");
221 	}
222 }
223 
224 /*
225  * put a block into the map
226  */
227 setblock(fs, cp, h)
228 	struct fs *fs;
229 	unsigned char *cp;
230 	daddr_t h;
231 {
232 
233 	switch (fs->fs_frag) {
234 
235 	case 8:
236 		cp[h] = 0xff;
237 		return;
238 	case 4:
239 		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
240 		return;
241 	case 2:
242 		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
243 		return;
244 	case 1:
245 		cp[h >> 3] |= (0x01 << (h & 0x7));
246 		return;
247 	default:
248 		panic("setblock");
249 	}
250 }
251 
252 #ifdef KERNEL
253 /*
254  * Getfs maps a device number into a pointer to the incore super block.
255  *
256  * The algorithm is a linear search through the mount table. A
257  * consistency check of the super block magic number is performed.
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 mount *mp;
267 	register struct fs *fs;
268 
269 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
270 		if (mp->m_bufp == NULL || mp->m_dev != dev)
271 			continue;
272 		fs = mp->m_bufp->b_un.b_fs;
273 		if (fs->fs_magic != FS_MAGIC) {
274 			printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt);
275 			panic("getfs: bad magic");
276 		}
277 		return (fs);
278 	}
279 	printf("dev = 0x%x\n", dev);
280 	panic("getfs: no fs");
281 	return (NULL);
282 }
283 
284 /*
285  * Getfsx returns the index in the file system
286  * table of the specified device.  The swap device
287  * is also assigned a pseudo-index.  The index may
288  * be used as a compressed indication of the location
289  * of a block, recording
290  *	<getfsx(dev),blkno>
291  * rather than
292  *	<dev, blkno>
293  * provided the information need remain valid only
294  * as long as the file system is mounted.
295  */
296 getfsx(dev)
297 	dev_t dev;
298 {
299 	register struct mount *mp;
300 
301 	if (dev == swapdev)
302 		return (MSWAPX);
303 	for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
304 		if (mp->m_dev == dev)
305 			return (mp - &mount[0]);
306 	return (-1);
307 }
308 
309 /*
310  * Print out statistics on the current allocation of the buffer pool.
311  * Can be enabled to print out on every ``sync'' by setting "syncprt"
312  * above.
313  */
314 bufstats()
315 {
316 	int s, i, j, count;
317 	register struct buf *bp, *dp;
318 	int counts[MAXBSIZE/CLBYTES+1];
319 	static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
320 
321 	for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) {
322 		count = 0;
323 		for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
324 			counts[j] = 0;
325 		s = spl6();
326 		for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) {
327 			counts[dp->b_bufsize/CLBYTES]++;
328 			count++;
329 		}
330 		splx(s);
331 		printf("%s: total-%d", bname[i], count);
332 		for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
333 			if (counts[j] != 0)
334 				printf(", %d-%d", j * CLBYTES, counts[j]);
335 		printf("\n");
336 	}
337 }
338 #endif
339