xref: /csrg-svn/sys/ufs/ffs/ffs_subr.c (revision 9167)
1*9167Ssam /*	ffs_subr.c	4.3	82/11/13	*/
28719Sroot 
38719Sroot #ifdef KERNEL
48719Sroot #include "../h/param.h"
5*9167Ssam #include "../h/systm.h"
6*9167Ssam #include "../h/mount.h"
78719Sroot #include "../h/fs.h"
8*9167Ssam #include "../h/conf.h"
9*9167Ssam #include "../h/buf.h"
10*9167Ssam #include "../h/inode.h"
11*9167Ssam #include "../h/dir.h"
12*9167Ssam #include "../h/user.h"
13*9167Ssam #include "../h/quota.h"
14*9167Ssam #include "../h/kernel.h"
158719Sroot #else
168719Sroot #include <sys/param.h>
17*9167Ssam #include <sys/systm.h>
18*9167Ssam #include <sys/mount.h>
198719Sroot #include <sys/fs.h>
20*9167Ssam #include <sys/conf.h>
21*9167Ssam #include <sys/buf.h>
22*9167Ssam #include <sys/inode.h>
23*9167Ssam #include <sys/dir.h>
24*9167Ssam #include <sys/user.h>
25*9167Ssam #include <sys/quota.h>
26*9167Ssam #include <sys/kernel.h>
278719Sroot #endif
288719Sroot 
29*9167Ssam #ifdef KERNEL
30*9167Ssam int	syncprt = 0;
31*9167Ssam 
32*9167Ssam /*
33*9167Ssam  * Update is the internal name of 'sync'.  It goes through the disk
34*9167Ssam  * queues to initiate sandbagged IO; goes through the inodes to write
35*9167Ssam  * modified nodes; and it goes through the mount table to initiate
36*9167Ssam  * the writing of the modified super blocks.
37*9167Ssam  */
38*9167Ssam update()
39*9167Ssam {
40*9167Ssam 	register struct inode *ip;
41*9167Ssam 	register struct mount *mp;
42*9167Ssam 	struct fs *fs;
43*9167Ssam 
44*9167Ssam 	if (syncprt)
45*9167Ssam 		bufstats();
46*9167Ssam 	if (updlock)
47*9167Ssam 		return;
48*9167Ssam 	updlock++;
49*9167Ssam 	/*
50*9167Ssam 	 * Write back modified superblocks.
51*9167Ssam 	 * Consistency check that the superblock
52*9167Ssam 	 * of each file system is still in the buffer cache.
53*9167Ssam 	 */
54*9167Ssam 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
55*9167Ssam 		if (mp->m_bufp == NULL)
56*9167Ssam 			continue;
57*9167Ssam 		fs = mp->m_bufp->b_un.b_fs;
58*9167Ssam 		if (fs->fs_fmod == 0)
59*9167Ssam 			continue;
60*9167Ssam 		if (fs->fs_ronly != 0) {		/* XXX */
61*9167Ssam 			printf("fs = %s\n", fs->fs_fsmnt);
62*9167Ssam 			panic("update: rofs mod");
63*9167Ssam 		}
64*9167Ssam 		fs->fs_fmod = 0;
65*9167Ssam 		fs->fs_time = time.tv_sec;
66*9167Ssam 		sbupdate(mp);
67*9167Ssam 	}
68*9167Ssam 	/*
69*9167Ssam 	 * Write back each (modified) inode.
70*9167Ssam 	 */
71*9167Ssam 	for (ip = inode; ip < inodeNINODE; ip++) {
72*9167Ssam 		if ((ip->i_flag & ILOCKED) != 0 || ip->i_count == 0)
73*9167Ssam 			continue;
74*9167Ssam 		ip->i_flag |= ILOCKED;
75*9167Ssam 		ip->i_count++;
76*9167Ssam 		iupdat(ip, &time, &time, 0);
77*9167Ssam 		iput(ip);
78*9167Ssam 	}
79*9167Ssam 	updlock = 0;
80*9167Ssam 	/*
81*9167Ssam 	 * Force stale buffer cache information to be flushed,
82*9167Ssam 	 * for all devices.
83*9167Ssam 	 */
84*9167Ssam 	bflush(NODEV);
85*9167Ssam }
86*9167Ssam 
87*9167Ssam /*
88*9167Ssam  * Flush all the blocks associated with an inode.
89*9167Ssam  * Note that we make a more stringent check of
90*9167Ssam  * writing out any block in the buffer pool that may
91*9167Ssam  * overlap the inode. This brings the inode up to
92*9167Ssam  * date with recent mods to the cooked device.
93*9167Ssam  */
94*9167Ssam syncip(ip)
95*9167Ssam 	register struct inode *ip;
96*9167Ssam {
97*9167Ssam 	register struct fs *fs;
98*9167Ssam 	long lbn, lastlbn;
99*9167Ssam 	daddr_t blkno;
100*9167Ssam 
101*9167Ssam 	fs = ip->i_fs;
102*9167Ssam 	lastlbn = howmany(ip->i_size, fs->fs_bsize);
103*9167Ssam 	for (lbn = 0; lbn < lastlbn; lbn++) {
104*9167Ssam 		blkno = fsbtodb(fs, bmap(ip, lbn, B_READ));
105*9167Ssam 		blkflush(ip->i_dev, blkno, blksize(fs, ip, lbn));
106*9167Ssam 	}
107*9167Ssam }
108*9167Ssam #endif
109*9167Ssam 
1108719Sroot extern	int around[9];
1118719Sroot extern	int inside[9];
1128719Sroot extern	u_char *fragtbl[];
1138719Sroot 
1148719Sroot /*
1158719Sroot  * Update the frsum fields to reflect addition or deletion
1168719Sroot  * of some frags.
1178719Sroot  */
1188719Sroot fragacct(fs, fragmap, fraglist, cnt)
1198719Sroot 	struct fs *fs;
1208719Sroot 	int fragmap;
1218719Sroot 	long fraglist[];
1228719Sroot 	int cnt;
1238719Sroot {
1248719Sroot 	int inblk;
1258719Sroot 	register int field, subfield;
1268719Sroot 	register int siz, pos;
1278719Sroot 
1288719Sroot 	inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
1298719Sroot 	fragmap <<= 1;
1308719Sroot 	for (siz = 1; siz < fs->fs_frag; siz++) {
1318719Sroot 		if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
1328719Sroot 			continue;
1338719Sroot 		field = around[siz];
1348719Sroot 		subfield = inside[siz];
1358719Sroot 		for (pos = siz; pos <= fs->fs_frag; pos++) {
1368719Sroot 			if ((fragmap & field) == subfield) {
1378719Sroot 				fraglist[siz] += cnt;
1388719Sroot 				pos += siz;
1398719Sroot 				field <<= siz;
1408719Sroot 				subfield <<= siz;
1418719Sroot 			}
1428719Sroot 			field <<= 1;
1438719Sroot 			subfield <<= 1;
1448719Sroot 		}
1458719Sroot 	}
1468719Sroot }
1478719Sroot 
1488719Sroot #ifdef KERNEL
1498719Sroot /*
1508719Sroot  * Check that a specified block number is in range.
1518719Sroot  */
1528719Sroot badblock(fs, bn)
1538719Sroot 	register struct fs *fs;
1548719Sroot 	daddr_t bn;
1558719Sroot {
1568719Sroot 
1578719Sroot 	if ((unsigned)bn >= fs->fs_size) {
1588719Sroot 		printf("bad block %d, ", bn);
1598719Sroot 		fserr(fs, "bad block");
1608719Sroot 		return (1);
1618719Sroot 	}
1628719Sroot 	return (0);
1638719Sroot }
1648719Sroot #endif
1658719Sroot 
1668719Sroot /*
1678719Sroot  * block operations
1688719Sroot  *
1698719Sroot  * check if a block is available
1708719Sroot  */
1718719Sroot isblock(fs, cp, h)
1728719Sroot 	struct fs *fs;
1738719Sroot 	unsigned char *cp;
1748719Sroot 	daddr_t h;
1758719Sroot {
1768719Sroot 	unsigned char mask;
1778719Sroot 
1788719Sroot 	switch (fs->fs_frag) {
1798719Sroot 	case 8:
1808719Sroot 		return (cp[h] == 0xff);
1818719Sroot 	case 4:
1828719Sroot 		mask = 0x0f << ((h & 0x1) << 2);
1838719Sroot 		return ((cp[h >> 1] & mask) == mask);
1848719Sroot 	case 2:
1858719Sroot 		mask = 0x03 << ((h & 0x3) << 1);
1868719Sroot 		return ((cp[h >> 2] & mask) == mask);
1878719Sroot 	case 1:
1888719Sroot 		mask = 0x01 << (h & 0x7);
1898719Sroot 		return ((cp[h >> 3] & mask) == mask);
1908719Sroot 	default:
1918719Sroot 		panic("isblock");
1928719Sroot 		return (NULL);
1938719Sroot 	}
1948719Sroot }
1958719Sroot 
1968719Sroot /*
1978719Sroot  * take a block out of the map
1988719Sroot  */
1998719Sroot clrblock(fs, cp, h)
2008719Sroot 	struct fs *fs;
2018770Sroot 	u_char *cp;
2028719Sroot 	daddr_t h;
2038719Sroot {
2048719Sroot 
2058719Sroot 	switch ((fs)->fs_frag) {
2068719Sroot 	case 8:
2078719Sroot 		cp[h] = 0;
2088719Sroot 		return;
2098719Sroot 	case 4:
2108719Sroot 		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
2118719Sroot 		return;
2128719Sroot 	case 2:
2138719Sroot 		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
2148719Sroot 		return;
2158719Sroot 	case 1:
2168719Sroot 		cp[h >> 3] &= ~(0x01 << (h & 0x7));
2178719Sroot 		return;
2188719Sroot 	default:
2198719Sroot 		panic("clrblock");
2208719Sroot 	}
2218719Sroot }
2228719Sroot 
2238719Sroot /*
2248719Sroot  * put a block into the map
2258719Sroot  */
2268719Sroot setblock(fs, cp, h)
2278719Sroot 	struct fs *fs;
2288719Sroot 	unsigned char *cp;
2298719Sroot 	daddr_t h;
2308719Sroot {
2318719Sroot 
2328719Sroot 	switch (fs->fs_frag) {
2338719Sroot 
2348719Sroot 	case 8:
2358719Sroot 		cp[h] = 0xff;
2368719Sroot 		return;
2378719Sroot 	case 4:
2388719Sroot 		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
2398719Sroot 		return;
2408719Sroot 	case 2:
2418719Sroot 		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
2428719Sroot 		return;
2438719Sroot 	case 1:
2448719Sroot 		cp[h >> 3] |= (0x01 << (h & 0x7));
2458719Sroot 		return;
2468719Sroot 	default:
2478719Sroot 		panic("setblock");
2488719Sroot 	}
2498719Sroot }
250*9167Ssam 
251*9167Ssam #ifdef KERNEL
252*9167Ssam /*
253*9167Ssam  * Getfs maps a device number into a pointer to the incore super block.
254*9167Ssam  *
255*9167Ssam  * The algorithm is a linear search through the mount table. A
256*9167Ssam  * consistency check of the super block magic number is performed.
257*9167Ssam  *
258*9167Ssam  * panic: no fs -- the device is not mounted.
259*9167Ssam  *	this "cannot happen"
260*9167Ssam  */
261*9167Ssam struct fs *
262*9167Ssam getfs(dev)
263*9167Ssam 	dev_t dev;
264*9167Ssam {
265*9167Ssam 	register struct mount *mp;
266*9167Ssam 	register struct fs *fs;
267*9167Ssam 
268*9167Ssam 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
269*9167Ssam 		if (mp->m_bufp == NULL || mp->m_dev != dev)
270*9167Ssam 			continue;
271*9167Ssam 		fs = mp->m_bufp->b_un.b_fs;
272*9167Ssam 		if (fs->fs_magic != FS_MAGIC) {
273*9167Ssam 			printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt);
274*9167Ssam 			panic("getfs: bad magic");
275*9167Ssam 		}
276*9167Ssam 		return (fs);
277*9167Ssam 	}
278*9167Ssam 	printf("dev = 0x%x\n", dev);
279*9167Ssam 	panic("getfs: no fs");
280*9167Ssam 	return (NULL);
281*9167Ssam }
282*9167Ssam 
283*9167Ssam /*
284*9167Ssam  * Getfsx returns the index in the file system
285*9167Ssam  * table of the specified device.  The swap device
286*9167Ssam  * is also assigned a pseudo-index.  The index may
287*9167Ssam  * be used as a compressed indication of the location
288*9167Ssam  * of a block, recording
289*9167Ssam  *	<getfsx(dev),blkno>
290*9167Ssam  * rather than
291*9167Ssam  *	<dev, blkno>
292*9167Ssam  * provided the information need remain valid only
293*9167Ssam  * as long as the file system is mounted.
294*9167Ssam  */
295*9167Ssam getfsx(dev)
296*9167Ssam 	dev_t dev;
297*9167Ssam {
298*9167Ssam 	register struct mount *mp;
299*9167Ssam 
300*9167Ssam 	if (dev == swapdev)
301*9167Ssam 		return (MSWAPX);
302*9167Ssam 	for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
303*9167Ssam 		if (mp->m_dev == dev)
304*9167Ssam 			return (mp - &mount[0]);
305*9167Ssam 	return (-1);
306*9167Ssam }
307*9167Ssam 
308*9167Ssam /*
309*9167Ssam  * Print out statistics on the current allocation of the buffer pool.
310*9167Ssam  * Can be enabled to print out on every ``sync'' by setting "syncprt"
311*9167Ssam  * above.
312*9167Ssam  */
313*9167Ssam bufstats()
314*9167Ssam {
315*9167Ssam 	int s, i, j, count;
316*9167Ssam 	register struct buf *bp, *dp;
317*9167Ssam 	int counts[MAXBSIZE/CLBYTES+1];
318*9167Ssam 	static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
319*9167Ssam 
320*9167Ssam 	for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) {
321*9167Ssam 		count = 0;
322*9167Ssam 		for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
323*9167Ssam 			counts[j] = 0;
324*9167Ssam 		s = spl6();
325*9167Ssam 		for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) {
326*9167Ssam 			counts[dp->b_bufsize/CLBYTES]++;
327*9167Ssam 			count++;
328*9167Ssam 		}
329*9167Ssam 		splx(s);
330*9167Ssam 		printf("%s: total-%d", bname[i], count);
331*9167Ssam 		for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
332*9167Ssam 			if (counts[j] != 0)
333*9167Ssam 				printf(", %d-%d", j * CLBYTES, counts[j]);
334*9167Ssam 		printf("\n");
335*9167Ssam 	}
336*9167Ssam }
337*9167Ssam #endif
338