1*7483Skre /* lfs_alloc.c 2.9 82/07/22 */ 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" 12*7483Skre #include "../h/quota.h" 134359Smckusick 145212Smckusic extern u_long hashalloc(); 155212Smckusic extern ino_t ialloccg(); 164651Smckusic extern daddr_t alloccg(); 174651Smckusic extern daddr_t alloccgblk(); 184651Smckusic extern daddr_t fragextend(); 194651Smckusic extern daddr_t blkpref(); 204651Smckusic extern daddr_t mapsearch(); 214607Smckusic extern int inside[], around[]; 225322Smckusic extern unsigned char *fragtbl[]; 234359Smckusick 245375Smckusic /* 255375Smckusic * Allocate a block in the file system. 265375Smckusic * 275375Smckusic * The size of the requested block is given, which must be some 285375Smckusic * multiple of fs_fsize and <= fs_bsize. 295375Smckusic * A preference may be optionally specified. If a preference is given 305375Smckusic * the following hierarchy is used to allocate a block: 315375Smckusic * 1) allocate the requested block. 325375Smckusic * 2) allocate a rotationally optimal block in the same cylinder. 335375Smckusic * 3) allocate a block in the same cylinder group. 345375Smckusic * 4) quadradically rehash into other cylinder groups, until an 355375Smckusic * available block is located. 365375Smckusic * If no block preference is given the following heirarchy is used 375375Smckusic * to allocate a block: 385375Smckusic * 1) allocate a block in the cylinder group that contains the 395375Smckusic * inode for the file. 405375Smckusic * 2) quadradically rehash into other cylinder groups, until an 415375Smckusic * available block is located. 425375Smckusic */ 434359Smckusick struct buf * 445965Smckusic alloc(ip, bpref, size) 454463Smckusic register struct inode *ip; 464359Smckusick daddr_t bpref; 474359Smckusick int size; 484359Smckusick { 494359Smckusick daddr_t bno; 504359Smckusick register struct fs *fs; 514463Smckusic register struct buf *bp; 524359Smckusick int cg; 534359Smckusick 545965Smckusic fs = ip->i_fs; 556716Smckusick if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0) { 566716Smckusick printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n", 576716Smckusick ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt); 584463Smckusic panic("alloc: bad size"); 596716Smckusick } 605322Smckusic if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0) 614359Smckusick goto nospace; 624792Smckusic if (u.u_uid != 0 && 635322Smckusic fs->fs_cstotal.cs_nbfree * fs->fs_frag + fs->fs_cstotal.cs_nffree < 645322Smckusic fs->fs_dsize * fs->fs_minfree / 100) 654792Smckusic goto nospace; 66*7483Skre #ifdef QUOTA 67*7483Skre if (chkdq(ip, (long)((unsigned)size/DEV_BSIZE), 0)) 68*7483Skre return(NULL); 69*7483Skre #endif 704948Smckusic if (bpref >= fs->fs_size) 714948Smckusic bpref = 0; 724359Smckusick if (bpref == 0) 735377Smckusic cg = itog(fs, ip->i_number); 744359Smckusick else 755377Smckusic cg = dtog(fs, bpref); 765965Smckusic bno = (daddr_t)hashalloc(ip, cg, (long)bpref, size, alloccg); 776567Smckusic if (bno <= 0) 784359Smckusick goto nospace; 795965Smckusic bp = getblk(ip->i_dev, fsbtodb(fs, bno), size); 804359Smckusick clrbuf(bp); 814359Smckusick return (bp); 824359Smckusick nospace: 834359Smckusick fserr(fs, "file system full"); 844359Smckusick uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); 854359Smckusick u.u_error = ENOSPC; 864359Smckusick return (NULL); 874359Smckusick } 884359Smckusick 895375Smckusic /* 905375Smckusic * Reallocate a fragment to a bigger size 915375Smckusic * 925375Smckusic * The number and size of the old block is given, and a preference 935375Smckusic * and new size is also specified. The allocator attempts to extend 945375Smckusic * the original block. Failing that, the regular block allocator is 955375Smckusic * invoked to get an appropriate block. 965375Smckusic */ 974426Smckusic struct buf * 985965Smckusic realloccg(ip, bprev, bpref, osize, nsize) 995965Smckusic register struct inode *ip; 1004651Smckusic daddr_t bprev, bpref; 1014426Smckusic int osize, nsize; 1024426Smckusic { 1034426Smckusic daddr_t bno; 1044426Smckusic register struct fs *fs; 1054463Smckusic register struct buf *bp, *obp; 1064426Smckusic int cg; 1074426Smckusic 1085965Smckusic fs = ip->i_fs; 1095960Smckusic if ((unsigned)osize > fs->fs_bsize || fragoff(fs, osize) != 0 || 1106716Smckusick (unsigned)nsize > fs->fs_bsize || fragoff(fs, nsize) != 0) { 1116716Smckusick printf("dev = 0x%x, bsize = %d, osize = %d, nsize = %d, fs = %s\n", 1126716Smckusick ip->i_dev, fs->fs_bsize, osize, nsize, fs->fs_fsmnt); 1134463Smckusic panic("realloccg: bad size"); 1146716Smckusick } 1154792Smckusic if (u.u_uid != 0 && 1165322Smckusic fs->fs_cstotal.cs_nbfree * fs->fs_frag + fs->fs_cstotal.cs_nffree < 1175322Smckusic fs->fs_dsize * fs->fs_minfree / 100) 1184792Smckusic goto nospace; 1196716Smckusick if (bprev == 0) { 1206716Smckusick printf("dev = 0x%x, bsize = %d, bprev = %d, fs = %s\n", 1216716Smckusick ip->i_dev, fs->fs_bsize, bprev, fs->fs_fsmnt); 1224463Smckusic panic("realloccg: bad bprev"); 1236716Smckusick } 124*7483Skre #ifdef QUOTA 125*7483Skre if (chkdq(ip, (long)((unsigned)(nsize-osize)/DEV_BSIZE), 0)) 126*7483Skre return(NULL); 127*7483Skre #endif 1286294Smckusick cg = dtog(fs, bprev); 1295965Smckusic bno = fragextend(ip, cg, (long)bprev, osize, nsize); 1304463Smckusic if (bno != 0) { 1317187Sroot do { 1327187Sroot bp = bread(ip->i_dev, fsbtodb(fs, bno), osize); 1337187Sroot if (bp->b_flags & B_ERROR) { 1347187Sroot brelse(bp); 1357187Sroot return (NULL); 1367187Sroot } 1377187Sroot } while (brealloc(bp, nsize) == 0); 1387187Sroot bp->b_flags |= B_DONE; 1397437Sroot bzero(bp->b_un.b_addr + osize, nsize - osize); 1404463Smckusic return (bp); 1414463Smckusic } 1424948Smckusic if (bpref >= fs->fs_size) 1434948Smckusic bpref = 0; 1445965Smckusic bno = (daddr_t)hashalloc(ip, cg, (long)bpref, nsize, alloccg); 1456567Smckusic if (bno > 0) { 1465965Smckusic obp = bread(ip->i_dev, fsbtodb(fs, bprev), osize); 1475960Smckusic if (obp->b_flags & B_ERROR) { 1485960Smckusic brelse(obp); 1496294Smckusick return (NULL); 1505960Smckusic } 1515965Smckusic bp = getblk(ip->i_dev, fsbtodb(fs, bno), nsize); 1526567Smckusic bcopy(obp->b_un.b_addr, bp->b_un.b_addr, osize); 1537437Sroot bzero(bp->b_un.b_addr + osize, nsize - osize); 1544463Smckusic brelse(obp); 1555965Smckusic fre(ip, bprev, (off_t)osize); 1566294Smckusick return (bp); 1574463Smckusic } 1584792Smckusic nospace: 1594463Smckusic /* 1604463Smckusic * no space available 1614463Smckusic */ 1624426Smckusic fserr(fs, "file system full"); 1634426Smckusic uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); 1644426Smckusic u.u_error = ENOSPC; 1654426Smckusic return (NULL); 1664426Smckusic } 1674426Smckusic 1685375Smckusic /* 1695375Smckusic * Allocate an inode in the file system. 1705375Smckusic * 1715375Smckusic * A preference may be optionally specified. If a preference is given 1725375Smckusic * the following hierarchy is used to allocate an inode: 1735375Smckusic * 1) allocate the requested inode. 1745375Smckusic * 2) allocate an inode in the same cylinder group. 1755375Smckusic * 3) quadradically rehash into other cylinder groups, until an 1765375Smckusic * available inode is located. 1775375Smckusic * If no inode preference is given the following heirarchy is used 1785375Smckusic * to allocate an inode: 1795375Smckusic * 1) allocate an inode in cylinder group 0. 1805375Smckusic * 2) quadradically rehash into other cylinder groups, until an 1815375Smckusic * available inode is located. 1825375Smckusic */ 1834359Smckusick struct inode * 1845965Smckusic ialloc(pip, ipref, mode) 1855965Smckusic register struct inode *pip; 1864359Smckusick ino_t ipref; 1874359Smckusick int mode; 1884359Smckusick { 1895212Smckusic ino_t ino; 1904359Smckusick register struct fs *fs; 1914359Smckusick register struct inode *ip; 1924359Smckusick int cg; 1934359Smckusick 1945965Smckusic fs = pip->i_fs; 1954792Smckusic if (fs->fs_cstotal.cs_nifree == 0) 1964359Smckusick goto noinodes; 197*7483Skre #ifdef QUOTA 198*7483Skre if (chkiq(pip->i_dev, NULL, u.u_uid, 0)) 199*7483Skre return(NULL); 200*7483Skre #endif 2014948Smckusic if (ipref >= fs->fs_ncg * fs->fs_ipg) 2024948Smckusic ipref = 0; 2035377Smckusic cg = itog(fs, ipref); 2045965Smckusic ino = (ino_t)hashalloc(pip, cg, (long)ipref, mode, ialloccg); 2054359Smckusick if (ino == 0) 2064359Smckusick goto noinodes; 2075965Smckusic ip = iget(pip->i_dev, pip->i_fs, ino); 2084359Smckusick if (ip == NULL) { 2095965Smckusic ifree(ip, ino, 0); 2104359Smckusick return (NULL); 2114359Smckusick } 2126716Smckusick if (ip->i_mode) { 2136716Smckusick printf("mode = 0%o, inum = %d, fs = %s\n", 2146716Smckusick ip->i_mode, ip->i_number, fs->fs_fsmnt); 2154359Smckusick panic("ialloc: dup alloc"); 2166716Smckusick } 2174359Smckusick return (ip); 2184359Smckusick noinodes: 2194359Smckusick fserr(fs, "out of inodes"); 2206294Smckusick uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt); 2214359Smckusick u.u_error = ENOSPC; 2224359Smckusick return (NULL); 2234359Smckusick } 2244359Smckusick 2254651Smckusic /* 2265375Smckusic * Find a cylinder to place a directory. 2275375Smckusic * 2285375Smckusic * The policy implemented by this algorithm is to select from 2295375Smckusic * among those cylinder groups with above the average number of 2305375Smckusic * free inodes, the one with the smallest number of directories. 2314651Smckusic */ 2325965Smckusic dirpref(fs) 2335965Smckusic register struct fs *fs; 2344359Smckusick { 2354651Smckusic int cg, minndir, mincg, avgifree; 2364359Smckusick 2374792Smckusic avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg; 2384651Smckusic minndir = fs->fs_ipg; 2394359Smckusick mincg = 0; 2404651Smckusic for (cg = 0; cg < fs->fs_ncg; cg++) 2415322Smckusic if (fs->fs_cs(fs, cg).cs_ndir < minndir && 2425322Smckusic fs->fs_cs(fs, cg).cs_nifree >= avgifree) { 2434359Smckusick mincg = cg; 2445322Smckusic minndir = fs->fs_cs(fs, cg).cs_ndir; 2454359Smckusick } 2464359Smckusick return (fs->fs_ipg * mincg); 2474359Smckusick } 2484359Smckusick 2494651Smckusic /* 2505375Smckusic * Select a cylinder to place a large block of data. 2515375Smckusic * 2525375Smckusic * The policy implemented by this algorithm is to maintain a 2535375Smckusic * rotor that sweeps the cylinder groups. When a block is 2545375Smckusic * needed, the rotor is advanced until a cylinder group with 2555375Smckusic * greater than the average number of free blocks is found. 2564651Smckusic */ 2575212Smckusic daddr_t 2585965Smckusic blkpref(fs) 2595965Smckusic register struct fs *fs; 2604651Smckusic { 2614651Smckusic int cg, avgbfree; 2624651Smckusic 2634792Smckusic avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; 2644651Smckusic for (cg = fs->fs_cgrotor + 1; cg < fs->fs_ncg; cg++) 2655322Smckusic if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { 2664651Smckusic fs->fs_cgrotor = cg; 2675322Smckusic return (fs->fs_fpg * cg + fs->fs_frag); 2684651Smckusic } 2694651Smckusic for (cg = 0; cg <= fs->fs_cgrotor; cg++) 2705322Smckusic if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { 2714651Smckusic fs->fs_cgrotor = cg; 2725322Smckusic return (fs->fs_fpg * cg + fs->fs_frag); 2734651Smckusic } 2746294Smckusick return (NULL); 2754651Smckusic } 2764651Smckusic 2775375Smckusic /* 2785375Smckusic * Implement the cylinder overflow algorithm. 2795375Smckusic * 2805375Smckusic * The policy implemented by this algorithm is: 2815375Smckusic * 1) allocate the block in its requested cylinder group. 2825375Smckusic * 2) quadradically rehash on the cylinder group number. 2835375Smckusic * 3) brute force search for a free block. 2845375Smckusic */ 2855212Smckusic /*VARARGS5*/ 2865212Smckusic u_long 2875965Smckusic hashalloc(ip, cg, pref, size, allocator) 2885965Smckusic struct inode *ip; 2894359Smckusick int cg; 2904359Smckusick long pref; 2914359Smckusick int size; /* size for data blocks, mode for inodes */ 2925212Smckusic u_long (*allocator)(); 2934359Smckusick { 2945965Smckusic register struct fs *fs; 2954359Smckusick long result; 2964359Smckusick int i, icg = cg; 2974359Smckusick 2985965Smckusic fs = ip->i_fs; 2994359Smckusick /* 3004359Smckusick * 1: preferred cylinder group 3014359Smckusick */ 3025965Smckusic result = (*allocator)(ip, cg, pref, size); 3034359Smckusick if (result) 3044359Smckusick return (result); 3054359Smckusick /* 3064359Smckusick * 2: quadratic rehash 3074359Smckusick */ 3084359Smckusick for (i = 1; i < fs->fs_ncg; i *= 2) { 3094359Smckusick cg += i; 3104359Smckusick if (cg >= fs->fs_ncg) 3114359Smckusick cg -= fs->fs_ncg; 3125965Smckusic result = (*allocator)(ip, cg, 0, size); 3134359Smckusick if (result) 3144359Smckusick return (result); 3154359Smckusick } 3164359Smckusick /* 3174359Smckusick * 3: brute force search 3184359Smckusick */ 3194359Smckusick cg = icg; 3204359Smckusick for (i = 0; i < fs->fs_ncg; i++) { 3215965Smckusic result = (*allocator)(ip, cg, 0, size); 3224359Smckusick if (result) 3234359Smckusick return (result); 3244359Smckusick cg++; 3254359Smckusick if (cg == fs->fs_ncg) 3264359Smckusick cg = 0; 3274359Smckusick } 3286294Smckusick return (NULL); 3294359Smckusick } 3304359Smckusick 3315375Smckusic /* 3325375Smckusic * Determine whether a fragment can be extended. 3335375Smckusic * 3345375Smckusic * Check to see if the necessary fragments are available, and 3355375Smckusic * if they are, allocate them. 3365375Smckusic */ 3374359Smckusick daddr_t 3385965Smckusic fragextend(ip, cg, bprev, osize, nsize) 3395965Smckusic struct inode *ip; 3404426Smckusic int cg; 3414463Smckusic long bprev; 3424426Smckusic int osize, nsize; 3434426Smckusic { 3445965Smckusic register struct fs *fs; 3454463Smckusic register struct buf *bp; 3464463Smckusic register struct cg *cgp; 3474463Smckusic long bno; 3484463Smckusic int frags, bbase; 3494426Smckusic int i; 3504426Smckusic 3515965Smckusic fs = ip->i_fs; 3526531Smckusick if (fs->fs_cs(fs, cg).cs_nffree < nsize - osize) 3536531Smckusick return (NULL); 3545960Smckusic frags = numfrags(fs, nsize); 3555960Smckusic bbase = fragoff(fs, bprev); 3565322Smckusic if (bbase > (bprev + frags - 1) % fs->fs_frag) { 3574463Smckusic /* cannot extend across a block boundry */ 3586294Smckusick return (NULL); 3594463Smckusic } 3605965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 3616531Smckusick cgp = bp->b_un.b_cg; 3626531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 3635960Smckusic brelse(bp); 3646294Smckusick return (NULL); 3655960Smckusic } 3667116Smckusick cgp->cg_time = time; 3675377Smckusic bno = dtogd(fs, bprev); 3685960Smckusic for (i = numfrags(fs, osize); i < frags; i++) 3695361Smckusic if (isclr(cgp->cg_free, bno + i)) { 3705361Smckusic brelse(bp); 3716294Smckusick return (NULL); 3725361Smckusic } 3735361Smckusic /* 3745361Smckusic * the current fragment can be extended 3755361Smckusic * deduct the count on fragment being extended into 3765361Smckusic * increase the count on the remaining fragment (if any) 3775361Smckusic * allocate the extended piece 3785361Smckusic */ 3795361Smckusic for (i = frags; i < fs->fs_frag - bbase; i++) 3804463Smckusic if (isclr(cgp->cg_free, bno + i)) 3814463Smckusic break; 3825960Smckusic cgp->cg_frsum[i - numfrags(fs, osize)]--; 3835361Smckusic if (i != frags) 3845361Smckusic cgp->cg_frsum[i - frags]++; 3855960Smckusic for (i = numfrags(fs, osize); i < frags; i++) { 3865361Smckusic clrbit(cgp->cg_free, bno + i); 3875361Smckusic cgp->cg_cs.cs_nffree--; 3885361Smckusic fs->fs_cstotal.cs_nffree--; 3895361Smckusic fs->fs_cs(fs, cg).cs_nffree--; 3904463Smckusic } 3915361Smckusic fs->fs_fmod++; 3925361Smckusic bdwrite(bp); 3935361Smckusic return (bprev); 3944426Smckusic } 3954426Smckusic 3965375Smckusic /* 3975375Smckusic * Determine whether a block can be allocated. 3985375Smckusic * 3995375Smckusic * Check to see if a block of the apprpriate size is available, 4005375Smckusic * and if it is, allocate it. 4015375Smckusic */ 4024426Smckusic daddr_t 4035965Smckusic alloccg(ip, cg, bpref, size) 4045965Smckusic struct inode *ip; 4054359Smckusick int cg; 4064359Smckusick daddr_t bpref; 4074359Smckusick int size; 4084359Smckusick { 4095965Smckusic register struct fs *fs; 4104463Smckusic register struct buf *bp; 4114463Smckusic register struct cg *cgp; 4124463Smckusic int bno, frags; 4134463Smckusic int allocsiz; 4144463Smckusic register int i; 4154359Smckusick 4165965Smckusic fs = ip->i_fs; 4175322Smckusic if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize) 4186294Smckusick return (NULL); 4195965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 4206531Smckusick cgp = bp->b_un.b_cg; 4216531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 4225960Smckusic brelse(bp); 4236294Smckusick return (NULL); 4245960Smckusic } 4257116Smckusick cgp->cg_time = time; 4265322Smckusic if (size == fs->fs_bsize) { 4275212Smckusic bno = alloccgblk(fs, cgp, bpref); 4284463Smckusic bdwrite(bp); 4294463Smckusic return (bno); 4304463Smckusic } 4314463Smckusic /* 4324463Smckusic * check to see if any fragments are already available 4334463Smckusic * allocsiz is the size which will be allocated, hacking 4344463Smckusic * it down to a smaller size if necessary 4354463Smckusic */ 4365960Smckusic frags = numfrags(fs, size); 4375322Smckusic for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++) 4384463Smckusic if (cgp->cg_frsum[allocsiz] != 0) 4394463Smckusic break; 4405322Smckusic if (allocsiz == fs->fs_frag) { 4414463Smckusic /* 4424463Smckusic * no fragments were available, so a block will be 4434463Smckusic * allocated, and hacked up 4444463Smckusic */ 4454792Smckusic if (cgp->cg_cs.cs_nbfree == 0) { 4464463Smckusic brelse(bp); 4476294Smckusick return (NULL); 4484463Smckusic } 4495212Smckusic bno = alloccgblk(fs, cgp, bpref); 4505377Smckusic bpref = dtogd(fs, bno); 4515322Smckusic for (i = frags; i < fs->fs_frag; i++) 4524463Smckusic setbit(cgp->cg_free, bpref + i); 4535322Smckusic i = fs->fs_frag - frags; 4544792Smckusic cgp->cg_cs.cs_nffree += i; 4554792Smckusic fs->fs_cstotal.cs_nffree += i; 4565322Smckusic fs->fs_cs(fs, cg).cs_nffree += i; 4574463Smckusic cgp->cg_frsum[i]++; 4584463Smckusic bdwrite(bp); 4594463Smckusic return (bno); 4604463Smckusic } 4614651Smckusic bno = mapsearch(fs, cgp, bpref, allocsiz); 4626567Smckusic if (bno < 0) 4636294Smckusick return (NULL); 4644463Smckusic for (i = 0; i < frags; i++) 4654463Smckusic clrbit(cgp->cg_free, bno + i); 4664792Smckusic cgp->cg_cs.cs_nffree -= frags; 4674792Smckusic fs->fs_cstotal.cs_nffree -= frags; 4685322Smckusic fs->fs_cs(fs, cg).cs_nffree -= frags; 4694463Smckusic cgp->cg_frsum[allocsiz]--; 4704463Smckusic if (frags != allocsiz) 4714463Smckusic cgp->cg_frsum[allocsiz - frags]++; 4724463Smckusic bdwrite(bp); 4734463Smckusic return (cg * fs->fs_fpg + bno); 4744463Smckusic } 4754463Smckusic 4765375Smckusic /* 4775375Smckusic * Allocate a block in a cylinder group. 4785375Smckusic * 4795375Smckusic * This algorithm implements the following policy: 4805375Smckusic * 1) allocate the requested block. 4815375Smckusic * 2) allocate a rotationally optimal block in the same cylinder. 4825375Smckusic * 3) allocate the next available block on the block rotor for the 4835375Smckusic * specified cylinder group. 4845375Smckusic * Note that this routine only allocates fs_bsize blocks; these 4855375Smckusic * blocks may be fragmented by the routine that allocates them. 4865375Smckusic */ 4874463Smckusic daddr_t 4885212Smckusic alloccgblk(fs, cgp, bpref) 4895965Smckusic register struct fs *fs; 4904463Smckusic register struct cg *cgp; 4914463Smckusic daddr_t bpref; 4924463Smckusic { 4934651Smckusic daddr_t bno; 4946294Smckusick int cylno, pos, delta; 4954651Smckusic short *cylbp; 4965361Smckusic register int i; 4974463Smckusic 4984651Smckusic if (bpref == 0) { 4994651Smckusic bpref = cgp->cg_rotor; 5005361Smckusic goto norot; 5015361Smckusic } 5025361Smckusic bpref &= ~(fs->fs_frag - 1); 5035377Smckusic bpref = dtogd(fs, bpref); 5045361Smckusic /* 5055361Smckusic * if the requested block is available, use it 5065361Smckusic */ 5077187Sroot /* 5087187Sroot * disallow sequential layout. 5097187Sroot * 5105361Smckusic if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) { 5115361Smckusic bno = bpref; 5125361Smckusic goto gotit; 5135361Smckusic } 5147187Sroot */ 5155361Smckusic /* 5165361Smckusic * check for a block available on the same cylinder 5175361Smckusic */ 5185361Smckusic cylno = cbtocylno(fs, bpref); 5195375Smckusic if (cgp->cg_btot[cylno] == 0) 5205375Smckusic goto norot; 5215375Smckusic if (fs->fs_cpc == 0) { 5225375Smckusic /* 5235375Smckusic * block layout info is not available, so just have 5245375Smckusic * to take any block in this cylinder. 5255375Smckusic */ 5265375Smckusic bpref = howmany(fs->fs_spc * cylno, NSPF(fs)); 5275375Smckusic goto norot; 5285375Smckusic } 5295375Smckusic /* 5305375Smckusic * find a block that is rotationally optimal 5315375Smckusic */ 5325361Smckusic cylbp = cgp->cg_b[cylno]; 5335361Smckusic if (fs->fs_rotdelay == 0) { 5345361Smckusic pos = cbtorpos(fs, bpref); 5354651Smckusic } else { 5364651Smckusic /* 5375361Smckusic * here we convert ms of delay to frags as: 5385361Smckusic * (frags) = (ms) * (rev/sec) * (sect/rev) / 5395361Smckusic * ((sect/frag) * (ms/sec)) 5405361Smckusic * then round up to the next rotational position 5414651Smckusic */ 5425361Smckusic bpref += fs->fs_rotdelay * fs->fs_rps * fs->fs_nsect / 5435361Smckusic (NSPF(fs) * 1000); 5445361Smckusic pos = cbtorpos(fs, bpref); 5455361Smckusic pos = (pos + 1) % NRPOS; 5465361Smckusic } 5475361Smckusic /* 5485361Smckusic * check the summary information to see if a block is 5495361Smckusic * available in the requested cylinder starting at the 5505361Smckusic * optimal rotational position and proceeding around. 5515361Smckusic */ 5525361Smckusic for (i = pos; i < NRPOS; i++) 5535361Smckusic if (cylbp[i] > 0) 5545361Smckusic break; 5555361Smckusic if (i == NRPOS) 5565361Smckusic for (i = 0; i < pos; i++) 5575361Smckusic if (cylbp[i] > 0) 5585361Smckusic break; 5595361Smckusic if (cylbp[i] > 0) { 5604651Smckusic /* 5615361Smckusic * found a rotational position, now find the actual 5625361Smckusic * block. A panic if none is actually there. 5634651Smckusic */ 5645361Smckusic pos = cylno % fs->fs_cpc; 5655361Smckusic bno = (cylno - pos) * fs->fs_spc / NSPB(fs); 5666716Smckusick if (fs->fs_postbl[pos][i] == -1) { 5676716Smckusick printf("pos = %d, i = %d, fs = %s\n", 5686716Smckusick pos, i, fs->fs_fsmnt); 5695361Smckusic panic("alloccgblk: cyl groups corrupted"); 5706716Smckusick } 5716294Smckusick for (i = fs->fs_postbl[pos][i];; ) { 5725361Smckusic if (isblock(fs, cgp->cg_free, bno + i)) { 5735361Smckusic bno = (bno + i) * fs->fs_frag; 5745361Smckusic goto gotit; 5755361Smckusic } 5766294Smckusick delta = fs->fs_rotbl[i]; 5776294Smckusick if (delta <= 0 || delta > MAXBPC - i) 5784651Smckusic break; 5796294Smckusick i += delta; 5804651Smckusic } 5816716Smckusick printf("pos = %d, i = %d, fs = %s\n", pos, i, fs->fs_fsmnt); 5825361Smckusic panic("alloccgblk: can't find blk in cyl"); 5834359Smckusick } 5845361Smckusic norot: 5855361Smckusic /* 5865361Smckusic * no blocks in the requested cylinder, so take next 5875361Smckusic * available one in this cylinder group. 5885361Smckusic */ 5895322Smckusic bno = mapsearch(fs, cgp, bpref, fs->fs_frag); 5906567Smckusic if (bno < 0) 5916294Smckusick return (NULL); 5924651Smckusic cgp->cg_rotor = bno; 5934359Smckusick gotit: 5945322Smckusic clrblock(fs, cgp->cg_free, bno/fs->fs_frag); 5954792Smckusic cgp->cg_cs.cs_nbfree--; 5964792Smckusic fs->fs_cstotal.cs_nbfree--; 5975322Smckusic fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--; 5985375Smckusic cylno = cbtocylno(fs, bno); 5995375Smckusic cgp->cg_b[cylno][cbtorpos(fs, bno)]--; 6005375Smckusic cgp->cg_btot[cylno]--; 6014359Smckusick fs->fs_fmod++; 6024651Smckusic return (cgp->cg_cgx * fs->fs_fpg + bno); 6034359Smckusick } 6044359Smckusick 6055375Smckusic /* 6065375Smckusic * Determine whether an inode can be allocated. 6075375Smckusic * 6085375Smckusic * Check to see if an inode is available, and if it is, 6095375Smckusic * allocate it using the following policy: 6105375Smckusic * 1) allocate the requested inode. 6115375Smckusic * 2) allocate the next available inode after the requested 6125375Smckusic * inode in the specified cylinder group. 6135375Smckusic */ 6145212Smckusic ino_t 6155965Smckusic ialloccg(ip, cg, ipref, mode) 6165965Smckusic struct inode *ip; 6174359Smckusick int cg; 6184359Smckusick daddr_t ipref; 6194359Smckusick int mode; 6204359Smckusick { 6215965Smckusic register struct fs *fs; 6224463Smckusic register struct buf *bp; 6234463Smckusic register struct cg *cgp; 6244359Smckusick int i; 6254359Smckusick 6265965Smckusic fs = ip->i_fs; 6275322Smckusic if (fs->fs_cs(fs, cg).cs_nifree == 0) 6286294Smckusick return (NULL); 6295965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 6306531Smckusick cgp = bp->b_un.b_cg; 6316531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 6325960Smckusic brelse(bp); 6336294Smckusick return (NULL); 6345960Smckusic } 6357116Smckusick cgp->cg_time = time; 6364359Smckusick if (ipref) { 6374359Smckusick ipref %= fs->fs_ipg; 6384359Smckusick if (isclr(cgp->cg_iused, ipref)) 6394359Smckusick goto gotit; 6404359Smckusick } else 6414359Smckusick ipref = cgp->cg_irotor; 6424359Smckusick for (i = 0; i < fs->fs_ipg; i++) { 6434359Smckusick ipref++; 6444359Smckusick if (ipref >= fs->fs_ipg) 6454359Smckusick ipref = 0; 6464359Smckusick if (isclr(cgp->cg_iused, ipref)) { 6474359Smckusick cgp->cg_irotor = ipref; 6484359Smckusick goto gotit; 6494359Smckusick } 6504359Smckusick } 6514359Smckusick brelse(bp); 6526294Smckusick return (NULL); 6534359Smckusick gotit: 6544359Smckusick setbit(cgp->cg_iused, ipref); 6554792Smckusic cgp->cg_cs.cs_nifree--; 6564792Smckusic fs->fs_cstotal.cs_nifree--; 6575322Smckusic fs->fs_cs(fs, cg).cs_nifree--; 6584359Smckusick fs->fs_fmod++; 6594359Smckusick if ((mode & IFMT) == IFDIR) { 6604792Smckusic cgp->cg_cs.cs_ndir++; 6614792Smckusic fs->fs_cstotal.cs_ndir++; 6625322Smckusic fs->fs_cs(fs, cg).cs_ndir++; 6634359Smckusick } 6644359Smckusick bdwrite(bp); 6654359Smckusick return (cg * fs->fs_ipg + ipref); 6664359Smckusick } 6674359Smckusick 6685375Smckusic /* 6695375Smckusic * Free a block or fragment. 6705375Smckusic * 6715375Smckusic * The specified block or fragment is placed back in the 6725375Smckusic * free map. If a fragment is deallocated, a possible 6735375Smckusic * block reassembly is checked. 6745375Smckusic */ 6755965Smckusic fre(ip, bno, size) 6765965Smckusic register struct inode *ip; 6774359Smckusick daddr_t bno; 6785212Smckusic off_t size; 6794359Smckusick { 6804359Smckusick register struct fs *fs; 6814359Smckusick register struct cg *cgp; 6824359Smckusick register struct buf *bp; 6834463Smckusic int cg, blk, frags, bbase; 6844463Smckusic register int i; 6854359Smckusick 6865965Smckusic fs = ip->i_fs; 6876716Smckusick if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0) { 6886716Smckusick printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n", 6896716Smckusick ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt); 6904426Smckusic panic("free: bad size"); 6916716Smckusick } 6925377Smckusic cg = dtog(fs, bno); 6936567Smckusic if (badblock(fs, bno)) { 6946567Smckusic printf("bad block %d, ino %d\n", bno, ip->i_number); 6954359Smckusick return; 6966567Smckusic } 6975965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 6986531Smckusick cgp = bp->b_un.b_cg; 6996531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 7005960Smckusic brelse(bp); 7014359Smckusick return; 7025960Smckusic } 7037116Smckusick cgp->cg_time = time; 7045377Smckusic bno = dtogd(fs, bno); 7055322Smckusic if (size == fs->fs_bsize) { 7066567Smckusic if (isblock(fs, cgp->cg_free, bno/fs->fs_frag)) { 7076716Smckusick printf("dev = 0x%x, block = %d, fs = %s\n", 7086716Smckusick ip->i_dev, bno, fs->fs_fsmnt); 7094426Smckusic panic("free: freeing free block"); 7106567Smckusic } 7115322Smckusic setblock(fs, cgp->cg_free, bno/fs->fs_frag); 7124792Smckusic cgp->cg_cs.cs_nbfree++; 7134792Smckusic fs->fs_cstotal.cs_nbfree++; 7145322Smckusic fs->fs_cs(fs, cg).cs_nbfree++; 7155375Smckusic i = cbtocylno(fs, bno); 7165375Smckusic cgp->cg_b[i][cbtorpos(fs, bno)]++; 7175375Smckusic cgp->cg_btot[i]++; 7184426Smckusic } else { 7195322Smckusic bbase = bno - (bno % fs->fs_frag); 7204463Smckusic /* 7214463Smckusic * decrement the counts associated with the old frags 7224463Smckusic */ 7236294Smckusick blk = blkmap(fs, cgp->cg_free, bbase); 7245322Smckusic fragacct(fs, blk, cgp->cg_frsum, -1); 7254463Smckusic /* 7264463Smckusic * deallocate the fragment 7274463Smckusic */ 7285960Smckusic frags = numfrags(fs, size); 7294463Smckusic for (i = 0; i < frags; i++) { 7306716Smckusick if (isset(cgp->cg_free, bno + i)) { 7316716Smckusick printf("dev = 0x%x, block = %d, fs = %s\n", 7326716Smckusick ip->i_dev, bno + i, fs->fs_fsmnt); 7334426Smckusic panic("free: freeing free frag"); 7346716Smckusick } 7354426Smckusic setbit(cgp->cg_free, bno + i); 7364426Smckusic } 7376294Smckusick cgp->cg_cs.cs_nffree += i; 7386294Smckusick fs->fs_cstotal.cs_nffree += i; 7396294Smckusick fs->fs_cs(fs, cg).cs_nffree += i; 7404463Smckusic /* 7414463Smckusic * add back in counts associated with the new frags 7424463Smckusic */ 7436294Smckusick blk = blkmap(fs, cgp->cg_free, bbase); 7445322Smckusic fragacct(fs, blk, cgp->cg_frsum, 1); 7454463Smckusic /* 7464463Smckusic * if a complete block has been reassembled, account for it 7474463Smckusic */ 7485322Smckusic if (isblock(fs, cgp->cg_free, bbase / fs->fs_frag)) { 7495322Smckusic cgp->cg_cs.cs_nffree -= fs->fs_frag; 7505322Smckusic fs->fs_cstotal.cs_nffree -= fs->fs_frag; 7515322Smckusic fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; 7524792Smckusic cgp->cg_cs.cs_nbfree++; 7534792Smckusic fs->fs_cstotal.cs_nbfree++; 7545322Smckusic fs->fs_cs(fs, cg).cs_nbfree++; 7555375Smckusic i = cbtocylno(fs, bbase); 7565375Smckusic cgp->cg_b[i][cbtorpos(fs, bbase)]++; 7575375Smckusic cgp->cg_btot[i]++; 7584426Smckusic } 7594426Smckusic } 7604359Smckusick fs->fs_fmod++; 7614359Smckusick bdwrite(bp); 7624359Smckusick } 7634359Smckusick 7645375Smckusic /* 7655375Smckusic * Free an inode. 7665375Smckusic * 7675375Smckusic * The specified inode is placed back in the free map. 7685375Smckusic */ 7695965Smckusic ifree(ip, ino, mode) 7705965Smckusic struct inode *ip; 7714359Smckusick ino_t ino; 7724359Smckusick int mode; 7734359Smckusick { 7744359Smckusick register struct fs *fs; 7754359Smckusick register struct cg *cgp; 7764359Smckusick register struct buf *bp; 7774359Smckusick int cg; 7784359Smckusick 7795965Smckusic fs = ip->i_fs; 7806716Smckusick if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg) { 7816716Smckusick printf("dev = 0x%x, ino = %d, fs = %s\n", 7826716Smckusick ip->i_dev, ino, fs->fs_fsmnt); 7834359Smckusick panic("ifree: range"); 7846716Smckusick } 7855377Smckusic cg = itog(fs, ino); 7865965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 7876531Smckusick cgp = bp->b_un.b_cg; 7886531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 7895960Smckusic brelse(bp); 7904359Smckusick return; 7915960Smckusic } 7927116Smckusick cgp->cg_time = time; 7934359Smckusick ino %= fs->fs_ipg; 7946716Smckusick if (isclr(cgp->cg_iused, ino)) { 7956716Smckusick printf("dev = 0x%x, ino = %d, fs = %s\n", 7966716Smckusick ip->i_dev, ino, fs->fs_fsmnt); 7974359Smckusick panic("ifree: freeing free inode"); 7986716Smckusick } 7994359Smckusick clrbit(cgp->cg_iused, ino); 8004792Smckusic cgp->cg_cs.cs_nifree++; 8014792Smckusic fs->fs_cstotal.cs_nifree++; 8025322Smckusic fs->fs_cs(fs, cg).cs_nifree++; 8034359Smckusick if ((mode & IFMT) == IFDIR) { 8044792Smckusic cgp->cg_cs.cs_ndir--; 8054792Smckusic fs->fs_cstotal.cs_ndir--; 8065322Smckusic fs->fs_cs(fs, cg).cs_ndir--; 8074359Smckusick } 8084359Smckusick fs->fs_fmod++; 8094359Smckusick bdwrite(bp); 8104359Smckusick } 8114359Smckusick 8124463Smckusic /* 8135375Smckusic * Find a block of the specified size in the specified cylinder group. 8145375Smckusic * 8154651Smckusic * It is a panic if a request is made to find a block if none are 8164651Smckusic * available. 8174651Smckusic */ 8184651Smckusic daddr_t 8194651Smckusic mapsearch(fs, cgp, bpref, allocsiz) 8204651Smckusic register struct fs *fs; 8214651Smckusic register struct cg *cgp; 8224651Smckusic daddr_t bpref; 8234651Smckusic int allocsiz; 8244651Smckusic { 8254651Smckusic daddr_t bno; 8264651Smckusic int start, len, loc, i; 8274651Smckusic int blk, field, subfield, pos; 8284651Smckusic 8294651Smckusic /* 8304651Smckusic * find the fragment by searching through the free block 8314651Smckusic * map for an appropriate bit pattern 8324651Smckusic */ 8334651Smckusic if (bpref) 8345377Smckusic start = dtogd(fs, bpref) / NBBY; 8354651Smckusic else 8364651Smckusic start = cgp->cg_frotor / NBBY; 8375398Smckusic len = howmany(fs->fs_fpg, NBBY) - start; 8385322Smckusic loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag], 8396292Smckusick 1 << (allocsiz - 1 + (fs->fs_frag % NBBY))); 8404651Smckusic if (loc == 0) { 8416531Smckusick len = start + 1; 8426531Smckusick start = 0; 8435322Smckusic loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag], 8446292Smckusick 1 << (allocsiz - 1 + (fs->fs_frag % NBBY))); 8454651Smckusic if (loc == 0) { 8466716Smckusick printf("start = %d, len = %d, fs = %s\n", 8476716Smckusick start, len, fs->fs_fsmnt); 8484651Smckusic panic("alloccg: map corrupted"); 8496531Smckusick return (-1); 8504651Smckusic } 8514651Smckusic } 8524651Smckusic bno = (start + len - loc) * NBBY; 8534651Smckusic cgp->cg_frotor = bno; 8544651Smckusic /* 8554651Smckusic * found the byte in the map 8564651Smckusic * sift through the bits to find the selected frag 8574651Smckusic */ 8586294Smckusick for (i = bno + NBBY; bno < i; bno += fs->fs_frag) { 8596294Smckusick blk = blkmap(fs, cgp->cg_free, bno); 8604651Smckusic blk <<= 1; 8614651Smckusic field = around[allocsiz]; 8624651Smckusic subfield = inside[allocsiz]; 8635322Smckusic for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) { 8646294Smckusick if ((blk & field) == subfield) 8656294Smckusick return (bno + pos); 8664651Smckusic field <<= 1; 8674651Smckusic subfield <<= 1; 8684651Smckusic } 8694651Smckusic } 8706716Smckusick printf("bno = %d, fs = %s\n", bno, fs->fs_fsmnt); 8714651Smckusic panic("alloccg: block not in map"); 8726531Smckusick return (-1); 8734651Smckusic } 8744651Smckusic 8754651Smckusic /* 8765375Smckusic * Update the frsum fields to reflect addition or deletion 8775375Smckusic * of some frags. 8784463Smckusic */ 8795322Smckusic fragacct(fs, fragmap, fraglist, cnt) 8805322Smckusic struct fs *fs; 8814472Smckusic int fragmap; 8824792Smckusic long fraglist[]; 8834463Smckusic int cnt; 8844463Smckusic { 8854463Smckusic int inblk; 8864463Smckusic register int field, subfield; 8874463Smckusic register int siz, pos; 8884463Smckusic 8895322Smckusic inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 8904463Smckusic fragmap <<= 1; 8915322Smckusic for (siz = 1; siz < fs->fs_frag; siz++) { 8926292Smckusick if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 8934463Smckusic continue; 8944463Smckusic field = around[siz]; 8954463Smckusic subfield = inside[siz]; 8965322Smckusic for (pos = siz; pos <= fs->fs_frag; pos++) { 8974463Smckusic if ((fragmap & field) == subfield) { 8984463Smckusic fraglist[siz] += cnt; 8994463Smckusic pos += siz; 9004463Smckusic field <<= siz; 9014463Smckusic subfield <<= siz; 9024463Smckusic } 9034463Smckusic field <<= 1; 9044463Smckusic subfield <<= 1; 9054463Smckusic } 9064463Smckusic } 9074463Smckusic } 9084463Smckusic 9095375Smckusic /* 9105375Smckusic * Check that a specified block number is in range. 9115375Smckusic */ 9124359Smckusick badblock(fs, bn) 9134359Smckusick register struct fs *fs; 9144359Smckusick daddr_t bn; 9154359Smckusick { 9164359Smckusick 9176531Smckusick if ((unsigned)bn >= fs->fs_size) { 9186567Smckusic printf("bad block %d, ", bn); 9194359Smckusick fserr(fs, "bad block"); 9204359Smckusick return (1); 9214359Smckusick } 9224359Smckusick return (0); 9234359Smckusick } 9244359Smckusick 9254359Smckusick /* 9265375Smckusic * Getfs maps a device number into a pointer to the incore super block. 9274359Smckusick * 9285375Smckusic * The algorithm is a linear search through the mount table. A 9295375Smckusic * consistency check of the super block magic number is performed. 9305375Smckusic * 9314359Smckusick * panic: no fs -- the device is not mounted. 9324359Smckusick * this "cannot happen" 9334359Smckusick */ 9344359Smckusick struct fs * 9354359Smckusick getfs(dev) 9364359Smckusick dev_t dev; 9374359Smckusick { 9384359Smckusick register struct mount *mp; 9394359Smckusick register struct fs *fs; 9404359Smckusick 9416294Smckusick for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 9426294Smckusick if (mp->m_bufp == NULL || mp->m_dev != dev) 9436294Smckusick continue; 9446294Smckusick fs = mp->m_bufp->b_un.b_fs; 9456716Smckusick if (fs->fs_magic != FS_MAGIC) { 9466716Smckusick printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt); 9476294Smckusick panic("getfs: bad magic"); 9486716Smckusick } 9496294Smckusick return (fs); 9506294Smckusick } 9516716Smckusick printf("dev = 0x%x\n", dev); 9524359Smckusick panic("getfs: no fs"); 9534359Smckusick return (NULL); 9544359Smckusick } 9554359Smckusick 9564359Smckusick /* 9575375Smckusic * Fserr prints the name of a file system with an error diagnostic. 9585375Smckusic * 9595375Smckusic * The form of the error message is: 9604359Smckusick * fs: error message 9614359Smckusick */ 9624359Smckusick fserr(fs, cp) 9634359Smckusick struct fs *fs; 9644359Smckusick char *cp; 9654359Smckusick { 9664359Smckusick 9674359Smckusick printf("%s: %s\n", fs->fs_fsmnt, cp); 9684359Smckusick } 9694359Smckusick 9704359Smckusick /* 9714359Smckusick * Getfsx returns the index in the file system 9724359Smckusick * table of the specified device. The swap device 9734359Smckusick * is also assigned a pseudo-index. The index may 9744359Smckusick * be used as a compressed indication of the location 9754359Smckusick * of a block, recording 9764359Smckusick * <getfsx(dev),blkno> 9774359Smckusick * rather than 9784359Smckusick * <dev, blkno> 9794359Smckusick * provided the information need remain valid only 9804359Smckusick * as long as the file system is mounted. 9814359Smckusick */ 9824359Smckusick getfsx(dev) 9834359Smckusick dev_t dev; 9844359Smckusick { 9854359Smckusick register struct mount *mp; 9864359Smckusick 9874359Smckusick if (dev == swapdev) 9884359Smckusick return (MSWAPX); 9894359Smckusick for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 9904359Smckusick if (mp->m_dev == dev) 9914359Smckusick return (mp - &mount[0]); 9924359Smckusick return (-1); 9934359Smckusick } 9944359Smckusick 9954359Smckusick /* 9964359Smckusick * Update is the internal name of 'sync'. It goes through the disk 9974359Smckusick * queues to initiate sandbagged IO; goes through the inodes to write 9985375Smckusic * modified nodes; and it goes through the mount table to initiate 9995375Smckusic * the writing of the modified super blocks. 10004359Smckusick */ 10016294Smckusick update(flag) 10026294Smckusick int flag; 10034359Smckusick { 10044359Smckusick register struct inode *ip; 10054359Smckusick register struct mount *mp; 10064359Smckusick register struct buf *bp; 10074359Smckusick struct fs *fs; 10084651Smckusic int i, blks; 10094359Smckusick 10104359Smckusick if (updlock) 10114359Smckusick return; 10124359Smckusick updlock++; 10134359Smckusick /* 10144359Smckusick * Write back modified superblocks. 10154359Smckusick * Consistency check that the superblock 10164359Smckusick * of each file system is still in the buffer cache. 10174359Smckusick */ 10186294Smckusick for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 10196294Smckusick if (mp->m_bufp == NULL) 10206294Smckusick continue; 10216294Smckusick fs = mp->m_bufp->b_un.b_fs; 10226294Smckusick if (fs->fs_fmod == 0) 10236294Smckusick continue; 10247187Sroot if (fs->fs_ronly != 0) { /* ### */ 10256716Smckusick printf("fs = %s\n", fs->fs_fsmnt); 10266294Smckusick panic("update: rofs mod"); 10276716Smckusick } 10286294Smckusick fs->fs_fmod = 0; 10296310Smckusick fs->fs_time = time; 10307187Sroot sbupdate(mp); 10316294Smckusick } 10324359Smckusick /* 10334359Smckusick * Write back each (modified) inode. 10344359Smckusick */ 10356294Smckusick for (ip = inode; ip < inodeNINODE; ip++) { 10366294Smckusick if ((ip->i_flag & ILOCK) != 0 || ip->i_count == 0) 10376294Smckusick continue; 10386294Smckusick ip->i_flag |= ILOCK; 10396294Smckusick ip->i_count++; 10406310Smckusick iupdat(ip, &time, &time, 0); 10416294Smckusick iput(ip); 10426294Smckusick } 10434359Smckusick updlock = 0; 10444359Smckusick /* 10454359Smckusick * Force stale buffer cache information to be flushed, 10464359Smckusick * for all devices. 10474359Smckusick */ 10484359Smckusick bflush(NODEV); 10494359Smckusick } 10505322Smckusic 10515322Smckusic /* 10525375Smckusic * block operations 10535375Smckusic * 10545375Smckusic * check if a block is available 10555322Smckusic */ 10565322Smckusic isblock(fs, cp, h) 10575322Smckusic struct fs *fs; 10585322Smckusic unsigned char *cp; 10595322Smckusic int h; 10605322Smckusic { 10615322Smckusic unsigned char mask; 10625322Smckusic 10635322Smckusic switch (fs->fs_frag) { 10645322Smckusic case 8: 10655322Smckusic return (cp[h] == 0xff); 10665322Smckusic case 4: 10675322Smckusic mask = 0x0f << ((h & 0x1) << 2); 10685322Smckusic return ((cp[h >> 1] & mask) == mask); 10695322Smckusic case 2: 10705322Smckusic mask = 0x03 << ((h & 0x3) << 1); 10715322Smckusic return ((cp[h >> 2] & mask) == mask); 10725322Smckusic case 1: 10735322Smckusic mask = 0x01 << (h & 0x7); 10745322Smckusic return ((cp[h >> 3] & mask) == mask); 10755322Smckusic default: 10766294Smckusick panic("isblock"); 10776294Smckusick return (NULL); 10785322Smckusic } 10795322Smckusic } 10805375Smckusic 10815375Smckusic /* 10825375Smckusic * take a block out of the map 10835375Smckusic */ 10845322Smckusic clrblock(fs, cp, h) 10855322Smckusic struct fs *fs; 10865322Smckusic unsigned char *cp; 10875322Smckusic int h; 10885322Smckusic { 10895322Smckusic switch ((fs)->fs_frag) { 10905322Smckusic case 8: 10915322Smckusic cp[h] = 0; 10925322Smckusic return; 10935322Smckusic case 4: 10945322Smckusic cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 10955322Smckusic return; 10965322Smckusic case 2: 10975322Smckusic cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 10985322Smckusic return; 10995322Smckusic case 1: 11005322Smckusic cp[h >> 3] &= ~(0x01 << (h & 0x7)); 11015322Smckusic return; 11025322Smckusic default: 11036294Smckusick panic("clrblock"); 11045322Smckusic return; 11055322Smckusic } 11065322Smckusic } 11075375Smckusic 11085375Smckusic /* 11095375Smckusic * put a block into the map 11105375Smckusic */ 11115322Smckusic setblock(fs, cp, h) 11125322Smckusic struct fs *fs; 11135322Smckusic unsigned char *cp; 11145322Smckusic int h; 11155322Smckusic { 11165322Smckusic switch (fs->fs_frag) { 11175322Smckusic case 8: 11185322Smckusic cp[h] = 0xff; 11195322Smckusic return; 11205322Smckusic case 4: 11215322Smckusic cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 11225322Smckusic return; 11235322Smckusic case 2: 11245322Smckusic cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 11255322Smckusic return; 11265322Smckusic case 1: 11275322Smckusic cp[h >> 3] |= (0x01 << (h & 0x7)); 11285322Smckusic return; 11295322Smckusic default: 11306294Smckusick panic("setblock"); 11315322Smckusic return; 11325322Smckusic } 11335322Smckusic } 1134