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: * @(#)ufs_subr.c 7.1 (Berkeley) 6/5/86 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: for (lbn = 0; lbn < lastlbn; lbn++) { 120: blkno = fsbtodb(fs, bmap(ip, lbn, B_READ)); 121: blkflush(ip->i_dev, blkno, blksize(fs, ip, lbn)); 122: } 123: } else { 124: lastbufp = &buf[nbuf]; 125: for (bp = buf; bp < lastbufp; bp++) { 126: if (bp->b_dev != ip->i_dev || 127: (bp->b_flags & B_DELWRI) == 0) 128: continue; 129: s = splbio(); 130: if (bp->b_flags & B_BUSY) { 131: bp->b_flags |= B_WANTED; 132: sleep((caddr_t)bp, PRIBIO+1); 133: splx(s); 134: bp--; 135: continue; 136: } 137: splx(s); 138: notavail(bp); 139: bwrite(bp); 140: } 141: } 142: ip->i_flag |= ICHG; 143: iupdat(ip, &time, &time, 1); 144: } 145: #endif 146: 147: extern int around[9]; 148: extern int inside[9]; 149: extern u_char *fragtbl[]; 150: 151: /* 152: * Update the frsum fields to reflect addition or deletion 153: * of some frags. 154: */ 155: fragacct(fs, fragmap, fraglist, cnt) 156: struct fs *fs; 157: int fragmap; 158: long fraglist[]; 159: int cnt; 160: { 161: int inblk; 162: register int field, subfield; 163: register int siz, pos; 164: 165: inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 166: fragmap <<= 1; 167: for (siz = 1; siz < fs->fs_frag; siz++) { 168: if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 169: continue; 170: field = around[siz]; 171: subfield = inside[siz]; 172: for (pos = siz; pos <= fs->fs_frag; pos++) { 173: if ((fragmap & field) == subfield) { 174: fraglist[siz] += cnt; 175: pos += siz; 176: field <<= siz; 177: subfield <<= siz; 178: } 179: field <<= 1; 180: subfield <<= 1; 181: } 182: } 183: } 184: 185: #ifdef KERNEL 186: /* 187: * Check that a specified block number is in range. 188: */ 189: badblock(fs, bn) 190: register struct fs *fs; 191: daddr_t bn; 192: { 193: 194: if ((unsigned)bn >= fs->fs_size) { 195: printf("bad block %d, ", bn); 196: fserr(fs, "bad block"); 197: return (1); 198: } 199: return (0); 200: } 201: #endif 202: 203: /* 204: * block operations 205: * 206: * check if a block is available 207: */ 208: isblock(fs, cp, h) 209: struct fs *fs; 210: unsigned char *cp; 211: daddr_t h; 212: { 213: unsigned char mask; 214: 215: switch ((int)fs->fs_frag) { 216: case 8: 217: return (cp[h] == 0xff); 218: case 4: 219: mask = 0x0f << ((h & 0x1) << 2); 220: return ((cp[h >> 1] & mask) == mask); 221: case 2: 222: mask = 0x03 << ((h & 0x3) << 1); 223: return ((cp[h >> 2] & mask) == mask); 224: case 1: 225: mask = 0x01 << (h & 0x7); 226: return ((cp[h >> 3] & mask) == mask); 227: default: 228: panic("isblock"); 229: return (NULL); 230: } 231: } 232: 233: /* 234: * take a block out of the map 235: */ 236: clrblock(fs, cp, h) 237: struct fs *fs; 238: u_char *cp; 239: daddr_t h; 240: { 241: 242: switch ((int)fs->fs_frag) { 243: case 8: 244: cp[h] = 0; 245: return; 246: case 4: 247: cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 248: return; 249: case 2: 250: cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 251: return; 252: case 1: 253: cp[h >> 3] &= ~(0x01 << (h & 0x7)); 254: return; 255: default: 256: panic("clrblock"); 257: } 258: } 259: 260: /* 261: * put a block into the map 262: */ 263: setblock(fs, cp, h) 264: struct fs *fs; 265: unsigned char *cp; 266: daddr_t h; 267: { 268: 269: switch ((int)fs->fs_frag) { 270: 271: case 8: 272: cp[h] = 0xff; 273: return; 274: case 4: 275: cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 276: return; 277: case 2: 278: cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 279: return; 280: case 1: 281: cp[h >> 3] |= (0x01 << (h & 0x7)); 282: return; 283: default: 284: panic("setblock"); 285: } 286: } 287: 288: #ifdef KERNEL 289: /* 290: * Getfs maps a device number into a pointer to the incore super block. 291: * 292: * The algorithm is a linear search through the mount table. A 293: * consistency check of the super block magic number is performed. 294: * 295: * panic: no fs -- the device is not mounted. 296: * this "cannot happen" 297: */ 298: struct fs * 299: getfs(dev) 300: dev_t dev; 301: { 302: register struct mount *mp; 303: register struct fs *fs; 304: 305: for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 306: if (mp->m_bufp == NULL || mp->m_dev != dev) 307: continue; 308: fs = mp->m_bufp->b_un.b_fs; 309: if (fs->fs_magic != FS_MAGIC) { 310: printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt); 311: panic("getfs: bad magic"); 312: } 313: return (fs); 314: } 315: printf("dev = 0x%x\n", dev); 316: panic("getfs: no fs"); 317: return (NULL); 318: } 319: 320: /* 321: * Getfsx returns the index in the file system 322: * table of the specified device. The swap device 323: * is also assigned a pseudo-index. The index may 324: * be used as a compressed indication of the location 325: * of a block, recording 326: * <getfsx(dev),blkno> 327: * rather than 328: * <dev, blkno> 329: * provided the information need remain valid only 330: * as long as the file system is mounted. 331: */ 332: getfsx(dev) 333: dev_t dev; 334: { 335: register struct mount *mp; 336: 337: if (dev == swapdev) 338: return (MSWAPX); 339: for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 340: if (mp->m_dev == dev) 341: return (mp - &mount[0]); 342: return (-1); 343: } 344: 345: /* 346: * Print out statistics on the current allocation of the buffer pool. 347: * Can be enabled to print out on every ``sync'' by setting "syncprt" 348: * above. 349: */ 350: bufstats() 351: { 352: int s, i, j, count; 353: register struct buf *bp, *dp; 354: int counts[MAXBSIZE/CLBYTES+1]; 355: static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; 356: 357: for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { 358: count = 0; 359: for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 360: counts[j] = 0; 361: s = splbio(); 362: for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { 363: counts[dp->b_bufsize/CLBYTES]++; 364: count++; 365: } 366: splx(s); 367: printf("%s: total-%d", bname[i], count); 368: for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 369: if (counts[j] != 0) 370: printf(", %d-%d", j * CLBYTES, counts[j]); 371: printf("\n"); 372: } 373: } 374: #endif 375: 376: #if !defined(vax) || defined(VAX630) 377: /* 378: * C definitions of special vax instructions. 379: */ 380: scanc(size, cp, table, mask) 381: u_int size; 382: register u_char *cp, table[]; 383: register u_char mask; 384: { 385: register u_char *end = &cp[size]; 386: 387: while (cp < end && (table[*cp] & mask) == 0) 388: cp++; 389: return (end - cp); 390: } 391: 392: #endif 393: #if !defined(vax) 394: 395: skpc(mask, size, cp) 396: register u_char mask; 397: u_int size; 398: register u_char *cp; 399: { 400: register u_char *end = &cp[size]; 401: 402: while (cp < end && *cp == mask) 403: cp++; 404: return (end - cp); 405: } 406: 407: locc(mask, size, cp) 408: register u_char mask; 409: u_int size; 410: register u_char *cp; 411: { 412: register u_char *end = &cp[size]; 413: 414: while (cp < end && *cp != mask) 415: cp++; 416: return (end - cp); 417: } 418: #endif vax