1*11637Ssam /* ffs_subr.c 4.5 83/03/21 */ 28719Sroot 38719Sroot #ifdef KERNEL 48719Sroot #include "../h/param.h" 59167Ssam #include "../h/systm.h" 69167Ssam #include "../h/mount.h" 78719Sroot #include "../h/fs.h" 89167Ssam #include "../h/conf.h" 99167Ssam #include "../h/buf.h" 109167Ssam #include "../h/inode.h" 119167Ssam #include "../h/dir.h" 129167Ssam #include "../h/user.h" 139167Ssam #include "../h/quota.h" 149167Ssam #include "../h/kernel.h" 158719Sroot #else 168719Sroot #include <sys/param.h> 179167Ssam #include <sys/systm.h> 189167Ssam #include <sys/mount.h> 198719Sroot #include <sys/fs.h> 209167Ssam #include <sys/conf.h> 219167Ssam #include <sys/buf.h> 229167Ssam #include <sys/inode.h> 239167Ssam #include <sys/dir.h> 249167Ssam #include <sys/user.h> 259167Ssam #include <sys/quota.h> 268719Sroot #endif 278719Sroot 289167Ssam #ifdef KERNEL 299167Ssam int syncprt = 0; 309167Ssam 319167Ssam /* 329167Ssam * Update is the internal name of 'sync'. It goes through the disk 339167Ssam * queues to initiate sandbagged IO; goes through the inodes to write 349167Ssam * modified nodes; and it goes through the mount table to initiate 359167Ssam * the writing of the modified super blocks. 369167Ssam */ 379167Ssam update() 389167Ssam { 399167Ssam register struct inode *ip; 409167Ssam register struct mount *mp; 419167Ssam struct fs *fs; 429167Ssam 439167Ssam if (syncprt) 449167Ssam bufstats(); 459167Ssam if (updlock) 469167Ssam return; 479167Ssam updlock++; 489167Ssam /* 499167Ssam * Write back modified superblocks. 509167Ssam * Consistency check that the superblock 519167Ssam * of each file system is still in the buffer cache. 529167Ssam */ 539167Ssam for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 549764Ssam if (mp->m_bufp == NULL || mp->m_dev == NODEV) 559167Ssam continue; 569167Ssam fs = mp->m_bufp->b_un.b_fs; 579167Ssam if (fs->fs_fmod == 0) 589167Ssam continue; 599167Ssam if (fs->fs_ronly != 0) { /* XXX */ 609167Ssam printf("fs = %s\n", fs->fs_fsmnt); 619167Ssam panic("update: rofs mod"); 629167Ssam } 639167Ssam fs->fs_fmod = 0; 649167Ssam fs->fs_time = time.tv_sec; 659167Ssam sbupdate(mp); 669167Ssam } 679167Ssam /* 689167Ssam * Write back each (modified) inode. 699167Ssam */ 709167Ssam for (ip = inode; ip < inodeNINODE; ip++) { 719167Ssam if ((ip->i_flag & ILOCKED) != 0 || ip->i_count == 0) 729167Ssam continue; 739167Ssam ip->i_flag |= ILOCKED; 749167Ssam ip->i_count++; 759167Ssam iupdat(ip, &time, &time, 0); 769167Ssam iput(ip); 779167Ssam } 789167Ssam updlock = 0; 799167Ssam /* 809167Ssam * Force stale buffer cache information to be flushed, 819167Ssam * for all devices. 829167Ssam */ 839167Ssam bflush(NODEV); 849167Ssam } 859167Ssam 869167Ssam /* 879167Ssam * Flush all the blocks associated with an inode. 889167Ssam * Note that we make a more stringent check of 899167Ssam * writing out any block in the buffer pool that may 909167Ssam * overlap the inode. This brings the inode up to 919167Ssam * date with recent mods to the cooked device. 929167Ssam */ 939167Ssam syncip(ip) 949167Ssam register struct inode *ip; 959167Ssam { 969167Ssam register struct fs *fs; 979167Ssam long lbn, lastlbn; 989167Ssam daddr_t blkno; 999167Ssam 1009167Ssam fs = ip->i_fs; 1019167Ssam lastlbn = howmany(ip->i_size, fs->fs_bsize); 1029167Ssam for (lbn = 0; lbn < lastlbn; lbn++) { 1039167Ssam blkno = fsbtodb(fs, bmap(ip, lbn, B_READ)); 1049167Ssam blkflush(ip->i_dev, blkno, blksize(fs, ip, lbn)); 1059167Ssam } 106*11637Ssam ip->i_flag |= ICHG; 107*11637Ssam iupdat(ip, &time, &time, 1); 1089167Ssam } 1099167Ssam #endif 1109167Ssam 1118719Sroot extern int around[9]; 1128719Sroot extern int inside[9]; 1138719Sroot extern u_char *fragtbl[]; 1148719Sroot 1158719Sroot /* 1168719Sroot * Update the frsum fields to reflect addition or deletion 1178719Sroot * of some frags. 1188719Sroot */ 1198719Sroot fragacct(fs, fragmap, fraglist, cnt) 1208719Sroot struct fs *fs; 1218719Sroot int fragmap; 1228719Sroot long fraglist[]; 1238719Sroot int cnt; 1248719Sroot { 1258719Sroot int inblk; 1268719Sroot register int field, subfield; 1278719Sroot register int siz, pos; 1288719Sroot 1298719Sroot inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 1308719Sroot fragmap <<= 1; 1318719Sroot for (siz = 1; siz < fs->fs_frag; siz++) { 1328719Sroot if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 1338719Sroot continue; 1348719Sroot field = around[siz]; 1358719Sroot subfield = inside[siz]; 1368719Sroot for (pos = siz; pos <= fs->fs_frag; pos++) { 1378719Sroot if ((fragmap & field) == subfield) { 1388719Sroot fraglist[siz] += cnt; 1398719Sroot pos += siz; 1408719Sroot field <<= siz; 1418719Sroot subfield <<= siz; 1428719Sroot } 1438719Sroot field <<= 1; 1448719Sroot subfield <<= 1; 1458719Sroot } 1468719Sroot } 1478719Sroot } 1488719Sroot 1498719Sroot #ifdef KERNEL 1508719Sroot /* 1518719Sroot * Check that a specified block number is in range. 1528719Sroot */ 1538719Sroot badblock(fs, bn) 1548719Sroot register struct fs *fs; 1558719Sroot daddr_t bn; 1568719Sroot { 1578719Sroot 1588719Sroot if ((unsigned)bn >= fs->fs_size) { 1598719Sroot printf("bad block %d, ", bn); 1608719Sroot fserr(fs, "bad block"); 1618719Sroot return (1); 1628719Sroot } 1638719Sroot return (0); 1648719Sroot } 1658719Sroot #endif 1668719Sroot 1678719Sroot /* 1688719Sroot * block operations 1698719Sroot * 1708719Sroot * check if a block is available 1718719Sroot */ 1728719Sroot isblock(fs, cp, h) 1738719Sroot struct fs *fs; 1748719Sroot unsigned char *cp; 1758719Sroot daddr_t h; 1768719Sroot { 1778719Sroot unsigned char mask; 1788719Sroot 1798719Sroot switch (fs->fs_frag) { 1808719Sroot case 8: 1818719Sroot return (cp[h] == 0xff); 1828719Sroot case 4: 1838719Sroot mask = 0x0f << ((h & 0x1) << 2); 1848719Sroot return ((cp[h >> 1] & mask) == mask); 1858719Sroot case 2: 1868719Sroot mask = 0x03 << ((h & 0x3) << 1); 1878719Sroot return ((cp[h >> 2] & mask) == mask); 1888719Sroot case 1: 1898719Sroot mask = 0x01 << (h & 0x7); 1908719Sroot return ((cp[h >> 3] & mask) == mask); 1918719Sroot default: 1928719Sroot panic("isblock"); 1938719Sroot return (NULL); 1948719Sroot } 1958719Sroot } 1968719Sroot 1978719Sroot /* 1988719Sroot * take a block out of the map 1998719Sroot */ 2008719Sroot clrblock(fs, cp, h) 2018719Sroot struct fs *fs; 2028770Sroot u_char *cp; 2038719Sroot daddr_t h; 2048719Sroot { 2058719Sroot 2068719Sroot switch ((fs)->fs_frag) { 2078719Sroot case 8: 2088719Sroot cp[h] = 0; 2098719Sroot return; 2108719Sroot case 4: 2118719Sroot cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 2128719Sroot return; 2138719Sroot case 2: 2148719Sroot cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 2158719Sroot return; 2168719Sroot case 1: 2178719Sroot cp[h >> 3] &= ~(0x01 << (h & 0x7)); 2188719Sroot return; 2198719Sroot default: 2208719Sroot panic("clrblock"); 2218719Sroot } 2228719Sroot } 2238719Sroot 2248719Sroot /* 2258719Sroot * put a block into the map 2268719Sroot */ 2278719Sroot setblock(fs, cp, h) 2288719Sroot struct fs *fs; 2298719Sroot unsigned char *cp; 2308719Sroot daddr_t h; 2318719Sroot { 2328719Sroot 2338719Sroot switch (fs->fs_frag) { 2348719Sroot 2358719Sroot case 8: 2368719Sroot cp[h] = 0xff; 2378719Sroot return; 2388719Sroot case 4: 2398719Sroot cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 2408719Sroot return; 2418719Sroot case 2: 2428719Sroot cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 2438719Sroot return; 2448719Sroot case 1: 2458719Sroot cp[h >> 3] |= (0x01 << (h & 0x7)); 2468719Sroot return; 2478719Sroot default: 2488719Sroot panic("setblock"); 2498719Sroot } 2508719Sroot } 2519167Ssam 2529167Ssam #ifdef KERNEL 2539167Ssam /* 2549167Ssam * Getfs maps a device number into a pointer to the incore super block. 2559167Ssam * 2569167Ssam * The algorithm is a linear search through the mount table. A 2579167Ssam * consistency check of the super block magic number is performed. 2589167Ssam * 2599167Ssam * panic: no fs -- the device is not mounted. 2609167Ssam * this "cannot happen" 2619167Ssam */ 2629167Ssam struct fs * 2639167Ssam getfs(dev) 2649167Ssam dev_t dev; 2659167Ssam { 2669167Ssam register struct mount *mp; 2679167Ssam register struct fs *fs; 2689167Ssam 2699167Ssam for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 2709167Ssam if (mp->m_bufp == NULL || mp->m_dev != dev) 2719167Ssam continue; 2729167Ssam fs = mp->m_bufp->b_un.b_fs; 2739167Ssam if (fs->fs_magic != FS_MAGIC) { 2749167Ssam printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt); 2759167Ssam panic("getfs: bad magic"); 2769167Ssam } 2779167Ssam return (fs); 2789167Ssam } 2799167Ssam printf("dev = 0x%x\n", dev); 2809167Ssam panic("getfs: no fs"); 2819167Ssam return (NULL); 2829167Ssam } 2839167Ssam 2849167Ssam /* 2859167Ssam * Getfsx returns the index in the file system 2869167Ssam * table of the specified device. The swap device 2879167Ssam * is also assigned a pseudo-index. The index may 2889167Ssam * be used as a compressed indication of the location 2899167Ssam * of a block, recording 2909167Ssam * <getfsx(dev),blkno> 2919167Ssam * rather than 2929167Ssam * <dev, blkno> 2939167Ssam * provided the information need remain valid only 2949167Ssam * as long as the file system is mounted. 2959167Ssam */ 2969167Ssam getfsx(dev) 2979167Ssam dev_t dev; 2989167Ssam { 2999167Ssam register struct mount *mp; 3009167Ssam 3019167Ssam if (dev == swapdev) 3029167Ssam return (MSWAPX); 3039167Ssam for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 3049167Ssam if (mp->m_dev == dev) 3059167Ssam return (mp - &mount[0]); 3069167Ssam return (-1); 3079167Ssam } 3089167Ssam 3099167Ssam /* 3109167Ssam * Print out statistics on the current allocation of the buffer pool. 3119167Ssam * Can be enabled to print out on every ``sync'' by setting "syncprt" 3129167Ssam * above. 3139167Ssam */ 3149167Ssam bufstats() 3159167Ssam { 3169167Ssam int s, i, j, count; 3179167Ssam register struct buf *bp, *dp; 3189167Ssam int counts[MAXBSIZE/CLBYTES+1]; 3199167Ssam static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; 3209167Ssam 3219167Ssam for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { 3229167Ssam count = 0; 3239167Ssam for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 3249167Ssam counts[j] = 0; 3259167Ssam s = spl6(); 3269167Ssam for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { 3279167Ssam counts[dp->b_bufsize/CLBYTES]++; 3289167Ssam count++; 3299167Ssam } 3309167Ssam splx(s); 3319167Ssam printf("%s: total-%d", bname[i], count); 3329167Ssam for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 3339167Ssam if (counts[j] != 0) 3349167Ssam printf(", %d-%d", j * CLBYTES, counts[j]); 3359167Ssam printf("\n"); 3369167Ssam } 3379167Ssam } 3389167Ssam #endif 339