check for multiple includes; change for POSIX compliance
[unix-history] / usr / src / sys / ufs / ffs / ffs_subr.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
a94023e0 6 * @(#)ffs_subr.c 7.7 (Berkeley) %G%
da7c5cc6 7 */
764e2379
BJ
8
9#ifdef KERNEL
94368568
JB
10#include "param.h"
11#include "systm.h"
12#include "mount.h"
13#include "fs.h"
94368568
JB
14#include "buf.h"
15#include "inode.h"
16#include "dir.h"
17#include "user.h"
18#include "quota.h"
19#include "kernel.h"
764e2379
BJ
20#else
21#include <sys/param.h>
4f083fd7
SL
22#include <sys/systm.h>
23#include <sys/mount.h>
764e2379 24#include <sys/fs.h>
4f083fd7
SL
25#include <sys/buf.h>
26#include <sys/inode.h>
27#include <sys/dir.h>
28#include <sys/user.h>
29#include <sys/quota.h>
4f083fd7
SL
30#endif
31
32#ifdef KERNEL
33int syncprt = 0;
34
35/*
36 * Update is the internal name of 'sync'. It goes through the disk
37 * queues to initiate sandbagged IO; goes through the inodes to write
38 * modified nodes; and it goes through the mount table to initiate
39 * the writing of the modified super blocks.
40 */
41update()
42{
43 register struct inode *ip;
44 register struct mount *mp;
45 struct fs *fs;
46
47 if (syncprt)
48 bufstats();
49 if (updlock)
50 return;
51 updlock++;
52 /*
53 * Write back modified superblocks.
54 * Consistency check that the superblock
55 * of each file system is still in the buffer cache.
56 */
57 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
3649dfe2 58 if (mp->m_fs == NULL || mp->m_fs == (struct fs *)1) /* XXX */
4f083fd7 59 continue;
e4f5c903 60 fs = mp->m_fs;
4f083fd7
SL
61 if (fs->fs_fmod == 0)
62 continue;
63 if (fs->fs_ronly != 0) { /* XXX */
64 printf("fs = %s\n", fs->fs_fsmnt);
65 panic("update: rofs mod");
66 }
67 fs->fs_fmod = 0;
68 fs->fs_time = time.tv_sec;
69 sbupdate(mp);
70 }
71 /*
72 * Write back each (modified) inode.
73 */
74 for (ip = inode; ip < inodeNINODE; ip++) {
d2c01817 75 if ((ip->i_flag & ILOCKED) != 0 || ip->i_count == 0 ||
38601d83 76 (ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0)
4f083fd7
SL
77 continue;
78 ip->i_flag |= ILOCKED;
79 ip->i_count++;
80 iupdat(ip, &time, &time, 0);
81 iput(ip);
82 }
83 updlock = 0;
84 /*
85 * Force stale buffer cache information to be flushed,
86 * for all devices.
87 */
88 bflush(NODEV);
89}
90
91/*
92 * Flush all the blocks associated with an inode.
9a5e5086
KM
93 * There are two strategies based on the size of the file;
94 * large files are those with more than (nbuf / 2) blocks.
95 * Large files
96 * Walk through the buffer pool and push any dirty pages
97 * associated with the device on which the file resides.
98 * Small files
99 * Look up each block in the file to see if it is in the
100 * buffer pool writing any that are found to disk.
101 * Note that we make a more stringent check of
102 * writing out any block in the buffer pool that may
103 * overlap the inode. This brings the inode up to
104 * date with recent mods to the cooked device.
4f083fd7
SL
105 */
106syncip(ip)
107 register struct inode *ip;
108{
109 register struct fs *fs;
9a5e5086
KM
110 register struct buf *bp;
111 struct buf *lastbufp;
a5e62f37
MK
112 long lbn, lastlbn;
113 int s;
4f083fd7
SL
114 daddr_t blkno;
115
116 fs = ip->i_fs;
117 lastlbn = howmany(ip->i_size, fs->fs_bsize);
9a5e5086 118 if (lastlbn < nbuf / 2) {
ec67a3ce
MK
119#ifdef SECSIZE
120 lastlbn--;
121 s = fsbtodb(fs, fs->fs_frag);
122 for (lbn = 0; lbn < lastlbn; lbn++) {
123 blkno = fsbtodb(fs, bmap(ip, lbn, B_READ));
124 blkflush(ip->i_dev, blkno, s);
125 }
126 if (lastlbn >= 0)
127 blkflush(ip->i_dev, blkno, (int)fsbtodb(fs,
128 blksize(fs, ip, lbn) / fs->fs_fsize));
129#else SECSIZE
9a5e5086
KM
130 for (lbn = 0; lbn < lastlbn; lbn++) {
131 blkno = fsbtodb(fs, bmap(ip, lbn, B_READ));
132 blkflush(ip->i_dev, blkno, blksize(fs, ip, lbn));
133 }
ec67a3ce 134#endif SECSIZE
9a5e5086
KM
135 } else {
136 lastbufp = &buf[nbuf];
137 for (bp = buf; bp < lastbufp; bp++) {
138 if (bp->b_dev != ip->i_dev ||
139 (bp->b_flags & B_DELWRI) == 0)
140 continue;
a5e62f37 141 s = splbio();
9a5e5086
KM
142 if (bp->b_flags & B_BUSY) {
143 bp->b_flags |= B_WANTED;
144 sleep((caddr_t)bp, PRIBIO+1);
145 splx(s);
146 bp--;
147 continue;
148 }
149 splx(s);
150 notavail(bp);
151 bwrite(bp);
152 }
4f083fd7 153 }
5b973eee 154 iupdat(ip, &time, &time, 1);
4f083fd7 155}
764e2379
BJ
156#endif
157
158extern int around[9];
159extern int inside[9];
160extern u_char *fragtbl[];
161
162/*
163 * Update the frsum fields to reflect addition or deletion
164 * of some frags.
165 */
166fragacct(fs, fragmap, fraglist, cnt)
167 struct fs *fs;
168 int fragmap;
169 long fraglist[];
170 int cnt;
171{
172 int inblk;
173 register int field, subfield;
174 register int siz, pos;
175
176 inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
177 fragmap <<= 1;
178 for (siz = 1; siz < fs->fs_frag; siz++) {
179 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
180 continue;
181 field = around[siz];
182 subfield = inside[siz];
183 for (pos = siz; pos <= fs->fs_frag; pos++) {
184 if ((fragmap & field) == subfield) {
185 fraglist[siz] += cnt;
186 pos += siz;
187 field <<= siz;
188 subfield <<= siz;
189 }
190 field <<= 1;
191 subfield <<= 1;
192 }
193 }
194}
195
196#ifdef KERNEL
197/*
198 * Check that a specified block number is in range.
199 */
200badblock(fs, bn)
201 register struct fs *fs;
202 daddr_t bn;
203{
204
205 if ((unsigned)bn >= fs->fs_size) {
206 printf("bad block %d, ", bn);
207 fserr(fs, "bad block");
208 return (1);
209 }
210 return (0);
211}
212#endif
213
214/*
215 * block operations
216 *
217 * check if a block is available
218 */
219isblock(fs, cp, h)
220 struct fs *fs;
221 unsigned char *cp;
222 daddr_t h;
223{
224 unsigned char mask;
225
cae611dc 226 switch ((int)fs->fs_frag) {
764e2379
BJ
227 case 8:
228 return (cp[h] == 0xff);
229 case 4:
230 mask = 0x0f << ((h & 0x1) << 2);
231 return ((cp[h >> 1] & mask) == mask);
232 case 2:
233 mask = 0x03 << ((h & 0x3) << 1);
234 return ((cp[h >> 2] & mask) == mask);
235 case 1:
236 mask = 0x01 << (h & 0x7);
237 return ((cp[h >> 3] & mask) == mask);
238 default:
239 panic("isblock");
240 return (NULL);
241 }
242}
243
244/*
245 * take a block out of the map
246 */
247clrblock(fs, cp, h)
248 struct fs *fs;
39d536e6 249 u_char *cp;
764e2379
BJ
250 daddr_t h;
251{
252
cae611dc 253 switch ((int)fs->fs_frag) {
764e2379
BJ
254 case 8:
255 cp[h] = 0;
256 return;
257 case 4:
258 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
259 return;
260 case 2:
261 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
262 return;
263 case 1:
264 cp[h >> 3] &= ~(0x01 << (h & 0x7));
265 return;
266 default:
267 panic("clrblock");
268 }
269}
270
271/*
272 * put a block into the map
273 */
274setblock(fs, cp, h)
275 struct fs *fs;
276 unsigned char *cp;
277 daddr_t h;
278{
279
cae611dc 280 switch ((int)fs->fs_frag) {
764e2379
BJ
281
282 case 8:
283 cp[h] = 0xff;
284 return;
285 case 4:
286 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
287 return;
288 case 2:
289 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
290 return;
291 case 1:
292 cp[h >> 3] |= (0x01 << (h & 0x7));
293 return;
294 default:
295 panic("setblock");
296 }
297}
4f083fd7
SL
298
299#ifdef KERNEL
300/*
301 * Getfs maps a device number into a pointer to the incore super block.
302 *
303 * The algorithm is a linear search through the mount table. A
304 * consistency check of the super block magic number is performed.
3649dfe2 305 * Filesystems still working on a mount are skipped.
4f083fd7
SL
306 *
307 * panic: no fs -- the device is not mounted.
308 * this "cannot happen"
309 */
310struct fs *
311getfs(dev)
312 dev_t dev;
313{
314 register struct mount *mp;
315 register struct fs *fs;
316
317 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
3649dfe2
MK
318 if (mp->m_dev != dev || mp->m_fs == NULL ||
319 mp->m_fs == (struct fs *)1) /* XXX */
4f083fd7 320 continue;
e4f5c903 321 fs = mp->m_fs;
4f083fd7
SL
322 if (fs->fs_magic != FS_MAGIC) {
323 printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt);
324 panic("getfs: bad magic");
325 }
326 return (fs);
327 }
328 printf("dev = 0x%x\n", dev);
329 panic("getfs: no fs");
330 return (NULL);
331}
332
333/*
334 * Getfsx returns the index in the file system
335 * table of the specified device. The swap device
336 * is also assigned a pseudo-index. The index may
337 * be used as a compressed indication of the location
338 * of a block, recording
339 * <getfsx(dev),blkno>
340 * rather than
341 * <dev, blkno>
342 * provided the information need remain valid only
343 * as long as the file system is mounted.
344 */
345getfsx(dev)
346 dev_t dev;
347{
348 register struct mount *mp;
349
350 if (dev == swapdev)
351 return (MSWAPX);
352 for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
353 if (mp->m_dev == dev)
354 return (mp - &mount[0]);
355 return (-1);
356}
357
358/*
359 * Print out statistics on the current allocation of the buffer pool.
360 * Can be enabled to print out on every ``sync'' by setting "syncprt"
361 * above.
362 */
363bufstats()
364{
365 int s, i, j, count;
366 register struct buf *bp, *dp;
367 int counts[MAXBSIZE/CLBYTES+1];
368 static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
369
370 for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) {
371 count = 0;
372 for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
373 counts[j] = 0;
a5e62f37 374 s = splbio();
4f083fd7
SL
375 for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) {
376 counts[dp->b_bufsize/CLBYTES]++;
377 count++;
378 }
379 splx(s);
380 printf("%s: total-%d", bname[i], count);
381 for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
382 if (counts[j] != 0)
383 printf(", %d-%d", j * CLBYTES, counts[j]);
384 printf("\n");
385 }
386}
387#endif
8570887c 388
a94023e0 389#if (!defined(vax) && !defined(tahoe)) || defined(VAX630) || defined(VAX650)
8570887c 390/*
fb1db32c
MK
391 * C definitions of special instructions.
392 * Normally expanded with inline.
8570887c
KM
393 */
394scanc(size, cp, table, mask)
395 u_int size;
396 register u_char *cp, table[];
397 register u_char mask;
398{
399 register u_char *end = &cp[size];
400
401 while (cp < end && (table[*cp] & mask) == 0)
402 cp++;
403 return (end - cp);
404}
ac3e1f5c 405#endif
ac3e1f5c 406
fb1db32c 407#if !defined(vax) && !defined(tahoe)
8570887c
KM
408skpc(mask, size, cp)
409 register u_char mask;
410 u_int size;
411 register u_char *cp;
412{
413 register u_char *end = &cp[size];
414
415 while (cp < end && *cp == mask)
416 cp++;
417 return (end - cp);
418}
419
420locc(mask, size, cp)
421 register u_char mask;
422 u_int size;
423 register u_char *cp;
424{
425 register u_char *end = &cp[size];
426
427 while (cp < end && *cp != mask)
428 cp++;
429 return (end - cp);
430}
fb1db32c 431#endif