missing iput's on errors
[unix-history] / usr / src / sys / ufs / ffs / ffs_subr.c
CommitLineData
b11be056 1/* ffs_subr.c 6.1 83/07/29 */
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++) {
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 */
93syncip(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 }
5b973eee
SL
106 ip->i_flag |= ICHG;
107 iupdat(ip, &time, &time, 1);
4f083fd7 108}
764e2379
BJ
109#endif
110
111extern int around[9];
112extern int inside[9];
113extern u_char *fragtbl[];
114
115/*
116 * Update the frsum fields to reflect addition or deletion
117 * of some frags.
118 */
119fragacct(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 */
153badblock(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 */
172isblock(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 */
200clrblock(fs, cp, h)
201 struct fs *fs;
39d536e6 202 u_char *cp;
764e2379
BJ
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 */
227setblock(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}
4f083fd7
SL
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 */
262struct fs *
263getfs(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 */
296getfsx(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 */
314bufstats()
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