1*7187Sroot /* lfs_alloc.c 2.7 82/06/14 */ 24359Smckusick 34359Smckusick #include "../h/param.h" 44359Smckusick #include "../h/systm.h" 54359Smckusick #include "../h/mount.h" 64359Smckusick #include "../h/fs.h" 74359Smckusick #include "../h/conf.h" 84359Smckusick #include "../h/buf.h" 94359Smckusick #include "../h/inode.h" 106567Smckusic #include "../h/dir.h" 114359Smckusick #include "../h/user.h" 124359Smckusick 135212Smckusic extern u_long hashalloc(); 145212Smckusic extern ino_t ialloccg(); 154651Smckusic extern daddr_t alloccg(); 164651Smckusic extern daddr_t alloccgblk(); 174651Smckusic extern daddr_t fragextend(); 184651Smckusic extern daddr_t blkpref(); 194651Smckusic extern daddr_t mapsearch(); 204607Smckusic extern int inside[], around[]; 215322Smckusic extern unsigned char *fragtbl[]; 224359Smckusick 235375Smckusic /* 245375Smckusic * Allocate a block in the file system. 255375Smckusic * 265375Smckusic * The size of the requested block is given, which must be some 275375Smckusic * multiple of fs_fsize and <= fs_bsize. 285375Smckusic * A preference may be optionally specified. If a preference is given 295375Smckusic * the following hierarchy is used to allocate a block: 305375Smckusic * 1) allocate the requested block. 315375Smckusic * 2) allocate a rotationally optimal block in the same cylinder. 325375Smckusic * 3) allocate a block in the same cylinder group. 335375Smckusic * 4) quadradically rehash into other cylinder groups, until an 345375Smckusic * available block is located. 355375Smckusic * If no block preference is given the following heirarchy is used 365375Smckusic * to allocate a block: 375375Smckusic * 1) allocate a block in the cylinder group that contains the 385375Smckusic * inode for the file. 395375Smckusic * 2) quadradically rehash into other cylinder groups, until an 405375Smckusic * available block is located. 415375Smckusic */ 424359Smckusick struct buf * 435965Smckusic alloc(ip, bpref, size) 444463Smckusic register struct inode *ip; 454359Smckusick daddr_t bpref; 464359Smckusick int size; 474359Smckusick { 484359Smckusick daddr_t bno; 494359Smckusick register struct fs *fs; 504463Smckusic register struct buf *bp; 514359Smckusick int cg; 524359Smckusick 535965Smckusic fs = ip->i_fs; 546716Smckusick if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0) { 556716Smckusick printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n", 566716Smckusick ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt); 574463Smckusic panic("alloc: bad size"); 586716Smckusick } 595322Smckusic if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0) 604359Smckusick goto nospace; 614792Smckusic if (u.u_uid != 0 && 625322Smckusic fs->fs_cstotal.cs_nbfree * fs->fs_frag + fs->fs_cstotal.cs_nffree < 635322Smckusic fs->fs_dsize * fs->fs_minfree / 100) 644792Smckusic goto nospace; 654948Smckusic if (bpref >= fs->fs_size) 664948Smckusic bpref = 0; 674359Smckusick if (bpref == 0) 685377Smckusic cg = itog(fs, ip->i_number); 694359Smckusick else 705377Smckusic cg = dtog(fs, bpref); 715965Smckusic bno = (daddr_t)hashalloc(ip, cg, (long)bpref, size, alloccg); 726567Smckusic if (bno <= 0) 734359Smckusick goto nospace; 745965Smckusic bp = getblk(ip->i_dev, fsbtodb(fs, bno), size); 754359Smckusick clrbuf(bp); 764359Smckusick return (bp); 774359Smckusick nospace: 784359Smckusick fserr(fs, "file system full"); 794359Smckusick uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); 804359Smckusick u.u_error = ENOSPC; 814359Smckusick return (NULL); 824359Smckusick } 834359Smckusick 845375Smckusic /* 855375Smckusic * Reallocate a fragment to a bigger size 865375Smckusic * 875375Smckusic * The number and size of the old block is given, and a preference 885375Smckusic * and new size is also specified. The allocator attempts to extend 895375Smckusic * the original block. Failing that, the regular block allocator is 905375Smckusic * invoked to get an appropriate block. 915375Smckusic */ 924426Smckusic struct buf * 935965Smckusic realloccg(ip, bprev, bpref, osize, nsize) 945965Smckusic register struct inode *ip; 954651Smckusic daddr_t bprev, bpref; 964426Smckusic int osize, nsize; 974426Smckusic { 984426Smckusic daddr_t bno; 994426Smckusic register struct fs *fs; 1004463Smckusic register struct buf *bp, *obp; 1014426Smckusic int cg; 1024426Smckusic 1035965Smckusic fs = ip->i_fs; 1045960Smckusic if ((unsigned)osize > fs->fs_bsize || fragoff(fs, osize) != 0 || 1056716Smckusick (unsigned)nsize > fs->fs_bsize || fragoff(fs, nsize) != 0) { 1066716Smckusick printf("dev = 0x%x, bsize = %d, osize = %d, nsize = %d, fs = %s\n", 1076716Smckusick ip->i_dev, fs->fs_bsize, osize, nsize, fs->fs_fsmnt); 1084463Smckusic panic("realloccg: bad size"); 1096716Smckusick } 1104792Smckusic if (u.u_uid != 0 && 1115322Smckusic fs->fs_cstotal.cs_nbfree * fs->fs_frag + fs->fs_cstotal.cs_nffree < 1125322Smckusic fs->fs_dsize * fs->fs_minfree / 100) 1134792Smckusic goto nospace; 1146716Smckusick if (bprev == 0) { 1156716Smckusick printf("dev = 0x%x, bsize = %d, bprev = %d, fs = %s\n", 1166716Smckusick ip->i_dev, fs->fs_bsize, bprev, fs->fs_fsmnt); 1174463Smckusic panic("realloccg: bad bprev"); 1186716Smckusick } 1196294Smckusick cg = dtog(fs, bprev); 1205965Smckusic bno = fragextend(ip, cg, (long)bprev, osize, nsize); 1214463Smckusic if (bno != 0) { 122*7187Sroot do { 123*7187Sroot bp = bread(ip->i_dev, fsbtodb(fs, bno), osize); 124*7187Sroot if (bp->b_flags & B_ERROR) { 125*7187Sroot brelse(bp); 126*7187Sroot return (NULL); 127*7187Sroot } 128*7187Sroot } while (brealloc(bp, nsize) == 0); 129*7187Sroot bp->b_flags |= B_DONE; 1304463Smckusic blkclr(bp->b_un.b_addr + osize, nsize - osize); 1314463Smckusic return (bp); 1324463Smckusic } 1334948Smckusic if (bpref >= fs->fs_size) 1344948Smckusic bpref = 0; 1355965Smckusic bno = (daddr_t)hashalloc(ip, cg, (long)bpref, nsize, alloccg); 1366567Smckusic if (bno > 0) { 1375965Smckusic obp = bread(ip->i_dev, fsbtodb(fs, bprev), osize); 1385960Smckusic if (obp->b_flags & B_ERROR) { 1395960Smckusic brelse(obp); 1406294Smckusick return (NULL); 1415960Smckusic } 1425965Smckusic bp = getblk(ip->i_dev, fsbtodb(fs, bno), nsize); 1436567Smckusic bcopy(obp->b_un.b_addr, bp->b_un.b_addr, osize); 1446567Smckusic blkclr(bp->b_un.b_addr + osize, nsize - osize); 1454463Smckusic brelse(obp); 1465965Smckusic fre(ip, bprev, (off_t)osize); 1476294Smckusick return (bp); 1484463Smckusic } 1494792Smckusic nospace: 1504463Smckusic /* 1514463Smckusic * no space available 1524463Smckusic */ 1534426Smckusic fserr(fs, "file system full"); 1544426Smckusic uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); 1554426Smckusic u.u_error = ENOSPC; 1564426Smckusic return (NULL); 1574426Smckusic } 1584426Smckusic 1595375Smckusic /* 1605375Smckusic * Allocate an inode in the file system. 1615375Smckusic * 1625375Smckusic * A preference may be optionally specified. If a preference is given 1635375Smckusic * the following hierarchy is used to allocate an inode: 1645375Smckusic * 1) allocate the requested inode. 1655375Smckusic * 2) allocate an inode in the same cylinder group. 1665375Smckusic * 3) quadradically rehash into other cylinder groups, until an 1675375Smckusic * available inode is located. 1685375Smckusic * If no inode preference is given the following heirarchy is used 1695375Smckusic * to allocate an inode: 1705375Smckusic * 1) allocate an inode in cylinder group 0. 1715375Smckusic * 2) quadradically rehash into other cylinder groups, until an 1725375Smckusic * available inode is located. 1735375Smckusic */ 1744359Smckusick struct inode * 1755965Smckusic ialloc(pip, ipref, mode) 1765965Smckusic register struct inode *pip; 1774359Smckusick ino_t ipref; 1784359Smckusick int mode; 1794359Smckusick { 1805212Smckusic ino_t ino; 1814359Smckusick register struct fs *fs; 1824359Smckusick register struct inode *ip; 1834359Smckusick int cg; 1844359Smckusick 1855965Smckusic fs = pip->i_fs; 1864792Smckusic if (fs->fs_cstotal.cs_nifree == 0) 1874359Smckusick goto noinodes; 1884948Smckusic if (ipref >= fs->fs_ncg * fs->fs_ipg) 1894948Smckusic ipref = 0; 1905377Smckusic cg = itog(fs, ipref); 1915965Smckusic ino = (ino_t)hashalloc(pip, cg, (long)ipref, mode, ialloccg); 1924359Smckusick if (ino == 0) 1934359Smckusick goto noinodes; 1945965Smckusic ip = iget(pip->i_dev, pip->i_fs, ino); 1954359Smckusick if (ip == NULL) { 1965965Smckusic ifree(ip, ino, 0); 1974359Smckusick return (NULL); 1984359Smckusick } 1996716Smckusick if (ip->i_mode) { 2006716Smckusick printf("mode = 0%o, inum = %d, fs = %s\n", 2016716Smckusick ip->i_mode, ip->i_number, fs->fs_fsmnt); 2024359Smckusick panic("ialloc: dup alloc"); 2036716Smckusick } 2044359Smckusick return (ip); 2054359Smckusick noinodes: 2064359Smckusick fserr(fs, "out of inodes"); 2076294Smckusick uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt); 2084359Smckusick u.u_error = ENOSPC; 2094359Smckusick return (NULL); 2104359Smckusick } 2114359Smckusick 2124651Smckusic /* 2135375Smckusic * Find a cylinder to place a directory. 2145375Smckusic * 2155375Smckusic * The policy implemented by this algorithm is to select from 2165375Smckusic * among those cylinder groups with above the average number of 2175375Smckusic * free inodes, the one with the smallest number of directories. 2184651Smckusic */ 2195965Smckusic dirpref(fs) 2205965Smckusic register struct fs *fs; 2214359Smckusick { 2224651Smckusic int cg, minndir, mincg, avgifree; 2234359Smckusick 2244792Smckusic avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg; 2254651Smckusic minndir = fs->fs_ipg; 2264359Smckusick mincg = 0; 2274651Smckusic for (cg = 0; cg < fs->fs_ncg; cg++) 2285322Smckusic if (fs->fs_cs(fs, cg).cs_ndir < minndir && 2295322Smckusic fs->fs_cs(fs, cg).cs_nifree >= avgifree) { 2304359Smckusick mincg = cg; 2315322Smckusic minndir = fs->fs_cs(fs, cg).cs_ndir; 2324359Smckusick } 2334359Smckusick return (fs->fs_ipg * mincg); 2344359Smckusick } 2354359Smckusick 2364651Smckusic /* 2375375Smckusic * Select a cylinder to place a large block of data. 2385375Smckusic * 2395375Smckusic * The policy implemented by this algorithm is to maintain a 2405375Smckusic * rotor that sweeps the cylinder groups. When a block is 2415375Smckusic * needed, the rotor is advanced until a cylinder group with 2425375Smckusic * greater than the average number of free blocks is found. 2434651Smckusic */ 2445212Smckusic daddr_t 2455965Smckusic blkpref(fs) 2465965Smckusic register struct fs *fs; 2474651Smckusic { 2484651Smckusic int cg, avgbfree; 2494651Smckusic 2504792Smckusic avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; 2514651Smckusic for (cg = fs->fs_cgrotor + 1; cg < fs->fs_ncg; cg++) 2525322Smckusic if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { 2534651Smckusic fs->fs_cgrotor = cg; 2545322Smckusic return (fs->fs_fpg * cg + fs->fs_frag); 2554651Smckusic } 2564651Smckusic for (cg = 0; cg <= fs->fs_cgrotor; cg++) 2575322Smckusic if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { 2584651Smckusic fs->fs_cgrotor = cg; 2595322Smckusic return (fs->fs_fpg * cg + fs->fs_frag); 2604651Smckusic } 2616294Smckusick return (NULL); 2624651Smckusic } 2634651Smckusic 2645375Smckusic /* 2655375Smckusic * Implement the cylinder overflow algorithm. 2665375Smckusic * 2675375Smckusic * The policy implemented by this algorithm is: 2685375Smckusic * 1) allocate the block in its requested cylinder group. 2695375Smckusic * 2) quadradically rehash on the cylinder group number. 2705375Smckusic * 3) brute force search for a free block. 2715375Smckusic */ 2725212Smckusic /*VARARGS5*/ 2735212Smckusic u_long 2745965Smckusic hashalloc(ip, cg, pref, size, allocator) 2755965Smckusic struct inode *ip; 2764359Smckusick int cg; 2774359Smckusick long pref; 2784359Smckusick int size; /* size for data blocks, mode for inodes */ 2795212Smckusic u_long (*allocator)(); 2804359Smckusick { 2815965Smckusic register struct fs *fs; 2824359Smckusick long result; 2834359Smckusick int i, icg = cg; 2844359Smckusick 2855965Smckusic fs = ip->i_fs; 2864359Smckusick /* 2874359Smckusick * 1: preferred cylinder group 2884359Smckusick */ 2895965Smckusic result = (*allocator)(ip, cg, pref, size); 2904359Smckusick if (result) 2914359Smckusick return (result); 2924359Smckusick /* 2934359Smckusick * 2: quadratic rehash 2944359Smckusick */ 2954359Smckusick for (i = 1; i < fs->fs_ncg; i *= 2) { 2964359Smckusick cg += i; 2974359Smckusick if (cg >= fs->fs_ncg) 2984359Smckusick cg -= fs->fs_ncg; 2995965Smckusic result = (*allocator)(ip, cg, 0, size); 3004359Smckusick if (result) 3014359Smckusick return (result); 3024359Smckusick } 3034359Smckusick /* 3044359Smckusick * 3: brute force search 3054359Smckusick */ 3064359Smckusick cg = icg; 3074359Smckusick for (i = 0; i < fs->fs_ncg; i++) { 3085965Smckusic result = (*allocator)(ip, cg, 0, size); 3094359Smckusick if (result) 3104359Smckusick return (result); 3114359Smckusick cg++; 3124359Smckusick if (cg == fs->fs_ncg) 3134359Smckusick cg = 0; 3144359Smckusick } 3156294Smckusick return (NULL); 3164359Smckusick } 3174359Smckusick 3185375Smckusic /* 3195375Smckusic * Determine whether a fragment can be extended. 3205375Smckusic * 3215375Smckusic * Check to see if the necessary fragments are available, and 3225375Smckusic * if they are, allocate them. 3235375Smckusic */ 3244359Smckusick daddr_t 3255965Smckusic fragextend(ip, cg, bprev, osize, nsize) 3265965Smckusic struct inode *ip; 3274426Smckusic int cg; 3284463Smckusic long bprev; 3294426Smckusic int osize, nsize; 3304426Smckusic { 3315965Smckusic register struct fs *fs; 3324463Smckusic register struct buf *bp; 3334463Smckusic register struct cg *cgp; 3344463Smckusic long bno; 3354463Smckusic int frags, bbase; 3364426Smckusic int i; 3374426Smckusic 3385965Smckusic fs = ip->i_fs; 3396531Smckusick if (fs->fs_cs(fs, cg).cs_nffree < nsize - osize) 3406531Smckusick return (NULL); 3415960Smckusic frags = numfrags(fs, nsize); 3425960Smckusic bbase = fragoff(fs, bprev); 3435322Smckusic if (bbase > (bprev + frags - 1) % fs->fs_frag) { 3444463Smckusic /* cannot extend across a block boundry */ 3456294Smckusick return (NULL); 3464463Smckusic } 3475965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 3486531Smckusick cgp = bp->b_un.b_cg; 3496531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 3505960Smckusic brelse(bp); 3516294Smckusick return (NULL); 3525960Smckusic } 3537116Smckusick cgp->cg_time = time; 3545377Smckusic bno = dtogd(fs, bprev); 3555960Smckusic for (i = numfrags(fs, osize); i < frags; i++) 3565361Smckusic if (isclr(cgp->cg_free, bno + i)) { 3575361Smckusic brelse(bp); 3586294Smckusick return (NULL); 3595361Smckusic } 3605361Smckusic /* 3615361Smckusic * the current fragment can be extended 3625361Smckusic * deduct the count on fragment being extended into 3635361Smckusic * increase the count on the remaining fragment (if any) 3645361Smckusic * allocate the extended piece 3655361Smckusic */ 3665361Smckusic for (i = frags; i < fs->fs_frag - bbase; i++) 3674463Smckusic if (isclr(cgp->cg_free, bno + i)) 3684463Smckusic break; 3695960Smckusic cgp->cg_frsum[i - numfrags(fs, osize)]--; 3705361Smckusic if (i != frags) 3715361Smckusic cgp->cg_frsum[i - frags]++; 3725960Smckusic for (i = numfrags(fs, osize); i < frags; i++) { 3735361Smckusic clrbit(cgp->cg_free, bno + i); 3745361Smckusic cgp->cg_cs.cs_nffree--; 3755361Smckusic fs->fs_cstotal.cs_nffree--; 3765361Smckusic fs->fs_cs(fs, cg).cs_nffree--; 3774463Smckusic } 3785361Smckusic fs->fs_fmod++; 3795361Smckusic bdwrite(bp); 3805361Smckusic return (bprev); 3814426Smckusic } 3824426Smckusic 3835375Smckusic /* 3845375Smckusic * Determine whether a block can be allocated. 3855375Smckusic * 3865375Smckusic * Check to see if a block of the apprpriate size is available, 3875375Smckusic * and if it is, allocate it. 3885375Smckusic */ 3894426Smckusic daddr_t 3905965Smckusic alloccg(ip, cg, bpref, size) 3915965Smckusic struct inode *ip; 3924359Smckusick int cg; 3934359Smckusick daddr_t bpref; 3944359Smckusick int size; 3954359Smckusick { 3965965Smckusic register struct fs *fs; 3974463Smckusic register struct buf *bp; 3984463Smckusic register struct cg *cgp; 3994463Smckusic int bno, frags; 4004463Smckusic int allocsiz; 4014463Smckusic register int i; 4024359Smckusick 4035965Smckusic fs = ip->i_fs; 4045322Smckusic if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize) 4056294Smckusick return (NULL); 4065965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 4076531Smckusick cgp = bp->b_un.b_cg; 4086531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 4095960Smckusic brelse(bp); 4106294Smckusick return (NULL); 4115960Smckusic } 4127116Smckusick cgp->cg_time = time; 4135322Smckusic if (size == fs->fs_bsize) { 4145212Smckusic bno = alloccgblk(fs, cgp, bpref); 4154463Smckusic bdwrite(bp); 4164463Smckusic return (bno); 4174463Smckusic } 4184463Smckusic /* 4194463Smckusic * check to see if any fragments are already available 4204463Smckusic * allocsiz is the size which will be allocated, hacking 4214463Smckusic * it down to a smaller size if necessary 4224463Smckusic */ 4235960Smckusic frags = numfrags(fs, size); 4245322Smckusic for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++) 4254463Smckusic if (cgp->cg_frsum[allocsiz] != 0) 4264463Smckusic break; 4275322Smckusic if (allocsiz == fs->fs_frag) { 4284463Smckusic /* 4294463Smckusic * no fragments were available, so a block will be 4304463Smckusic * allocated, and hacked up 4314463Smckusic */ 4324792Smckusic if (cgp->cg_cs.cs_nbfree == 0) { 4334463Smckusic brelse(bp); 4346294Smckusick return (NULL); 4354463Smckusic } 4365212Smckusic bno = alloccgblk(fs, cgp, bpref); 4375377Smckusic bpref = dtogd(fs, bno); 4385322Smckusic for (i = frags; i < fs->fs_frag; i++) 4394463Smckusic setbit(cgp->cg_free, bpref + i); 4405322Smckusic i = fs->fs_frag - frags; 4414792Smckusic cgp->cg_cs.cs_nffree += i; 4424792Smckusic fs->fs_cstotal.cs_nffree += i; 4435322Smckusic fs->fs_cs(fs, cg).cs_nffree += i; 4444463Smckusic cgp->cg_frsum[i]++; 4454463Smckusic bdwrite(bp); 4464463Smckusic return (bno); 4474463Smckusic } 4484651Smckusic bno = mapsearch(fs, cgp, bpref, allocsiz); 4496567Smckusic if (bno < 0) 4506294Smckusick return (NULL); 4514463Smckusic for (i = 0; i < frags; i++) 4524463Smckusic clrbit(cgp->cg_free, bno + i); 4534792Smckusic cgp->cg_cs.cs_nffree -= frags; 4544792Smckusic fs->fs_cstotal.cs_nffree -= frags; 4555322Smckusic fs->fs_cs(fs, cg).cs_nffree -= frags; 4564463Smckusic cgp->cg_frsum[allocsiz]--; 4574463Smckusic if (frags != allocsiz) 4584463Smckusic cgp->cg_frsum[allocsiz - frags]++; 4594463Smckusic bdwrite(bp); 4604463Smckusic return (cg * fs->fs_fpg + bno); 4614463Smckusic } 4624463Smckusic 4635375Smckusic /* 4645375Smckusic * Allocate a block in a cylinder group. 4655375Smckusic * 4665375Smckusic * This algorithm implements the following policy: 4675375Smckusic * 1) allocate the requested block. 4685375Smckusic * 2) allocate a rotationally optimal block in the same cylinder. 4695375Smckusic * 3) allocate the next available block on the block rotor for the 4705375Smckusic * specified cylinder group. 4715375Smckusic * Note that this routine only allocates fs_bsize blocks; these 4725375Smckusic * blocks may be fragmented by the routine that allocates them. 4735375Smckusic */ 4744463Smckusic daddr_t 4755212Smckusic alloccgblk(fs, cgp, bpref) 4765965Smckusic register struct fs *fs; 4774463Smckusic register struct cg *cgp; 4784463Smckusic daddr_t bpref; 4794463Smckusic { 4804651Smckusic daddr_t bno; 4816294Smckusick int cylno, pos, delta; 4824651Smckusic short *cylbp; 4835361Smckusic register int i; 4844463Smckusic 4854651Smckusic if (bpref == 0) { 4864651Smckusic bpref = cgp->cg_rotor; 4875361Smckusic goto norot; 4885361Smckusic } 4895361Smckusic bpref &= ~(fs->fs_frag - 1); 4905377Smckusic bpref = dtogd(fs, bpref); 4915361Smckusic /* 4925361Smckusic * if the requested block is available, use it 4935361Smckusic */ 494*7187Sroot /* 495*7187Sroot * disallow sequential layout. 496*7187Sroot * 4975361Smckusic if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) { 4985361Smckusic bno = bpref; 4995361Smckusic goto gotit; 5005361Smckusic } 501*7187Sroot */ 5025361Smckusic /* 5035361Smckusic * check for a block available on the same cylinder 5045361Smckusic */ 5055361Smckusic cylno = cbtocylno(fs, bpref); 5065375Smckusic if (cgp->cg_btot[cylno] == 0) 5075375Smckusic goto norot; 5085375Smckusic if (fs->fs_cpc == 0) { 5095375Smckusic /* 5105375Smckusic * block layout info is not available, so just have 5115375Smckusic * to take any block in this cylinder. 5125375Smckusic */ 5135375Smckusic bpref = howmany(fs->fs_spc * cylno, NSPF(fs)); 5145375Smckusic goto norot; 5155375Smckusic } 5165375Smckusic /* 5175375Smckusic * find a block that is rotationally optimal 5185375Smckusic */ 5195361Smckusic cylbp = cgp->cg_b[cylno]; 5205361Smckusic if (fs->fs_rotdelay == 0) { 5215361Smckusic pos = cbtorpos(fs, bpref); 5224651Smckusic } else { 5234651Smckusic /* 5245361Smckusic * here we convert ms of delay to frags as: 5255361Smckusic * (frags) = (ms) * (rev/sec) * (sect/rev) / 5265361Smckusic * ((sect/frag) * (ms/sec)) 5275361Smckusic * then round up to the next rotational position 5284651Smckusic */ 5295361Smckusic bpref += fs->fs_rotdelay * fs->fs_rps * fs->fs_nsect / 5305361Smckusic (NSPF(fs) * 1000); 5315361Smckusic pos = cbtorpos(fs, bpref); 5325361Smckusic pos = (pos + 1) % NRPOS; 5335361Smckusic } 5345361Smckusic /* 5355361Smckusic * check the summary information to see if a block is 5365361Smckusic * available in the requested cylinder starting at the 5375361Smckusic * optimal rotational position and proceeding around. 5385361Smckusic */ 5395361Smckusic for (i = pos; i < NRPOS; i++) 5405361Smckusic if (cylbp[i] > 0) 5415361Smckusic break; 5425361Smckusic if (i == NRPOS) 5435361Smckusic for (i = 0; i < pos; i++) 5445361Smckusic if (cylbp[i] > 0) 5455361Smckusic break; 5465361Smckusic if (cylbp[i] > 0) { 5474651Smckusic /* 5485361Smckusic * found a rotational position, now find the actual 5495361Smckusic * block. A panic if none is actually there. 5504651Smckusic */ 5515361Smckusic pos = cylno % fs->fs_cpc; 5525361Smckusic bno = (cylno - pos) * fs->fs_spc / NSPB(fs); 5536716Smckusick if (fs->fs_postbl[pos][i] == -1) { 5546716Smckusick printf("pos = %d, i = %d, fs = %s\n", 5556716Smckusick pos, i, fs->fs_fsmnt); 5565361Smckusic panic("alloccgblk: cyl groups corrupted"); 5576716Smckusick } 5586294Smckusick for (i = fs->fs_postbl[pos][i];; ) { 5595361Smckusic if (isblock(fs, cgp->cg_free, bno + i)) { 5605361Smckusic bno = (bno + i) * fs->fs_frag; 5615361Smckusic goto gotit; 5625361Smckusic } 5636294Smckusick delta = fs->fs_rotbl[i]; 5646294Smckusick if (delta <= 0 || delta > MAXBPC - i) 5654651Smckusic break; 5666294Smckusick i += delta; 5674651Smckusic } 5686716Smckusick printf("pos = %d, i = %d, fs = %s\n", pos, i, fs->fs_fsmnt); 5695361Smckusic panic("alloccgblk: can't find blk in cyl"); 5704359Smckusick } 5715361Smckusic norot: 5725361Smckusic /* 5735361Smckusic * no blocks in the requested cylinder, so take next 5745361Smckusic * available one in this cylinder group. 5755361Smckusic */ 5765322Smckusic bno = mapsearch(fs, cgp, bpref, fs->fs_frag); 5776567Smckusic if (bno < 0) 5786294Smckusick return (NULL); 5794651Smckusic cgp->cg_rotor = bno; 5804359Smckusick gotit: 5815322Smckusic clrblock(fs, cgp->cg_free, bno/fs->fs_frag); 5824792Smckusic cgp->cg_cs.cs_nbfree--; 5834792Smckusic fs->fs_cstotal.cs_nbfree--; 5845322Smckusic fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--; 5855375Smckusic cylno = cbtocylno(fs, bno); 5865375Smckusic cgp->cg_b[cylno][cbtorpos(fs, bno)]--; 5875375Smckusic cgp->cg_btot[cylno]--; 5884359Smckusick fs->fs_fmod++; 5894651Smckusic return (cgp->cg_cgx * fs->fs_fpg + bno); 5904359Smckusick } 5914359Smckusick 5925375Smckusic /* 5935375Smckusic * Determine whether an inode can be allocated. 5945375Smckusic * 5955375Smckusic * Check to see if an inode is available, and if it is, 5965375Smckusic * allocate it using the following policy: 5975375Smckusic * 1) allocate the requested inode. 5985375Smckusic * 2) allocate the next available inode after the requested 5995375Smckusic * inode in the specified cylinder group. 6005375Smckusic */ 6015212Smckusic ino_t 6025965Smckusic ialloccg(ip, cg, ipref, mode) 6035965Smckusic struct inode *ip; 6044359Smckusick int cg; 6054359Smckusick daddr_t ipref; 6064359Smckusick int mode; 6074359Smckusick { 6085965Smckusic register struct fs *fs; 6094463Smckusic register struct buf *bp; 6104463Smckusic register struct cg *cgp; 6114359Smckusick int i; 6124359Smckusick 6135965Smckusic fs = ip->i_fs; 6145322Smckusic if (fs->fs_cs(fs, cg).cs_nifree == 0) 6156294Smckusick return (NULL); 6165965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 6176531Smckusick cgp = bp->b_un.b_cg; 6186531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 6195960Smckusic brelse(bp); 6206294Smckusick return (NULL); 6215960Smckusic } 6227116Smckusick cgp->cg_time = time; 6234359Smckusick if (ipref) { 6244359Smckusick ipref %= fs->fs_ipg; 6254359Smckusick if (isclr(cgp->cg_iused, ipref)) 6264359Smckusick goto gotit; 6274359Smckusick } else 6284359Smckusick ipref = cgp->cg_irotor; 6294359Smckusick for (i = 0; i < fs->fs_ipg; i++) { 6304359Smckusick ipref++; 6314359Smckusick if (ipref >= fs->fs_ipg) 6324359Smckusick ipref = 0; 6334359Smckusick if (isclr(cgp->cg_iused, ipref)) { 6344359Smckusick cgp->cg_irotor = ipref; 6354359Smckusick goto gotit; 6364359Smckusick } 6374359Smckusick } 6384359Smckusick brelse(bp); 6396294Smckusick return (NULL); 6404359Smckusick gotit: 6414359Smckusick setbit(cgp->cg_iused, ipref); 6424792Smckusic cgp->cg_cs.cs_nifree--; 6434792Smckusic fs->fs_cstotal.cs_nifree--; 6445322Smckusic fs->fs_cs(fs, cg).cs_nifree--; 6454359Smckusick fs->fs_fmod++; 6464359Smckusick if ((mode & IFMT) == IFDIR) { 6474792Smckusic cgp->cg_cs.cs_ndir++; 6484792Smckusic fs->fs_cstotal.cs_ndir++; 6495322Smckusic fs->fs_cs(fs, cg).cs_ndir++; 6504359Smckusick } 6514359Smckusick bdwrite(bp); 6524359Smckusick return (cg * fs->fs_ipg + ipref); 6534359Smckusick } 6544359Smckusick 6555375Smckusic /* 6565375Smckusic * Free a block or fragment. 6575375Smckusic * 6585375Smckusic * The specified block or fragment is placed back in the 6595375Smckusic * free map. If a fragment is deallocated, a possible 6605375Smckusic * block reassembly is checked. 6615375Smckusic */ 6625965Smckusic fre(ip, bno, size) 6635965Smckusic register struct inode *ip; 6644359Smckusick daddr_t bno; 6655212Smckusic off_t size; 6664359Smckusick { 6674359Smckusick register struct fs *fs; 6684359Smckusick register struct cg *cgp; 6694359Smckusick register struct buf *bp; 6704463Smckusic int cg, blk, frags, bbase; 6714463Smckusic register int i; 6724359Smckusick 6735965Smckusic fs = ip->i_fs; 6746716Smckusick if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0) { 6756716Smckusick printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n", 6766716Smckusick ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt); 6774426Smckusic panic("free: bad size"); 6786716Smckusick } 6795377Smckusic cg = dtog(fs, bno); 6806567Smckusic if (badblock(fs, bno)) { 6816567Smckusic printf("bad block %d, ino %d\n", bno, ip->i_number); 6824359Smckusick return; 6836567Smckusic } 6845965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 6856531Smckusick cgp = bp->b_un.b_cg; 6866531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 6875960Smckusic brelse(bp); 6884359Smckusick return; 6895960Smckusic } 6907116Smckusick cgp->cg_time = time; 6915377Smckusic bno = dtogd(fs, bno); 6925322Smckusic if (size == fs->fs_bsize) { 6936567Smckusic if (isblock(fs, cgp->cg_free, bno/fs->fs_frag)) { 6946716Smckusick printf("dev = 0x%x, block = %d, fs = %s\n", 6956716Smckusick ip->i_dev, bno, fs->fs_fsmnt); 6964426Smckusic panic("free: freeing free block"); 6976567Smckusic } 6985322Smckusic setblock(fs, cgp->cg_free, bno/fs->fs_frag); 6994792Smckusic cgp->cg_cs.cs_nbfree++; 7004792Smckusic fs->fs_cstotal.cs_nbfree++; 7015322Smckusic fs->fs_cs(fs, cg).cs_nbfree++; 7025375Smckusic i = cbtocylno(fs, bno); 7035375Smckusic cgp->cg_b[i][cbtorpos(fs, bno)]++; 7045375Smckusic cgp->cg_btot[i]++; 7054426Smckusic } else { 7065322Smckusic bbase = bno - (bno % fs->fs_frag); 7074463Smckusic /* 7084463Smckusic * decrement the counts associated with the old frags 7094463Smckusic */ 7106294Smckusick blk = blkmap(fs, cgp->cg_free, bbase); 7115322Smckusic fragacct(fs, blk, cgp->cg_frsum, -1); 7124463Smckusic /* 7134463Smckusic * deallocate the fragment 7144463Smckusic */ 7155960Smckusic frags = numfrags(fs, size); 7164463Smckusic for (i = 0; i < frags; i++) { 7176716Smckusick if (isset(cgp->cg_free, bno + i)) { 7186716Smckusick printf("dev = 0x%x, block = %d, fs = %s\n", 7196716Smckusick ip->i_dev, bno + i, fs->fs_fsmnt); 7204426Smckusic panic("free: freeing free frag"); 7216716Smckusick } 7224426Smckusic setbit(cgp->cg_free, bno + i); 7234426Smckusic } 7246294Smckusick cgp->cg_cs.cs_nffree += i; 7256294Smckusick fs->fs_cstotal.cs_nffree += i; 7266294Smckusick fs->fs_cs(fs, cg).cs_nffree += i; 7274463Smckusic /* 7284463Smckusic * add back in counts associated with the new frags 7294463Smckusic */ 7306294Smckusick blk = blkmap(fs, cgp->cg_free, bbase); 7315322Smckusic fragacct(fs, blk, cgp->cg_frsum, 1); 7324463Smckusic /* 7334463Smckusic * if a complete block has been reassembled, account for it 7344463Smckusic */ 7355322Smckusic if (isblock(fs, cgp->cg_free, bbase / fs->fs_frag)) { 7365322Smckusic cgp->cg_cs.cs_nffree -= fs->fs_frag; 7375322Smckusic fs->fs_cstotal.cs_nffree -= fs->fs_frag; 7385322Smckusic fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; 7394792Smckusic cgp->cg_cs.cs_nbfree++; 7404792Smckusic fs->fs_cstotal.cs_nbfree++; 7415322Smckusic fs->fs_cs(fs, cg).cs_nbfree++; 7425375Smckusic i = cbtocylno(fs, bbase); 7435375Smckusic cgp->cg_b[i][cbtorpos(fs, bbase)]++; 7445375Smckusic cgp->cg_btot[i]++; 7454426Smckusic } 7464426Smckusic } 7474359Smckusick fs->fs_fmod++; 7484359Smckusick bdwrite(bp); 7494359Smckusick } 7504359Smckusick 7515375Smckusic /* 7525375Smckusic * Free an inode. 7535375Smckusic * 7545375Smckusic * The specified inode is placed back in the free map. 7555375Smckusic */ 7565965Smckusic ifree(ip, ino, mode) 7575965Smckusic struct inode *ip; 7584359Smckusick ino_t ino; 7594359Smckusick int mode; 7604359Smckusick { 7614359Smckusick register struct fs *fs; 7624359Smckusick register struct cg *cgp; 7634359Smckusick register struct buf *bp; 7644359Smckusick int cg; 7654359Smckusick 7665965Smckusic fs = ip->i_fs; 7676716Smckusick if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg) { 7686716Smckusick printf("dev = 0x%x, ino = %d, fs = %s\n", 7696716Smckusick ip->i_dev, ino, fs->fs_fsmnt); 7704359Smckusick panic("ifree: range"); 7716716Smckusick } 7725377Smckusic cg = itog(fs, ino); 7735965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 7746531Smckusick cgp = bp->b_un.b_cg; 7756531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 7765960Smckusic brelse(bp); 7774359Smckusick return; 7785960Smckusic } 7797116Smckusick cgp->cg_time = time; 7804359Smckusick ino %= fs->fs_ipg; 7816716Smckusick if (isclr(cgp->cg_iused, ino)) { 7826716Smckusick printf("dev = 0x%x, ino = %d, fs = %s\n", 7836716Smckusick ip->i_dev, ino, fs->fs_fsmnt); 7844359Smckusick panic("ifree: freeing free inode"); 7856716Smckusick } 7864359Smckusick clrbit(cgp->cg_iused, ino); 7874792Smckusic cgp->cg_cs.cs_nifree++; 7884792Smckusic fs->fs_cstotal.cs_nifree++; 7895322Smckusic fs->fs_cs(fs, cg).cs_nifree++; 7904359Smckusick if ((mode & IFMT) == IFDIR) { 7914792Smckusic cgp->cg_cs.cs_ndir--; 7924792Smckusic fs->fs_cstotal.cs_ndir--; 7935322Smckusic fs->fs_cs(fs, cg).cs_ndir--; 7944359Smckusick } 7954359Smckusick fs->fs_fmod++; 7964359Smckusick bdwrite(bp); 7974359Smckusick } 7984359Smckusick 7994463Smckusic /* 8005375Smckusic * Find a block of the specified size in the specified cylinder group. 8015375Smckusic * 8024651Smckusic * It is a panic if a request is made to find a block if none are 8034651Smckusic * available. 8044651Smckusic */ 8054651Smckusic daddr_t 8064651Smckusic mapsearch(fs, cgp, bpref, allocsiz) 8074651Smckusic register struct fs *fs; 8084651Smckusic register struct cg *cgp; 8094651Smckusic daddr_t bpref; 8104651Smckusic int allocsiz; 8114651Smckusic { 8124651Smckusic daddr_t bno; 8134651Smckusic int start, len, loc, i; 8144651Smckusic int blk, field, subfield, pos; 8154651Smckusic 8164651Smckusic /* 8174651Smckusic * find the fragment by searching through the free block 8184651Smckusic * map for an appropriate bit pattern 8194651Smckusic */ 8204651Smckusic if (bpref) 8215377Smckusic start = dtogd(fs, bpref) / NBBY; 8224651Smckusic else 8234651Smckusic start = cgp->cg_frotor / NBBY; 8245398Smckusic len = howmany(fs->fs_fpg, NBBY) - start; 8255322Smckusic loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag], 8266292Smckusick 1 << (allocsiz - 1 + (fs->fs_frag % NBBY))); 8274651Smckusic if (loc == 0) { 8286531Smckusick len = start + 1; 8296531Smckusick start = 0; 8305322Smckusic loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag], 8316292Smckusick 1 << (allocsiz - 1 + (fs->fs_frag % NBBY))); 8324651Smckusic if (loc == 0) { 8336716Smckusick printf("start = %d, len = %d, fs = %s\n", 8346716Smckusick start, len, fs->fs_fsmnt); 8354651Smckusic panic("alloccg: map corrupted"); 8366531Smckusick return (-1); 8374651Smckusic } 8384651Smckusic } 8394651Smckusic bno = (start + len - loc) * NBBY; 8404651Smckusic cgp->cg_frotor = bno; 8414651Smckusic /* 8424651Smckusic * found the byte in the map 8434651Smckusic * sift through the bits to find the selected frag 8444651Smckusic */ 8456294Smckusick for (i = bno + NBBY; bno < i; bno += fs->fs_frag) { 8466294Smckusick blk = blkmap(fs, cgp->cg_free, bno); 8474651Smckusic blk <<= 1; 8484651Smckusic field = around[allocsiz]; 8494651Smckusic subfield = inside[allocsiz]; 8505322Smckusic for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) { 8516294Smckusick if ((blk & field) == subfield) 8526294Smckusick return (bno + pos); 8534651Smckusic field <<= 1; 8544651Smckusic subfield <<= 1; 8554651Smckusic } 8564651Smckusic } 8576716Smckusick printf("bno = %d, fs = %s\n", bno, fs->fs_fsmnt); 8584651Smckusic panic("alloccg: block not in map"); 8596531Smckusick return (-1); 8604651Smckusic } 8614651Smckusic 8624651Smckusic /* 8635375Smckusic * Update the frsum fields to reflect addition or deletion 8645375Smckusic * of some frags. 8654463Smckusic */ 8665322Smckusic fragacct(fs, fragmap, fraglist, cnt) 8675322Smckusic struct fs *fs; 8684472Smckusic int fragmap; 8694792Smckusic long fraglist[]; 8704463Smckusic int cnt; 8714463Smckusic { 8724463Smckusic int inblk; 8734463Smckusic register int field, subfield; 8744463Smckusic register int siz, pos; 8754463Smckusic 8765322Smckusic inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 8774463Smckusic fragmap <<= 1; 8785322Smckusic for (siz = 1; siz < fs->fs_frag; siz++) { 8796292Smckusick if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 8804463Smckusic continue; 8814463Smckusic field = around[siz]; 8824463Smckusic subfield = inside[siz]; 8835322Smckusic for (pos = siz; pos <= fs->fs_frag; pos++) { 8844463Smckusic if ((fragmap & field) == subfield) { 8854463Smckusic fraglist[siz] += cnt; 8864463Smckusic pos += siz; 8874463Smckusic field <<= siz; 8884463Smckusic subfield <<= siz; 8894463Smckusic } 8904463Smckusic field <<= 1; 8914463Smckusic subfield <<= 1; 8924463Smckusic } 8934463Smckusic } 8944463Smckusic } 8954463Smckusic 8965375Smckusic /* 8975375Smckusic * Check that a specified block number is in range. 8985375Smckusic */ 8994359Smckusick badblock(fs, bn) 9004359Smckusick register struct fs *fs; 9014359Smckusick daddr_t bn; 9024359Smckusick { 9034359Smckusick 9046531Smckusick if ((unsigned)bn >= fs->fs_size) { 9056567Smckusic printf("bad block %d, ", bn); 9064359Smckusick fserr(fs, "bad block"); 9074359Smckusick return (1); 9084359Smckusick } 9094359Smckusick return (0); 9104359Smckusick } 9114359Smckusick 9124359Smckusick /* 9135375Smckusic * Getfs maps a device number into a pointer to the incore super block. 9144359Smckusick * 9155375Smckusic * The algorithm is a linear search through the mount table. A 9165375Smckusic * consistency check of the super block magic number is performed. 9175375Smckusic * 9184359Smckusick * panic: no fs -- the device is not mounted. 9194359Smckusick * this "cannot happen" 9204359Smckusick */ 9214359Smckusick struct fs * 9224359Smckusick getfs(dev) 9234359Smckusick dev_t dev; 9244359Smckusick { 9254359Smckusick register struct mount *mp; 9264359Smckusick register struct fs *fs; 9274359Smckusick 9286294Smckusick for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 9296294Smckusick if (mp->m_bufp == NULL || mp->m_dev != dev) 9306294Smckusick continue; 9316294Smckusick fs = mp->m_bufp->b_un.b_fs; 9326716Smckusick if (fs->fs_magic != FS_MAGIC) { 9336716Smckusick printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt); 9346294Smckusick panic("getfs: bad magic"); 9356716Smckusick } 9366294Smckusick return (fs); 9376294Smckusick } 9386716Smckusick printf("dev = 0x%x\n", dev); 9394359Smckusick panic("getfs: no fs"); 9404359Smckusick return (NULL); 9414359Smckusick } 9424359Smckusick 9434359Smckusick /* 9445375Smckusic * Fserr prints the name of a file system with an error diagnostic. 9455375Smckusic * 9465375Smckusic * The form of the error message is: 9474359Smckusick * fs: error message 9484359Smckusick */ 9494359Smckusick fserr(fs, cp) 9504359Smckusick struct fs *fs; 9514359Smckusick char *cp; 9524359Smckusick { 9534359Smckusick 9544359Smckusick printf("%s: %s\n", fs->fs_fsmnt, cp); 9554359Smckusick } 9564359Smckusick 9574359Smckusick /* 9584359Smckusick * Getfsx returns the index in the file system 9594359Smckusick * table of the specified device. The swap device 9604359Smckusick * is also assigned a pseudo-index. The index may 9614359Smckusick * be used as a compressed indication of the location 9624359Smckusick * of a block, recording 9634359Smckusick * <getfsx(dev),blkno> 9644359Smckusick * rather than 9654359Smckusick * <dev, blkno> 9664359Smckusick * provided the information need remain valid only 9674359Smckusick * as long as the file system is mounted. 9684359Smckusick */ 9694359Smckusick getfsx(dev) 9704359Smckusick dev_t dev; 9714359Smckusick { 9724359Smckusick register struct mount *mp; 9734359Smckusick 9744359Smckusick if (dev == swapdev) 9754359Smckusick return (MSWAPX); 9764359Smckusick for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 9774359Smckusick if (mp->m_dev == dev) 9784359Smckusick return (mp - &mount[0]); 9794359Smckusick return (-1); 9804359Smckusick } 9814359Smckusick 9824359Smckusick /* 9834359Smckusick * Update is the internal name of 'sync'. It goes through the disk 9844359Smckusick * queues to initiate sandbagged IO; goes through the inodes to write 9855375Smckusic * modified nodes; and it goes through the mount table to initiate 9865375Smckusic * the writing of the modified super blocks. 9874359Smckusick */ 9886294Smckusick update(flag) 9896294Smckusick int flag; 9904359Smckusick { 9914359Smckusick register struct inode *ip; 9924359Smckusick register struct mount *mp; 9934359Smckusick register struct buf *bp; 9944359Smckusick struct fs *fs; 9954651Smckusic int i, blks; 9964359Smckusick 9974359Smckusick if (updlock) 9984359Smckusick return; 9994359Smckusick updlock++; 10004359Smckusick /* 10014359Smckusick * Write back modified superblocks. 10024359Smckusick * Consistency check that the superblock 10034359Smckusick * of each file system is still in the buffer cache. 10044359Smckusick */ 10056294Smckusick for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 10066294Smckusick if (mp->m_bufp == NULL) 10076294Smckusick continue; 10086294Smckusick fs = mp->m_bufp->b_un.b_fs; 10096294Smckusick if (fs->fs_fmod == 0) 10106294Smckusick continue; 1011*7187Sroot if (fs->fs_ronly != 0) { /* ### */ 10126716Smckusick printf("fs = %s\n", fs->fs_fsmnt); 10136294Smckusick panic("update: rofs mod"); 10146716Smckusick } 10156294Smckusick fs->fs_fmod = 0; 10166310Smckusick fs->fs_time = time; 1017*7187Sroot sbupdate(mp); 10186294Smckusick } 10194359Smckusick /* 10204359Smckusick * Write back each (modified) inode. 10214359Smckusick */ 10226294Smckusick for (ip = inode; ip < inodeNINODE; ip++) { 10236294Smckusick if ((ip->i_flag & ILOCK) != 0 || ip->i_count == 0) 10246294Smckusick continue; 10256294Smckusick ip->i_flag |= ILOCK; 10266294Smckusick ip->i_count++; 10276310Smckusick iupdat(ip, &time, &time, 0); 10286294Smckusick iput(ip); 10296294Smckusick } 10304359Smckusick updlock = 0; 10314359Smckusick /* 10324359Smckusick * Force stale buffer cache information to be flushed, 10334359Smckusick * for all devices. 10344359Smckusick */ 10354359Smckusick bflush(NODEV); 10364359Smckusick } 10375322Smckusic 10385322Smckusic /* 10395375Smckusic * block operations 10405375Smckusic * 10415375Smckusic * check if a block is available 10425322Smckusic */ 10435322Smckusic isblock(fs, cp, h) 10445322Smckusic struct fs *fs; 10455322Smckusic unsigned char *cp; 10465322Smckusic int h; 10475322Smckusic { 10485322Smckusic unsigned char mask; 10495322Smckusic 10505322Smckusic switch (fs->fs_frag) { 10515322Smckusic case 8: 10525322Smckusic return (cp[h] == 0xff); 10535322Smckusic case 4: 10545322Smckusic mask = 0x0f << ((h & 0x1) << 2); 10555322Smckusic return ((cp[h >> 1] & mask) == mask); 10565322Smckusic case 2: 10575322Smckusic mask = 0x03 << ((h & 0x3) << 1); 10585322Smckusic return ((cp[h >> 2] & mask) == mask); 10595322Smckusic case 1: 10605322Smckusic mask = 0x01 << (h & 0x7); 10615322Smckusic return ((cp[h >> 3] & mask) == mask); 10625322Smckusic default: 10636294Smckusick panic("isblock"); 10646294Smckusick return (NULL); 10655322Smckusic } 10665322Smckusic } 10675375Smckusic 10685375Smckusic /* 10695375Smckusic * take a block out of the map 10705375Smckusic */ 10715322Smckusic clrblock(fs, cp, h) 10725322Smckusic struct fs *fs; 10735322Smckusic unsigned char *cp; 10745322Smckusic int h; 10755322Smckusic { 10765322Smckusic switch ((fs)->fs_frag) { 10775322Smckusic case 8: 10785322Smckusic cp[h] = 0; 10795322Smckusic return; 10805322Smckusic case 4: 10815322Smckusic cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 10825322Smckusic return; 10835322Smckusic case 2: 10845322Smckusic cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 10855322Smckusic return; 10865322Smckusic case 1: 10875322Smckusic cp[h >> 3] &= ~(0x01 << (h & 0x7)); 10885322Smckusic return; 10895322Smckusic default: 10906294Smckusick panic("clrblock"); 10915322Smckusic return; 10925322Smckusic } 10935322Smckusic } 10945375Smckusic 10955375Smckusic /* 10965375Smckusic * put a block into the map 10975375Smckusic */ 10985322Smckusic setblock(fs, cp, h) 10995322Smckusic struct fs *fs; 11005322Smckusic unsigned char *cp; 11015322Smckusic int h; 11025322Smckusic { 11035322Smckusic switch (fs->fs_frag) { 11045322Smckusic case 8: 11055322Smckusic cp[h] = 0xff; 11065322Smckusic return; 11075322Smckusic case 4: 11085322Smckusic cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 11095322Smckusic return; 11105322Smckusic case 2: 11115322Smckusic cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 11125322Smckusic return; 11135322Smckusic case 1: 11145322Smckusic cp[h >> 3] |= (0x01 << (h & 0x7)); 11155322Smckusic return; 11165322Smckusic default: 11176294Smckusick panic("setblock"); 11185322Smckusic return; 11195322Smckusic } 11205322Smckusic } 1121