Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
7188ac27 KM |
2 | * Copyright (c) 1982, 1986, 1989 Regents of the University of California. |
3 | * All rights reserved. | |
da7c5cc6 | 4 | * |
7188ac27 KM |
5 | * Redistribution and use in source and binary forms are permitted |
6 | * provided that the above copyright notice and this paragraph are | |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
16 | * | |
17 | * @(#)ffs_subr.c 7.8 (Berkeley) %G% | |
da7c5cc6 | 18 | */ |
764e2379 BJ |
19 | |
20 | #ifdef KERNEL | |
94368568 JB |
21 | #include "param.h" |
22 | #include "systm.h" | |
94368568 | 23 | #include "buf.h" |
7188ac27 | 24 | #include "time.h" |
94368568 | 25 | #include "kernel.h" |
7188ac27 KM |
26 | #include "file.h" |
27 | #include "mount.h" | |
28 | #include "vnode.h" | |
29 | #include "../ufs/inode.h" | |
30 | #include "../ufs/ufsmount.h" | |
31 | #include "../ufs/fs.h" | |
32 | #include "../ufs/quota.h" | |
764e2379 BJ |
33 | #else |
34 | #include <sys/param.h> | |
4f083fd7 | 35 | #include <sys/systm.h> |
4f083fd7 | 36 | #include <sys/buf.h> |
7188ac27 KM |
37 | #include <sys/time.h> |
38 | #include <sys/file.h> | |
39 | #include <sys/mount.h> | |
40 | #include <sys/vnode.h> | |
41 | #include <ufs/inode.h> | |
42 | #include <ufs/ufsmount.h> | |
43 | #include <ufs/fs.h> | |
44 | #include <ufs/quota.h> | |
4f083fd7 SL |
45 | #endif |
46 | ||
47 | #ifdef KERNEL | |
4f083fd7 SL |
48 | /* |
49 | * Flush all the blocks associated with an inode. | |
9a5e5086 KM |
50 | * There are two strategies based on the size of the file; |
51 | * large files are those with more than (nbuf / 2) blocks. | |
52 | * Large files | |
53 | * Walk through the buffer pool and push any dirty pages | |
54 | * associated with the device on which the file resides. | |
55 | * Small files | |
56 | * Look up each block in the file to see if it is in the | |
57 | * buffer pool writing any that are found to disk. | |
58 | * Note that we make a more stringent check of | |
59 | * writing out any block in the buffer pool that may | |
60 | * overlap the inode. This brings the inode up to | |
61 | * date with recent mods to the cooked device. | |
4f083fd7 SL |
62 | */ |
63 | syncip(ip) | |
64 | register struct inode *ip; | |
65 | { | |
66 | register struct fs *fs; | |
9a5e5086 KM |
67 | register struct buf *bp; |
68 | struct buf *lastbufp; | |
a5e62f37 | 69 | long lbn, lastlbn; |
7188ac27 | 70 | int s, error, allerror = 0; |
4f083fd7 SL |
71 | daddr_t blkno; |
72 | ||
73 | fs = ip->i_fs; | |
74 | lastlbn = howmany(ip->i_size, fs->fs_bsize); | |
9a5e5086 | 75 | if (lastlbn < nbuf / 2) { |
ec67a3ce MK |
76 | #ifdef SECSIZE |
77 | lastlbn--; | |
78 | s = fsbtodb(fs, fs->fs_frag); | |
79 | for (lbn = 0; lbn < lastlbn; lbn++) { | |
7188ac27 KM |
80 | error = bmap(ip, lbn, &blkno, (daddr_t *)0, (int *)0); |
81 | if (error) | |
82 | allerror = error; | |
83 | if (error = blkflush(ip->i_devvp, blkno, | |
84 | blksize(fs, ip, lbn))) | |
85 | allerror = error; | |
9a5e5086 | 86 | } |
ec67a3ce | 87 | #endif SECSIZE |
9a5e5086 KM |
88 | } else { |
89 | lastbufp = &buf[nbuf]; | |
90 | for (bp = buf; bp < lastbufp; bp++) { | |
91 | if (bp->b_dev != ip->i_dev || | |
92 | (bp->b_flags & B_DELWRI) == 0) | |
93 | continue; | |
a5e62f37 | 94 | s = splbio(); |
9a5e5086 KM |
95 | if (bp->b_flags & B_BUSY) { |
96 | bp->b_flags |= B_WANTED; | |
97 | sleep((caddr_t)bp, PRIBIO+1); | |
98 | splx(s); | |
99 | bp--; | |
100 | continue; | |
101 | } | |
102 | splx(s); | |
103 | notavail(bp); | |
7188ac27 KM |
104 | if (error = bwrite(bp)) |
105 | allerror = error; | |
9a5e5086 | 106 | } |
4f083fd7 | 107 | } |
7188ac27 KM |
108 | if (error = iupdat(ip, &time, &time, 1)) |
109 | allerror = error; | |
110 | return (allerror); | |
4f083fd7 | 111 | } |
7188ac27 | 112 | #endif KERNEL |
764e2379 BJ |
113 | |
114 | extern int around[9]; | |
115 | extern int inside[9]; | |
116 | extern u_char *fragtbl[]; | |
117 | ||
118 | /* | |
119 | * Update the frsum fields to reflect addition or deletion | |
120 | * of some frags. | |
121 | */ | |
122 | fragacct(fs, fragmap, fraglist, cnt) | |
123 | struct fs *fs; | |
124 | int fragmap; | |
125 | long fraglist[]; | |
126 | int cnt; | |
127 | { | |
128 | int inblk; | |
129 | register int field, subfield; | |
130 | register int siz, pos; | |
131 | ||
132 | inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; | |
133 | fragmap <<= 1; | |
134 | for (siz = 1; siz < fs->fs_frag; siz++) { | |
135 | if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) | |
136 | continue; | |
137 | field = around[siz]; | |
138 | subfield = inside[siz]; | |
139 | for (pos = siz; pos <= fs->fs_frag; pos++) { | |
140 | if ((fragmap & field) == subfield) { | |
141 | fraglist[siz] += cnt; | |
142 | pos += siz; | |
143 | field <<= siz; | |
144 | subfield <<= siz; | |
145 | } | |
146 | field <<= 1; | |
147 | subfield <<= 1; | |
148 | } | |
149 | } | |
150 | } | |
151 | ||
152 | #ifdef KERNEL | |
153 | /* | |
154 | * Check that a specified block number is in range. | |
155 | */ | |
156 | badblock(fs, bn) | |
157 | register struct fs *fs; | |
158 | daddr_t bn; | |
159 | { | |
160 | ||
161 | if ((unsigned)bn >= fs->fs_size) { | |
162 | printf("bad block %d, ", bn); | |
163 | fserr(fs, "bad block"); | |
164 | return (1); | |
165 | } | |
166 | return (0); | |
167 | } | |
168 | #endif | |
169 | ||
170 | /* | |
171 | * block operations | |
172 | * | |
173 | * check if a block is available | |
174 | */ | |
175 | isblock(fs, cp, h) | |
176 | struct fs *fs; | |
177 | unsigned char *cp; | |
178 | daddr_t h; | |
179 | { | |
180 | unsigned char mask; | |
181 | ||
cae611dc | 182 | switch ((int)fs->fs_frag) { |
764e2379 BJ |
183 | case 8: |
184 | return (cp[h] == 0xff); | |
185 | case 4: | |
186 | mask = 0x0f << ((h & 0x1) << 2); | |
187 | return ((cp[h >> 1] & mask) == mask); | |
188 | case 2: | |
189 | mask = 0x03 << ((h & 0x3) << 1); | |
190 | return ((cp[h >> 2] & mask) == mask); | |
191 | case 1: | |
192 | mask = 0x01 << (h & 0x7); | |
193 | return ((cp[h >> 3] & mask) == mask); | |
194 | default: | |
195 | panic("isblock"); | |
196 | return (NULL); | |
197 | } | |
198 | } | |
199 | ||
200 | /* | |
201 | * take a block out of the map | |
202 | */ | |
203 | clrblock(fs, cp, h) | |
204 | struct fs *fs; | |
39d536e6 | 205 | u_char *cp; |
764e2379 BJ |
206 | daddr_t h; |
207 | { | |
208 | ||
cae611dc | 209 | switch ((int)fs->fs_frag) { |
764e2379 BJ |
210 | case 8: |
211 | cp[h] = 0; | |
212 | return; | |
213 | case 4: | |
214 | cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); | |
215 | return; | |
216 | case 2: | |
217 | cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); | |
218 | return; | |
219 | case 1: | |
220 | cp[h >> 3] &= ~(0x01 << (h & 0x7)); | |
221 | return; | |
222 | default: | |
223 | panic("clrblock"); | |
224 | } | |
225 | } | |
226 | ||
227 | /* | |
228 | * put a block into the map | |
229 | */ | |
230 | setblock(fs, cp, h) | |
231 | struct fs *fs; | |
232 | unsigned char *cp; | |
233 | daddr_t h; | |
234 | { | |
235 | ||
cae611dc | 236 | switch ((int)fs->fs_frag) { |
764e2379 BJ |
237 | |
238 | case 8: | |
239 | cp[h] = 0xff; | |
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("setblock"); | |
252 | } | |
253 | } | |
4f083fd7 SL |
254 | |
255 | #ifdef KERNEL | |
256 | /* | |
257 | * Getfs maps a device number into a pointer to the incore super block. | |
258 | * | |
259 | * The algorithm is a linear search through the mount table. A | |
260 | * consistency check of the super block magic number is performed. | |
3649dfe2 | 261 | * Filesystems still working on a mount are skipped. |
4f083fd7 SL |
262 | * |
263 | * panic: no fs -- the device is not mounted. | |
264 | * this "cannot happen" | |
265 | */ | |
266 | struct fs * | |
267 | getfs(dev) | |
268 | dev_t dev; | |
269 | { | |
7188ac27 | 270 | register struct ufsmount *mp; |
4f083fd7 SL |
271 | register struct fs *fs; |
272 | ||
7188ac27 KM |
273 | for (mp = &mounttab[0]; mp < &mounttab[NMOUNT]; mp++) { |
274 | if (mp->um_fs == NULL || mp->um_dev != dev || | |
275 | mp->um_fs == (struct fs *)1) /* XXX */ | |
4f083fd7 | 276 | continue; |
7188ac27 | 277 | fs = mp->um_fs; |
4f083fd7 SL |
278 | if (fs->fs_magic != FS_MAGIC) { |
279 | printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt); | |
280 | panic("getfs: bad magic"); | |
281 | } | |
282 | return (fs); | |
283 | } | |
284 | printf("dev = 0x%x\n", dev); | |
285 | panic("getfs: no fs"); | |
286 | return (NULL); | |
287 | } | |
288 | ||
289 | /* | |
290 | * Getfsx returns the index in the file system | |
291 | * table of the specified device. The swap device | |
292 | * is also assigned a pseudo-index. The index may | |
293 | * be used as a compressed indication of the location | |
294 | * of a block, recording | |
295 | * <getfsx(dev),blkno> | |
296 | * rather than | |
297 | * <dev, blkno> | |
298 | * provided the information need remain valid only | |
299 | * as long as the file system is mounted. | |
300 | */ | |
301 | getfsx(dev) | |
302 | dev_t dev; | |
303 | { | |
7188ac27 | 304 | register struct ufsmount *mp; |
4f083fd7 SL |
305 | |
306 | if (dev == swapdev) | |
307 | return (MSWAPX); | |
7188ac27 KM |
308 | for(mp = &mounttab[0]; mp < &mounttab[NMOUNT]; mp++) |
309 | if (mp->um_dev == dev) | |
310 | return (mp - &mounttab[0]); | |
4f083fd7 SL |
311 | return (-1); |
312 | } | |
4f083fd7 | 313 | #endif |
8570887c | 314 | |
a94023e0 | 315 | #if (!defined(vax) && !defined(tahoe)) || defined(VAX630) || defined(VAX650) |
8570887c | 316 | /* |
fb1db32c MK |
317 | * C definitions of special instructions. |
318 | * Normally expanded with inline. | |
8570887c KM |
319 | */ |
320 | scanc(size, cp, table, mask) | |
321 | u_int size; | |
322 | register u_char *cp, table[]; | |
323 | register u_char mask; | |
324 | { | |
325 | register u_char *end = &cp[size]; | |
326 | ||
327 | while (cp < end && (table[*cp] & mask) == 0) | |
328 | cp++; | |
329 | return (end - cp); | |
330 | } | |
ac3e1f5c | 331 | #endif |
ac3e1f5c | 332 | |
fb1db32c | 333 | #if !defined(vax) && !defined(tahoe) |
8570887c KM |
334 | skpc(mask, size, cp) |
335 | register u_char mask; | |
336 | u_int size; | |
337 | register u_char *cp; | |
338 | { | |
339 | register u_char *end = &cp[size]; | |
340 | ||
341 | while (cp < end && *cp == mask) | |
342 | cp++; | |
343 | return (end - cp); | |
344 | } | |
345 | ||
346 | locc(mask, size, cp) | |
347 | register u_char mask; | |
348 | u_int size; | |
349 | register u_char *cp; | |
350 | { | |
351 | register u_char *end = &cp[size]; | |
352 | ||
353 | while (cp < end && *cp != mask) | |
354 | cp++; | |
355 | return (end - cp); | |
356 | } | |
fb1db32c | 357 | #endif |