Commit | Line | Data |
---|---|---|
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 | |
29 | int 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 | */ | |
37 | update() | |
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 | */ | |
94 | syncip(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 | ||
112 | extern int around[9]; | |
113 | extern int inside[9]; | |
114 | extern u_char *fragtbl[]; | |
115 | ||
116 | /* | |
117 | * Update the frsum fields to reflect addition or deletion | |
118 | * of some frags. | |
119 | */ | |
120 | fragacct(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 | */ | |
154 | badblock(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 | */ | |
173 | isblock(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 | */ | |
201 | clrblock(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 | */ | |
228 | setblock(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 | */ | |
263 | struct fs * | |
264 | getfs(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 | */ | |
297 | getfsx(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 | */ | |
315 | bufstats() | |
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 |