1*6567Smckusic /* lfs_alloc.c 2.4 82/04/19 */ 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" 10*6567Smckusic #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; 545960Smckusic if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0) 554463Smckusic panic("alloc: bad size"); 565322Smckusic if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0) 574359Smckusick goto nospace; 584792Smckusic if (u.u_uid != 0 && 595322Smckusic fs->fs_cstotal.cs_nbfree * fs->fs_frag + fs->fs_cstotal.cs_nffree < 605322Smckusic fs->fs_dsize * fs->fs_minfree / 100) 614792Smckusic goto nospace; 624948Smckusic if (bpref >= fs->fs_size) 634948Smckusic bpref = 0; 644359Smckusick if (bpref == 0) 655377Smckusic cg = itog(fs, ip->i_number); 664359Smckusick else 675377Smckusic cg = dtog(fs, bpref); 685965Smckusic bno = (daddr_t)hashalloc(ip, cg, (long)bpref, size, alloccg); 69*6567Smckusic if (bno <= 0) 704359Smckusick goto nospace; 715965Smckusic bp = getblk(ip->i_dev, fsbtodb(fs, bno), size); 724359Smckusick clrbuf(bp); 734359Smckusick return (bp); 744359Smckusick nospace: 754359Smckusick fserr(fs, "file system full"); 764359Smckusick uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); 774359Smckusick u.u_error = ENOSPC; 784359Smckusick return (NULL); 794359Smckusick } 804359Smckusick 815375Smckusic /* 825375Smckusic * Reallocate a fragment to a bigger size 835375Smckusic * 845375Smckusic * The number and size of the old block is given, and a preference 855375Smckusic * and new size is also specified. The allocator attempts to extend 865375Smckusic * the original block. Failing that, the regular block allocator is 875375Smckusic * invoked to get an appropriate block. 885375Smckusic */ 894426Smckusic struct buf * 905965Smckusic realloccg(ip, bprev, bpref, osize, nsize) 915965Smckusic register struct inode *ip; 924651Smckusic daddr_t bprev, bpref; 934426Smckusic int osize, nsize; 944426Smckusic { 954426Smckusic daddr_t bno; 964426Smckusic register struct fs *fs; 974463Smckusic register struct buf *bp, *obp; 984426Smckusic int cg; 994426Smckusic 1005965Smckusic fs = ip->i_fs; 1015960Smckusic if ((unsigned)osize > fs->fs_bsize || fragoff(fs, osize) != 0 || 1025960Smckusic (unsigned)nsize > fs->fs_bsize || fragoff(fs, nsize) != 0) 1034463Smckusic panic("realloccg: bad size"); 1044792Smckusic if (u.u_uid != 0 && 1055322Smckusic fs->fs_cstotal.cs_nbfree * fs->fs_frag + fs->fs_cstotal.cs_nffree < 1065322Smckusic fs->fs_dsize * fs->fs_minfree / 100) 1074792Smckusic goto nospace; 1086294Smckusick if (bprev == 0) 1094463Smckusic panic("realloccg: bad bprev"); 1106294Smckusick cg = dtog(fs, bprev); 1115965Smckusic bno = fragextend(ip, cg, (long)bprev, osize, nsize); 1124463Smckusic if (bno != 0) { 1135965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, bno), osize); 1145960Smckusic if (bp->b_flags & B_ERROR) { 1155960Smckusic brelse(bp); 1166294Smckusick return (NULL); 1175960Smckusic } 118*6567Smckusic brealloc(bp, nsize); 1194463Smckusic blkclr(bp->b_un.b_addr + osize, nsize - osize); 1204463Smckusic return (bp); 1214463Smckusic } 1224948Smckusic if (bpref >= fs->fs_size) 1234948Smckusic bpref = 0; 1245965Smckusic bno = (daddr_t)hashalloc(ip, cg, (long)bpref, nsize, alloccg); 125*6567Smckusic if (bno > 0) { 1265965Smckusic obp = bread(ip->i_dev, fsbtodb(fs, bprev), osize); 1275960Smckusic if (obp->b_flags & B_ERROR) { 1285960Smckusic brelse(obp); 1296294Smckusick return (NULL); 1305960Smckusic } 1315965Smckusic bp = getblk(ip->i_dev, fsbtodb(fs, bno), nsize); 132*6567Smckusic bcopy(obp->b_un.b_addr, bp->b_un.b_addr, osize); 133*6567Smckusic blkclr(bp->b_un.b_addr + osize, nsize - osize); 1344463Smckusic brelse(obp); 1355965Smckusic fre(ip, bprev, (off_t)osize); 1366294Smckusick return (bp); 1374463Smckusic } 1384792Smckusic nospace: 1394463Smckusic /* 1404463Smckusic * no space available 1414463Smckusic */ 1424426Smckusic fserr(fs, "file system full"); 1434426Smckusic uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); 1444426Smckusic u.u_error = ENOSPC; 1454426Smckusic return (NULL); 1464426Smckusic } 1474426Smckusic 1485375Smckusic /* 1495375Smckusic * Allocate an inode in the file system. 1505375Smckusic * 1515375Smckusic * A preference may be optionally specified. If a preference is given 1525375Smckusic * the following hierarchy is used to allocate an inode: 1535375Smckusic * 1) allocate the requested inode. 1545375Smckusic * 2) allocate an inode in the same cylinder group. 1555375Smckusic * 3) quadradically rehash into other cylinder groups, until an 1565375Smckusic * available inode is located. 1575375Smckusic * If no inode preference is given the following heirarchy is used 1585375Smckusic * to allocate an inode: 1595375Smckusic * 1) allocate an inode in cylinder group 0. 1605375Smckusic * 2) quadradically rehash into other cylinder groups, until an 1615375Smckusic * available inode is located. 1625375Smckusic */ 1634359Smckusick struct inode * 1645965Smckusic ialloc(pip, ipref, mode) 1655965Smckusic register struct inode *pip; 1664359Smckusick ino_t ipref; 1674359Smckusick int mode; 1684359Smckusick { 1695212Smckusic ino_t ino; 1704359Smckusick register struct fs *fs; 1714359Smckusick register struct inode *ip; 1724359Smckusick int cg; 1734359Smckusick 1745965Smckusic fs = pip->i_fs; 1754792Smckusic if (fs->fs_cstotal.cs_nifree == 0) 1764359Smckusick goto noinodes; 1774948Smckusic if (ipref >= fs->fs_ncg * fs->fs_ipg) 1784948Smckusic ipref = 0; 1795377Smckusic cg = itog(fs, ipref); 1805965Smckusic ino = (ino_t)hashalloc(pip, cg, (long)ipref, mode, ialloccg); 1814359Smckusick if (ino == 0) 1824359Smckusick goto noinodes; 1835965Smckusic ip = iget(pip->i_dev, pip->i_fs, ino); 1844359Smckusick if (ip == NULL) { 1855965Smckusic ifree(ip, ino, 0); 1864359Smckusick return (NULL); 1874359Smckusick } 1884359Smckusick if (ip->i_mode) 1894359Smckusick panic("ialloc: dup alloc"); 1904359Smckusick return (ip); 1914359Smckusick noinodes: 1924359Smckusick fserr(fs, "out of inodes"); 1936294Smckusick uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt); 1944359Smckusick u.u_error = ENOSPC; 1954359Smckusick return (NULL); 1964359Smckusick } 1974359Smckusick 1984651Smckusic /* 1995375Smckusic * Find a cylinder to place a directory. 2005375Smckusic * 2015375Smckusic * The policy implemented by this algorithm is to select from 2025375Smckusic * among those cylinder groups with above the average number of 2035375Smckusic * free inodes, the one with the smallest number of directories. 2044651Smckusic */ 2055965Smckusic dirpref(fs) 2065965Smckusic register struct fs *fs; 2074359Smckusick { 2084651Smckusic int cg, minndir, mincg, avgifree; 2094359Smckusick 2104792Smckusic avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg; 2114651Smckusic minndir = fs->fs_ipg; 2124359Smckusick mincg = 0; 2134651Smckusic for (cg = 0; cg < fs->fs_ncg; cg++) 2145322Smckusic if (fs->fs_cs(fs, cg).cs_ndir < minndir && 2155322Smckusic fs->fs_cs(fs, cg).cs_nifree >= avgifree) { 2164359Smckusick mincg = cg; 2175322Smckusic minndir = fs->fs_cs(fs, cg).cs_ndir; 2184359Smckusick } 2194359Smckusick return (fs->fs_ipg * mincg); 2204359Smckusick } 2214359Smckusick 2224651Smckusic /* 2235375Smckusic * Select a cylinder to place a large block of data. 2245375Smckusic * 2255375Smckusic * The policy implemented by this algorithm is to maintain a 2265375Smckusic * rotor that sweeps the cylinder groups. When a block is 2275375Smckusic * needed, the rotor is advanced until a cylinder group with 2285375Smckusic * greater than the average number of free blocks is found. 2294651Smckusic */ 2305212Smckusic daddr_t 2315965Smckusic blkpref(fs) 2325965Smckusic register struct fs *fs; 2334651Smckusic { 2344651Smckusic int cg, avgbfree; 2354651Smckusic 2364792Smckusic avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; 2374651Smckusic for (cg = fs->fs_cgrotor + 1; cg < fs->fs_ncg; cg++) 2385322Smckusic if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { 2394651Smckusic fs->fs_cgrotor = cg; 2405322Smckusic return (fs->fs_fpg * cg + fs->fs_frag); 2414651Smckusic } 2424651Smckusic for (cg = 0; cg <= fs->fs_cgrotor; cg++) 2435322Smckusic if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { 2444651Smckusic fs->fs_cgrotor = cg; 2455322Smckusic return (fs->fs_fpg * cg + fs->fs_frag); 2464651Smckusic } 2476294Smckusick return (NULL); 2484651Smckusic } 2494651Smckusic 2505375Smckusic /* 2515375Smckusic * Implement the cylinder overflow algorithm. 2525375Smckusic * 2535375Smckusic * The policy implemented by this algorithm is: 2545375Smckusic * 1) allocate the block in its requested cylinder group. 2555375Smckusic * 2) quadradically rehash on the cylinder group number. 2565375Smckusic * 3) brute force search for a free block. 2575375Smckusic */ 2585212Smckusic /*VARARGS5*/ 2595212Smckusic u_long 2605965Smckusic hashalloc(ip, cg, pref, size, allocator) 2615965Smckusic struct inode *ip; 2624359Smckusick int cg; 2634359Smckusick long pref; 2644359Smckusick int size; /* size for data blocks, mode for inodes */ 2655212Smckusic u_long (*allocator)(); 2664359Smckusick { 2675965Smckusic register struct fs *fs; 2684359Smckusick long result; 2694359Smckusick int i, icg = cg; 2704359Smckusick 2715965Smckusic fs = ip->i_fs; 2724359Smckusick /* 2734359Smckusick * 1: preferred cylinder group 2744359Smckusick */ 2755965Smckusic result = (*allocator)(ip, cg, pref, size); 2764359Smckusick if (result) 2774359Smckusick return (result); 2784359Smckusick /* 2794359Smckusick * 2: quadratic rehash 2804359Smckusick */ 2814359Smckusick for (i = 1; i < fs->fs_ncg; i *= 2) { 2824359Smckusick cg += i; 2834359Smckusick if (cg >= fs->fs_ncg) 2844359Smckusick cg -= fs->fs_ncg; 2855965Smckusic result = (*allocator)(ip, cg, 0, size); 2864359Smckusick if (result) 2874359Smckusick return (result); 2884359Smckusick } 2894359Smckusick /* 2904359Smckusick * 3: brute force search 2914359Smckusick */ 2924359Smckusick cg = icg; 2934359Smckusick for (i = 0; i < fs->fs_ncg; i++) { 2945965Smckusic result = (*allocator)(ip, cg, 0, size); 2954359Smckusick if (result) 2964359Smckusick return (result); 2974359Smckusick cg++; 2984359Smckusick if (cg == fs->fs_ncg) 2994359Smckusick cg = 0; 3004359Smckusick } 3016294Smckusick return (NULL); 3024359Smckusick } 3034359Smckusick 3045375Smckusic /* 3055375Smckusic * Determine whether a fragment can be extended. 3065375Smckusic * 3075375Smckusic * Check to see if the necessary fragments are available, and 3085375Smckusic * if they are, allocate them. 3095375Smckusic */ 3104359Smckusick daddr_t 3115965Smckusic fragextend(ip, cg, bprev, osize, nsize) 3125965Smckusic struct inode *ip; 3134426Smckusic int cg; 3144463Smckusic long bprev; 3154426Smckusic int osize, nsize; 3164426Smckusic { 3175965Smckusic register struct fs *fs; 3184463Smckusic register struct buf *bp; 3194463Smckusic register struct cg *cgp; 3204463Smckusic long bno; 3214463Smckusic int frags, bbase; 3224426Smckusic int i; 3234426Smckusic 3245965Smckusic fs = ip->i_fs; 3256531Smckusick if (fs->fs_cs(fs, cg).cs_nffree < nsize - osize) 3266531Smckusick return (NULL); 3275960Smckusic frags = numfrags(fs, nsize); 3285960Smckusic bbase = fragoff(fs, bprev); 3295322Smckusic if (bbase > (bprev + frags - 1) % fs->fs_frag) { 3304463Smckusic /* cannot extend across a block boundry */ 3316294Smckusick return (NULL); 3324463Smckusic } 3335965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 3346531Smckusick cgp = bp->b_un.b_cg; 3356531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 3365960Smckusic brelse(bp); 3376294Smckusick return (NULL); 3385960Smckusic } 3395377Smckusic bno = dtogd(fs, bprev); 3405960Smckusic for (i = numfrags(fs, osize); i < frags; i++) 3415361Smckusic if (isclr(cgp->cg_free, bno + i)) { 3425361Smckusic brelse(bp); 3436294Smckusick return (NULL); 3445361Smckusic } 3455361Smckusic /* 3465361Smckusic * the current fragment can be extended 3475361Smckusic * deduct the count on fragment being extended into 3485361Smckusic * increase the count on the remaining fragment (if any) 3495361Smckusic * allocate the extended piece 3505361Smckusic */ 3515361Smckusic for (i = frags; i < fs->fs_frag - bbase; i++) 3524463Smckusic if (isclr(cgp->cg_free, bno + i)) 3534463Smckusic break; 3545960Smckusic cgp->cg_frsum[i - numfrags(fs, osize)]--; 3555361Smckusic if (i != frags) 3565361Smckusic cgp->cg_frsum[i - frags]++; 3575960Smckusic for (i = numfrags(fs, osize); i < frags; i++) { 3585361Smckusic clrbit(cgp->cg_free, bno + i); 3595361Smckusic cgp->cg_cs.cs_nffree--; 3605361Smckusic fs->fs_cstotal.cs_nffree--; 3615361Smckusic fs->fs_cs(fs, cg).cs_nffree--; 3624463Smckusic } 3635361Smckusic fs->fs_fmod++; 3645361Smckusic bdwrite(bp); 3655361Smckusic return (bprev); 3664426Smckusic } 3674426Smckusic 3685375Smckusic /* 3695375Smckusic * Determine whether a block can be allocated. 3705375Smckusic * 3715375Smckusic * Check to see if a block of the apprpriate size is available, 3725375Smckusic * and if it is, allocate it. 3735375Smckusic */ 3744426Smckusic daddr_t 3755965Smckusic alloccg(ip, cg, bpref, size) 3765965Smckusic struct inode *ip; 3774359Smckusick int cg; 3784359Smckusick daddr_t bpref; 3794359Smckusick int size; 3804359Smckusick { 3815965Smckusic register struct fs *fs; 3824463Smckusic register struct buf *bp; 3834463Smckusic register struct cg *cgp; 3844463Smckusic int bno, frags; 3854463Smckusic int allocsiz; 3864463Smckusic register int i; 3874359Smckusick 3885965Smckusic fs = ip->i_fs; 3895322Smckusic if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize) 3906294Smckusick return (NULL); 3915965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 3926531Smckusick cgp = bp->b_un.b_cg; 3936531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 3945960Smckusic brelse(bp); 3956294Smckusick return (NULL); 3965960Smckusic } 3975322Smckusic if (size == fs->fs_bsize) { 3985212Smckusic bno = alloccgblk(fs, cgp, bpref); 3994463Smckusic bdwrite(bp); 4004463Smckusic return (bno); 4014463Smckusic } 4024463Smckusic /* 4034463Smckusic * check to see if any fragments are already available 4044463Smckusic * allocsiz is the size which will be allocated, hacking 4054463Smckusic * it down to a smaller size if necessary 4064463Smckusic */ 4075960Smckusic frags = numfrags(fs, size); 4085322Smckusic for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++) 4094463Smckusic if (cgp->cg_frsum[allocsiz] != 0) 4104463Smckusic break; 4115322Smckusic if (allocsiz == fs->fs_frag) { 4124463Smckusic /* 4134463Smckusic * no fragments were available, so a block will be 4144463Smckusic * allocated, and hacked up 4154463Smckusic */ 4164792Smckusic if (cgp->cg_cs.cs_nbfree == 0) { 4174463Smckusic brelse(bp); 4186294Smckusick return (NULL); 4194463Smckusic } 4205212Smckusic bno = alloccgblk(fs, cgp, bpref); 4215377Smckusic bpref = dtogd(fs, bno); 4225322Smckusic for (i = frags; i < fs->fs_frag; i++) 4234463Smckusic setbit(cgp->cg_free, bpref + i); 4245322Smckusic i = fs->fs_frag - frags; 4254792Smckusic cgp->cg_cs.cs_nffree += i; 4264792Smckusic fs->fs_cstotal.cs_nffree += i; 4275322Smckusic fs->fs_cs(fs, cg).cs_nffree += i; 4284463Smckusic cgp->cg_frsum[i]++; 4294463Smckusic bdwrite(bp); 4304463Smckusic return (bno); 4314463Smckusic } 4324651Smckusic bno = mapsearch(fs, cgp, bpref, allocsiz); 433*6567Smckusic if (bno < 0) 4346294Smckusick return (NULL); 4354463Smckusic for (i = 0; i < frags; i++) 4364463Smckusic clrbit(cgp->cg_free, bno + i); 4374792Smckusic cgp->cg_cs.cs_nffree -= frags; 4384792Smckusic fs->fs_cstotal.cs_nffree -= frags; 4395322Smckusic fs->fs_cs(fs, cg).cs_nffree -= frags; 4404463Smckusic cgp->cg_frsum[allocsiz]--; 4414463Smckusic if (frags != allocsiz) 4424463Smckusic cgp->cg_frsum[allocsiz - frags]++; 4434463Smckusic bdwrite(bp); 4444463Smckusic return (cg * fs->fs_fpg + bno); 4454463Smckusic } 4464463Smckusic 4475375Smckusic /* 4485375Smckusic * Allocate a block in a cylinder group. 4495375Smckusic * 4505375Smckusic * This algorithm implements the following policy: 4515375Smckusic * 1) allocate the requested block. 4525375Smckusic * 2) allocate a rotationally optimal block in the same cylinder. 4535375Smckusic * 3) allocate the next available block on the block rotor for the 4545375Smckusic * specified cylinder group. 4555375Smckusic * Note that this routine only allocates fs_bsize blocks; these 4565375Smckusic * blocks may be fragmented by the routine that allocates them. 4575375Smckusic */ 4584463Smckusic daddr_t 4595212Smckusic alloccgblk(fs, cgp, bpref) 4605965Smckusic register struct fs *fs; 4614463Smckusic register struct cg *cgp; 4624463Smckusic daddr_t bpref; 4634463Smckusic { 4644651Smckusic daddr_t bno; 4656294Smckusick int cylno, pos, delta; 4664651Smckusic short *cylbp; 4675361Smckusic register int i; 4684463Smckusic 4694651Smckusic if (bpref == 0) { 4704651Smckusic bpref = cgp->cg_rotor; 4715361Smckusic goto norot; 4725361Smckusic } 4735361Smckusic bpref &= ~(fs->fs_frag - 1); 4745377Smckusic bpref = dtogd(fs, bpref); 4755361Smckusic /* 4765361Smckusic * if the requested block is available, use it 4775361Smckusic */ 4785361Smckusic if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) { 4795361Smckusic bno = bpref; 4805361Smckusic goto gotit; 4815361Smckusic } 4825361Smckusic /* 4835361Smckusic * check for a block available on the same cylinder 4845361Smckusic */ 4855361Smckusic cylno = cbtocylno(fs, bpref); 4865375Smckusic if (cgp->cg_btot[cylno] == 0) 4875375Smckusic goto norot; 4885375Smckusic if (fs->fs_cpc == 0) { 4895375Smckusic /* 4905375Smckusic * block layout info is not available, so just have 4915375Smckusic * to take any block in this cylinder. 4925375Smckusic */ 4935375Smckusic bpref = howmany(fs->fs_spc * cylno, NSPF(fs)); 4945375Smckusic goto norot; 4955375Smckusic } 4965375Smckusic /* 4975375Smckusic * find a block that is rotationally optimal 4985375Smckusic */ 4995361Smckusic cylbp = cgp->cg_b[cylno]; 5005361Smckusic if (fs->fs_rotdelay == 0) { 5015361Smckusic pos = cbtorpos(fs, bpref); 5024651Smckusic } else { 5034651Smckusic /* 5045361Smckusic * here we convert ms of delay to frags as: 5055361Smckusic * (frags) = (ms) * (rev/sec) * (sect/rev) / 5065361Smckusic * ((sect/frag) * (ms/sec)) 5075361Smckusic * then round up to the next rotational position 5084651Smckusic */ 5095361Smckusic bpref += fs->fs_rotdelay * fs->fs_rps * fs->fs_nsect / 5105361Smckusic (NSPF(fs) * 1000); 5115361Smckusic pos = cbtorpos(fs, bpref); 5125361Smckusic pos = (pos + 1) % NRPOS; 5135361Smckusic } 5145361Smckusic /* 5155361Smckusic * check the summary information to see if a block is 5165361Smckusic * available in the requested cylinder starting at the 5175361Smckusic * optimal rotational position and proceeding around. 5185361Smckusic */ 5195361Smckusic for (i = pos; i < NRPOS; i++) 5205361Smckusic if (cylbp[i] > 0) 5215361Smckusic break; 5225361Smckusic if (i == NRPOS) 5235361Smckusic for (i = 0; i < pos; i++) 5245361Smckusic if (cylbp[i] > 0) 5255361Smckusic break; 5265361Smckusic if (cylbp[i] > 0) { 5274651Smckusic /* 5285361Smckusic * found a rotational position, now find the actual 5295361Smckusic * block. A panic if none is actually there. 5304651Smckusic */ 5315361Smckusic pos = cylno % fs->fs_cpc; 5325361Smckusic bno = (cylno - pos) * fs->fs_spc / NSPB(fs); 5335361Smckusic if (fs->fs_postbl[pos][i] == -1) 5345361Smckusic panic("alloccgblk: cyl groups corrupted"); 5356294Smckusick for (i = fs->fs_postbl[pos][i];; ) { 5365361Smckusic if (isblock(fs, cgp->cg_free, bno + i)) { 5375361Smckusic bno = (bno + i) * fs->fs_frag; 5385361Smckusic goto gotit; 5395361Smckusic } 5406294Smckusick delta = fs->fs_rotbl[i]; 5416294Smckusick if (delta <= 0 || delta > MAXBPC - i) 5424651Smckusic break; 5436294Smckusick i += delta; 5444651Smckusic } 5455361Smckusic panic("alloccgblk: can't find blk in cyl"); 5464359Smckusick } 5475361Smckusic norot: 5485361Smckusic /* 5495361Smckusic * no blocks in the requested cylinder, so take next 5505361Smckusic * available one in this cylinder group. 5515361Smckusic */ 5525322Smckusic bno = mapsearch(fs, cgp, bpref, fs->fs_frag); 553*6567Smckusic if (bno < 0) 5546294Smckusick return (NULL); 5554651Smckusic cgp->cg_rotor = bno; 5564359Smckusick gotit: 5575322Smckusic clrblock(fs, cgp->cg_free, bno/fs->fs_frag); 5584792Smckusic cgp->cg_cs.cs_nbfree--; 5594792Smckusic fs->fs_cstotal.cs_nbfree--; 5605322Smckusic fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--; 5615375Smckusic cylno = cbtocylno(fs, bno); 5625375Smckusic cgp->cg_b[cylno][cbtorpos(fs, bno)]--; 5635375Smckusic cgp->cg_btot[cylno]--; 5644359Smckusick fs->fs_fmod++; 5654651Smckusic return (cgp->cg_cgx * fs->fs_fpg + bno); 5664359Smckusick } 5674359Smckusick 5685375Smckusic /* 5695375Smckusic * Determine whether an inode can be allocated. 5705375Smckusic * 5715375Smckusic * Check to see if an inode is available, and if it is, 5725375Smckusic * allocate it using the following policy: 5735375Smckusic * 1) allocate the requested inode. 5745375Smckusic * 2) allocate the next available inode after the requested 5755375Smckusic * inode in the specified cylinder group. 5765375Smckusic */ 5775212Smckusic ino_t 5785965Smckusic ialloccg(ip, cg, ipref, mode) 5795965Smckusic struct inode *ip; 5804359Smckusick int cg; 5814359Smckusick daddr_t ipref; 5824359Smckusick int mode; 5834359Smckusick { 5845965Smckusic register struct fs *fs; 5854463Smckusic register struct buf *bp; 5864463Smckusic register struct cg *cgp; 5874359Smckusick int i; 5884359Smckusick 5895965Smckusic fs = ip->i_fs; 5905322Smckusic if (fs->fs_cs(fs, cg).cs_nifree == 0) 5916294Smckusick return (NULL); 5925965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 5936531Smckusick cgp = bp->b_un.b_cg; 5946531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 5955960Smckusic brelse(bp); 5966294Smckusick return (NULL); 5975960Smckusic } 5984359Smckusick if (ipref) { 5994359Smckusick ipref %= fs->fs_ipg; 6004359Smckusick if (isclr(cgp->cg_iused, ipref)) 6014359Smckusick goto gotit; 6024359Smckusick } else 6034359Smckusick ipref = cgp->cg_irotor; 6044359Smckusick for (i = 0; i < fs->fs_ipg; i++) { 6054359Smckusick ipref++; 6064359Smckusick if (ipref >= fs->fs_ipg) 6074359Smckusick ipref = 0; 6084359Smckusick if (isclr(cgp->cg_iused, ipref)) { 6094359Smckusick cgp->cg_irotor = ipref; 6104359Smckusick goto gotit; 6114359Smckusick } 6124359Smckusick } 6134359Smckusick brelse(bp); 6146294Smckusick return (NULL); 6154359Smckusick gotit: 6164359Smckusick setbit(cgp->cg_iused, ipref); 6174792Smckusic cgp->cg_cs.cs_nifree--; 6184792Smckusic fs->fs_cstotal.cs_nifree--; 6195322Smckusic fs->fs_cs(fs, cg).cs_nifree--; 6204359Smckusick fs->fs_fmod++; 6214359Smckusick if ((mode & IFMT) == IFDIR) { 6224792Smckusic cgp->cg_cs.cs_ndir++; 6234792Smckusic fs->fs_cstotal.cs_ndir++; 6245322Smckusic fs->fs_cs(fs, cg).cs_ndir++; 6254359Smckusick } 6264359Smckusick bdwrite(bp); 6274359Smckusick return (cg * fs->fs_ipg + ipref); 6284359Smckusick } 6294359Smckusick 6305375Smckusic /* 6315375Smckusic * Free a block or fragment. 6325375Smckusic * 6335375Smckusic * The specified block or fragment is placed back in the 6345375Smckusic * free map. If a fragment is deallocated, a possible 6355375Smckusic * block reassembly is checked. 6365375Smckusic */ 6375965Smckusic fre(ip, bno, size) 6385965Smckusic register struct inode *ip; 6394359Smckusick daddr_t bno; 6405212Smckusic off_t size; 6414359Smckusick { 6424359Smckusick register struct fs *fs; 6434359Smckusick register struct cg *cgp; 6444359Smckusick register struct buf *bp; 6454463Smckusic int cg, blk, frags, bbase; 6464463Smckusic register int i; 6474359Smckusick 6485965Smckusic fs = ip->i_fs; 6495960Smckusic if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0) 6504426Smckusic panic("free: bad size"); 6515377Smckusic cg = dtog(fs, bno); 652*6567Smckusic if (badblock(fs, bno)) { 653*6567Smckusic printf("bad block %d, ino %d\n", bno, ip->i_number); 6544359Smckusick return; 655*6567Smckusic } 6565965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 6576531Smckusick cgp = bp->b_un.b_cg; 6586531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 6595960Smckusic brelse(bp); 6604359Smckusick return; 6615960Smckusic } 6625377Smckusic bno = dtogd(fs, bno); 6635322Smckusic if (size == fs->fs_bsize) { 664*6567Smckusic if (isblock(fs, cgp->cg_free, bno/fs->fs_frag)) { 665*6567Smckusic printf("free block %d, fs %s\n", bno, fs->fs_fsmnt); 6664426Smckusic panic("free: freeing free block"); 667*6567Smckusic } 6685322Smckusic setblock(fs, cgp->cg_free, bno/fs->fs_frag); 6694792Smckusic cgp->cg_cs.cs_nbfree++; 6704792Smckusic fs->fs_cstotal.cs_nbfree++; 6715322Smckusic fs->fs_cs(fs, cg).cs_nbfree++; 6725375Smckusic i = cbtocylno(fs, bno); 6735375Smckusic cgp->cg_b[i][cbtorpos(fs, bno)]++; 6745375Smckusic cgp->cg_btot[i]++; 6754426Smckusic } else { 6765322Smckusic bbase = bno - (bno % fs->fs_frag); 6774463Smckusic /* 6784463Smckusic * decrement the counts associated with the old frags 6794463Smckusic */ 6806294Smckusick blk = blkmap(fs, cgp->cg_free, bbase); 6815322Smckusic fragacct(fs, blk, cgp->cg_frsum, -1); 6824463Smckusic /* 6834463Smckusic * deallocate the fragment 6844463Smckusic */ 6855960Smckusic frags = numfrags(fs, size); 6864463Smckusic for (i = 0; i < frags; i++) { 6874426Smckusic if (isset(cgp->cg_free, bno + i)) 6884426Smckusic panic("free: freeing free frag"); 6894426Smckusic setbit(cgp->cg_free, bno + i); 6904426Smckusic } 6916294Smckusick cgp->cg_cs.cs_nffree += i; 6926294Smckusick fs->fs_cstotal.cs_nffree += i; 6936294Smckusick fs->fs_cs(fs, cg).cs_nffree += i; 6944463Smckusic /* 6954463Smckusic * add back in counts associated with the new frags 6964463Smckusic */ 6976294Smckusick blk = blkmap(fs, cgp->cg_free, bbase); 6985322Smckusic fragacct(fs, blk, cgp->cg_frsum, 1); 6994463Smckusic /* 7004463Smckusic * if a complete block has been reassembled, account for it 7014463Smckusic */ 7025322Smckusic if (isblock(fs, cgp->cg_free, bbase / fs->fs_frag)) { 7035322Smckusic cgp->cg_cs.cs_nffree -= fs->fs_frag; 7045322Smckusic fs->fs_cstotal.cs_nffree -= fs->fs_frag; 7055322Smckusic fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; 7064792Smckusic cgp->cg_cs.cs_nbfree++; 7074792Smckusic fs->fs_cstotal.cs_nbfree++; 7085322Smckusic fs->fs_cs(fs, cg).cs_nbfree++; 7095375Smckusic i = cbtocylno(fs, bbase); 7105375Smckusic cgp->cg_b[i][cbtorpos(fs, bbase)]++; 7115375Smckusic cgp->cg_btot[i]++; 7124426Smckusic } 7134426Smckusic } 7144359Smckusick fs->fs_fmod++; 7154359Smckusick bdwrite(bp); 7164359Smckusick } 7174359Smckusick 7185375Smckusic /* 7195375Smckusic * Free an inode. 7205375Smckusic * 7215375Smckusic * The specified inode is placed back in the free map. 7225375Smckusic */ 7235965Smckusic ifree(ip, ino, mode) 7245965Smckusic struct inode *ip; 7254359Smckusick ino_t ino; 7264359Smckusick int mode; 7274359Smckusick { 7284359Smckusick register struct fs *fs; 7294359Smckusick register struct cg *cgp; 7304359Smckusick register struct buf *bp; 7314359Smckusick int cg; 7324359Smckusick 7335965Smckusic fs = ip->i_fs; 7344359Smckusick if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg) 7354359Smckusick panic("ifree: range"); 7365377Smckusic cg = itog(fs, ino); 7375965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 7386531Smckusick cgp = bp->b_un.b_cg; 7396531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 7405960Smckusic brelse(bp); 7414359Smckusick return; 7425960Smckusic } 7434359Smckusick ino %= fs->fs_ipg; 7444359Smckusick if (isclr(cgp->cg_iused, ino)) 7454359Smckusick panic("ifree: freeing free inode"); 7464359Smckusick clrbit(cgp->cg_iused, ino); 7474792Smckusic cgp->cg_cs.cs_nifree++; 7484792Smckusic fs->fs_cstotal.cs_nifree++; 7495322Smckusic fs->fs_cs(fs, cg).cs_nifree++; 7504359Smckusick if ((mode & IFMT) == IFDIR) { 7514792Smckusic cgp->cg_cs.cs_ndir--; 7524792Smckusic fs->fs_cstotal.cs_ndir--; 7535322Smckusic fs->fs_cs(fs, cg).cs_ndir--; 7544359Smckusick } 7554359Smckusick fs->fs_fmod++; 7564359Smckusick bdwrite(bp); 7574359Smckusick } 7584359Smckusick 7594463Smckusic /* 7605375Smckusic * Find a block of the specified size in the specified cylinder group. 7615375Smckusic * 7624651Smckusic * It is a panic if a request is made to find a block if none are 7634651Smckusic * available. 7644651Smckusic */ 7654651Smckusic daddr_t 7664651Smckusic mapsearch(fs, cgp, bpref, allocsiz) 7674651Smckusic register struct fs *fs; 7684651Smckusic register struct cg *cgp; 7694651Smckusic daddr_t bpref; 7704651Smckusic int allocsiz; 7714651Smckusic { 7724651Smckusic daddr_t bno; 7734651Smckusic int start, len, loc, i; 7744651Smckusic int blk, field, subfield, pos; 7754651Smckusic 7764651Smckusic /* 7774651Smckusic * find the fragment by searching through the free block 7784651Smckusic * map for an appropriate bit pattern 7794651Smckusic */ 7804651Smckusic if (bpref) 7815377Smckusic start = dtogd(fs, bpref) / NBBY; 7824651Smckusic else 7834651Smckusic start = cgp->cg_frotor / NBBY; 7845398Smckusic len = howmany(fs->fs_fpg, NBBY) - start; 7855322Smckusic loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag], 7866292Smckusick 1 << (allocsiz - 1 + (fs->fs_frag % NBBY))); 7874651Smckusic if (loc == 0) { 7886531Smckusick len = start + 1; 7896531Smckusick start = 0; 7905322Smckusic loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag], 7916292Smckusick 1 << (allocsiz - 1 + (fs->fs_frag % NBBY))); 7924651Smckusic if (loc == 0) { 7934651Smckusic panic("alloccg: map corrupted"); 7946531Smckusick return (-1); 7954651Smckusic } 7964651Smckusic } 7974651Smckusic bno = (start + len - loc) * NBBY; 7984651Smckusic cgp->cg_frotor = bno; 7994651Smckusic /* 8004651Smckusic * found the byte in the map 8014651Smckusic * sift through the bits to find the selected frag 8024651Smckusic */ 8036294Smckusick for (i = bno + NBBY; bno < i; bno += fs->fs_frag) { 8046294Smckusick blk = blkmap(fs, cgp->cg_free, bno); 8054651Smckusic blk <<= 1; 8064651Smckusic field = around[allocsiz]; 8074651Smckusic subfield = inside[allocsiz]; 8085322Smckusic for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) { 8096294Smckusick if ((blk & field) == subfield) 8106294Smckusick return (bno + pos); 8114651Smckusic field <<= 1; 8124651Smckusic subfield <<= 1; 8134651Smckusic } 8144651Smckusic } 8154651Smckusic panic("alloccg: block not in map"); 8166531Smckusick return (-1); 8174651Smckusic } 8184651Smckusic 8194651Smckusic /* 8205375Smckusic * Update the frsum fields to reflect addition or deletion 8215375Smckusic * of some frags. 8224463Smckusic */ 8235322Smckusic fragacct(fs, fragmap, fraglist, cnt) 8245322Smckusic struct fs *fs; 8254472Smckusic int fragmap; 8264792Smckusic long fraglist[]; 8274463Smckusic int cnt; 8284463Smckusic { 8294463Smckusic int inblk; 8304463Smckusic register int field, subfield; 8314463Smckusic register int siz, pos; 8324463Smckusic 8335322Smckusic inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 8344463Smckusic fragmap <<= 1; 8355322Smckusic for (siz = 1; siz < fs->fs_frag; siz++) { 8366292Smckusick if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 8374463Smckusic continue; 8384463Smckusic field = around[siz]; 8394463Smckusic subfield = inside[siz]; 8405322Smckusic for (pos = siz; pos <= fs->fs_frag; pos++) { 8414463Smckusic if ((fragmap & field) == subfield) { 8424463Smckusic fraglist[siz] += cnt; 8434463Smckusic pos += siz; 8444463Smckusic field <<= siz; 8454463Smckusic subfield <<= siz; 8464463Smckusic } 8474463Smckusic field <<= 1; 8484463Smckusic subfield <<= 1; 8494463Smckusic } 8504463Smckusic } 8514463Smckusic } 8524463Smckusic 8535375Smckusic /* 8545375Smckusic * Check that a specified block number is in range. 8555375Smckusic */ 8564359Smckusick badblock(fs, bn) 8574359Smckusick register struct fs *fs; 8584359Smckusick daddr_t bn; 8594359Smckusick { 8604359Smckusick 8616531Smckusick if ((unsigned)bn >= fs->fs_size) { 862*6567Smckusic printf("bad block %d, ", bn); 8634359Smckusick fserr(fs, "bad block"); 8644359Smckusick return (1); 8654359Smckusick } 8664359Smckusick return (0); 8674359Smckusick } 8684359Smckusick 8694359Smckusick /* 8705375Smckusic * Getfs maps a device number into a pointer to the incore super block. 8714359Smckusick * 8725375Smckusic * The algorithm is a linear search through the mount table. A 8735375Smckusic * consistency check of the super block magic number is performed. 8745375Smckusic * 8754359Smckusick * panic: no fs -- the device is not mounted. 8764359Smckusick * this "cannot happen" 8774359Smckusick */ 8784359Smckusick struct fs * 8794359Smckusick getfs(dev) 8804359Smckusick dev_t dev; 8814359Smckusick { 8824359Smckusick register struct mount *mp; 8834359Smckusick register struct fs *fs; 8844359Smckusick 8856294Smckusick for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 8866294Smckusick if (mp->m_bufp == NULL || mp->m_dev != dev) 8876294Smckusick continue; 8886294Smckusick fs = mp->m_bufp->b_un.b_fs; 8896294Smckusick if (fs->fs_magic != FS_MAGIC) 8906294Smckusick panic("getfs: bad magic"); 8916294Smckusick return (fs); 8926294Smckusick } 8934359Smckusick panic("getfs: no fs"); 8944359Smckusick return (NULL); 8954359Smckusick } 8964359Smckusick 8974359Smckusick /* 8985375Smckusic * Fserr prints the name of a file system with an error diagnostic. 8995375Smckusic * 9005375Smckusic * The form of the error message is: 9014359Smckusick * fs: error message 9024359Smckusick */ 9034359Smckusick fserr(fs, cp) 9044359Smckusick struct fs *fs; 9054359Smckusick char *cp; 9064359Smckusick { 9074359Smckusick 9084359Smckusick printf("%s: %s\n", fs->fs_fsmnt, cp); 9094359Smckusick } 9104359Smckusick 9114359Smckusick /* 9124359Smckusick * Getfsx returns the index in the file system 9134359Smckusick * table of the specified device. The swap device 9144359Smckusick * is also assigned a pseudo-index. The index may 9154359Smckusick * be used as a compressed indication of the location 9164359Smckusick * of a block, recording 9174359Smckusick * <getfsx(dev),blkno> 9184359Smckusick * rather than 9194359Smckusick * <dev, blkno> 9204359Smckusick * provided the information need remain valid only 9214359Smckusick * as long as the file system is mounted. 9224359Smckusick */ 9234359Smckusick getfsx(dev) 9244359Smckusick dev_t dev; 9254359Smckusick { 9264359Smckusick register struct mount *mp; 9274359Smckusick 9284359Smckusick if (dev == swapdev) 9294359Smckusick return (MSWAPX); 9304359Smckusick for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 9314359Smckusick if (mp->m_dev == dev) 9324359Smckusick return (mp - &mount[0]); 9334359Smckusick return (-1); 9344359Smckusick } 9354359Smckusick 9364359Smckusick /* 9374359Smckusick * Update is the internal name of 'sync'. It goes through the disk 9384359Smckusick * queues to initiate sandbagged IO; goes through the inodes to write 9395375Smckusic * modified nodes; and it goes through the mount table to initiate 9405375Smckusic * the writing of the modified super blocks. 9414359Smckusick */ 9426294Smckusick update(flag) 9436294Smckusick int flag; 9444359Smckusick { 9454359Smckusick register struct inode *ip; 9464359Smckusick register struct mount *mp; 9474359Smckusick register struct buf *bp; 9484359Smckusick struct fs *fs; 9494651Smckusic int i, blks; 9504359Smckusick 9514359Smckusick if (updlock) 9524359Smckusick return; 9534359Smckusick updlock++; 9544359Smckusick /* 9554359Smckusick * Write back modified superblocks. 9564359Smckusick * Consistency check that the superblock 9574359Smckusick * of each file system is still in the buffer cache. 9584359Smckusick */ 9596294Smckusick for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 9606294Smckusick if (mp->m_bufp == NULL) 9616294Smckusick continue; 9626294Smckusick fs = mp->m_bufp->b_un.b_fs; 9636294Smckusick if (fs->fs_fmod == 0) 9646294Smckusick continue; 9656294Smckusick if (fs->fs_ronly != 0) 9666294Smckusick panic("update: rofs mod"); 9676294Smckusick bp = getblk(mp->m_dev, SBLOCK, SBSIZE); 9686531Smckusick if (bp->b_un.b_fs != fs || fs->fs_magic != FS_MAGIC) 9696531Smckusick panic("update: bad b_fs"); 9706294Smckusick fs->fs_fmod = 0; 9716310Smckusick fs->fs_time = time; 9726294Smckusick bwrite(bp); 9736531Smckusick blks = howmany(fs->fs_cssize, fs->fs_fsize); 9746531Smckusick for (i = 0; i < blks; i += fs->fs_frag) { 9756294Smckusick bp = getblk(mp->m_dev, 9766531Smckusick fsbtodb(fs, fs->fs_csaddr + i), 9776531Smckusick blks - i < fs->fs_frag ? 9786531Smckusick (blks - i) * fs->fs_fsize : 9796531Smckusick fs->fs_bsize); 9804359Smckusick bwrite(bp); 9814359Smckusick } 9826294Smckusick } 9834359Smckusick /* 9844359Smckusick * Write back each (modified) inode. 9854359Smckusick */ 9866294Smckusick for (ip = inode; ip < inodeNINODE; ip++) { 9876294Smckusick if ((ip->i_flag & ILOCK) != 0 || ip->i_count == 0) 9886294Smckusick continue; 9896294Smckusick ip->i_flag |= ILOCK; 9906294Smckusick ip->i_count++; 9916310Smckusick iupdat(ip, &time, &time, 0); 9926294Smckusick iput(ip); 9936294Smckusick } 9944359Smckusick updlock = 0; 9954359Smckusick /* 9964359Smckusick * Force stale buffer cache information to be flushed, 9974359Smckusick * for all devices. 9984359Smckusick */ 9994359Smckusick bflush(NODEV); 10004359Smckusick } 10015322Smckusic 10025322Smckusic /* 10035375Smckusic * block operations 10045375Smckusic * 10055375Smckusic * check if a block is available 10065322Smckusic */ 10075322Smckusic isblock(fs, cp, h) 10085322Smckusic struct fs *fs; 10095322Smckusic unsigned char *cp; 10105322Smckusic int h; 10115322Smckusic { 10125322Smckusic unsigned char mask; 10135322Smckusic 10145322Smckusic switch (fs->fs_frag) { 10155322Smckusic case 8: 10165322Smckusic return (cp[h] == 0xff); 10175322Smckusic case 4: 10185322Smckusic mask = 0x0f << ((h & 0x1) << 2); 10195322Smckusic return ((cp[h >> 1] & mask) == mask); 10205322Smckusic case 2: 10215322Smckusic mask = 0x03 << ((h & 0x3) << 1); 10225322Smckusic return ((cp[h >> 2] & mask) == mask); 10235322Smckusic case 1: 10245322Smckusic mask = 0x01 << (h & 0x7); 10255322Smckusic return ((cp[h >> 3] & mask) == mask); 10265322Smckusic default: 10276294Smckusick panic("isblock"); 10286294Smckusick return (NULL); 10295322Smckusic } 10305322Smckusic } 10315375Smckusic 10325375Smckusic /* 10335375Smckusic * take a block out of the map 10345375Smckusic */ 10355322Smckusic clrblock(fs, cp, h) 10365322Smckusic struct fs *fs; 10375322Smckusic unsigned char *cp; 10385322Smckusic int h; 10395322Smckusic { 10405322Smckusic switch ((fs)->fs_frag) { 10415322Smckusic case 8: 10425322Smckusic cp[h] = 0; 10435322Smckusic return; 10445322Smckusic case 4: 10455322Smckusic cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 10465322Smckusic return; 10475322Smckusic case 2: 10485322Smckusic cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 10495322Smckusic return; 10505322Smckusic case 1: 10515322Smckusic cp[h >> 3] &= ~(0x01 << (h & 0x7)); 10525322Smckusic return; 10535322Smckusic default: 10546294Smckusick panic("clrblock"); 10555322Smckusic return; 10565322Smckusic } 10575322Smckusic } 10585375Smckusic 10595375Smckusic /* 10605375Smckusic * put a block into the map 10615375Smckusic */ 10625322Smckusic setblock(fs, cp, h) 10635322Smckusic struct fs *fs; 10645322Smckusic unsigned char *cp; 10655322Smckusic int h; 10665322Smckusic { 10675322Smckusic switch (fs->fs_frag) { 10685322Smckusic case 8: 10695322Smckusic cp[h] = 0xff; 10705322Smckusic return; 10715322Smckusic case 4: 10725322Smckusic cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 10735322Smckusic return; 10745322Smckusic case 2: 10755322Smckusic cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 10765322Smckusic return; 10775322Smckusic case 1: 10785322Smckusic cp[h >> 3] |= (0x01 << (h & 0x7)); 10795322Smckusic return; 10805322Smckusic default: 10816294Smckusick panic("setblock"); 10825322Smckusic return; 10835322Smckusic } 10845322Smckusic } 1085