1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)ffs_subr.c 7.3.1.1 (Berkeley) 04/02/87 7 */ 8 9 #ifdef KERNEL 10 #include "param.h" 11 #include "systm.h" 12 #include "mount.h" 13 #include "fs.h" 14 #include "buf.h" 15 #include "inode.h" 16 #include "dir.h" 17 #include "user.h" 18 #include "quota.h" 19 #include "kernel.h" 20 #else 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/mount.h> 24 #include <sys/fs.h> 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> 30 #endif 31 32 #ifdef KERNEL 33 int 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 */ 41 update() 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++) { 58 if (mp->m_bufp == NULL || mp->m_dev == NODEV) 59 continue; 60 fs = mp->m_bufp->b_un.b_fs; 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++) { 75 if ((ip->i_flag & ILOCKED) != 0 || ip->i_count == 0 || 76 (ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0) 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. 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. 105 */ 106 syncip(ip) 107 register struct inode *ip; 108 { 109 register struct fs *fs; 110 register struct buf *bp; 111 struct buf *lastbufp; 112 long lbn, lastlbn; 113 int s; 114 daddr_t blkno; 115 116 fs = ip->i_fs; 117 lastlbn = howmany(ip->i_size, fs->fs_bsize); 118 if (lastlbn < nbuf / 2) { 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 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 } 134 #endif SECSIZE 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; 141 s = splbio(); 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 } 153 } 154 iupdat(ip, &time, &time, 1); 155 } 156 #endif 157 158 extern int around[9]; 159 extern int inside[9]; 160 extern u_char *fragtbl[]; 161 162 /* 163 * Update the frsum fields to reflect addition or deletion 164 * of some frags. 165 */ 166 fragacct(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 */ 200 badblock(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 */ 219 isblock(fs, cp, h) 220 struct fs *fs; 221 unsigned char *cp; 222 daddr_t h; 223 { 224 unsigned char mask; 225 226 switch ((int)fs->fs_frag) { 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 */ 247 clrblock(fs, cp, h) 248 struct fs *fs; 249 u_char *cp; 250 daddr_t h; 251 { 252 253 switch ((int)fs->fs_frag) { 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 */ 274 setblock(fs, cp, h) 275 struct fs *fs; 276 unsigned char *cp; 277 daddr_t h; 278 { 279 280 switch ((int)fs->fs_frag) { 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 } 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. 305 * 306 * panic: no fs -- the device is not mounted. 307 * this "cannot happen" 308 */ 309 struct fs * 310 getfs(dev) 311 dev_t dev; 312 { 313 register struct mount *mp; 314 register struct fs *fs; 315 316 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 317 if (mp->m_bufp == NULL || mp->m_dev != dev) 318 continue; 319 fs = mp->m_bufp->b_un.b_fs; 320 if (fs->fs_magic != FS_MAGIC) { 321 printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt); 322 panic("getfs: bad magic"); 323 } 324 return (fs); 325 } 326 printf("dev = 0x%x\n", dev); 327 panic("getfs: no fs"); 328 return (NULL); 329 } 330 331 /* 332 * Getfsx returns the index in the file system 333 * table of the specified device. The swap device 334 * is also assigned a pseudo-index. The index may 335 * be used as a compressed indication of the location 336 * of a block, recording 337 * <getfsx(dev),blkno> 338 * rather than 339 * <dev, blkno> 340 * provided the information need remain valid only 341 * as long as the file system is mounted. 342 */ 343 getfsx(dev) 344 dev_t dev; 345 { 346 register struct mount *mp; 347 348 if (dev == swapdev) 349 return (MSWAPX); 350 for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 351 if (mp->m_dev == dev) 352 return (mp - &mount[0]); 353 return (-1); 354 } 355 356 /* 357 * Print out statistics on the current allocation of the buffer pool. 358 * Can be enabled to print out on every ``sync'' by setting "syncprt" 359 * above. 360 */ 361 bufstats() 362 { 363 int s, i, j, count; 364 register struct buf *bp, *dp; 365 int counts[MAXBSIZE/CLBYTES+1]; 366 static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; 367 368 for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { 369 count = 0; 370 for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 371 counts[j] = 0; 372 s = splbio(); 373 for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { 374 counts[dp->b_bufsize/CLBYTES]++; 375 count++; 376 } 377 splx(s); 378 printf("%s: total-%d", bname[i], count); 379 for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 380 if (counts[j] != 0) 381 printf(", %d-%d", j * CLBYTES, counts[j]); 382 printf("\n"); 383 } 384 } 385 #endif 386 387 #if (!defined(vax) && !defined(tahoe)) || defined(VAX630) 388 /* 389 * C definitions of special instructions. 390 * Normally expanded with inline. 391 */ 392 scanc(size, cp, table, mask) 393 u_int size; 394 register u_char *cp, table[]; 395 register u_char mask; 396 { 397 register u_char *end = &cp[size]; 398 399 while (cp < end && (table[*cp] & mask) == 0) 400 cp++; 401 return (end - cp); 402 } 403 #endif 404 405 #if !defined(vax) && !defined(tahoe) 406 skpc(mask, size, cp) 407 register u_char mask; 408 u_int size; 409 register u_char *cp; 410 { 411 register u_char *end = &cp[size]; 412 413 while (cp < end && *cp == mask) 414 cp++; 415 return (end - cp); 416 } 417 418 locc(mask, size, cp) 419 register u_char mask; 420 u_int size; 421 register u_char *cp; 422 { 423 register u_char *end = &cp[size]; 424 425 while (cp < end && *cp != mask) 426 cp++; 427 return (end - cp); 428 } 429 #endif 430