14359Smckusick /* Copyright (c) 1981 Regents of the University of California */ 24359Smckusick 3*4607Smckusic static char vers[] = "@(#)lfs_alloc.c 1.6 10/25/81"; 44359Smckusick 54359Smckusick /* alloc.c 4.8 81/03/08 */ 64359Smckusick 74359Smckusick #include "../h/param.h" 84359Smckusick #include "../h/systm.h" 94359Smckusick #include "../h/mount.h" 104359Smckusick #include "../h/fs.h" 114359Smckusick #include "../h/conf.h" 124359Smckusick #include "../h/buf.h" 134359Smckusick #include "../h/inode.h" 144359Smckusick #include "../h/dir.h" 154359Smckusick #include "../h/user.h" 164359Smckusick 17*4607Smckusic extern long hashalloc(); 18*4607Smckusic extern long alloccg(); 19*4607Smckusic extern long ialloccg(); 20*4607Smckusic extern int inside[], around[]; 21*4607Smckusic extern unsigned char fragtbl[]; 224359Smckusick 234359Smckusick struct buf * 244359Smckusick alloc(dev, ip, bpref, size) 254359Smckusick dev_t dev; 264463Smckusic register struct inode *ip; 274359Smckusick daddr_t bpref; 284359Smckusick int size; 294359Smckusick { 304359Smckusick daddr_t bno; 314359Smckusick register struct fs *fs; 324463Smckusic register struct buf *bp; 334359Smckusick int cg; 344359Smckusick 354463Smckusic if ((unsigned)size > BSIZE || size % FSIZE != 0) 364463Smckusic panic("alloc: bad size"); 374359Smckusick fs = getfs(dev); 384359Smckusick if (fs->fs_nbfree == 0 && size == BSIZE) 394359Smckusick goto nospace; 404359Smckusick if (bpref == 0) 414359Smckusick cg = itog(ip->i_number, fs); 424359Smckusick else 434359Smckusick cg = dtog(bpref, fs); 444359Smckusick bno = hashalloc(dev, fs, cg, (long)bpref, size, alloccg); 454359Smckusick if (bno == 0) 464359Smckusick goto nospace; 474426Smckusic bp = getblk(dev, bno, size); 484359Smckusick clrbuf(bp); 494359Smckusick return (bp); 504359Smckusick nospace: 514359Smckusick fserr(fs, "file system full"); 524359Smckusick uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); 534359Smckusick u.u_error = ENOSPC; 544359Smckusick return (NULL); 554359Smckusick } 564359Smckusick 574426Smckusic struct buf * 584463Smckusic realloccg(dev, ip, bprev, osize, nsize) 594426Smckusic dev_t dev; 604463Smckusic register struct inode *ip; 614463Smckusic daddr_t bprev; 624426Smckusic int osize, nsize; 634426Smckusic { 644426Smckusic daddr_t bno; 654426Smckusic register struct fs *fs; 664463Smckusic register struct buf *bp, *obp; 674463Smckusic caddr_t cp; 684426Smckusic int cg; 694426Smckusic 704463Smckusic if ((unsigned)osize > BSIZE || osize % FSIZE != 0 || 714463Smckusic (unsigned)nsize > BSIZE || nsize % FSIZE != 0) 724463Smckusic panic("realloccg: bad size"); 734426Smckusic fs = getfs(dev); 744463Smckusic if (bprev == 0) 754463Smckusic panic("realloccg: bad bprev"); 764426Smckusic else 774463Smckusic cg = dtog(bprev, fs); 784463Smckusic bno = fragextend(dev, fs, cg, (long)bprev, osize, nsize); 794463Smckusic if (bno != 0) { 804463Smckusic bp = bread(dev, bno, osize); 814463Smckusic bp->b_bcount = nsize; 824463Smckusic blkclr(bp->b_un.b_addr + osize, nsize - osize); 834463Smckusic return (bp); 844463Smckusic } 854463Smckusic bno = hashalloc(dev, fs, cg, (long)bprev, nsize, alloccg); 864463Smckusic if (bno != 0) { 874463Smckusic /* 884463Smckusic * make a new copy 894463Smckusic */ 904463Smckusic obp = bread(dev, bprev, osize); 914463Smckusic bp = getblk(dev, bno, nsize); 924463Smckusic cp = bp->b_un.b_addr; 934463Smckusic bp->b_un.b_addr = obp->b_un.b_addr; 944463Smckusic obp->b_un.b_addr = cp; 954463Smckusic obp->b_flags |= B_INVAL; 964463Smckusic brelse(obp); 974463Smckusic fre(dev, bprev, osize); 984463Smckusic blkclr(bp->b_un.b_addr + osize, nsize - osize); 994463Smckusic return(bp); 1004463Smckusic } 1014463Smckusic /* 1024463Smckusic * no space available 1034463Smckusic */ 1044426Smckusic fserr(fs, "file system full"); 1054426Smckusic uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); 1064426Smckusic u.u_error = ENOSPC; 1074426Smckusic return (NULL); 1084426Smckusic } 1094426Smckusic 1104359Smckusick struct inode * 1114359Smckusick ialloc(dev, ipref, mode) 1124359Smckusick dev_t dev; 1134359Smckusick ino_t ipref; 1144359Smckusick int mode; 1154359Smckusick { 1164359Smckusick daddr_t ino; 1174359Smckusick register struct fs *fs; 1184359Smckusick register struct inode *ip; 1194359Smckusick int cg; 1204359Smckusick 1214359Smckusick fs = getfs(dev); 1224359Smckusick if (fs->fs_nifree == 0) 1234359Smckusick goto noinodes; 1244359Smckusick cg = itog(ipref, fs); 1254359Smckusick ino = hashalloc(dev, fs, cg, (long)ipref, mode, ialloccg); 1264359Smckusick if (ino == 0) 1274359Smckusick goto noinodes; 1284359Smckusick ip = iget(dev, ino); 1294359Smckusick if (ip == NULL) { 1304359Smckusick ifree(dev, ino); 1314359Smckusick return (NULL); 1324359Smckusick } 1334359Smckusick if (ip->i_mode) 1344359Smckusick panic("ialloc: dup alloc"); 1354359Smckusick return (ip); 1364359Smckusick noinodes: 1374359Smckusick fserr(fs, "out of inodes"); 1384359Smckusick uprintf("\n%s: create failed, no inodes free\n", fs->fs_fsmnt); 1394359Smckusick u.u_error = ENOSPC; 1404359Smckusick return (NULL); 1414359Smckusick } 1424359Smckusick 1434359Smckusick dipref(dev) 1444359Smckusick dev_t dev; 1454359Smckusick { 1464359Smckusick register struct fs *fs; 1474359Smckusick int cg, minndir, mincg; 1484359Smckusick 1494359Smckusick fs = getfs(dev); 1504359Smckusick minndir = fs->fs_cs[0].cs_ndir; 1514359Smckusick mincg = 0; 1524359Smckusick for (cg = 1; cg < fs->fs_ncg; cg++) 1534359Smckusick if (fs->fs_cs[cg].cs_ndir < minndir) { 1544359Smckusick mincg = cg; 1554359Smckusick minndir = fs->fs_cs[cg].cs_ndir; 1564359Smckusick if (minndir == 0) 1574359Smckusick break; 1584359Smckusick } 1594359Smckusick return (fs->fs_ipg * mincg); 1604359Smckusick } 1614359Smckusick 1624359Smckusick long 1634359Smckusick hashalloc(dev, fs, cg, pref, size, allocator) 1644359Smckusick dev_t dev; 1654359Smckusick register struct fs *fs; 1664359Smckusick int cg; 1674359Smckusick long pref; 1684359Smckusick int size; /* size for data blocks, mode for inodes */ 1694359Smckusick long (*allocator)(); 1704359Smckusick { 1714359Smckusick long result; 1724359Smckusick int i, icg = cg; 1734359Smckusick 1744359Smckusick /* 1754359Smckusick * 1: preferred cylinder group 1764359Smckusick */ 1774359Smckusick result = (*allocator)(dev, fs, cg, pref, size); 1784359Smckusick if (result) 1794359Smckusick return (result); 1804359Smckusick /* 1814359Smckusick * 2: quadratic rehash 1824359Smckusick */ 1834359Smckusick for (i = 1; i < fs->fs_ncg; i *= 2) { 1844359Smckusick cg += i; 1854359Smckusick if (cg >= fs->fs_ncg) 1864359Smckusick cg -= fs->fs_ncg; 1874359Smckusick result = (*allocator)(dev, fs, cg, 0, size); 1884359Smckusick if (result) 1894359Smckusick return (result); 1904359Smckusick } 1914359Smckusick /* 1924359Smckusick * 3: brute force search 1934359Smckusick */ 1944359Smckusick cg = icg; 1954359Smckusick for (i = 0; i < fs->fs_ncg; i++) { 1964359Smckusick result = (*allocator)(dev, fs, cg, 0, size); 1974359Smckusick if (result) 1984359Smckusick return (result); 1994359Smckusick cg++; 2004359Smckusick if (cg == fs->fs_ncg) 2014359Smckusick cg = 0; 2024359Smckusick } 2034359Smckusick return (0); 2044359Smckusick } 2054359Smckusick 2064359Smckusick daddr_t 2074463Smckusic fragextend(dev, fs, cg, bprev, osize, nsize) 2084426Smckusic dev_t dev; 2094426Smckusic register struct fs *fs; 2104426Smckusic int cg; 2114463Smckusic long bprev; 2124426Smckusic int osize, nsize; 2134426Smckusic { 2144463Smckusic register struct buf *bp; 2154463Smckusic register struct cg *cgp; 2164463Smckusic long bno; 2174463Smckusic int frags, bbase; 2184426Smckusic int i; 2194426Smckusic 2204463Smckusic frags = nsize / FSIZE; 2214463Smckusic bbase = bprev % FRAG; 2224463Smckusic if (bbase > (bprev + frags - 1) % FRAG) { 2234463Smckusic /* cannot extend across a block boundry */ 2244463Smckusic return (0); 2254463Smckusic } 2264426Smckusic bp = bread(dev, cgtod(cg, fs), BSIZE); 2274426Smckusic if (bp->b_flags & B_ERROR) 2284426Smckusic return (0); 2294426Smckusic cgp = bp->b_un.b_cg; 2304463Smckusic bno = bprev % fs->fs_fpg; 2314463Smckusic for (i = osize / FSIZE; i < frags; i++) { 2324463Smckusic if (isclr(cgp->cg_free, bno + i)) 2334463Smckusic break; 2344463Smckusic } 2354463Smckusic if (i == frags) { 2364463Smckusic /* 2374463Smckusic * the current fragment can be extended 2384463Smckusic * deduct the count on fragment being extended into 2394463Smckusic * increase the count on the remaining fragment (if any) 2404463Smckusic * allocate the extended piece 2414463Smckusic */ 2424463Smckusic for (i = frags; i < FRAG - bbase; i++) 2434463Smckusic if (isclr(cgp->cg_free, bno + i)) 2444426Smckusic break; 2454463Smckusic cgp->cg_frsum[i - osize / FSIZE]--; 2464463Smckusic if (i != frags) 2474463Smckusic cgp->cg_frsum[i - frags]++; 2484463Smckusic for (i = osize / FSIZE; i < frags; i++) { 2494463Smckusic clrbit(cgp->cg_free, bno + i); 2504463Smckusic cgp->cg_nffree--; 2514463Smckusic fs->fs_nffree--; 2524426Smckusic } 2534463Smckusic fs->fs_fmod++; 2544463Smckusic bdwrite(bp); 2554463Smckusic return (bprev); 2564426Smckusic } 2574426Smckusic brelse(bp); 2584426Smckusic return (0); 2594426Smckusic } 2604426Smckusic 2614426Smckusic daddr_t 2624359Smckusick alloccg(dev, fs, cg, bpref, size) 2634359Smckusick dev_t dev; 2644463Smckusic register struct fs *fs; 2654359Smckusick int cg; 2664359Smckusick daddr_t bpref; 2674359Smckusick int size; 2684359Smckusick { 2694463Smckusic register struct buf *bp; 2704463Smckusic register struct cg *cgp; 2714463Smckusic int bno, frags; 2724463Smckusic int allocsiz; 2734463Smckusic int start, len, loc; 2744463Smckusic int blk, field, subfield, pos; 2754463Smckusic register int i; 2764359Smckusick 2774426Smckusic bp = bread(dev, cgtod(cg, fs), BSIZE); 2784359Smckusick if (bp->b_flags & B_ERROR) 2794359Smckusick return (0); 2804359Smckusick cgp = bp->b_un.b_cg; 2814463Smckusic if (size == BSIZE) { 2824463Smckusic if (cgp->cg_nbfree == 0) { 2834463Smckusic brelse(bp); 2844463Smckusic return (0); 2854463Smckusic } 2864463Smckusic bno = alloccgblk(dev, fs, cgp, bpref); 2874463Smckusic bdwrite(bp); 2884463Smckusic return (bno); 2894463Smckusic } 2904463Smckusic /* 2914463Smckusic * check to see if any fragments are already available 2924463Smckusic * allocsiz is the size which will be allocated, hacking 2934463Smckusic * it down to a smaller size if necessary 2944463Smckusic */ 2954463Smckusic frags = size / FSIZE; 2964463Smckusic for (allocsiz = frags; allocsiz < FRAG; allocsiz++) 2974463Smckusic if (cgp->cg_frsum[allocsiz] != 0) 2984463Smckusic break; 2994463Smckusic if (allocsiz == FRAG) { 3004463Smckusic /* 3014463Smckusic * no fragments were available, so a block will be 3024463Smckusic * allocated, and hacked up 3034463Smckusic */ 3044463Smckusic if (cgp->cg_nbfree == 0) { 3054463Smckusic brelse(bp); 3064463Smckusic return (0); 3074463Smckusic } 3084463Smckusic bno = alloccgblk(dev, fs, cgp, bpref); 3094463Smckusic bpref = bno % fs->fs_fpg; 3104463Smckusic for (i = frags; i < FRAG; i++) 3114463Smckusic setbit(cgp->cg_free, bpref + i); 3124463Smckusic i = FRAG - frags; 3134463Smckusic cgp->cg_nffree += i; 3144463Smckusic fs->fs_nffree += i; 3154463Smckusic cgp->cg_frsum[i]++; 3164463Smckusic bdwrite(bp); 3174463Smckusic return (bno); 3184463Smckusic } 3194463Smckusic /* 3204463Smckusic * find the fragment by searching through the free block 3214463Smckusic * map for an appropriate bit pattern 3224463Smckusic */ 3234463Smckusic if (bpref) 3244463Smckusic start = bpref % fs->fs_fpg / NBBY; 3254463Smckusic else 3264463Smckusic start = cgp->cg_frotor / NBBY; 3274463Smckusic len = roundup(fs->fs_fpg - 1, NBBY) / NBBY - start; 3284463Smckusic loc = scanc(len, &cgp->cg_free[start], fragtbl, 1 << (allocsiz - 1)); 3294463Smckusic if (loc == 0) { 3304463Smckusic len = start - 1; 3314463Smckusic start = (cgdmin(cg, fs) - cgbase(cg, fs)) / NBBY; 3324463Smckusic loc = scanc(len, &cgp->cg_free[start], fragtbl, 3334463Smckusic 1 << (allocsiz - 1)); 3344463Smckusic if (loc == 0) 3354463Smckusic panic("alloccg: can't find frag"); 3364463Smckusic } 3374463Smckusic bno = (start + len - loc) * NBBY; 3384463Smckusic cgp->cg_frotor = bno; 3394463Smckusic /* 3404463Smckusic * found the byte in the map 3414463Smckusic * sift through the bits to find the selected frag 3424463Smckusic */ 3434463Smckusic for (i = 0; i < NBBY; i += FRAG) { 3444463Smckusic blk = (cgp->cg_free[bno / NBBY] >> i) & (0xff >> NBBY - FRAG); 3454463Smckusic blk <<= 1; 3464463Smckusic field = around[allocsiz]; 3474463Smckusic subfield = inside[allocsiz]; 3484463Smckusic for (pos = 0; pos <= FRAG - allocsiz; pos++) { 3494463Smckusic if ((blk & field) == subfield) { 3504463Smckusic bno += i + pos; 3514463Smckusic goto gotit; 3524463Smckusic } 3534463Smckusic field <<= 1; 3544463Smckusic subfield <<= 1; 3554463Smckusic } 3564463Smckusic } 3574463Smckusic panic("alloccg: frag not in block"); 3584463Smckusic gotit: 3594463Smckusic for (i = 0; i < frags; i++) 3604463Smckusic clrbit(cgp->cg_free, bno + i); 3614463Smckusic cgp->cg_nffree -= frags; 3624463Smckusic fs->fs_nffree -= frags; 3634463Smckusic cgp->cg_frsum[allocsiz]--; 3644463Smckusic if (frags != allocsiz) 3654463Smckusic cgp->cg_frsum[allocsiz - frags]++; 3664463Smckusic bdwrite(bp); 3674463Smckusic return (cg * fs->fs_fpg + bno); 3684463Smckusic } 3694463Smckusic 3704463Smckusic daddr_t 3714463Smckusic alloccgblk(dev, fs, cgp, bpref) 3724463Smckusic dev_t dev; 3734463Smckusic struct fs *fs; 3744463Smckusic register struct cg *cgp; 3754463Smckusic daddr_t bpref; 3764463Smckusic { 3774463Smckusic register int i; 3784463Smckusic 3794359Smckusick if (bpref) { 3804463Smckusic bpref &= ~(FRAG - 1); 3814359Smckusick bpref %= fs->fs_fpg; 3824359Smckusick if (isblock(cgp->cg_free, bpref/FRAG)) 3834359Smckusick goto gotit; 3844359Smckusick } else 3854359Smckusick bpref = cgp->cg_rotor; 3864359Smckusick for (i = 0; i < cgp->cg_ndblk; i += FRAG) { 3874359Smckusick bpref += FRAG; 3884359Smckusick if (bpref >= cgp->cg_ndblk) 3894359Smckusick bpref = 0; 3904359Smckusick if (isblock(cgp->cg_free, bpref/FRAG)) { 3914359Smckusick cgp->cg_rotor = bpref; 3924359Smckusick goto gotit; 3934359Smckusick } 3944359Smckusick } 3954463Smckusic panic("alloccgblk: can't find a blk"); 3964359Smckusick return (0); 3974359Smckusick gotit: 3984463Smckusic clrblock(cgp->cg_free, bpref/FRAG); 3994463Smckusic cgp->cg_nbfree--; 4004463Smckusic fs->fs_nbfree--; 4014463Smckusic fs->fs_cs[cgp->cg_cgx].cs_nbfree--; 4024463Smckusic i = bpref * NSPF; 4034463Smckusic cgp->cg_b[i/fs->fs_spc][i%fs->fs_nsect*NRPOS/fs->fs_nsect]--; 4044359Smckusick fs->fs_fmod++; 4054463Smckusic return (cgp->cg_cgx * fs->fs_fpg + bpref); 4064359Smckusick } 4074359Smckusick 4084359Smckusick long 4094359Smckusick ialloccg(dev, fs, cg, ipref, mode) 4104359Smckusick dev_t dev; 4114463Smckusic register struct fs *fs; 4124359Smckusick int cg; 4134359Smckusick daddr_t ipref; 4144359Smckusick int mode; 4154359Smckusick { 4164463Smckusic register struct buf *bp; 4174463Smckusic register struct cg *cgp; 4184359Smckusick int i; 4194359Smckusick 4204426Smckusic bp = bread(dev, cgtod(cg, fs), BSIZE); 4214359Smckusick if (bp->b_flags & B_ERROR) 4224359Smckusick return (0); 4234359Smckusick cgp = bp->b_un.b_cg; 4244359Smckusick if (cgp->cg_nifree == 0) { 4254359Smckusick brelse(bp); 4264359Smckusick return (0); 4274359Smckusick } 4284359Smckusick if (ipref) { 4294359Smckusick ipref %= fs->fs_ipg; 4304359Smckusick if (isclr(cgp->cg_iused, ipref)) 4314359Smckusick goto gotit; 4324359Smckusick } else 4334359Smckusick ipref = cgp->cg_irotor; 4344359Smckusick for (i = 0; i < fs->fs_ipg; i++) { 4354359Smckusick ipref++; 4364359Smckusick if (ipref >= fs->fs_ipg) 4374359Smckusick ipref = 0; 4384359Smckusick if (isclr(cgp->cg_iused, ipref)) { 4394359Smckusick cgp->cg_irotor = ipref; 4404359Smckusick goto gotit; 4414359Smckusick } 4424359Smckusick } 4434359Smckusick brelse(bp); 4444359Smckusick return (0); 4454359Smckusick gotit: 4464359Smckusick setbit(cgp->cg_iused, ipref); 4474359Smckusick cgp->cg_nifree--; 4484359Smckusick fs->fs_nifree--; 4494359Smckusick fs->fs_cs[cg].cs_nifree--; 4504359Smckusick fs->fs_fmod++; 4514359Smckusick if ((mode & IFMT) == IFDIR) { 4524359Smckusick cgp->cg_ndir++; 4534359Smckusick fs->fs_cs[cg].cs_ndir++; 4544359Smckusick } 4554359Smckusick bdwrite(bp); 4564359Smckusick return (cg * fs->fs_ipg + ipref); 4574359Smckusick } 4584359Smckusick 4594359Smckusick fre(dev, bno, size) 4604359Smckusick dev_t dev; 4614359Smckusick daddr_t bno; 4624359Smckusick int size; 4634359Smckusick { 4644359Smckusick register struct fs *fs; 4654359Smckusick register struct cg *cgp; 4664359Smckusick register struct buf *bp; 4674463Smckusic int cg, blk, frags, bbase; 4684463Smckusic register int i; 4694359Smckusick 4704426Smckusic if ((unsigned)size > BSIZE || size % FSIZE != 0) 4714426Smckusic panic("free: bad size"); 4724359Smckusick fs = getfs(dev); 4734359Smckusick cg = dtog(bno, fs); 4744359Smckusick if (badblock(fs, bno)) 4754359Smckusick return; 4764426Smckusic bp = bread(dev, cgtod(cg, fs), BSIZE); 4774359Smckusick if (bp->b_flags & B_ERROR) 4784359Smckusick return; 4794359Smckusick cgp = bp->b_un.b_cg; 4804359Smckusick bno %= fs->fs_fpg; 4814426Smckusic if (size == BSIZE) { 4824426Smckusic if (isblock(cgp->cg_free, bno/FRAG)) 4834426Smckusic panic("free: freeing free block"); 4844426Smckusic setblock(cgp->cg_free, bno/FRAG); 4854426Smckusic cgp->cg_nbfree++; 4864426Smckusic fs->fs_nbfree++; 4874426Smckusic fs->fs_cs[cg].cs_nbfree++; 4884426Smckusic i = bno * NSPF; 4894426Smckusic cgp->cg_b[i/fs->fs_spc][i%fs->fs_nsect*NRPOS/fs->fs_nsect]++; 4904426Smckusic } else { 4914463Smckusic bbase = bno - (bno % FRAG); 4924463Smckusic /* 4934463Smckusic * decrement the counts associated with the old frags 4944463Smckusic */ 4954463Smckusic blk = ((cgp->cg_free[bbase / NBBY] >> (bbase % NBBY)) & 4964463Smckusic (0xff >> (NBBY - FRAG))); 4974463Smckusic fragacct(blk, cgp->cg_frsum, -1); 4984463Smckusic /* 4994463Smckusic * deallocate the fragment 5004463Smckusic */ 5014463Smckusic frags = size / FSIZE; 5024463Smckusic for (i = 0; i < frags; i++) { 5034426Smckusic if (isset(cgp->cg_free, bno + i)) 5044426Smckusic panic("free: freeing free frag"); 5054426Smckusic setbit(cgp->cg_free, bno + i); 5064426Smckusic cgp->cg_nffree++; 5074426Smckusic fs->fs_nffree++; 5084426Smckusic } 5094463Smckusic /* 5104463Smckusic * add back in counts associated with the new frags 5114463Smckusic */ 5124463Smckusic blk = ((cgp->cg_free[bbase / NBBY] >> (bbase % NBBY)) & 5134463Smckusic (0xff >> (NBBY - FRAG))); 5144463Smckusic fragacct(blk, cgp->cg_frsum, 1); 5154463Smckusic /* 5164463Smckusic * if a complete block has been reassembled, account for it 5174463Smckusic */ 5184463Smckusic if (isblock(cgp->cg_free, bbase / FRAG)) { 5194426Smckusic cgp->cg_nffree -= FRAG; 5204426Smckusic fs->fs_nffree -= FRAG; 5214426Smckusic cgp->cg_nbfree++; 5224426Smckusic fs->fs_nbfree++; 5234426Smckusic fs->fs_cs[cg].cs_nbfree++; 5244463Smckusic i = bbase * NSPF; 5254426Smckusic cgp->cg_b[i / fs->fs_spc] 5264426Smckusic [i % fs->fs_nsect * NRPOS / fs->fs_nsect]++; 5274426Smckusic } 5284426Smckusic } 5294359Smckusick fs->fs_fmod++; 5304359Smckusick bdwrite(bp); 5314359Smckusick } 5324359Smckusick 5334359Smckusick ifree(dev, ino, mode) 5344359Smckusick dev_t dev; 5354359Smckusick ino_t ino; 5364359Smckusick int mode; 5374359Smckusick { 5384359Smckusick register struct fs *fs; 5394359Smckusick register struct cg *cgp; 5404359Smckusick register struct buf *bp; 5414359Smckusick int i; 5424359Smckusick int cg; 5434359Smckusick 5444359Smckusick fs = getfs(dev); 5454359Smckusick if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg) 5464359Smckusick panic("ifree: range"); 5474359Smckusick cg = itog(ino, fs); 5484426Smckusic bp = bread(dev, cgtod(cg, fs), BSIZE); 5494359Smckusick if (bp->b_flags & B_ERROR) 5504359Smckusick return; 5514359Smckusick cgp = bp->b_un.b_cg; 5524359Smckusick ino %= fs->fs_ipg; 5534359Smckusick if (isclr(cgp->cg_iused, ino)) 5544359Smckusick panic("ifree: freeing free inode"); 5554359Smckusick clrbit(cgp->cg_iused, ino); 5564359Smckusick cgp->cg_nifree++; 5574359Smckusick fs->fs_nifree++; 5584359Smckusick fs->fs_cs[cg].cs_nifree++; 5594359Smckusick if ((mode & IFMT) == IFDIR) { 5604359Smckusick cgp->cg_ndir--; 5614359Smckusick fs->fs_cs[cg].cs_ndir--; 5624359Smckusick } 5634359Smckusick fs->fs_fmod++; 5644359Smckusick bdwrite(bp); 5654359Smckusick } 5664359Smckusick 5674463Smckusic /* 5684463Smckusic * update the frsum fields to reflect addition or deletion 5694463Smckusic * of some frags 5704463Smckusic */ 5714463Smckusic fragacct(fragmap, fraglist, cnt) 5724472Smckusic int fragmap; 5734463Smckusic short fraglist[]; 5744463Smckusic int cnt; 5754463Smckusic { 5764463Smckusic int inblk; 5774463Smckusic register int field, subfield; 5784463Smckusic register int siz, pos; 5794463Smckusic 5804472Smckusic inblk = (int)(fragtbl[fragmap]) << 1; 5814463Smckusic fragmap <<= 1; 5824463Smckusic for (siz = 1; siz < FRAG; siz++) { 5834463Smckusic if (((1 << siz) & inblk) == 0) 5844463Smckusic continue; 5854463Smckusic field = around[siz]; 5864463Smckusic subfield = inside[siz]; 5874463Smckusic for (pos = siz; pos <= FRAG; pos++) { 5884463Smckusic if ((fragmap & field) == subfield) { 5894463Smckusic fraglist[siz] += cnt; 5904463Smckusic pos += siz; 5914463Smckusic field <<= siz; 5924463Smckusic subfield <<= siz; 5934463Smckusic } 5944463Smckusic field <<= 1; 5954463Smckusic subfield <<= 1; 5964463Smckusic } 5974463Smckusic } 5984463Smckusic } 5994463Smckusic 6004359Smckusick badblock(fs, bn) 6014359Smckusick register struct fs *fs; 6024359Smckusick daddr_t bn; 6034359Smckusick { 6044359Smckusick 6054359Smckusick if ((unsigned)bn >= fs->fs_size || bn < cgdmin(dtog(bn, fs), fs)) { 6064359Smckusick fserr(fs, "bad block"); 6074359Smckusick return (1); 6084359Smckusick } 6094359Smckusick return (0); 6104359Smckusick } 6114359Smckusick 6124359Smckusick /* 6134359Smckusick * getfs maps a device number into 6144359Smckusick * a pointer to the incore super 6154359Smckusick * block. The algorithm is a linear 6164359Smckusick * search through the mount table. 6174359Smckusick * A consistency check of the 6184359Smckusick * in core free-block and i-node 6194359Smckusick * counts is performed. 6204359Smckusick * 6214359Smckusick * panic: no fs -- the device is not mounted. 6224359Smckusick * this "cannot happen" 6234359Smckusick */ 6244359Smckusick struct fs * 6254359Smckusick getfs(dev) 6264359Smckusick dev_t dev; 6274359Smckusick { 6284359Smckusick register struct mount *mp; 6294359Smckusick register struct fs *fs; 6304359Smckusick 6314359Smckusick for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 6324359Smckusick if (mp->m_bufp != NULL && mp->m_dev == dev) { 6334359Smckusick fs = mp->m_bufp->b_un.b_fs; 6344359Smckusick if (fs->fs_magic != FS_MAGIC) 6354359Smckusick panic("getfs: bad magic"); 6364359Smckusick return (fs); 6374359Smckusick } 6384359Smckusick panic("getfs: no fs"); 6394359Smckusick return (NULL); 6404359Smckusick } 6414359Smckusick 6424359Smckusick /* 6434359Smckusick * Fserr prints the name of a file system 6444359Smckusick * with an error diagnostic, in the form 6454359Smckusick * fs: error message 6464359Smckusick */ 6474359Smckusick fserr(fs, cp) 6484359Smckusick struct fs *fs; 6494359Smckusick char *cp; 6504359Smckusick { 6514359Smckusick 6524359Smckusick printf("%s: %s\n", fs->fs_fsmnt, cp); 6534359Smckusick } 6544359Smckusick 6554359Smckusick /* 6564359Smckusick * Getfsx returns the index in the file system 6574359Smckusick * table of the specified device. The swap device 6584359Smckusick * is also assigned a pseudo-index. The index may 6594359Smckusick * be used as a compressed indication of the location 6604359Smckusick * of a block, recording 6614359Smckusick * <getfsx(dev),blkno> 6624359Smckusick * rather than 6634359Smckusick * <dev, blkno> 6644359Smckusick * provided the information need remain valid only 6654359Smckusick * as long as the file system is mounted. 6664359Smckusick */ 6674359Smckusick getfsx(dev) 6684359Smckusick dev_t dev; 6694359Smckusick { 6704359Smckusick register struct mount *mp; 6714359Smckusick 6724359Smckusick if (dev == swapdev) 6734359Smckusick return (MSWAPX); 6744359Smckusick for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 6754359Smckusick if (mp->m_dev == dev) 6764359Smckusick return (mp - &mount[0]); 6774359Smckusick return (-1); 6784359Smckusick } 6794359Smckusick 6804359Smckusick /* 6814359Smckusick * Update is the internal name of 'sync'. It goes through the disk 6824359Smckusick * queues to initiate sandbagged IO; goes through the inodes to write 6834359Smckusick * modified nodes; and it goes through the mount table to initiate modified 6844359Smckusick * super blocks. 6854359Smckusick */ 6864359Smckusick update() 6874359Smckusick { 6884359Smckusick register struct inode *ip; 6894359Smckusick register struct mount *mp; 6904359Smckusick register struct buf *bp; 6914359Smckusick struct fs *fs; 6924359Smckusick time_t tim; 6934359Smckusick int i; 6944359Smckusick 6954359Smckusick if (updlock) 6964359Smckusick return; 6974359Smckusick updlock++; 6984359Smckusick /* 6994359Smckusick * Write back modified superblocks. 7004359Smckusick * Consistency check that the superblock 7014359Smckusick * of each file system is still in the buffer cache. 7024359Smckusick */ 7034359Smckusick for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 7044359Smckusick if (mp->m_bufp != NULL) { 7054359Smckusick fs = mp->m_bufp->b_un.b_fs; 7064359Smckusick if (fs->fs_fmod == 0) 7074359Smckusick continue; 7084359Smckusick if (fs->fs_ronly != 0) 7094359Smckusick panic("update: rofs mod"); 7104426Smckusic bp = getblk(mp->m_dev, SBLOCK, BSIZE); 7114359Smckusick fs->fs_fmod = 0; 7124359Smckusick fs->fs_time = TIME; 7134359Smckusick if (bp->b_un.b_fs != fs) 7144359Smckusick panic("update: bad b_fs"); 7154359Smckusick bwrite(bp); 7164359Smckusick for (i = 0; i < cssize(fs); i += BSIZE) { 7174426Smckusic bp = getblk(mp->m_dev, csaddr(fs) + i / FSIZE, 7184426Smckusic BSIZE); 7194359Smckusick bcopy(fs->fs_cs + i, bp->b_un.b_addr, BSIZE); 7204359Smckusick bwrite(bp); 7214359Smckusick } 7224359Smckusick } 7234359Smckusick /* 7244359Smckusick * Write back each (modified) inode. 7254359Smckusick */ 7264359Smckusick for (ip = inode; ip < inodeNINODE; ip++) 7274359Smckusick if((ip->i_flag&ILOCK)==0 && ip->i_count) { 7284359Smckusick ip->i_flag |= ILOCK; 7294359Smckusick ip->i_count++; 7304359Smckusick tim = TIME; 7314359Smckusick iupdat(ip, &tim, &tim, 0); 7324359Smckusick iput(ip); 7334359Smckusick } 7344359Smckusick updlock = 0; 7354359Smckusick /* 7364359Smckusick * Force stale buffer cache information to be flushed, 7374359Smckusick * for all devices. 7384359Smckusick */ 7394359Smckusick bflush(NODEV); 7404359Smckusick } 741