1*9764Ssam /* ffs_subr.c 4.4 82/12/17 */ 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++) { 54*9764Ssam 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 } 1069167Ssam } 1079167Ssam #endif 1089167Ssam 1098719Sroot extern int around[9]; 1108719Sroot extern int inside[9]; 1118719Sroot extern u_char *fragtbl[]; 1128719Sroot 1138719Sroot /* 1148719Sroot * Update the frsum fields to reflect addition or deletion 1158719Sroot * of some frags. 1168719Sroot */ 1178719Sroot fragacct(fs, fragmap, fraglist, cnt) 1188719Sroot struct fs *fs; 1198719Sroot int fragmap; 1208719Sroot long fraglist[]; 1218719Sroot int cnt; 1228719Sroot { 1238719Sroot int inblk; 1248719Sroot register int field, subfield; 1258719Sroot register int siz, pos; 1268719Sroot 1278719Sroot inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 1288719Sroot fragmap <<= 1; 1298719Sroot for (siz = 1; siz < fs->fs_frag; siz++) { 1308719Sroot if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 1318719Sroot continue; 1328719Sroot field = around[siz]; 1338719Sroot subfield = inside[siz]; 1348719Sroot for (pos = siz; pos <= fs->fs_frag; pos++) { 1358719Sroot if ((fragmap & field) == subfield) { 1368719Sroot fraglist[siz] += cnt; 1378719Sroot pos += siz; 1388719Sroot field <<= siz; 1398719Sroot subfield <<= siz; 1408719Sroot } 1418719Sroot field <<= 1; 1428719Sroot subfield <<= 1; 1438719Sroot } 1448719Sroot } 1458719Sroot } 1468719Sroot 1478719Sroot #ifdef KERNEL 1488719Sroot /* 1498719Sroot * Check that a specified block number is in range. 1508719Sroot */ 1518719Sroot badblock(fs, bn) 1528719Sroot register struct fs *fs; 1538719Sroot daddr_t bn; 1548719Sroot { 1558719Sroot 1568719Sroot if ((unsigned)bn >= fs->fs_size) { 1578719Sroot printf("bad block %d, ", bn); 1588719Sroot fserr(fs, "bad block"); 1598719Sroot return (1); 1608719Sroot } 1618719Sroot return (0); 1628719Sroot } 1638719Sroot #endif 1648719Sroot 1658719Sroot /* 1668719Sroot * block operations 1678719Sroot * 1688719Sroot * check if a block is available 1698719Sroot */ 1708719Sroot isblock(fs, cp, h) 1718719Sroot struct fs *fs; 1728719Sroot unsigned char *cp; 1738719Sroot daddr_t h; 1748719Sroot { 1758719Sroot unsigned char mask; 1768719Sroot 1778719Sroot switch (fs->fs_frag) { 1788719Sroot case 8: 1798719Sroot return (cp[h] == 0xff); 1808719Sroot case 4: 1818719Sroot mask = 0x0f << ((h & 0x1) << 2); 1828719Sroot return ((cp[h >> 1] & mask) == mask); 1838719Sroot case 2: 1848719Sroot mask = 0x03 << ((h & 0x3) << 1); 1858719Sroot return ((cp[h >> 2] & mask) == mask); 1868719Sroot case 1: 1878719Sroot mask = 0x01 << (h & 0x7); 1888719Sroot return ((cp[h >> 3] & mask) == mask); 1898719Sroot default: 1908719Sroot panic("isblock"); 1918719Sroot return (NULL); 1928719Sroot } 1938719Sroot } 1948719Sroot 1958719Sroot /* 1968719Sroot * take a block out of the map 1978719Sroot */ 1988719Sroot clrblock(fs, cp, h) 1998719Sroot struct fs *fs; 2008770Sroot u_char *cp; 2018719Sroot daddr_t h; 2028719Sroot { 2038719Sroot 2048719Sroot switch ((fs)->fs_frag) { 2058719Sroot case 8: 2068719Sroot cp[h] = 0; 2078719Sroot return; 2088719Sroot case 4: 2098719Sroot cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 2108719Sroot return; 2118719Sroot case 2: 2128719Sroot cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 2138719Sroot return; 2148719Sroot case 1: 2158719Sroot cp[h >> 3] &= ~(0x01 << (h & 0x7)); 2168719Sroot return; 2178719Sroot default: 2188719Sroot panic("clrblock"); 2198719Sroot } 2208719Sroot } 2218719Sroot 2228719Sroot /* 2238719Sroot * put a block into the map 2248719Sroot */ 2258719Sroot setblock(fs, cp, h) 2268719Sroot struct fs *fs; 2278719Sroot unsigned char *cp; 2288719Sroot daddr_t h; 2298719Sroot { 2308719Sroot 2318719Sroot switch (fs->fs_frag) { 2328719Sroot 2338719Sroot case 8: 2348719Sroot cp[h] = 0xff; 2358719Sroot return; 2368719Sroot case 4: 2378719Sroot cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 2388719Sroot return; 2398719Sroot case 2: 2408719Sroot cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 2418719Sroot return; 2428719Sroot case 1: 2438719Sroot cp[h >> 3] |= (0x01 << (h & 0x7)); 2448719Sroot return; 2458719Sroot default: 2468719Sroot panic("setblock"); 2478719Sroot } 2488719Sroot } 2499167Ssam 2509167Ssam #ifdef KERNEL 2519167Ssam /* 2529167Ssam * Getfs maps a device number into a pointer to the incore super block. 2539167Ssam * 2549167Ssam * The algorithm is a linear search through the mount table. A 2559167Ssam * consistency check of the super block magic number is performed. 2569167Ssam * 2579167Ssam * panic: no fs -- the device is not mounted. 2589167Ssam * this "cannot happen" 2599167Ssam */ 2609167Ssam struct fs * 2619167Ssam getfs(dev) 2629167Ssam dev_t dev; 2639167Ssam { 2649167Ssam register struct mount *mp; 2659167Ssam register struct fs *fs; 2669167Ssam 2679167Ssam for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 2689167Ssam if (mp->m_bufp == NULL || mp->m_dev != dev) 2699167Ssam continue; 2709167Ssam fs = mp->m_bufp->b_un.b_fs; 2719167Ssam if (fs->fs_magic != FS_MAGIC) { 2729167Ssam printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt); 2739167Ssam panic("getfs: bad magic"); 2749167Ssam } 2759167Ssam return (fs); 2769167Ssam } 2779167Ssam printf("dev = 0x%x\n", dev); 2789167Ssam panic("getfs: no fs"); 2799167Ssam return (NULL); 2809167Ssam } 2819167Ssam 2829167Ssam /* 2839167Ssam * Getfsx returns the index in the file system 2849167Ssam * table of the specified device. The swap device 2859167Ssam * is also assigned a pseudo-index. The index may 2869167Ssam * be used as a compressed indication of the location 2879167Ssam * of a block, recording 2889167Ssam * <getfsx(dev),blkno> 2899167Ssam * rather than 2909167Ssam * <dev, blkno> 2919167Ssam * provided the information need remain valid only 2929167Ssam * as long as the file system is mounted. 2939167Ssam */ 2949167Ssam getfsx(dev) 2959167Ssam dev_t dev; 2969167Ssam { 2979167Ssam register struct mount *mp; 2989167Ssam 2999167Ssam if (dev == swapdev) 3009167Ssam return (MSWAPX); 3019167Ssam for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 3029167Ssam if (mp->m_dev == dev) 3039167Ssam return (mp - &mount[0]); 3049167Ssam return (-1); 3059167Ssam } 3069167Ssam 3079167Ssam /* 3089167Ssam * Print out statistics on the current allocation of the buffer pool. 3099167Ssam * Can be enabled to print out on every ``sync'' by setting "syncprt" 3109167Ssam * above. 3119167Ssam */ 3129167Ssam bufstats() 3139167Ssam { 3149167Ssam int s, i, j, count; 3159167Ssam register struct buf *bp, *dp; 3169167Ssam int counts[MAXBSIZE/CLBYTES+1]; 3179167Ssam static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; 3189167Ssam 3199167Ssam for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { 3209167Ssam count = 0; 3219167Ssam for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 3229167Ssam counts[j] = 0; 3239167Ssam s = spl6(); 3249167Ssam for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { 3259167Ssam counts[dp->b_bufsize/CLBYTES]++; 3269167Ssam count++; 3279167Ssam } 3289167Ssam splx(s); 3299167Ssam printf("%s: total-%d", bname[i], count); 3309167Ssam for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 3319167Ssam if (counts[j] != 0) 3329167Ssam printf(", %d-%d", j * CLBYTES, counts[j]); 3339167Ssam printf("\n"); 3349167Ssam } 3359167Ssam } 3369167Ssam #endif 337