14359Smckusick /* Copyright (c) 1981 Regents of the University of California */ 24359Smckusick 3*4472Smckusic static char vers[] = "@(#)lfs_alloc.c 1.5 10/07/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 174359Smckusick long hashalloc(); 184359Smckusick long alloccg(); 194359Smckusick long ialloccg(); 204359Smckusick 214359Smckusick struct buf * 224359Smckusick alloc(dev, ip, bpref, size) 234359Smckusick dev_t dev; 244463Smckusic register struct inode *ip; 254359Smckusick daddr_t bpref; 264359Smckusick int size; 274359Smckusick { 284359Smckusick daddr_t bno; 294359Smckusick register struct fs *fs; 304463Smckusic register struct buf *bp; 314359Smckusick int cg; 324359Smckusick 334463Smckusic if ((unsigned)size > BSIZE || size % FSIZE != 0) 344463Smckusic panic("alloc: bad size"); 354359Smckusick fs = getfs(dev); 364359Smckusick if (fs->fs_nbfree == 0 && size == BSIZE) 374359Smckusick goto nospace; 384359Smckusick if (bpref == 0) 394359Smckusick cg = itog(ip->i_number, fs); 404359Smckusick else 414359Smckusick cg = dtog(bpref, fs); 424359Smckusick bno = hashalloc(dev, fs, cg, (long)bpref, size, alloccg); 434359Smckusick if (bno == 0) 444359Smckusick goto nospace; 454426Smckusic bp = getblk(dev, bno, size); 464359Smckusick clrbuf(bp); 474359Smckusick return (bp); 484359Smckusick nospace: 494359Smckusick fserr(fs, "file system full"); 504359Smckusick uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); 514359Smckusick u.u_error = ENOSPC; 524359Smckusick return (NULL); 534359Smckusick } 544359Smckusick 554426Smckusic struct buf * 564463Smckusic realloccg(dev, ip, bprev, osize, nsize) 574426Smckusic dev_t dev; 584463Smckusic register struct inode *ip; 594463Smckusic daddr_t bprev; 604426Smckusic int osize, nsize; 614426Smckusic { 624426Smckusic daddr_t bno; 634426Smckusic register struct fs *fs; 644463Smckusic register struct buf *bp, *obp; 654463Smckusic caddr_t cp; 664426Smckusic int cg; 674426Smckusic 684463Smckusic if ((unsigned)osize > BSIZE || osize % FSIZE != 0 || 694463Smckusic (unsigned)nsize > BSIZE || nsize % FSIZE != 0) 704463Smckusic panic("realloccg: bad size"); 714426Smckusic fs = getfs(dev); 724463Smckusic if (bprev == 0) 734463Smckusic panic("realloccg: bad bprev"); 744426Smckusic else 754463Smckusic cg = dtog(bprev, fs); 764463Smckusic bno = fragextend(dev, fs, cg, (long)bprev, osize, nsize); 774463Smckusic if (bno != 0) { 784463Smckusic bp = bread(dev, bno, osize); 794463Smckusic bp->b_bcount = nsize; 804463Smckusic blkclr(bp->b_un.b_addr + osize, nsize - osize); 814463Smckusic return (bp); 824463Smckusic } 834463Smckusic bno = hashalloc(dev, fs, cg, (long)bprev, nsize, alloccg); 844463Smckusic if (bno != 0) { 854463Smckusic /* 864463Smckusic * make a new copy 874463Smckusic */ 884463Smckusic obp = bread(dev, bprev, osize); 894463Smckusic bp = getblk(dev, bno, nsize); 904463Smckusic cp = bp->b_un.b_addr; 914463Smckusic bp->b_un.b_addr = obp->b_un.b_addr; 924463Smckusic obp->b_un.b_addr = cp; 934463Smckusic obp->b_flags |= B_INVAL; 944463Smckusic brelse(obp); 954463Smckusic fre(dev, bprev, osize); 964463Smckusic blkclr(bp->b_un.b_addr + osize, nsize - osize); 974463Smckusic return(bp); 984463Smckusic } 994463Smckusic /* 1004463Smckusic * no space available 1014463Smckusic */ 1024426Smckusic fserr(fs, "file system full"); 1034426Smckusic uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); 1044426Smckusic u.u_error = ENOSPC; 1054426Smckusic return (NULL); 1064426Smckusic } 1074426Smckusic 1084359Smckusick struct inode * 1094359Smckusick ialloc(dev, ipref, mode) 1104359Smckusick dev_t dev; 1114359Smckusick ino_t ipref; 1124359Smckusick int mode; 1134359Smckusick { 1144359Smckusick daddr_t ino; 1154359Smckusick register struct fs *fs; 1164359Smckusick register struct inode *ip; 1174359Smckusick int cg; 1184359Smckusick 1194359Smckusick fs = getfs(dev); 1204359Smckusick if (fs->fs_nifree == 0) 1214359Smckusick goto noinodes; 1224359Smckusick cg = itog(ipref, fs); 1234359Smckusick ino = hashalloc(dev, fs, cg, (long)ipref, mode, ialloccg); 1244359Smckusick if (ino == 0) 1254359Smckusick goto noinodes; 1264359Smckusick ip = iget(dev, ino); 1274359Smckusick if (ip == NULL) { 1284359Smckusick ifree(dev, ino); 1294359Smckusick return (NULL); 1304359Smckusick } 1314359Smckusick if (ip->i_mode) 1324359Smckusick panic("ialloc: dup alloc"); 1334359Smckusick return (ip); 1344359Smckusick noinodes: 1354359Smckusick fserr(fs, "out of inodes"); 1364359Smckusick uprintf("\n%s: create failed, no inodes free\n", fs->fs_fsmnt); 1374359Smckusick u.u_error = ENOSPC; 1384359Smckusick return (NULL); 1394359Smckusick } 1404359Smckusick 1414359Smckusick dipref(dev) 1424359Smckusick dev_t dev; 1434359Smckusick { 1444359Smckusick register struct fs *fs; 1454359Smckusick int cg, minndir, mincg; 1464359Smckusick 1474359Smckusick fs = getfs(dev); 1484359Smckusick minndir = fs->fs_cs[0].cs_ndir; 1494359Smckusick mincg = 0; 1504359Smckusick for (cg = 1; cg < fs->fs_ncg; cg++) 1514359Smckusick if (fs->fs_cs[cg].cs_ndir < minndir) { 1524359Smckusick mincg = cg; 1534359Smckusick minndir = fs->fs_cs[cg].cs_ndir; 1544359Smckusick if (minndir == 0) 1554359Smckusick break; 1564359Smckusick } 1574359Smckusick return (fs->fs_ipg * mincg); 1584359Smckusick } 1594359Smckusick 1604359Smckusick long 1614359Smckusick hashalloc(dev, fs, cg, pref, size, allocator) 1624359Smckusick dev_t dev; 1634359Smckusick register struct fs *fs; 1644359Smckusick int cg; 1654359Smckusick long pref; 1664359Smckusick int size; /* size for data blocks, mode for inodes */ 1674359Smckusick long (*allocator)(); 1684359Smckusick { 1694359Smckusick long result; 1704359Smckusick int i, icg = cg; 1714359Smckusick 1724359Smckusick /* 1734359Smckusick * 1: preferred cylinder group 1744359Smckusick */ 1754359Smckusick result = (*allocator)(dev, fs, cg, pref, size); 1764359Smckusick if (result) 1774359Smckusick return (result); 1784359Smckusick /* 1794359Smckusick * 2: quadratic rehash 1804359Smckusick */ 1814359Smckusick for (i = 1; i < fs->fs_ncg; i *= 2) { 1824359Smckusick cg += i; 1834359Smckusick if (cg >= fs->fs_ncg) 1844359Smckusick cg -= fs->fs_ncg; 1854359Smckusick result = (*allocator)(dev, fs, cg, 0, size); 1864359Smckusick if (result) 1874359Smckusick return (result); 1884359Smckusick } 1894359Smckusick /* 1904359Smckusick * 3: brute force search 1914359Smckusick */ 1924359Smckusick cg = icg; 1934359Smckusick for (i = 0; i < fs->fs_ncg; i++) { 1944359Smckusick result = (*allocator)(dev, fs, cg, 0, size); 1954359Smckusick if (result) 1964359Smckusick return (result); 1974359Smckusick cg++; 1984359Smckusick if (cg == fs->fs_ncg) 1994359Smckusick cg = 0; 2004359Smckusick } 2014359Smckusick return (0); 2024359Smckusick } 2034359Smckusick 2044359Smckusick daddr_t 2054463Smckusic fragextend(dev, fs, cg, bprev, osize, nsize) 2064426Smckusic dev_t dev; 2074426Smckusic register struct fs *fs; 2084426Smckusic int cg; 2094463Smckusic long bprev; 2104426Smckusic int osize, nsize; 2114426Smckusic { 2124463Smckusic register struct buf *bp; 2134463Smckusic register struct cg *cgp; 2144463Smckusic long bno; 2154463Smckusic int frags, bbase; 2164426Smckusic int i; 2174426Smckusic 2184463Smckusic frags = nsize / FSIZE; 2194463Smckusic bbase = bprev % FRAG; 2204463Smckusic if (bbase > (bprev + frags - 1) % FRAG) { 2214463Smckusic /* cannot extend across a block boundry */ 2224463Smckusic return (0); 2234463Smckusic } 2244426Smckusic bp = bread(dev, cgtod(cg, fs), BSIZE); 2254426Smckusic if (bp->b_flags & B_ERROR) 2264426Smckusic return (0); 2274426Smckusic cgp = bp->b_un.b_cg; 2284463Smckusic bno = bprev % fs->fs_fpg; 2294463Smckusic for (i = osize / FSIZE; i < frags; i++) { 2304463Smckusic if (isclr(cgp->cg_free, bno + i)) 2314463Smckusic break; 2324463Smckusic } 2334463Smckusic if (i == frags) { 2344463Smckusic /* 2354463Smckusic * the current fragment can be extended 2364463Smckusic * deduct the count on fragment being extended into 2374463Smckusic * increase the count on the remaining fragment (if any) 2384463Smckusic * allocate the extended piece 2394463Smckusic */ 2404463Smckusic for (i = frags; i < FRAG - bbase; i++) 2414463Smckusic if (isclr(cgp->cg_free, bno + i)) 2424426Smckusic break; 2434463Smckusic cgp->cg_frsum[i - osize / FSIZE]--; 2444463Smckusic if (i != frags) 2454463Smckusic cgp->cg_frsum[i - frags]++; 2464463Smckusic for (i = osize / FSIZE; i < frags; i++) { 2474463Smckusic clrbit(cgp->cg_free, bno + i); 2484463Smckusic cgp->cg_nffree--; 2494463Smckusic fs->fs_nffree--; 2504426Smckusic } 2514463Smckusic fs->fs_fmod++; 2524463Smckusic bdwrite(bp); 2534463Smckusic return (bprev); 2544426Smckusic } 2554426Smckusic brelse(bp); 2564426Smckusic return (0); 2574426Smckusic } 2584426Smckusic 2594426Smckusic daddr_t 2604359Smckusick alloccg(dev, fs, cg, bpref, size) 2614359Smckusick dev_t dev; 2624463Smckusic register struct fs *fs; 2634359Smckusick int cg; 2644359Smckusick daddr_t bpref; 2654359Smckusick int size; 2664359Smckusick { 2674463Smckusic register struct buf *bp; 2684463Smckusic register struct cg *cgp; 2694463Smckusic int bno, frags; 2704463Smckusic int allocsiz; 2714463Smckusic int start, len, loc; 2724463Smckusic int blk, field, subfield, pos; 2734463Smckusic register int i; 2744359Smckusick 2754426Smckusic bp = bread(dev, cgtod(cg, fs), BSIZE); 2764359Smckusick if (bp->b_flags & B_ERROR) 2774359Smckusick return (0); 2784359Smckusick cgp = bp->b_un.b_cg; 2794463Smckusic if (size == BSIZE) { 2804463Smckusic if (cgp->cg_nbfree == 0) { 2814463Smckusic brelse(bp); 2824463Smckusic return (0); 2834463Smckusic } 2844463Smckusic bno = alloccgblk(dev, fs, cgp, bpref); 2854463Smckusic bdwrite(bp); 2864463Smckusic return (bno); 2874463Smckusic } 2884463Smckusic /* 2894463Smckusic * check to see if any fragments are already available 2904463Smckusic * allocsiz is the size which will be allocated, hacking 2914463Smckusic * it down to a smaller size if necessary 2924463Smckusic */ 2934463Smckusic frags = size / FSIZE; 2944463Smckusic for (allocsiz = frags; allocsiz < FRAG; allocsiz++) 2954463Smckusic if (cgp->cg_frsum[allocsiz] != 0) 2964463Smckusic break; 2974463Smckusic if (allocsiz == FRAG) { 2984463Smckusic /* 2994463Smckusic * no fragments were available, so a block will be 3004463Smckusic * allocated, and hacked up 3014463Smckusic */ 3024463Smckusic if (cgp->cg_nbfree == 0) { 3034463Smckusic brelse(bp); 3044463Smckusic return (0); 3054463Smckusic } 3064463Smckusic bno = alloccgblk(dev, fs, cgp, bpref); 3074463Smckusic bpref = bno % fs->fs_fpg; 3084463Smckusic for (i = frags; i < FRAG; i++) 3094463Smckusic setbit(cgp->cg_free, bpref + i); 3104463Smckusic i = FRAG - frags; 3114463Smckusic cgp->cg_nffree += i; 3124463Smckusic fs->fs_nffree += i; 3134463Smckusic cgp->cg_frsum[i]++; 3144463Smckusic bdwrite(bp); 3154463Smckusic return (bno); 3164463Smckusic } 3174463Smckusic /* 3184463Smckusic * find the fragment by searching through the free block 3194463Smckusic * map for an appropriate bit pattern 3204463Smckusic */ 3214463Smckusic if (bpref) 3224463Smckusic start = bpref % fs->fs_fpg / NBBY; 3234463Smckusic else 3244463Smckusic start = cgp->cg_frotor / NBBY; 3254463Smckusic len = roundup(fs->fs_fpg - 1, NBBY) / NBBY - start; 3264463Smckusic loc = scanc(len, &cgp->cg_free[start], fragtbl, 1 << (allocsiz - 1)); 3274463Smckusic if (loc == 0) { 3284463Smckusic len = start - 1; 3294463Smckusic start = (cgdmin(cg, fs) - cgbase(cg, fs)) / NBBY; 3304463Smckusic loc = scanc(len, &cgp->cg_free[start], fragtbl, 3314463Smckusic 1 << (allocsiz - 1)); 3324463Smckusic if (loc == 0) 3334463Smckusic panic("alloccg: can't find frag"); 3344463Smckusic } 3354463Smckusic bno = (start + len - loc) * NBBY; 3364463Smckusic cgp->cg_frotor = bno; 3374463Smckusic /* 3384463Smckusic * found the byte in the map 3394463Smckusic * sift through the bits to find the selected frag 3404463Smckusic */ 3414463Smckusic for (i = 0; i < NBBY; i += FRAG) { 3424463Smckusic blk = (cgp->cg_free[bno / NBBY] >> i) & (0xff >> NBBY - FRAG); 3434463Smckusic blk <<= 1; 3444463Smckusic field = around[allocsiz]; 3454463Smckusic subfield = inside[allocsiz]; 3464463Smckusic for (pos = 0; pos <= FRAG - allocsiz; pos++) { 3474463Smckusic if ((blk & field) == subfield) { 3484463Smckusic bno += i + pos; 3494463Smckusic goto gotit; 3504463Smckusic } 3514463Smckusic field <<= 1; 3524463Smckusic subfield <<= 1; 3534463Smckusic } 3544463Smckusic } 3554463Smckusic panic("alloccg: frag not in block"); 3564463Smckusic gotit: 3574463Smckusic for (i = 0; i < frags; i++) 3584463Smckusic clrbit(cgp->cg_free, bno + i); 3594463Smckusic cgp->cg_nffree -= frags; 3604463Smckusic fs->fs_nffree -= frags; 3614463Smckusic cgp->cg_frsum[allocsiz]--; 3624463Smckusic if (frags != allocsiz) 3634463Smckusic cgp->cg_frsum[allocsiz - frags]++; 3644463Smckusic bdwrite(bp); 3654463Smckusic return (cg * fs->fs_fpg + bno); 3664463Smckusic } 3674463Smckusic 3684463Smckusic daddr_t 3694463Smckusic alloccgblk(dev, fs, cgp, bpref) 3704463Smckusic dev_t dev; 3714463Smckusic struct fs *fs; 3724463Smckusic register struct cg *cgp; 3734463Smckusic daddr_t bpref; 3744463Smckusic { 3754463Smckusic register int i; 3764463Smckusic 3774359Smckusick if (bpref) { 3784463Smckusic bpref &= ~(FRAG - 1); 3794359Smckusick bpref %= fs->fs_fpg; 3804359Smckusick if (isblock(cgp->cg_free, bpref/FRAG)) 3814359Smckusick goto gotit; 3824359Smckusick } else 3834359Smckusick bpref = cgp->cg_rotor; 3844359Smckusick for (i = 0; i < cgp->cg_ndblk; i += FRAG) { 3854359Smckusick bpref += FRAG; 3864359Smckusick if (bpref >= cgp->cg_ndblk) 3874359Smckusick bpref = 0; 3884359Smckusick if (isblock(cgp->cg_free, bpref/FRAG)) { 3894359Smckusick cgp->cg_rotor = bpref; 3904359Smckusick goto gotit; 3914359Smckusick } 3924359Smckusick } 3934463Smckusic panic("alloccgblk: can't find a blk"); 3944359Smckusick return (0); 3954359Smckusick gotit: 3964463Smckusic clrblock(cgp->cg_free, bpref/FRAG); 3974463Smckusic cgp->cg_nbfree--; 3984463Smckusic fs->fs_nbfree--; 3994463Smckusic fs->fs_cs[cgp->cg_cgx].cs_nbfree--; 4004463Smckusic i = bpref * NSPF; 4014463Smckusic cgp->cg_b[i/fs->fs_spc][i%fs->fs_nsect*NRPOS/fs->fs_nsect]--; 4024359Smckusick fs->fs_fmod++; 4034463Smckusic return (cgp->cg_cgx * fs->fs_fpg + bpref); 4044359Smckusick } 4054359Smckusick 4064359Smckusick long 4074359Smckusick ialloccg(dev, fs, cg, ipref, mode) 4084359Smckusick dev_t dev; 4094463Smckusic register struct fs *fs; 4104359Smckusick int cg; 4114359Smckusick daddr_t ipref; 4124359Smckusick int mode; 4134359Smckusick { 4144463Smckusic register struct buf *bp; 4154463Smckusic register struct cg *cgp; 4164359Smckusick int i; 4174359Smckusick 4184426Smckusic bp = bread(dev, cgtod(cg, fs), BSIZE); 4194359Smckusick if (bp->b_flags & B_ERROR) 4204359Smckusick return (0); 4214359Smckusick cgp = bp->b_un.b_cg; 4224359Smckusick if (cgp->cg_nifree == 0) { 4234359Smckusick brelse(bp); 4244359Smckusick return (0); 4254359Smckusick } 4264359Smckusick if (ipref) { 4274359Smckusick ipref %= fs->fs_ipg; 4284359Smckusick if (isclr(cgp->cg_iused, ipref)) 4294359Smckusick goto gotit; 4304359Smckusick } else 4314359Smckusick ipref = cgp->cg_irotor; 4324359Smckusick for (i = 0; i < fs->fs_ipg; i++) { 4334359Smckusick ipref++; 4344359Smckusick if (ipref >= fs->fs_ipg) 4354359Smckusick ipref = 0; 4364359Smckusick if (isclr(cgp->cg_iused, ipref)) { 4374359Smckusick cgp->cg_irotor = ipref; 4384359Smckusick goto gotit; 4394359Smckusick } 4404359Smckusick } 4414359Smckusick brelse(bp); 4424359Smckusick return (0); 4434359Smckusick gotit: 4444359Smckusick setbit(cgp->cg_iused, ipref); 4454359Smckusick cgp->cg_nifree--; 4464359Smckusick fs->fs_nifree--; 4474359Smckusick fs->fs_cs[cg].cs_nifree--; 4484359Smckusick fs->fs_fmod++; 4494359Smckusick if ((mode & IFMT) == IFDIR) { 4504359Smckusick cgp->cg_ndir++; 4514359Smckusick fs->fs_cs[cg].cs_ndir++; 4524359Smckusick } 4534359Smckusick bdwrite(bp); 4544359Smckusick return (cg * fs->fs_ipg + ipref); 4554359Smckusick } 4564359Smckusick 4574359Smckusick fre(dev, bno, size) 4584359Smckusick dev_t dev; 4594359Smckusick daddr_t bno; 4604359Smckusick int size; 4614359Smckusick { 4624359Smckusick register struct fs *fs; 4634359Smckusick register struct cg *cgp; 4644359Smckusick register struct buf *bp; 4654463Smckusic int cg, blk, frags, bbase; 4664463Smckusic register int i; 4674359Smckusick 4684426Smckusic if ((unsigned)size > BSIZE || size % FSIZE != 0) 4694426Smckusic panic("free: bad size"); 4704359Smckusick fs = getfs(dev); 4714359Smckusick cg = dtog(bno, fs); 4724359Smckusick if (badblock(fs, bno)) 4734359Smckusick return; 4744426Smckusic bp = bread(dev, cgtod(cg, fs), BSIZE); 4754359Smckusick if (bp->b_flags & B_ERROR) 4764359Smckusick return; 4774359Smckusick cgp = bp->b_un.b_cg; 4784359Smckusick bno %= fs->fs_fpg; 4794426Smckusic if (size == BSIZE) { 4804426Smckusic if (isblock(cgp->cg_free, bno/FRAG)) 4814426Smckusic panic("free: freeing free block"); 4824426Smckusic setblock(cgp->cg_free, bno/FRAG); 4834426Smckusic cgp->cg_nbfree++; 4844426Smckusic fs->fs_nbfree++; 4854426Smckusic fs->fs_cs[cg].cs_nbfree++; 4864426Smckusic i = bno * NSPF; 4874426Smckusic cgp->cg_b[i/fs->fs_spc][i%fs->fs_nsect*NRPOS/fs->fs_nsect]++; 4884426Smckusic } else { 4894463Smckusic bbase = bno - (bno % FRAG); 4904463Smckusic /* 4914463Smckusic * decrement the counts associated with the old frags 4924463Smckusic */ 4934463Smckusic blk = ((cgp->cg_free[bbase / NBBY] >> (bbase % NBBY)) & 4944463Smckusic (0xff >> (NBBY - FRAG))); 4954463Smckusic fragacct(blk, cgp->cg_frsum, -1); 4964463Smckusic /* 4974463Smckusic * deallocate the fragment 4984463Smckusic */ 4994463Smckusic frags = size / FSIZE; 5004463Smckusic for (i = 0; i < frags; i++) { 5014426Smckusic if (isset(cgp->cg_free, bno + i)) 5024426Smckusic panic("free: freeing free frag"); 5034426Smckusic setbit(cgp->cg_free, bno + i); 5044426Smckusic cgp->cg_nffree++; 5054426Smckusic fs->fs_nffree++; 5064426Smckusic } 5074463Smckusic /* 5084463Smckusic * add back in counts associated with the new frags 5094463Smckusic */ 5104463Smckusic blk = ((cgp->cg_free[bbase / NBBY] >> (bbase % NBBY)) & 5114463Smckusic (0xff >> (NBBY - FRAG))); 5124463Smckusic fragacct(blk, cgp->cg_frsum, 1); 5134463Smckusic /* 5144463Smckusic * if a complete block has been reassembled, account for it 5154463Smckusic */ 5164463Smckusic if (isblock(cgp->cg_free, bbase / FRAG)) { 5174426Smckusic cgp->cg_nffree -= FRAG; 5184426Smckusic fs->fs_nffree -= FRAG; 5194426Smckusic cgp->cg_nbfree++; 5204426Smckusic fs->fs_nbfree++; 5214426Smckusic fs->fs_cs[cg].cs_nbfree++; 5224463Smckusic i = bbase * NSPF; 5234426Smckusic cgp->cg_b[i / fs->fs_spc] 5244426Smckusic [i % fs->fs_nsect * NRPOS / fs->fs_nsect]++; 5254426Smckusic } 5264426Smckusic } 5274359Smckusick fs->fs_fmod++; 5284359Smckusick bdwrite(bp); 5294359Smckusick } 5304359Smckusick 5314359Smckusick ifree(dev, ino, mode) 5324359Smckusick dev_t dev; 5334359Smckusick ino_t ino; 5344359Smckusick int mode; 5354359Smckusick { 5364359Smckusick register struct fs *fs; 5374359Smckusick register struct cg *cgp; 5384359Smckusick register struct buf *bp; 5394359Smckusick int i; 5404359Smckusick int cg; 5414359Smckusick 5424359Smckusick fs = getfs(dev); 5434359Smckusick if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg) 5444359Smckusick panic("ifree: range"); 5454359Smckusick cg = itog(ino, fs); 5464426Smckusic bp = bread(dev, cgtod(cg, fs), BSIZE); 5474359Smckusick if (bp->b_flags & B_ERROR) 5484359Smckusick return; 5494359Smckusick cgp = bp->b_un.b_cg; 5504359Smckusick ino %= fs->fs_ipg; 5514359Smckusick if (isclr(cgp->cg_iused, ino)) 5524359Smckusick panic("ifree: freeing free inode"); 5534359Smckusick clrbit(cgp->cg_iused, ino); 5544359Smckusick cgp->cg_nifree++; 5554359Smckusick fs->fs_nifree++; 5564359Smckusick fs->fs_cs[cg].cs_nifree++; 5574359Smckusick if ((mode & IFMT) == IFDIR) { 5584359Smckusick cgp->cg_ndir--; 5594359Smckusick fs->fs_cs[cg].cs_ndir--; 5604359Smckusick } 5614359Smckusick fs->fs_fmod++; 5624359Smckusick bdwrite(bp); 5634359Smckusick } 5644359Smckusick 5654463Smckusic /* 5664463Smckusic * update the frsum fields to reflect addition or deletion 5674463Smckusic * of some frags 5684463Smckusic */ 5694463Smckusic fragacct(fragmap, fraglist, cnt) 570*4472Smckusic int fragmap; 5714463Smckusic short fraglist[]; 5724463Smckusic int cnt; 5734463Smckusic { 5744463Smckusic int inblk; 5754463Smckusic register int field, subfield; 5764463Smckusic register int siz, pos; 5774463Smckusic 578*4472Smckusic inblk = (int)(fragtbl[fragmap]) << 1; 5794463Smckusic fragmap <<= 1; 5804463Smckusic for (siz = 1; siz < FRAG; siz++) { 5814463Smckusic if (((1 << siz) & inblk) == 0) 5824463Smckusic continue; 5834463Smckusic field = around[siz]; 5844463Smckusic subfield = inside[siz]; 5854463Smckusic for (pos = siz; pos <= FRAG; pos++) { 5864463Smckusic if ((fragmap & field) == subfield) { 5874463Smckusic fraglist[siz] += cnt; 5884463Smckusic pos += siz; 5894463Smckusic field <<= siz; 5904463Smckusic subfield <<= siz; 5914463Smckusic } 5924463Smckusic field <<= 1; 5934463Smckusic subfield <<= 1; 5944463Smckusic } 5954463Smckusic } 5964463Smckusic } 5974463Smckusic 5984359Smckusick badblock(fs, bn) 5994359Smckusick register struct fs *fs; 6004359Smckusick daddr_t bn; 6014359Smckusick { 6024359Smckusick 6034359Smckusick if ((unsigned)bn >= fs->fs_size || bn < cgdmin(dtog(bn, fs), fs)) { 6044359Smckusick fserr(fs, "bad block"); 6054359Smckusick return (1); 6064359Smckusick } 6074359Smckusick return (0); 6084359Smckusick } 6094359Smckusick 6104359Smckusick /* 6114359Smckusick * getfs maps a device number into 6124359Smckusick * a pointer to the incore super 6134359Smckusick * block. The algorithm is a linear 6144359Smckusick * search through the mount table. 6154359Smckusick * A consistency check of the 6164359Smckusick * in core free-block and i-node 6174359Smckusick * counts is performed. 6184359Smckusick * 6194359Smckusick * panic: no fs -- the device is not mounted. 6204359Smckusick * this "cannot happen" 6214359Smckusick */ 6224359Smckusick struct fs * 6234359Smckusick getfs(dev) 6244359Smckusick dev_t dev; 6254359Smckusick { 6264359Smckusick register struct mount *mp; 6274359Smckusick register struct fs *fs; 6284359Smckusick 6294359Smckusick for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 6304359Smckusick if (mp->m_bufp != NULL && mp->m_dev == dev) { 6314359Smckusick fs = mp->m_bufp->b_un.b_fs; 6324359Smckusick if (fs->fs_magic != FS_MAGIC) 6334359Smckusick panic("getfs: bad magic"); 6344359Smckusick return (fs); 6354359Smckusick } 6364359Smckusick panic("getfs: no fs"); 6374359Smckusick return (NULL); 6384359Smckusick } 6394359Smckusick 6404359Smckusick /* 6414359Smckusick * Fserr prints the name of a file system 6424359Smckusick * with an error diagnostic, in the form 6434359Smckusick * fs: error message 6444359Smckusick */ 6454359Smckusick fserr(fs, cp) 6464359Smckusick struct fs *fs; 6474359Smckusick char *cp; 6484359Smckusick { 6494359Smckusick 6504359Smckusick printf("%s: %s\n", fs->fs_fsmnt, cp); 6514359Smckusick } 6524359Smckusick 6534359Smckusick /* 6544359Smckusick * Getfsx returns the index in the file system 6554359Smckusick * table of the specified device. The swap device 6564359Smckusick * is also assigned a pseudo-index. The index may 6574359Smckusick * be used as a compressed indication of the location 6584359Smckusick * of a block, recording 6594359Smckusick * <getfsx(dev),blkno> 6604359Smckusick * rather than 6614359Smckusick * <dev, blkno> 6624359Smckusick * provided the information need remain valid only 6634359Smckusick * as long as the file system is mounted. 6644359Smckusick */ 6654359Smckusick getfsx(dev) 6664359Smckusick dev_t dev; 6674359Smckusick { 6684359Smckusick register struct mount *mp; 6694359Smckusick 6704359Smckusick if (dev == swapdev) 6714359Smckusick return (MSWAPX); 6724359Smckusick for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 6734359Smckusick if (mp->m_dev == dev) 6744359Smckusick return (mp - &mount[0]); 6754359Smckusick return (-1); 6764359Smckusick } 6774359Smckusick 6784359Smckusick /* 6794359Smckusick * Update is the internal name of 'sync'. It goes through the disk 6804359Smckusick * queues to initiate sandbagged IO; goes through the inodes to write 6814359Smckusick * modified nodes; and it goes through the mount table to initiate modified 6824359Smckusick * super blocks. 6834359Smckusick */ 6844359Smckusick update() 6854359Smckusick { 6864359Smckusick register struct inode *ip; 6874359Smckusick register struct mount *mp; 6884359Smckusick register struct buf *bp; 6894359Smckusick struct fs *fs; 6904359Smckusick time_t tim; 6914359Smckusick int i; 6924359Smckusick 6934359Smckusick if (updlock) 6944359Smckusick return; 6954359Smckusick updlock++; 6964359Smckusick /* 6974359Smckusick * Write back modified superblocks. 6984359Smckusick * Consistency check that the superblock 6994359Smckusick * of each file system is still in the buffer cache. 7004359Smckusick */ 7014359Smckusick for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 7024359Smckusick if (mp->m_bufp != NULL) { 7034359Smckusick fs = mp->m_bufp->b_un.b_fs; 7044359Smckusick if (fs->fs_fmod == 0) 7054359Smckusick continue; 7064359Smckusick if (fs->fs_ronly != 0) 7074359Smckusick panic("update: rofs mod"); 7084426Smckusic bp = getblk(mp->m_dev, SBLOCK, BSIZE); 7094359Smckusick fs->fs_fmod = 0; 7104359Smckusick fs->fs_time = TIME; 7114359Smckusick if (bp->b_un.b_fs != fs) 7124359Smckusick panic("update: bad b_fs"); 7134359Smckusick bwrite(bp); 7144359Smckusick for (i = 0; i < cssize(fs); i += BSIZE) { 7154426Smckusic bp = getblk(mp->m_dev, csaddr(fs) + i / FSIZE, 7164426Smckusic BSIZE); 7174359Smckusick bcopy(fs->fs_cs + i, bp->b_un.b_addr, BSIZE); 7184359Smckusick bwrite(bp); 7194359Smckusick } 7204359Smckusick } 7214359Smckusick /* 7224359Smckusick * Write back each (modified) inode. 7234359Smckusick */ 7244359Smckusick for (ip = inode; ip < inodeNINODE; ip++) 7254359Smckusick if((ip->i_flag&ILOCK)==0 && ip->i_count) { 7264359Smckusick ip->i_flag |= ILOCK; 7274359Smckusick ip->i_count++; 7284359Smckusick tim = TIME; 7294359Smckusick iupdat(ip, &tim, &tim, 0); 7304359Smckusick iput(ip); 7314359Smckusick } 7324359Smckusick updlock = 0; 7334359Smckusick /* 7344359Smckusick * Force stale buffer cache information to be flushed, 7354359Smckusick * for all devices. 7364359Smckusick */ 7374359Smckusick bflush(NODEV); 7384359Smckusick } 739