1*7116Smckusick /* lfs_alloc.c 2.6 82/06/07 */ 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) { 1225965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, bno), osize); 1235960Smckusic if (bp->b_flags & B_ERROR) { 1245960Smckusic brelse(bp); 1256294Smckusick return (NULL); 1265960Smckusic } 1276567Smckusic brealloc(bp, nsize); 1284463Smckusic blkclr(bp->b_un.b_addr + osize, nsize - osize); 1294463Smckusic return (bp); 1304463Smckusic } 1314948Smckusic if (bpref >= fs->fs_size) 1324948Smckusic bpref = 0; 1335965Smckusic bno = (daddr_t)hashalloc(ip, cg, (long)bpref, nsize, alloccg); 1346567Smckusic if (bno > 0) { 1355965Smckusic obp = bread(ip->i_dev, fsbtodb(fs, bprev), osize); 1365960Smckusic if (obp->b_flags & B_ERROR) { 1375960Smckusic brelse(obp); 1386294Smckusick return (NULL); 1395960Smckusic } 1405965Smckusic bp = getblk(ip->i_dev, fsbtodb(fs, bno), nsize); 1416567Smckusic bcopy(obp->b_un.b_addr, bp->b_un.b_addr, osize); 1426567Smckusic blkclr(bp->b_un.b_addr + osize, nsize - osize); 1434463Smckusic brelse(obp); 1445965Smckusic fre(ip, bprev, (off_t)osize); 1456294Smckusick return (bp); 1464463Smckusic } 1474792Smckusic nospace: 1484463Smckusic /* 1494463Smckusic * no space available 1504463Smckusic */ 1514426Smckusic fserr(fs, "file system full"); 1524426Smckusic uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); 1534426Smckusic u.u_error = ENOSPC; 1544426Smckusic return (NULL); 1554426Smckusic } 1564426Smckusic 1575375Smckusic /* 1585375Smckusic * Allocate an inode in the file system. 1595375Smckusic * 1605375Smckusic * A preference may be optionally specified. If a preference is given 1615375Smckusic * the following hierarchy is used to allocate an inode: 1625375Smckusic * 1) allocate the requested inode. 1635375Smckusic * 2) allocate an inode in the same cylinder group. 1645375Smckusic * 3) quadradically rehash into other cylinder groups, until an 1655375Smckusic * available inode is located. 1665375Smckusic * If no inode preference is given the following heirarchy is used 1675375Smckusic * to allocate an inode: 1685375Smckusic * 1) allocate an inode in cylinder group 0. 1695375Smckusic * 2) quadradically rehash into other cylinder groups, until an 1705375Smckusic * available inode is located. 1715375Smckusic */ 1724359Smckusick struct inode * 1735965Smckusic ialloc(pip, ipref, mode) 1745965Smckusic register struct inode *pip; 1754359Smckusick ino_t ipref; 1764359Smckusick int mode; 1774359Smckusick { 1785212Smckusic ino_t ino; 1794359Smckusick register struct fs *fs; 1804359Smckusick register struct inode *ip; 1814359Smckusick int cg; 1824359Smckusick 1835965Smckusic fs = pip->i_fs; 1844792Smckusic if (fs->fs_cstotal.cs_nifree == 0) 1854359Smckusick goto noinodes; 1864948Smckusic if (ipref >= fs->fs_ncg * fs->fs_ipg) 1874948Smckusic ipref = 0; 1885377Smckusic cg = itog(fs, ipref); 1895965Smckusic ino = (ino_t)hashalloc(pip, cg, (long)ipref, mode, ialloccg); 1904359Smckusick if (ino == 0) 1914359Smckusick goto noinodes; 1925965Smckusic ip = iget(pip->i_dev, pip->i_fs, ino); 1934359Smckusick if (ip == NULL) { 1945965Smckusic ifree(ip, ino, 0); 1954359Smckusick return (NULL); 1964359Smckusick } 1976716Smckusick if (ip->i_mode) { 1986716Smckusick printf("mode = 0%o, inum = %d, fs = %s\n", 1996716Smckusick ip->i_mode, ip->i_number, fs->fs_fsmnt); 2004359Smckusick panic("ialloc: dup alloc"); 2016716Smckusick } 2024359Smckusick return (ip); 2034359Smckusick noinodes: 2044359Smckusick fserr(fs, "out of inodes"); 2056294Smckusick uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt); 2064359Smckusick u.u_error = ENOSPC; 2074359Smckusick return (NULL); 2084359Smckusick } 2094359Smckusick 2104651Smckusic /* 2115375Smckusic * Find a cylinder to place a directory. 2125375Smckusic * 2135375Smckusic * The policy implemented by this algorithm is to select from 2145375Smckusic * among those cylinder groups with above the average number of 2155375Smckusic * free inodes, the one with the smallest number of directories. 2164651Smckusic */ 2175965Smckusic dirpref(fs) 2185965Smckusic register struct fs *fs; 2194359Smckusick { 2204651Smckusic int cg, minndir, mincg, avgifree; 2214359Smckusick 2224792Smckusic avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg; 2234651Smckusic minndir = fs->fs_ipg; 2244359Smckusick mincg = 0; 2254651Smckusic for (cg = 0; cg < fs->fs_ncg; cg++) 2265322Smckusic if (fs->fs_cs(fs, cg).cs_ndir < minndir && 2275322Smckusic fs->fs_cs(fs, cg).cs_nifree >= avgifree) { 2284359Smckusick mincg = cg; 2295322Smckusic minndir = fs->fs_cs(fs, cg).cs_ndir; 2304359Smckusick } 2314359Smckusick return (fs->fs_ipg * mincg); 2324359Smckusick } 2334359Smckusick 2344651Smckusic /* 2355375Smckusic * Select a cylinder to place a large block of data. 2365375Smckusic * 2375375Smckusic * The policy implemented by this algorithm is to maintain a 2385375Smckusic * rotor that sweeps the cylinder groups. When a block is 2395375Smckusic * needed, the rotor is advanced until a cylinder group with 2405375Smckusic * greater than the average number of free blocks is found. 2414651Smckusic */ 2425212Smckusic daddr_t 2435965Smckusic blkpref(fs) 2445965Smckusic register struct fs *fs; 2454651Smckusic { 2464651Smckusic int cg, avgbfree; 2474651Smckusic 2484792Smckusic avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; 2494651Smckusic for (cg = fs->fs_cgrotor + 1; cg < fs->fs_ncg; cg++) 2505322Smckusic if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { 2514651Smckusic fs->fs_cgrotor = cg; 2525322Smckusic return (fs->fs_fpg * cg + fs->fs_frag); 2534651Smckusic } 2544651Smckusic for (cg = 0; cg <= fs->fs_cgrotor; cg++) 2555322Smckusic if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { 2564651Smckusic fs->fs_cgrotor = cg; 2575322Smckusic return (fs->fs_fpg * cg + fs->fs_frag); 2584651Smckusic } 2596294Smckusick return (NULL); 2604651Smckusic } 2614651Smckusic 2625375Smckusic /* 2635375Smckusic * Implement the cylinder overflow algorithm. 2645375Smckusic * 2655375Smckusic * The policy implemented by this algorithm is: 2665375Smckusic * 1) allocate the block in its requested cylinder group. 2675375Smckusic * 2) quadradically rehash on the cylinder group number. 2685375Smckusic * 3) brute force search for a free block. 2695375Smckusic */ 2705212Smckusic /*VARARGS5*/ 2715212Smckusic u_long 2725965Smckusic hashalloc(ip, cg, pref, size, allocator) 2735965Smckusic struct inode *ip; 2744359Smckusick int cg; 2754359Smckusick long pref; 2764359Smckusick int size; /* size for data blocks, mode for inodes */ 2775212Smckusic u_long (*allocator)(); 2784359Smckusick { 2795965Smckusic register struct fs *fs; 2804359Smckusick long result; 2814359Smckusick int i, icg = cg; 2824359Smckusick 2835965Smckusic fs = ip->i_fs; 2844359Smckusick /* 2854359Smckusick * 1: preferred cylinder group 2864359Smckusick */ 2875965Smckusic result = (*allocator)(ip, cg, pref, size); 2884359Smckusick if (result) 2894359Smckusick return (result); 2904359Smckusick /* 2914359Smckusick * 2: quadratic rehash 2924359Smckusick */ 2934359Smckusick for (i = 1; i < fs->fs_ncg; i *= 2) { 2944359Smckusick cg += i; 2954359Smckusick if (cg >= fs->fs_ncg) 2964359Smckusick cg -= fs->fs_ncg; 2975965Smckusic result = (*allocator)(ip, cg, 0, size); 2984359Smckusick if (result) 2994359Smckusick return (result); 3004359Smckusick } 3014359Smckusick /* 3024359Smckusick * 3: brute force search 3034359Smckusick */ 3044359Smckusick cg = icg; 3054359Smckusick for (i = 0; i < fs->fs_ncg; i++) { 3065965Smckusic result = (*allocator)(ip, cg, 0, size); 3074359Smckusick if (result) 3084359Smckusick return (result); 3094359Smckusick cg++; 3104359Smckusick if (cg == fs->fs_ncg) 3114359Smckusick cg = 0; 3124359Smckusick } 3136294Smckusick return (NULL); 3144359Smckusick } 3154359Smckusick 3165375Smckusic /* 3175375Smckusic * Determine whether a fragment can be extended. 3185375Smckusic * 3195375Smckusic * Check to see if the necessary fragments are available, and 3205375Smckusic * if they are, allocate them. 3215375Smckusic */ 3224359Smckusick daddr_t 3235965Smckusic fragextend(ip, cg, bprev, osize, nsize) 3245965Smckusic struct inode *ip; 3254426Smckusic int cg; 3264463Smckusic long bprev; 3274426Smckusic int osize, nsize; 3284426Smckusic { 3295965Smckusic register struct fs *fs; 3304463Smckusic register struct buf *bp; 3314463Smckusic register struct cg *cgp; 3324463Smckusic long bno; 3334463Smckusic int frags, bbase; 3344426Smckusic int i; 3354426Smckusic 3365965Smckusic fs = ip->i_fs; 3376531Smckusick if (fs->fs_cs(fs, cg).cs_nffree < nsize - osize) 3386531Smckusick return (NULL); 3395960Smckusic frags = numfrags(fs, nsize); 3405960Smckusic bbase = fragoff(fs, bprev); 3415322Smckusic if (bbase > (bprev + frags - 1) % fs->fs_frag) { 3424463Smckusic /* cannot extend across a block boundry */ 3436294Smckusick return (NULL); 3444463Smckusic } 3455965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 3466531Smckusick cgp = bp->b_un.b_cg; 3476531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 3485960Smckusic brelse(bp); 3496294Smckusick return (NULL); 3505960Smckusic } 351*7116Smckusick cgp->cg_time = time; 3525377Smckusic bno = dtogd(fs, bprev); 3535960Smckusic for (i = numfrags(fs, osize); i < frags; i++) 3545361Smckusic if (isclr(cgp->cg_free, bno + i)) { 3555361Smckusic brelse(bp); 3566294Smckusick return (NULL); 3575361Smckusic } 3585361Smckusic /* 3595361Smckusic * the current fragment can be extended 3605361Smckusic * deduct the count on fragment being extended into 3615361Smckusic * increase the count on the remaining fragment (if any) 3625361Smckusic * allocate the extended piece 3635361Smckusic */ 3645361Smckusic for (i = frags; i < fs->fs_frag - bbase; i++) 3654463Smckusic if (isclr(cgp->cg_free, bno + i)) 3664463Smckusic break; 3675960Smckusic cgp->cg_frsum[i - numfrags(fs, osize)]--; 3685361Smckusic if (i != frags) 3695361Smckusic cgp->cg_frsum[i - frags]++; 3705960Smckusic for (i = numfrags(fs, osize); i < frags; i++) { 3715361Smckusic clrbit(cgp->cg_free, bno + i); 3725361Smckusic cgp->cg_cs.cs_nffree--; 3735361Smckusic fs->fs_cstotal.cs_nffree--; 3745361Smckusic fs->fs_cs(fs, cg).cs_nffree--; 3754463Smckusic } 3765361Smckusic fs->fs_fmod++; 3775361Smckusic bdwrite(bp); 3785361Smckusic return (bprev); 3794426Smckusic } 3804426Smckusic 3815375Smckusic /* 3825375Smckusic * Determine whether a block can be allocated. 3835375Smckusic * 3845375Smckusic * Check to see if a block of the apprpriate size is available, 3855375Smckusic * and if it is, allocate it. 3865375Smckusic */ 3874426Smckusic daddr_t 3885965Smckusic alloccg(ip, cg, bpref, size) 3895965Smckusic struct inode *ip; 3904359Smckusick int cg; 3914359Smckusick daddr_t bpref; 3924359Smckusick int size; 3934359Smckusick { 3945965Smckusic register struct fs *fs; 3954463Smckusic register struct buf *bp; 3964463Smckusic register struct cg *cgp; 3974463Smckusic int bno, frags; 3984463Smckusic int allocsiz; 3994463Smckusic register int i; 4004359Smckusick 4015965Smckusic fs = ip->i_fs; 4025322Smckusic if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize) 4036294Smckusick return (NULL); 4045965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 4056531Smckusick cgp = bp->b_un.b_cg; 4066531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 4075960Smckusic brelse(bp); 4086294Smckusick return (NULL); 4095960Smckusic } 410*7116Smckusick cgp->cg_time = time; 4115322Smckusic if (size == fs->fs_bsize) { 4125212Smckusic bno = alloccgblk(fs, cgp, bpref); 4134463Smckusic bdwrite(bp); 4144463Smckusic return (bno); 4154463Smckusic } 4164463Smckusic /* 4174463Smckusic * check to see if any fragments are already available 4184463Smckusic * allocsiz is the size which will be allocated, hacking 4194463Smckusic * it down to a smaller size if necessary 4204463Smckusic */ 4215960Smckusic frags = numfrags(fs, size); 4225322Smckusic for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++) 4234463Smckusic if (cgp->cg_frsum[allocsiz] != 0) 4244463Smckusic break; 4255322Smckusic if (allocsiz == fs->fs_frag) { 4264463Smckusic /* 4274463Smckusic * no fragments were available, so a block will be 4284463Smckusic * allocated, and hacked up 4294463Smckusic */ 4304792Smckusic if (cgp->cg_cs.cs_nbfree == 0) { 4314463Smckusic brelse(bp); 4326294Smckusick return (NULL); 4334463Smckusic } 4345212Smckusic bno = alloccgblk(fs, cgp, bpref); 4355377Smckusic bpref = dtogd(fs, bno); 4365322Smckusic for (i = frags; i < fs->fs_frag; i++) 4374463Smckusic setbit(cgp->cg_free, bpref + i); 4385322Smckusic i = fs->fs_frag - frags; 4394792Smckusic cgp->cg_cs.cs_nffree += i; 4404792Smckusic fs->fs_cstotal.cs_nffree += i; 4415322Smckusic fs->fs_cs(fs, cg).cs_nffree += i; 4424463Smckusic cgp->cg_frsum[i]++; 4434463Smckusic bdwrite(bp); 4444463Smckusic return (bno); 4454463Smckusic } 4464651Smckusic bno = mapsearch(fs, cgp, bpref, allocsiz); 4476567Smckusic if (bno < 0) 4486294Smckusick return (NULL); 4494463Smckusic for (i = 0; i < frags; i++) 4504463Smckusic clrbit(cgp->cg_free, bno + i); 4514792Smckusic cgp->cg_cs.cs_nffree -= frags; 4524792Smckusic fs->fs_cstotal.cs_nffree -= frags; 4535322Smckusic fs->fs_cs(fs, cg).cs_nffree -= frags; 4544463Smckusic cgp->cg_frsum[allocsiz]--; 4554463Smckusic if (frags != allocsiz) 4564463Smckusic cgp->cg_frsum[allocsiz - frags]++; 4574463Smckusic bdwrite(bp); 4584463Smckusic return (cg * fs->fs_fpg + bno); 4594463Smckusic } 4604463Smckusic 4615375Smckusic /* 4625375Smckusic * Allocate a block in a cylinder group. 4635375Smckusic * 4645375Smckusic * This algorithm implements the following policy: 4655375Smckusic * 1) allocate the requested block. 4665375Smckusic * 2) allocate a rotationally optimal block in the same cylinder. 4675375Smckusic * 3) allocate the next available block on the block rotor for the 4685375Smckusic * specified cylinder group. 4695375Smckusic * Note that this routine only allocates fs_bsize blocks; these 4705375Smckusic * blocks may be fragmented by the routine that allocates them. 4715375Smckusic */ 4724463Smckusic daddr_t 4735212Smckusic alloccgblk(fs, cgp, bpref) 4745965Smckusic register struct fs *fs; 4754463Smckusic register struct cg *cgp; 4764463Smckusic daddr_t bpref; 4774463Smckusic { 4784651Smckusic daddr_t bno; 4796294Smckusick int cylno, pos, delta; 4804651Smckusic short *cylbp; 4815361Smckusic register int i; 4824463Smckusic 4834651Smckusic if (bpref == 0) { 4844651Smckusic bpref = cgp->cg_rotor; 4855361Smckusic goto norot; 4865361Smckusic } 4875361Smckusic bpref &= ~(fs->fs_frag - 1); 4885377Smckusic bpref = dtogd(fs, bpref); 4895361Smckusic /* 4905361Smckusic * if the requested block is available, use it 4915361Smckusic */ 4925361Smckusic if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) { 4935361Smckusic bno = bpref; 4945361Smckusic goto gotit; 4955361Smckusic } 4965361Smckusic /* 4975361Smckusic * check for a block available on the same cylinder 4985361Smckusic */ 4995361Smckusic cylno = cbtocylno(fs, bpref); 5005375Smckusic if (cgp->cg_btot[cylno] == 0) 5015375Smckusic goto norot; 5025375Smckusic if (fs->fs_cpc == 0) { 5035375Smckusic /* 5045375Smckusic * block layout info is not available, so just have 5055375Smckusic * to take any block in this cylinder. 5065375Smckusic */ 5075375Smckusic bpref = howmany(fs->fs_spc * cylno, NSPF(fs)); 5085375Smckusic goto norot; 5095375Smckusic } 5105375Smckusic /* 5115375Smckusic * find a block that is rotationally optimal 5125375Smckusic */ 5135361Smckusic cylbp = cgp->cg_b[cylno]; 5145361Smckusic if (fs->fs_rotdelay == 0) { 5155361Smckusic pos = cbtorpos(fs, bpref); 5164651Smckusic } else { 5174651Smckusic /* 5185361Smckusic * here we convert ms of delay to frags as: 5195361Smckusic * (frags) = (ms) * (rev/sec) * (sect/rev) / 5205361Smckusic * ((sect/frag) * (ms/sec)) 5215361Smckusic * then round up to the next rotational position 5224651Smckusic */ 5235361Smckusic bpref += fs->fs_rotdelay * fs->fs_rps * fs->fs_nsect / 5245361Smckusic (NSPF(fs) * 1000); 5255361Smckusic pos = cbtorpos(fs, bpref); 5265361Smckusic pos = (pos + 1) % NRPOS; 5275361Smckusic } 5285361Smckusic /* 5295361Smckusic * check the summary information to see if a block is 5305361Smckusic * available in the requested cylinder starting at the 5315361Smckusic * optimal rotational position and proceeding around. 5325361Smckusic */ 5335361Smckusic for (i = pos; i < NRPOS; i++) 5345361Smckusic if (cylbp[i] > 0) 5355361Smckusic break; 5365361Smckusic if (i == NRPOS) 5375361Smckusic for (i = 0; i < pos; i++) 5385361Smckusic if (cylbp[i] > 0) 5395361Smckusic break; 5405361Smckusic if (cylbp[i] > 0) { 5414651Smckusic /* 5425361Smckusic * found a rotational position, now find the actual 5435361Smckusic * block. A panic if none is actually there. 5444651Smckusic */ 5455361Smckusic pos = cylno % fs->fs_cpc; 5465361Smckusic bno = (cylno - pos) * fs->fs_spc / NSPB(fs); 5476716Smckusick if (fs->fs_postbl[pos][i] == -1) { 5486716Smckusick printf("pos = %d, i = %d, fs = %s\n", 5496716Smckusick pos, i, fs->fs_fsmnt); 5505361Smckusic panic("alloccgblk: cyl groups corrupted"); 5516716Smckusick } 5526294Smckusick for (i = fs->fs_postbl[pos][i];; ) { 5535361Smckusic if (isblock(fs, cgp->cg_free, bno + i)) { 5545361Smckusic bno = (bno + i) * fs->fs_frag; 5555361Smckusic goto gotit; 5565361Smckusic } 5576294Smckusick delta = fs->fs_rotbl[i]; 5586294Smckusick if (delta <= 0 || delta > MAXBPC - i) 5594651Smckusic break; 5606294Smckusick i += delta; 5614651Smckusic } 5626716Smckusick printf("pos = %d, i = %d, fs = %s\n", pos, i, fs->fs_fsmnt); 5635361Smckusic panic("alloccgblk: can't find blk in cyl"); 5644359Smckusick } 5655361Smckusic norot: 5665361Smckusic /* 5675361Smckusic * no blocks in the requested cylinder, so take next 5685361Smckusic * available one in this cylinder group. 5695361Smckusic */ 5705322Smckusic bno = mapsearch(fs, cgp, bpref, fs->fs_frag); 5716567Smckusic if (bno < 0) 5726294Smckusick return (NULL); 5734651Smckusic cgp->cg_rotor = bno; 5744359Smckusick gotit: 5755322Smckusic clrblock(fs, cgp->cg_free, bno/fs->fs_frag); 5764792Smckusic cgp->cg_cs.cs_nbfree--; 5774792Smckusic fs->fs_cstotal.cs_nbfree--; 5785322Smckusic fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--; 5795375Smckusic cylno = cbtocylno(fs, bno); 5805375Smckusic cgp->cg_b[cylno][cbtorpos(fs, bno)]--; 5815375Smckusic cgp->cg_btot[cylno]--; 5824359Smckusick fs->fs_fmod++; 5834651Smckusic return (cgp->cg_cgx * fs->fs_fpg + bno); 5844359Smckusick } 5854359Smckusick 5865375Smckusic /* 5875375Smckusic * Determine whether an inode can be allocated. 5885375Smckusic * 5895375Smckusic * Check to see if an inode is available, and if it is, 5905375Smckusic * allocate it using the following policy: 5915375Smckusic * 1) allocate the requested inode. 5925375Smckusic * 2) allocate the next available inode after the requested 5935375Smckusic * inode in the specified cylinder group. 5945375Smckusic */ 5955212Smckusic ino_t 5965965Smckusic ialloccg(ip, cg, ipref, mode) 5975965Smckusic struct inode *ip; 5984359Smckusick int cg; 5994359Smckusick daddr_t ipref; 6004359Smckusick int mode; 6014359Smckusick { 6025965Smckusic register struct fs *fs; 6034463Smckusic register struct buf *bp; 6044463Smckusic register struct cg *cgp; 6054359Smckusick int i; 6064359Smckusick 6075965Smckusic fs = ip->i_fs; 6085322Smckusic if (fs->fs_cs(fs, cg).cs_nifree == 0) 6096294Smckusick return (NULL); 6105965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 6116531Smckusick cgp = bp->b_un.b_cg; 6126531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 6135960Smckusic brelse(bp); 6146294Smckusick return (NULL); 6155960Smckusic } 616*7116Smckusick cgp->cg_time = time; 6174359Smckusick if (ipref) { 6184359Smckusick ipref %= fs->fs_ipg; 6194359Smckusick if (isclr(cgp->cg_iused, ipref)) 6204359Smckusick goto gotit; 6214359Smckusick } else 6224359Smckusick ipref = cgp->cg_irotor; 6234359Smckusick for (i = 0; i < fs->fs_ipg; i++) { 6244359Smckusick ipref++; 6254359Smckusick if (ipref >= fs->fs_ipg) 6264359Smckusick ipref = 0; 6274359Smckusick if (isclr(cgp->cg_iused, ipref)) { 6284359Smckusick cgp->cg_irotor = ipref; 6294359Smckusick goto gotit; 6304359Smckusick } 6314359Smckusick } 6324359Smckusick brelse(bp); 6336294Smckusick return (NULL); 6344359Smckusick gotit: 6354359Smckusick setbit(cgp->cg_iused, ipref); 6364792Smckusic cgp->cg_cs.cs_nifree--; 6374792Smckusic fs->fs_cstotal.cs_nifree--; 6385322Smckusic fs->fs_cs(fs, cg).cs_nifree--; 6394359Smckusick fs->fs_fmod++; 6404359Smckusick if ((mode & IFMT) == IFDIR) { 6414792Smckusic cgp->cg_cs.cs_ndir++; 6424792Smckusic fs->fs_cstotal.cs_ndir++; 6435322Smckusic fs->fs_cs(fs, cg).cs_ndir++; 6444359Smckusick } 6454359Smckusick bdwrite(bp); 6464359Smckusick return (cg * fs->fs_ipg + ipref); 6474359Smckusick } 6484359Smckusick 6495375Smckusic /* 6505375Smckusic * Free a block or fragment. 6515375Smckusic * 6525375Smckusic * The specified block or fragment is placed back in the 6535375Smckusic * free map. If a fragment is deallocated, a possible 6545375Smckusic * block reassembly is checked. 6555375Smckusic */ 6565965Smckusic fre(ip, bno, size) 6575965Smckusic register struct inode *ip; 6584359Smckusick daddr_t bno; 6595212Smckusic off_t size; 6604359Smckusick { 6614359Smckusick register struct fs *fs; 6624359Smckusick register struct cg *cgp; 6634359Smckusick register struct buf *bp; 6644463Smckusic int cg, blk, frags, bbase; 6654463Smckusic register int i; 6664359Smckusick 6675965Smckusic fs = ip->i_fs; 6686716Smckusick if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0) { 6696716Smckusick printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n", 6706716Smckusick ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt); 6714426Smckusic panic("free: bad size"); 6726716Smckusick } 6735377Smckusic cg = dtog(fs, bno); 6746567Smckusic if (badblock(fs, bno)) { 6756567Smckusic printf("bad block %d, ino %d\n", bno, ip->i_number); 6764359Smckusick return; 6776567Smckusic } 6785965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 6796531Smckusick cgp = bp->b_un.b_cg; 6806531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 6815960Smckusic brelse(bp); 6824359Smckusick return; 6835960Smckusic } 684*7116Smckusick cgp->cg_time = time; 6855377Smckusic bno = dtogd(fs, bno); 6865322Smckusic if (size == fs->fs_bsize) { 6876567Smckusic if (isblock(fs, cgp->cg_free, bno/fs->fs_frag)) { 6886716Smckusick printf("dev = 0x%x, block = %d, fs = %s\n", 6896716Smckusick ip->i_dev, bno, fs->fs_fsmnt); 6904426Smckusic panic("free: freeing free block"); 6916567Smckusic } 6925322Smckusic setblock(fs, cgp->cg_free, bno/fs->fs_frag); 6934792Smckusic cgp->cg_cs.cs_nbfree++; 6944792Smckusic fs->fs_cstotal.cs_nbfree++; 6955322Smckusic fs->fs_cs(fs, cg).cs_nbfree++; 6965375Smckusic i = cbtocylno(fs, bno); 6975375Smckusic cgp->cg_b[i][cbtorpos(fs, bno)]++; 6985375Smckusic cgp->cg_btot[i]++; 6994426Smckusic } else { 7005322Smckusic bbase = bno - (bno % fs->fs_frag); 7014463Smckusic /* 7024463Smckusic * decrement the counts associated with the old frags 7034463Smckusic */ 7046294Smckusick blk = blkmap(fs, cgp->cg_free, bbase); 7055322Smckusic fragacct(fs, blk, cgp->cg_frsum, -1); 7064463Smckusic /* 7074463Smckusic * deallocate the fragment 7084463Smckusic */ 7095960Smckusic frags = numfrags(fs, size); 7104463Smckusic for (i = 0; i < frags; i++) { 7116716Smckusick if (isset(cgp->cg_free, bno + i)) { 7126716Smckusick printf("dev = 0x%x, block = %d, fs = %s\n", 7136716Smckusick ip->i_dev, bno + i, fs->fs_fsmnt); 7144426Smckusic panic("free: freeing free frag"); 7156716Smckusick } 7164426Smckusic setbit(cgp->cg_free, bno + i); 7174426Smckusic } 7186294Smckusick cgp->cg_cs.cs_nffree += i; 7196294Smckusick fs->fs_cstotal.cs_nffree += i; 7206294Smckusick fs->fs_cs(fs, cg).cs_nffree += i; 7214463Smckusic /* 7224463Smckusic * add back in counts associated with the new frags 7234463Smckusic */ 7246294Smckusick blk = blkmap(fs, cgp->cg_free, bbase); 7255322Smckusic fragacct(fs, blk, cgp->cg_frsum, 1); 7264463Smckusic /* 7274463Smckusic * if a complete block has been reassembled, account for it 7284463Smckusic */ 7295322Smckusic if (isblock(fs, cgp->cg_free, bbase / fs->fs_frag)) { 7305322Smckusic cgp->cg_cs.cs_nffree -= fs->fs_frag; 7315322Smckusic fs->fs_cstotal.cs_nffree -= fs->fs_frag; 7325322Smckusic fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; 7334792Smckusic cgp->cg_cs.cs_nbfree++; 7344792Smckusic fs->fs_cstotal.cs_nbfree++; 7355322Smckusic fs->fs_cs(fs, cg).cs_nbfree++; 7365375Smckusic i = cbtocylno(fs, bbase); 7375375Smckusic cgp->cg_b[i][cbtorpos(fs, bbase)]++; 7385375Smckusic cgp->cg_btot[i]++; 7394426Smckusic } 7404426Smckusic } 7414359Smckusick fs->fs_fmod++; 7424359Smckusick bdwrite(bp); 7434359Smckusick } 7444359Smckusick 7455375Smckusic /* 7465375Smckusic * Free an inode. 7475375Smckusic * 7485375Smckusic * The specified inode is placed back in the free map. 7495375Smckusic */ 7505965Smckusic ifree(ip, ino, mode) 7515965Smckusic struct inode *ip; 7524359Smckusick ino_t ino; 7534359Smckusick int mode; 7544359Smckusick { 7554359Smckusick register struct fs *fs; 7564359Smckusick register struct cg *cgp; 7574359Smckusick register struct buf *bp; 7584359Smckusick int cg; 7594359Smckusick 7605965Smckusic fs = ip->i_fs; 7616716Smckusick if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg) { 7626716Smckusick printf("dev = 0x%x, ino = %d, fs = %s\n", 7636716Smckusick ip->i_dev, ino, fs->fs_fsmnt); 7644359Smckusick panic("ifree: range"); 7656716Smckusick } 7665377Smckusic cg = itog(fs, ino); 7675965Smckusic bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), fs->fs_bsize); 7686531Smckusick cgp = bp->b_un.b_cg; 7696531Smckusick if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { 7705960Smckusic brelse(bp); 7714359Smckusick return; 7725960Smckusic } 773*7116Smckusick cgp->cg_time = time; 7744359Smckusick ino %= fs->fs_ipg; 7756716Smckusick if (isclr(cgp->cg_iused, ino)) { 7766716Smckusick printf("dev = 0x%x, ino = %d, fs = %s\n", 7776716Smckusick ip->i_dev, ino, fs->fs_fsmnt); 7784359Smckusick panic("ifree: freeing free inode"); 7796716Smckusick } 7804359Smckusick clrbit(cgp->cg_iused, ino); 7814792Smckusic cgp->cg_cs.cs_nifree++; 7824792Smckusic fs->fs_cstotal.cs_nifree++; 7835322Smckusic fs->fs_cs(fs, cg).cs_nifree++; 7844359Smckusick if ((mode & IFMT) == IFDIR) { 7854792Smckusic cgp->cg_cs.cs_ndir--; 7864792Smckusic fs->fs_cstotal.cs_ndir--; 7875322Smckusic fs->fs_cs(fs, cg).cs_ndir--; 7884359Smckusick } 7894359Smckusick fs->fs_fmod++; 7904359Smckusick bdwrite(bp); 7914359Smckusick } 7924359Smckusick 7934463Smckusic /* 7945375Smckusic * Find a block of the specified size in the specified cylinder group. 7955375Smckusic * 7964651Smckusic * It is a panic if a request is made to find a block if none are 7974651Smckusic * available. 7984651Smckusic */ 7994651Smckusic daddr_t 8004651Smckusic mapsearch(fs, cgp, bpref, allocsiz) 8014651Smckusic register struct fs *fs; 8024651Smckusic register struct cg *cgp; 8034651Smckusic daddr_t bpref; 8044651Smckusic int allocsiz; 8054651Smckusic { 8064651Smckusic daddr_t bno; 8074651Smckusic int start, len, loc, i; 8084651Smckusic int blk, field, subfield, pos; 8094651Smckusic 8104651Smckusic /* 8114651Smckusic * find the fragment by searching through the free block 8124651Smckusic * map for an appropriate bit pattern 8134651Smckusic */ 8144651Smckusic if (bpref) 8155377Smckusic start = dtogd(fs, bpref) / NBBY; 8164651Smckusic else 8174651Smckusic start = cgp->cg_frotor / NBBY; 8185398Smckusic len = howmany(fs->fs_fpg, NBBY) - start; 8195322Smckusic loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag], 8206292Smckusick 1 << (allocsiz - 1 + (fs->fs_frag % NBBY))); 8214651Smckusic if (loc == 0) { 8226531Smckusick len = start + 1; 8236531Smckusick start = 0; 8245322Smckusic loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag], 8256292Smckusick 1 << (allocsiz - 1 + (fs->fs_frag % NBBY))); 8264651Smckusic if (loc == 0) { 8276716Smckusick printf("start = %d, len = %d, fs = %s\n", 8286716Smckusick start, len, fs->fs_fsmnt); 8294651Smckusic panic("alloccg: map corrupted"); 8306531Smckusick return (-1); 8314651Smckusic } 8324651Smckusic } 8334651Smckusic bno = (start + len - loc) * NBBY; 8344651Smckusic cgp->cg_frotor = bno; 8354651Smckusic /* 8364651Smckusic * found the byte in the map 8374651Smckusic * sift through the bits to find the selected frag 8384651Smckusic */ 8396294Smckusick for (i = bno + NBBY; bno < i; bno += fs->fs_frag) { 8406294Smckusick blk = blkmap(fs, cgp->cg_free, bno); 8414651Smckusic blk <<= 1; 8424651Smckusic field = around[allocsiz]; 8434651Smckusic subfield = inside[allocsiz]; 8445322Smckusic for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) { 8456294Smckusick if ((blk & field) == subfield) 8466294Smckusick return (bno + pos); 8474651Smckusic field <<= 1; 8484651Smckusic subfield <<= 1; 8494651Smckusic } 8504651Smckusic } 8516716Smckusick printf("bno = %d, fs = %s\n", bno, fs->fs_fsmnt); 8524651Smckusic panic("alloccg: block not in map"); 8536531Smckusick return (-1); 8544651Smckusic } 8554651Smckusic 8564651Smckusic /* 8575375Smckusic * Update the frsum fields to reflect addition or deletion 8585375Smckusic * of some frags. 8594463Smckusic */ 8605322Smckusic fragacct(fs, fragmap, fraglist, cnt) 8615322Smckusic struct fs *fs; 8624472Smckusic int fragmap; 8634792Smckusic long fraglist[]; 8644463Smckusic int cnt; 8654463Smckusic { 8664463Smckusic int inblk; 8674463Smckusic register int field, subfield; 8684463Smckusic register int siz, pos; 8694463Smckusic 8705322Smckusic inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 8714463Smckusic fragmap <<= 1; 8725322Smckusic for (siz = 1; siz < fs->fs_frag; siz++) { 8736292Smckusick if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 8744463Smckusic continue; 8754463Smckusic field = around[siz]; 8764463Smckusic subfield = inside[siz]; 8775322Smckusic for (pos = siz; pos <= fs->fs_frag; pos++) { 8784463Smckusic if ((fragmap & field) == subfield) { 8794463Smckusic fraglist[siz] += cnt; 8804463Smckusic pos += siz; 8814463Smckusic field <<= siz; 8824463Smckusic subfield <<= siz; 8834463Smckusic } 8844463Smckusic field <<= 1; 8854463Smckusic subfield <<= 1; 8864463Smckusic } 8874463Smckusic } 8884463Smckusic } 8894463Smckusic 8905375Smckusic /* 8915375Smckusic * Check that a specified block number is in range. 8925375Smckusic */ 8934359Smckusick badblock(fs, bn) 8944359Smckusick register struct fs *fs; 8954359Smckusick daddr_t bn; 8964359Smckusick { 8974359Smckusick 8986531Smckusick if ((unsigned)bn >= fs->fs_size) { 8996567Smckusic printf("bad block %d, ", bn); 9004359Smckusick fserr(fs, "bad block"); 9014359Smckusick return (1); 9024359Smckusick } 9034359Smckusick return (0); 9044359Smckusick } 9054359Smckusick 9064359Smckusick /* 9075375Smckusic * Getfs maps a device number into a pointer to the incore super block. 9084359Smckusick * 9095375Smckusic * The algorithm is a linear search through the mount table. A 9105375Smckusic * consistency check of the super block magic number is performed. 9115375Smckusic * 9124359Smckusick * panic: no fs -- the device is not mounted. 9134359Smckusick * this "cannot happen" 9144359Smckusick */ 9154359Smckusick struct fs * 9164359Smckusick getfs(dev) 9174359Smckusick dev_t dev; 9184359Smckusick { 9194359Smckusick register struct mount *mp; 9204359Smckusick register struct fs *fs; 9214359Smckusick 9226294Smckusick for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 9236294Smckusick if (mp->m_bufp == NULL || mp->m_dev != dev) 9246294Smckusick continue; 9256294Smckusick fs = mp->m_bufp->b_un.b_fs; 9266716Smckusick if (fs->fs_magic != FS_MAGIC) { 9276716Smckusick printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt); 9286294Smckusick panic("getfs: bad magic"); 9296716Smckusick } 9306294Smckusick return (fs); 9316294Smckusick } 9326716Smckusick printf("dev = 0x%x\n", dev); 9334359Smckusick panic("getfs: no fs"); 9344359Smckusick return (NULL); 9354359Smckusick } 9364359Smckusick 9374359Smckusick /* 9385375Smckusic * Fserr prints the name of a file system with an error diagnostic. 9395375Smckusic * 9405375Smckusic * The form of the error message is: 9414359Smckusick * fs: error message 9424359Smckusick */ 9434359Smckusick fserr(fs, cp) 9444359Smckusick struct fs *fs; 9454359Smckusick char *cp; 9464359Smckusick { 9474359Smckusick 9484359Smckusick printf("%s: %s\n", fs->fs_fsmnt, cp); 9494359Smckusick } 9504359Smckusick 9514359Smckusick /* 9524359Smckusick * Getfsx returns the index in the file system 9534359Smckusick * table of the specified device. The swap device 9544359Smckusick * is also assigned a pseudo-index. The index may 9554359Smckusick * be used as a compressed indication of the location 9564359Smckusick * of a block, recording 9574359Smckusick * <getfsx(dev),blkno> 9584359Smckusick * rather than 9594359Smckusick * <dev, blkno> 9604359Smckusick * provided the information need remain valid only 9614359Smckusick * as long as the file system is mounted. 9624359Smckusick */ 9634359Smckusick getfsx(dev) 9644359Smckusick dev_t dev; 9654359Smckusick { 9664359Smckusick register struct mount *mp; 9674359Smckusick 9684359Smckusick if (dev == swapdev) 9694359Smckusick return (MSWAPX); 9704359Smckusick for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 9714359Smckusick if (mp->m_dev == dev) 9724359Smckusick return (mp - &mount[0]); 9734359Smckusick return (-1); 9744359Smckusick } 9754359Smckusick 9764359Smckusick /* 9774359Smckusick * Update is the internal name of 'sync'. It goes through the disk 9784359Smckusick * queues to initiate sandbagged IO; goes through the inodes to write 9795375Smckusic * modified nodes; and it goes through the mount table to initiate 9805375Smckusic * the writing of the modified super blocks. 9814359Smckusick */ 9826294Smckusick update(flag) 9836294Smckusick int flag; 9844359Smckusick { 9854359Smckusick register struct inode *ip; 9864359Smckusick register struct mount *mp; 9874359Smckusick register struct buf *bp; 9884359Smckusick struct fs *fs; 9894651Smckusic int i, blks; 9904359Smckusick 9914359Smckusick if (updlock) 9924359Smckusick return; 9934359Smckusick updlock++; 9944359Smckusick /* 9954359Smckusick * Write back modified superblocks. 9964359Smckusick * Consistency check that the superblock 9974359Smckusick * of each file system is still in the buffer cache. 9984359Smckusick */ 9996294Smckusick for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 10006294Smckusick if (mp->m_bufp == NULL) 10016294Smckusick continue; 10026294Smckusick fs = mp->m_bufp->b_un.b_fs; 10036294Smckusick if (fs->fs_fmod == 0) 10046294Smckusick continue; 10056716Smckusick if (fs->fs_ronly != 0) { 10066716Smckusick printf("fs = %s\n", fs->fs_fsmnt); 10076294Smckusick panic("update: rofs mod"); 10086716Smckusick } 10096294Smckusick bp = getblk(mp->m_dev, SBLOCK, SBSIZE); 10106716Smckusick if (bp->b_un.b_fs != fs || fs->fs_magic != FS_MAGIC) { 10116716Smckusick printf("fs = %s\n", fs->fs_fsmnt); 10126531Smckusick panic("update: bad b_fs"); 10136716Smckusick } 10146294Smckusick fs->fs_fmod = 0; 10156310Smckusick fs->fs_time = time; 10166294Smckusick bwrite(bp); 10176531Smckusick blks = howmany(fs->fs_cssize, fs->fs_fsize); 10186531Smckusick for (i = 0; i < blks; i += fs->fs_frag) { 10196294Smckusick bp = getblk(mp->m_dev, 10206531Smckusick fsbtodb(fs, fs->fs_csaddr + i), 10216531Smckusick blks - i < fs->fs_frag ? 10226531Smckusick (blks - i) * fs->fs_fsize : 10236531Smckusick fs->fs_bsize); 10244359Smckusick bwrite(bp); 10254359Smckusick } 10266294Smckusick } 10274359Smckusick /* 10284359Smckusick * Write back each (modified) inode. 10294359Smckusick */ 10306294Smckusick for (ip = inode; ip < inodeNINODE; ip++) { 10316294Smckusick if ((ip->i_flag & ILOCK) != 0 || ip->i_count == 0) 10326294Smckusick continue; 10336294Smckusick ip->i_flag |= ILOCK; 10346294Smckusick ip->i_count++; 10356310Smckusick iupdat(ip, &time, &time, 0); 10366294Smckusick iput(ip); 10376294Smckusick } 10384359Smckusick updlock = 0; 10394359Smckusick /* 10404359Smckusick * Force stale buffer cache information to be flushed, 10414359Smckusick * for all devices. 10424359Smckusick */ 10434359Smckusick bflush(NODEV); 10444359Smckusick } 10455322Smckusic 10465322Smckusic /* 10475375Smckusic * block operations 10485375Smckusic * 10495375Smckusic * check if a block is available 10505322Smckusic */ 10515322Smckusic isblock(fs, cp, h) 10525322Smckusic struct fs *fs; 10535322Smckusic unsigned char *cp; 10545322Smckusic int h; 10555322Smckusic { 10565322Smckusic unsigned char mask; 10575322Smckusic 10585322Smckusic switch (fs->fs_frag) { 10595322Smckusic case 8: 10605322Smckusic return (cp[h] == 0xff); 10615322Smckusic case 4: 10625322Smckusic mask = 0x0f << ((h & 0x1) << 2); 10635322Smckusic return ((cp[h >> 1] & mask) == mask); 10645322Smckusic case 2: 10655322Smckusic mask = 0x03 << ((h & 0x3) << 1); 10665322Smckusic return ((cp[h >> 2] & mask) == mask); 10675322Smckusic case 1: 10685322Smckusic mask = 0x01 << (h & 0x7); 10695322Smckusic return ((cp[h >> 3] & mask) == mask); 10705322Smckusic default: 10716294Smckusick panic("isblock"); 10726294Smckusick return (NULL); 10735322Smckusic } 10745322Smckusic } 10755375Smckusic 10765375Smckusic /* 10775375Smckusic * take a block out of the map 10785375Smckusic */ 10795322Smckusic clrblock(fs, cp, h) 10805322Smckusic struct fs *fs; 10815322Smckusic unsigned char *cp; 10825322Smckusic int h; 10835322Smckusic { 10845322Smckusic switch ((fs)->fs_frag) { 10855322Smckusic case 8: 10865322Smckusic cp[h] = 0; 10875322Smckusic return; 10885322Smckusic case 4: 10895322Smckusic cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 10905322Smckusic return; 10915322Smckusic case 2: 10925322Smckusic cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 10935322Smckusic return; 10945322Smckusic case 1: 10955322Smckusic cp[h >> 3] &= ~(0x01 << (h & 0x7)); 10965322Smckusic return; 10975322Smckusic default: 10986294Smckusick panic("clrblock"); 10995322Smckusic return; 11005322Smckusic } 11015322Smckusic } 11025375Smckusic 11035375Smckusic /* 11045375Smckusic * put a block into the map 11055375Smckusic */ 11065322Smckusic setblock(fs, cp, h) 11075322Smckusic struct fs *fs; 11085322Smckusic unsigned char *cp; 11095322Smckusic int h; 11105322Smckusic { 11115322Smckusic switch (fs->fs_frag) { 11125322Smckusic case 8: 11135322Smckusic cp[h] = 0xff; 11145322Smckusic return; 11155322Smckusic case 4: 11165322Smckusic cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 11175322Smckusic return; 11185322Smckusic case 2: 11195322Smckusic cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 11205322Smckusic return; 11215322Smckusic case 1: 11225322Smckusic cp[h >> 3] |= (0x01 << (h & 0x7)); 11235322Smckusic return; 11245322Smckusic default: 11256294Smckusick panic("setblock"); 11265322Smckusic return; 11275322Smckusic } 11285322Smckusic } 1129