last line botched (fix from Mike Laman, NCR Torrey Pines)
[unix-history] / usr / src / sys / ufs / ffs / ffs_subr.c
CommitLineData
d2c01817 1/* ffs_subr.c 6.2 84/02/07 */
764e2379
BJ
2
3#ifdef KERNEL
4#include "../h/param.h"
4f083fd7
SL
5#include "../h/systm.h"
6#include "../h/mount.h"
764e2379 7#include "../h/fs.h"
4f083fd7
SL
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"
764e2379
BJ
15#else
16#include <sys/param.h>
4f083fd7
SL
17#include <sys/systm.h>
18#include <sys/mount.h>
764e2379 19#include <sys/fs.h>
4f083fd7
SL
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>
4f083fd7
SL
26#endif
27
28#ifdef KERNEL
29int 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 */
37update()
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++) {
961945a8 54 if (mp->m_bufp == NULL || mp->m_dev == NODEV)
4f083fd7
SL
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++) {
d2c01817
MK
71 if ((ip->i_flag & ILOCKED) != 0 || ip->i_count == 0 ||
72 (ip->i_flag & (IACC|IUPD|ICHG) == 0))
4f083fd7
SL
73 continue;
74 ip->i_flag |= ILOCKED;
75 ip->i_count++;
76 iupdat(ip, &time, &time, 0);
77 iput(ip);
78 }
79 updlock = 0;
80 /*
81 * Force stale buffer cache information to be flushed,
82 * for all devices.
83 */
84 bflush(NODEV);
85}
86
87/*
88 * Flush all the blocks associated with an inode.
89 * Note that we make a more stringent check of
90 * writing out any block in the buffer pool that may
91 * overlap the inode. This brings the inode up to
92 * date with recent mods to the cooked device.
93 */
94syncip(ip)
95 register struct inode *ip;
96{
97 register struct fs *fs;
98 long lbn, lastlbn;
99 daddr_t blkno;
100
101 fs = ip->i_fs;
102 lastlbn = howmany(ip->i_size, fs->fs_bsize);
103 for (lbn = 0; lbn < lastlbn; lbn++) {
104 blkno = fsbtodb(fs, bmap(ip, lbn, B_READ));
105 blkflush(ip->i_dev, blkno, blksize(fs, ip, lbn));
106 }
5b973eee
SL
107 ip->i_flag |= ICHG;
108 iupdat(ip, &time, &time, 1);
4f083fd7 109}
764e2379
BJ
110#endif
111
112extern int around[9];
113extern int inside[9];
114extern u_char *fragtbl[];
115
116/*
117 * Update the frsum fields to reflect addition or deletion
118 * of some frags.
119 */
120fragacct(fs, fragmap, fraglist, cnt)
121 struct fs *fs;
122 int fragmap;
123 long fraglist[];
124 int cnt;
125{
126 int inblk;
127 register int field, subfield;
128 register int siz, pos;
129
130 inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
131 fragmap <<= 1;
132 for (siz = 1; siz < fs->fs_frag; siz++) {
133 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
134 continue;
135 field = around[siz];
136 subfield = inside[siz];
137 for (pos = siz; pos <= fs->fs_frag; pos++) {
138 if ((fragmap & field) == subfield) {
139 fraglist[siz] += cnt;
140 pos += siz;
141 field <<= siz;
142 subfield <<= siz;
143 }
144 field <<= 1;
145 subfield <<= 1;
146 }
147 }
148}
149
150#ifdef KERNEL
151/*
152 * Check that a specified block number is in range.
153 */
154badblock(fs, bn)
155 register struct fs *fs;
156 daddr_t bn;
157{
158
159 if ((unsigned)bn >= fs->fs_size) {
160 printf("bad block %d, ", bn);
161 fserr(fs, "bad block");
162 return (1);
163 }
164 return (0);
165}
166#endif
167
168/*
169 * block operations
170 *
171 * check if a block is available
172 */
173isblock(fs, cp, h)
174 struct fs *fs;
175 unsigned char *cp;
176 daddr_t h;
177{
178 unsigned char mask;
179
180 switch (fs->fs_frag) {
181 case 8:
182 return (cp[h] == 0xff);
183 case 4:
184 mask = 0x0f << ((h & 0x1) << 2);
185 return ((cp[h >> 1] & mask) == mask);
186 case 2:
187 mask = 0x03 << ((h & 0x3) << 1);
188 return ((cp[h >> 2] & mask) == mask);
189 case 1:
190 mask = 0x01 << (h & 0x7);
191 return ((cp[h >> 3] & mask) == mask);
192 default:
193 panic("isblock");
194 return (NULL);
195 }
196}
197
198/*
199 * take a block out of the map
200 */
201clrblock(fs, cp, h)
202 struct fs *fs;
39d536e6 203 u_char *cp;
764e2379
BJ
204 daddr_t h;
205{
206
207 switch ((fs)->fs_frag) {
208 case 8:
209 cp[h] = 0;
210 return;
211 case 4:
212 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
213 return;
214 case 2:
215 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
216 return;
217 case 1:
218 cp[h >> 3] &= ~(0x01 << (h & 0x7));
219 return;
220 default:
221 panic("clrblock");
222 }
223}
224
225/*
226 * put a block into the map
227 */
228setblock(fs, cp, h)
229 struct fs *fs;
230 unsigned char *cp;
231 daddr_t h;
232{
233
234 switch (fs->fs_frag) {
235
236 case 8:
237 cp[h] = 0xff;
238 return;
239 case 4:
240 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
241 return;
242 case 2:
243 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
244 return;
245 case 1:
246 cp[h >> 3] |= (0x01 << (h & 0x7));
247 return;
248 default:
249 panic("setblock");
250 }
251}
4f083fd7
SL
252
253#ifdef KERNEL
254/*
255 * Getfs maps a device number into a pointer to the incore super block.
256 *
257 * The algorithm is a linear search through the mount table. A
258 * consistency check of the super block magic number is performed.
259 *
260 * panic: no fs -- the device is not mounted.
261 * this "cannot happen"
262 */
263struct fs *
264getfs(dev)
265 dev_t dev;
266{
267 register struct mount *mp;
268 register struct fs *fs;
269
270 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
271 if (mp->m_bufp == NULL || mp->m_dev != dev)
272 continue;
273 fs = mp->m_bufp->b_un.b_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 */
297getfsx(dev)
298 dev_t dev;
299{
300 register struct mount *mp;
301
302 if (dev == swapdev)
303 return (MSWAPX);
304 for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
305 if (mp->m_dev == dev)
306 return (mp - &mount[0]);
307 return (-1);
308}
309
310/*
311 * Print out statistics on the current allocation of the buffer pool.
312 * Can be enabled to print out on every ``sync'' by setting "syncprt"
313 * above.
314 */
315bufstats()
316{
317 int s, i, j, count;
318 register struct buf *bp, *dp;
319 int counts[MAXBSIZE/CLBYTES+1];
320 static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
321
322 for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) {
323 count = 0;
324 for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
325 counts[j] = 0;
326 s = spl6();
327 for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) {
328 counts[dp->b_bufsize/CLBYTES]++;
329 count++;
330 }
331 splx(s);
332 printf("%s: total-%d", bname[i], count);
333 for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
334 if (counts[j] != 0)
335 printf(", %d-%d", j * CLBYTES, counts[j]);
336 printf("\n");
337 }
338}
339#endif