1*9167Ssam /* ffs_subr.c 4.3 82/11/13 */ 28719Sroot 38719Sroot #ifdef KERNEL 48719Sroot #include "../h/param.h" 5*9167Ssam #include "../h/systm.h" 6*9167Ssam #include "../h/mount.h" 78719Sroot #include "../h/fs.h" 8*9167Ssam #include "../h/conf.h" 9*9167Ssam #include "../h/buf.h" 10*9167Ssam #include "../h/inode.h" 11*9167Ssam #include "../h/dir.h" 12*9167Ssam #include "../h/user.h" 13*9167Ssam #include "../h/quota.h" 14*9167Ssam #include "../h/kernel.h" 158719Sroot #else 168719Sroot #include <sys/param.h> 17*9167Ssam #include <sys/systm.h> 18*9167Ssam #include <sys/mount.h> 198719Sroot #include <sys/fs.h> 20*9167Ssam #include <sys/conf.h> 21*9167Ssam #include <sys/buf.h> 22*9167Ssam #include <sys/inode.h> 23*9167Ssam #include <sys/dir.h> 24*9167Ssam #include <sys/user.h> 25*9167Ssam #include <sys/quota.h> 26*9167Ssam #include <sys/kernel.h> 278719Sroot #endif 288719Sroot 29*9167Ssam #ifdef KERNEL 30*9167Ssam int syncprt = 0; 31*9167Ssam 32*9167Ssam /* 33*9167Ssam * Update is the internal name of 'sync'. It goes through the disk 34*9167Ssam * queues to initiate sandbagged IO; goes through the inodes to write 35*9167Ssam * modified nodes; and it goes through the mount table to initiate 36*9167Ssam * the writing of the modified super blocks. 37*9167Ssam */ 38*9167Ssam update() 39*9167Ssam { 40*9167Ssam register struct inode *ip; 41*9167Ssam register struct mount *mp; 42*9167Ssam struct fs *fs; 43*9167Ssam 44*9167Ssam if (syncprt) 45*9167Ssam bufstats(); 46*9167Ssam if (updlock) 47*9167Ssam return; 48*9167Ssam updlock++; 49*9167Ssam /* 50*9167Ssam * Write back modified superblocks. 51*9167Ssam * Consistency check that the superblock 52*9167Ssam * of each file system is still in the buffer cache. 53*9167Ssam */ 54*9167Ssam for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 55*9167Ssam if (mp->m_bufp == NULL) 56*9167Ssam continue; 57*9167Ssam fs = mp->m_bufp->b_un.b_fs; 58*9167Ssam if (fs->fs_fmod == 0) 59*9167Ssam continue; 60*9167Ssam if (fs->fs_ronly != 0) { /* XXX */ 61*9167Ssam printf("fs = %s\n", fs->fs_fsmnt); 62*9167Ssam panic("update: rofs mod"); 63*9167Ssam } 64*9167Ssam fs->fs_fmod = 0; 65*9167Ssam fs->fs_time = time.tv_sec; 66*9167Ssam sbupdate(mp); 67*9167Ssam } 68*9167Ssam /* 69*9167Ssam * Write back each (modified) inode. 70*9167Ssam */ 71*9167Ssam for (ip = inode; ip < inodeNINODE; ip++) { 72*9167Ssam if ((ip->i_flag & ILOCKED) != 0 || ip->i_count == 0) 73*9167Ssam continue; 74*9167Ssam ip->i_flag |= ILOCKED; 75*9167Ssam ip->i_count++; 76*9167Ssam iupdat(ip, &time, &time, 0); 77*9167Ssam iput(ip); 78*9167Ssam } 79*9167Ssam updlock = 0; 80*9167Ssam /* 81*9167Ssam * Force stale buffer cache information to be flushed, 82*9167Ssam * for all devices. 83*9167Ssam */ 84*9167Ssam bflush(NODEV); 85*9167Ssam } 86*9167Ssam 87*9167Ssam /* 88*9167Ssam * Flush all the blocks associated with an inode. 89*9167Ssam * Note that we make a more stringent check of 90*9167Ssam * writing out any block in the buffer pool that may 91*9167Ssam * overlap the inode. This brings the inode up to 92*9167Ssam * date with recent mods to the cooked device. 93*9167Ssam */ 94*9167Ssam syncip(ip) 95*9167Ssam register struct inode *ip; 96*9167Ssam { 97*9167Ssam register struct fs *fs; 98*9167Ssam long lbn, lastlbn; 99*9167Ssam daddr_t blkno; 100*9167Ssam 101*9167Ssam fs = ip->i_fs; 102*9167Ssam lastlbn = howmany(ip->i_size, fs->fs_bsize); 103*9167Ssam for (lbn = 0; lbn < lastlbn; lbn++) { 104*9167Ssam blkno = fsbtodb(fs, bmap(ip, lbn, B_READ)); 105*9167Ssam blkflush(ip->i_dev, blkno, blksize(fs, ip, lbn)); 106*9167Ssam } 107*9167Ssam } 108*9167Ssam #endif 109*9167Ssam 1108719Sroot extern int around[9]; 1118719Sroot extern int inside[9]; 1128719Sroot extern u_char *fragtbl[]; 1138719Sroot 1148719Sroot /* 1158719Sroot * Update the frsum fields to reflect addition or deletion 1168719Sroot * of some frags. 1178719Sroot */ 1188719Sroot fragacct(fs, fragmap, fraglist, cnt) 1198719Sroot struct fs *fs; 1208719Sroot int fragmap; 1218719Sroot long fraglist[]; 1228719Sroot int cnt; 1238719Sroot { 1248719Sroot int inblk; 1258719Sroot register int field, subfield; 1268719Sroot register int siz, pos; 1278719Sroot 1288719Sroot inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 1298719Sroot fragmap <<= 1; 1308719Sroot for (siz = 1; siz < fs->fs_frag; siz++) { 1318719Sroot if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 1328719Sroot continue; 1338719Sroot field = around[siz]; 1348719Sroot subfield = inside[siz]; 1358719Sroot for (pos = siz; pos <= fs->fs_frag; pos++) { 1368719Sroot if ((fragmap & field) == subfield) { 1378719Sroot fraglist[siz] += cnt; 1388719Sroot pos += siz; 1398719Sroot field <<= siz; 1408719Sroot subfield <<= siz; 1418719Sroot } 1428719Sroot field <<= 1; 1438719Sroot subfield <<= 1; 1448719Sroot } 1458719Sroot } 1468719Sroot } 1478719Sroot 1488719Sroot #ifdef KERNEL 1498719Sroot /* 1508719Sroot * Check that a specified block number is in range. 1518719Sroot */ 1528719Sroot badblock(fs, bn) 1538719Sroot register struct fs *fs; 1548719Sroot daddr_t bn; 1558719Sroot { 1568719Sroot 1578719Sroot if ((unsigned)bn >= fs->fs_size) { 1588719Sroot printf("bad block %d, ", bn); 1598719Sroot fserr(fs, "bad block"); 1608719Sroot return (1); 1618719Sroot } 1628719Sroot return (0); 1638719Sroot } 1648719Sroot #endif 1658719Sroot 1668719Sroot /* 1678719Sroot * block operations 1688719Sroot * 1698719Sroot * check if a block is available 1708719Sroot */ 1718719Sroot isblock(fs, cp, h) 1728719Sroot struct fs *fs; 1738719Sroot unsigned char *cp; 1748719Sroot daddr_t h; 1758719Sroot { 1768719Sroot unsigned char mask; 1778719Sroot 1788719Sroot switch (fs->fs_frag) { 1798719Sroot case 8: 1808719Sroot return (cp[h] == 0xff); 1818719Sroot case 4: 1828719Sroot mask = 0x0f << ((h & 0x1) << 2); 1838719Sroot return ((cp[h >> 1] & mask) == mask); 1848719Sroot case 2: 1858719Sroot mask = 0x03 << ((h & 0x3) << 1); 1868719Sroot return ((cp[h >> 2] & mask) == mask); 1878719Sroot case 1: 1888719Sroot mask = 0x01 << (h & 0x7); 1898719Sroot return ((cp[h >> 3] & mask) == mask); 1908719Sroot default: 1918719Sroot panic("isblock"); 1928719Sroot return (NULL); 1938719Sroot } 1948719Sroot } 1958719Sroot 1968719Sroot /* 1978719Sroot * take a block out of the map 1988719Sroot */ 1998719Sroot clrblock(fs, cp, h) 2008719Sroot struct fs *fs; 2018770Sroot u_char *cp; 2028719Sroot daddr_t h; 2038719Sroot { 2048719Sroot 2058719Sroot switch ((fs)->fs_frag) { 2068719Sroot case 8: 2078719Sroot cp[h] = 0; 2088719Sroot return; 2098719Sroot case 4: 2108719Sroot cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 2118719Sroot return; 2128719Sroot case 2: 2138719Sroot cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 2148719Sroot return; 2158719Sroot case 1: 2168719Sroot cp[h >> 3] &= ~(0x01 << (h & 0x7)); 2178719Sroot return; 2188719Sroot default: 2198719Sroot panic("clrblock"); 2208719Sroot } 2218719Sroot } 2228719Sroot 2238719Sroot /* 2248719Sroot * put a block into the map 2258719Sroot */ 2268719Sroot setblock(fs, cp, h) 2278719Sroot struct fs *fs; 2288719Sroot unsigned char *cp; 2298719Sroot daddr_t h; 2308719Sroot { 2318719Sroot 2328719Sroot switch (fs->fs_frag) { 2338719Sroot 2348719Sroot case 8: 2358719Sroot cp[h] = 0xff; 2368719Sroot return; 2378719Sroot case 4: 2388719Sroot cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 2398719Sroot return; 2408719Sroot case 2: 2418719Sroot cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 2428719Sroot return; 2438719Sroot case 1: 2448719Sroot cp[h >> 3] |= (0x01 << (h & 0x7)); 2458719Sroot return; 2468719Sroot default: 2478719Sroot panic("setblock"); 2488719Sroot } 2498719Sroot } 250*9167Ssam 251*9167Ssam #ifdef KERNEL 252*9167Ssam /* 253*9167Ssam * Getfs maps a device number into a pointer to the incore super block. 254*9167Ssam * 255*9167Ssam * The algorithm is a linear search through the mount table. A 256*9167Ssam * consistency check of the super block magic number is performed. 257*9167Ssam * 258*9167Ssam * panic: no fs -- the device is not mounted. 259*9167Ssam * this "cannot happen" 260*9167Ssam */ 261*9167Ssam struct fs * 262*9167Ssam getfs(dev) 263*9167Ssam dev_t dev; 264*9167Ssam { 265*9167Ssam register struct mount *mp; 266*9167Ssam register struct fs *fs; 267*9167Ssam 268*9167Ssam for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 269*9167Ssam if (mp->m_bufp == NULL || mp->m_dev != dev) 270*9167Ssam continue; 271*9167Ssam fs = mp->m_bufp->b_un.b_fs; 272*9167Ssam if (fs->fs_magic != FS_MAGIC) { 273*9167Ssam printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt); 274*9167Ssam panic("getfs: bad magic"); 275*9167Ssam } 276*9167Ssam return (fs); 277*9167Ssam } 278*9167Ssam printf("dev = 0x%x\n", dev); 279*9167Ssam panic("getfs: no fs"); 280*9167Ssam return (NULL); 281*9167Ssam } 282*9167Ssam 283*9167Ssam /* 284*9167Ssam * Getfsx returns the index in the file system 285*9167Ssam * table of the specified device. The swap device 286*9167Ssam * is also assigned a pseudo-index. The index may 287*9167Ssam * be used as a compressed indication of the location 288*9167Ssam * of a block, recording 289*9167Ssam * <getfsx(dev),blkno> 290*9167Ssam * rather than 291*9167Ssam * <dev, blkno> 292*9167Ssam * provided the information need remain valid only 293*9167Ssam * as long as the file system is mounted. 294*9167Ssam */ 295*9167Ssam getfsx(dev) 296*9167Ssam dev_t dev; 297*9167Ssam { 298*9167Ssam register struct mount *mp; 299*9167Ssam 300*9167Ssam if (dev == swapdev) 301*9167Ssam return (MSWAPX); 302*9167Ssam for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 303*9167Ssam if (mp->m_dev == dev) 304*9167Ssam return (mp - &mount[0]); 305*9167Ssam return (-1); 306*9167Ssam } 307*9167Ssam 308*9167Ssam /* 309*9167Ssam * Print out statistics on the current allocation of the buffer pool. 310*9167Ssam * Can be enabled to print out on every ``sync'' by setting "syncprt" 311*9167Ssam * above. 312*9167Ssam */ 313*9167Ssam bufstats() 314*9167Ssam { 315*9167Ssam int s, i, j, count; 316*9167Ssam register struct buf *bp, *dp; 317*9167Ssam int counts[MAXBSIZE/CLBYTES+1]; 318*9167Ssam static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; 319*9167Ssam 320*9167Ssam for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { 321*9167Ssam count = 0; 322*9167Ssam for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 323*9167Ssam counts[j] = 0; 324*9167Ssam s = spl6(); 325*9167Ssam for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { 326*9167Ssam counts[dp->b_bufsize/CLBYTES]++; 327*9167Ssam count++; 328*9167Ssam } 329*9167Ssam splx(s); 330*9167Ssam printf("%s: total-%d", bname[i], count); 331*9167Ssam for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 332*9167Ssam if (counts[j] != 0) 333*9167Ssam printf(", %d-%d", j * CLBYTES, counts[j]); 334*9167Ssam printf("\n"); 335*9167Ssam } 336*9167Ssam } 337*9167Ssam #endif 338