Change to includes. No more ../h
[unix-history] / usr / src / sys / ufs / ffs / ffs_subr.c
CommitLineData
9a5e5086 1/* ffs_subr.c 6.4 84/08/09 */
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 71 if ((ip->i_flag & ILOCKED) != 0 || ip->i_count == 0 ||
38601d83 72 (ip->i_flag & (IMOD|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.
9a5e5086
KM
89 * There are two strategies based on the size of the file;
90 * large files are those with more than (nbuf / 2) blocks.
91 * Large files
92 * Walk through the buffer pool and push any dirty pages
93 * associated with the device on which the file resides.
94 * Small files
95 * Look up each block in the file to see if it is in the
96 * buffer pool writing any that are found to disk.
97 * Note that we make a more stringent check of
98 * writing out any block in the buffer pool that may
99 * overlap the inode. This brings the inode up to
100 * date with recent mods to the cooked device.
4f083fd7
SL
101 */
102syncip(ip)
103 register struct inode *ip;
104{
105 register struct fs *fs;
9a5e5086
KM
106 register struct buf *bp;
107 struct buf *lastbufp;
108 long lbn, lastlbn, s;
4f083fd7
SL
109 daddr_t blkno;
110
111 fs = ip->i_fs;
112 lastlbn = howmany(ip->i_size, fs->fs_bsize);
9a5e5086
KM
113 if (lastlbn < nbuf / 2) {
114 for (lbn = 0; lbn < lastlbn; lbn++) {
115 blkno = fsbtodb(fs, bmap(ip, lbn, B_READ));
116 blkflush(ip->i_dev, blkno, blksize(fs, ip, lbn));
117 }
118 } else {
119 lastbufp = &buf[nbuf];
120 for (bp = buf; bp < lastbufp; bp++) {
121 if (bp->b_dev != ip->i_dev ||
122 (bp->b_flags & B_DELWRI) == 0)
123 continue;
124 s = spl6();
125 if (bp->b_flags & B_BUSY) {
126 bp->b_flags |= B_WANTED;
127 sleep((caddr_t)bp, PRIBIO+1);
128 splx(s);
129 bp--;
130 continue;
131 }
132 splx(s);
133 notavail(bp);
134 bwrite(bp);
135 }
4f083fd7 136 }
5b973eee
SL
137 ip->i_flag |= ICHG;
138 iupdat(ip, &time, &time, 1);
4f083fd7 139}
764e2379
BJ
140#endif
141
142extern int around[9];
143extern int inside[9];
144extern u_char *fragtbl[];
145
146/*
147 * Update the frsum fields to reflect addition or deletion
148 * of some frags.
149 */
150fragacct(fs, fragmap, fraglist, cnt)
151 struct fs *fs;
152 int fragmap;
153 long fraglist[];
154 int cnt;
155{
156 int inblk;
157 register int field, subfield;
158 register int siz, pos;
159
160 inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
161 fragmap <<= 1;
162 for (siz = 1; siz < fs->fs_frag; siz++) {
163 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
164 continue;
165 field = around[siz];
166 subfield = inside[siz];
167 for (pos = siz; pos <= fs->fs_frag; pos++) {
168 if ((fragmap & field) == subfield) {
169 fraglist[siz] += cnt;
170 pos += siz;
171 field <<= siz;
172 subfield <<= siz;
173 }
174 field <<= 1;
175 subfield <<= 1;
176 }
177 }
178}
179
180#ifdef KERNEL
181/*
182 * Check that a specified block number is in range.
183 */
184badblock(fs, bn)
185 register struct fs *fs;
186 daddr_t bn;
187{
188
189 if ((unsigned)bn >= fs->fs_size) {
190 printf("bad block %d, ", bn);
191 fserr(fs, "bad block");
192 return (1);
193 }
194 return (0);
195}
196#endif
197
198/*
199 * block operations
200 *
201 * check if a block is available
202 */
203isblock(fs, cp, h)
204 struct fs *fs;
205 unsigned char *cp;
206 daddr_t h;
207{
208 unsigned char mask;
209
210 switch (fs->fs_frag) {
211 case 8:
212 return (cp[h] == 0xff);
213 case 4:
214 mask = 0x0f << ((h & 0x1) << 2);
215 return ((cp[h >> 1] & mask) == mask);
216 case 2:
217 mask = 0x03 << ((h & 0x3) << 1);
218 return ((cp[h >> 2] & mask) == mask);
219 case 1:
220 mask = 0x01 << (h & 0x7);
221 return ((cp[h >> 3] & mask) == mask);
222 default:
223 panic("isblock");
224 return (NULL);
225 }
226}
227
228/*
229 * take a block out of the map
230 */
231clrblock(fs, cp, h)
232 struct fs *fs;
39d536e6 233 u_char *cp;
764e2379
BJ
234 daddr_t h;
235{
236
237 switch ((fs)->fs_frag) {
238 case 8:
239 cp[h] = 0;
240 return;
241 case 4:
242 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
243 return;
244 case 2:
245 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
246 return;
247 case 1:
248 cp[h >> 3] &= ~(0x01 << (h & 0x7));
249 return;
250 default:
251 panic("clrblock");
252 }
253}
254
255/*
256 * put a block into the map
257 */
258setblock(fs, cp, h)
259 struct fs *fs;
260 unsigned char *cp;
261 daddr_t h;
262{
263
264 switch (fs->fs_frag) {
265
266 case 8:
267 cp[h] = 0xff;
268 return;
269 case 4:
270 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
271 return;
272 case 2:
273 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
274 return;
275 case 1:
276 cp[h >> 3] |= (0x01 << (h & 0x7));
277 return;
278 default:
279 panic("setblock");
280 }
281}
4f083fd7
SL
282
283#ifdef KERNEL
284/*
285 * Getfs maps a device number into a pointer to the incore super block.
286 *
287 * The algorithm is a linear search through the mount table. A
288 * consistency check of the super block magic number is performed.
289 *
290 * panic: no fs -- the device is not mounted.
291 * this "cannot happen"
292 */
293struct fs *
294getfs(dev)
295 dev_t dev;
296{
297 register struct mount *mp;
298 register struct fs *fs;
299
300 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
301 if (mp->m_bufp == NULL || mp->m_dev != dev)
302 continue;
303 fs = mp->m_bufp->b_un.b_fs;
304 if (fs->fs_magic != FS_MAGIC) {
305 printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt);
306 panic("getfs: bad magic");
307 }
308 return (fs);
309 }
310 printf("dev = 0x%x\n", dev);
311 panic("getfs: no fs");
312 return (NULL);
313}
314
315/*
316 * Getfsx returns the index in the file system
317 * table of the specified device. The swap device
318 * is also assigned a pseudo-index. The index may
319 * be used as a compressed indication of the location
320 * of a block, recording
321 * <getfsx(dev),blkno>
322 * rather than
323 * <dev, blkno>
324 * provided the information need remain valid only
325 * as long as the file system is mounted.
326 */
327getfsx(dev)
328 dev_t dev;
329{
330 register struct mount *mp;
331
332 if (dev == swapdev)
333 return (MSWAPX);
334 for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
335 if (mp->m_dev == dev)
336 return (mp - &mount[0]);
337 return (-1);
338}
339
340/*
341 * Print out statistics on the current allocation of the buffer pool.
342 * Can be enabled to print out on every ``sync'' by setting "syncprt"
343 * above.
344 */
345bufstats()
346{
347 int s, i, j, count;
348 register struct buf *bp, *dp;
349 int counts[MAXBSIZE/CLBYTES+1];
350 static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
351
352 for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) {
353 count = 0;
354 for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
355 counts[j] = 0;
356 s = spl6();
357 for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) {
358 counts[dp->b_bufsize/CLBYTES]++;
359 count++;
360 }
361 splx(s);
362 printf("%s: total-%d", bname[i], count);
363 for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
364 if (counts[j] != 0)
365 printf(", %d-%d", j * CLBYTES, counts[j]);
366 printf("\n");
367 }
368}
369#endif