14359Smckusick /* Copyright (c) 1981 Regents of the University of California */ 24359Smckusick 3*4463Smckusic static char vers[] = "@(#)lfs_alloc.c 1.4 10/05/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; 24*4463Smckusic register struct inode *ip; 254359Smckusick daddr_t bpref; 264359Smckusick int size; 274359Smckusick { 284359Smckusick daddr_t bno; 294359Smckusick register struct fs *fs; 30*4463Smckusic register struct buf *bp; 314359Smckusick int cg; 324359Smckusick 33*4463Smckusic if ((unsigned)size > BSIZE || size % FSIZE != 0) 34*4463Smckusic 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 * 56*4463Smckusic realloccg(dev, ip, bprev, osize, nsize) 574426Smckusic dev_t dev; 58*4463Smckusic register struct inode *ip; 59*4463Smckusic daddr_t bprev; 604426Smckusic int osize, nsize; 614426Smckusic { 624426Smckusic daddr_t bno; 634426Smckusic register struct fs *fs; 64*4463Smckusic register struct buf *bp, *obp; 65*4463Smckusic caddr_t cp; 664426Smckusic int cg; 674426Smckusic 68*4463Smckusic if ((unsigned)osize > BSIZE || osize % FSIZE != 0 || 69*4463Smckusic (unsigned)nsize > BSIZE || nsize % FSIZE != 0) 70*4463Smckusic panic("realloccg: bad size"); 714426Smckusic fs = getfs(dev); 72*4463Smckusic if (bprev == 0) 73*4463Smckusic panic("realloccg: bad bprev"); 744426Smckusic else 75*4463Smckusic cg = dtog(bprev, fs); 76*4463Smckusic bno = fragextend(dev, fs, cg, (long)bprev, osize, nsize); 77*4463Smckusic if (bno != 0) { 78*4463Smckusic bp = bread(dev, bno, osize); 79*4463Smckusic bp->b_bcount = nsize; 80*4463Smckusic blkclr(bp->b_un.b_addr + osize, nsize - osize); 81*4463Smckusic return (bp); 82*4463Smckusic } 83*4463Smckusic bno = hashalloc(dev, fs, cg, (long)bprev, nsize, alloccg); 84*4463Smckusic if (bno != 0) { 85*4463Smckusic /* 86*4463Smckusic * make a new copy 87*4463Smckusic */ 88*4463Smckusic obp = bread(dev, bprev, osize); 89*4463Smckusic bp = getblk(dev, bno, nsize); 90*4463Smckusic cp = bp->b_un.b_addr; 91*4463Smckusic bp->b_un.b_addr = obp->b_un.b_addr; 92*4463Smckusic obp->b_un.b_addr = cp; 93*4463Smckusic obp->b_flags |= B_INVAL; 94*4463Smckusic brelse(obp); 95*4463Smckusic fre(dev, bprev, osize); 96*4463Smckusic blkclr(bp->b_un.b_addr + osize, nsize - osize); 97*4463Smckusic return(bp); 98*4463Smckusic } 99*4463Smckusic /* 100*4463Smckusic * no space available 101*4463Smckusic */ 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 205*4463Smckusic fragextend(dev, fs, cg, bprev, osize, nsize) 2064426Smckusic dev_t dev; 2074426Smckusic register struct fs *fs; 2084426Smckusic int cg; 209*4463Smckusic long bprev; 2104426Smckusic int osize, nsize; 2114426Smckusic { 212*4463Smckusic register struct buf *bp; 213*4463Smckusic register struct cg *cgp; 214*4463Smckusic long bno; 215*4463Smckusic int frags, bbase; 2164426Smckusic int i; 2174426Smckusic 218*4463Smckusic frags = nsize / FSIZE; 219*4463Smckusic bbase = bprev % FRAG; 220*4463Smckusic if (bbase > (bprev + frags - 1) % FRAG) { 221*4463Smckusic /* cannot extend across a block boundry */ 222*4463Smckusic return (0); 223*4463Smckusic } 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; 228*4463Smckusic bno = bprev % fs->fs_fpg; 229*4463Smckusic for (i = osize / FSIZE; i < frags; i++) { 230*4463Smckusic if (isclr(cgp->cg_free, bno + i)) 231*4463Smckusic break; 232*4463Smckusic } 233*4463Smckusic if (i == frags) { 234*4463Smckusic /* 235*4463Smckusic * the current fragment can be extended 236*4463Smckusic * deduct the count on fragment being extended into 237*4463Smckusic * increase the count on the remaining fragment (if any) 238*4463Smckusic * allocate the extended piece 239*4463Smckusic */ 240*4463Smckusic for (i = frags; i < FRAG - bbase; i++) 241*4463Smckusic if (isclr(cgp->cg_free, bno + i)) 2424426Smckusic break; 243*4463Smckusic cgp->cg_frsum[i - osize / FSIZE]--; 244*4463Smckusic if (i != frags) 245*4463Smckusic cgp->cg_frsum[i - frags]++; 246*4463Smckusic for (i = osize / FSIZE; i < frags; i++) { 247*4463Smckusic clrbit(cgp->cg_free, bno + i); 248*4463Smckusic cgp->cg_nffree--; 249*4463Smckusic fs->fs_nffree--; 2504426Smckusic } 251*4463Smckusic fs->fs_fmod++; 252*4463Smckusic bdwrite(bp); 253*4463Smckusic 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; 262*4463Smckusic register struct fs *fs; 2634359Smckusick int cg; 2644359Smckusick daddr_t bpref; 2654359Smckusick int size; 2664359Smckusick { 267*4463Smckusic register struct buf *bp; 268*4463Smckusic register struct cg *cgp; 269*4463Smckusic int bno, frags; 270*4463Smckusic int allocsiz; 271*4463Smckusic int start, len, loc; 272*4463Smckusic int blk, field, subfield, pos; 273*4463Smckusic 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; 279*4463Smckusic if (size == BSIZE) { 280*4463Smckusic if (cgp->cg_nbfree == 0) { 281*4463Smckusic brelse(bp); 282*4463Smckusic return (0); 283*4463Smckusic } 284*4463Smckusic bno = alloccgblk(dev, fs, cgp, bpref); 285*4463Smckusic bdwrite(bp); 286*4463Smckusic return (bno); 287*4463Smckusic } 288*4463Smckusic /* 289*4463Smckusic * check to see if any fragments are already available 290*4463Smckusic * allocsiz is the size which will be allocated, hacking 291*4463Smckusic * it down to a smaller size if necessary 292*4463Smckusic */ 293*4463Smckusic frags = size / FSIZE; 294*4463Smckusic for (allocsiz = frags; allocsiz < FRAG; allocsiz++) 295*4463Smckusic if (cgp->cg_frsum[allocsiz] != 0) 296*4463Smckusic break; 297*4463Smckusic if (allocsiz == FRAG) { 298*4463Smckusic /* 299*4463Smckusic * no fragments were available, so a block will be 300*4463Smckusic * allocated, and hacked up 301*4463Smckusic */ 302*4463Smckusic if (cgp->cg_nbfree == 0) { 303*4463Smckusic brelse(bp); 304*4463Smckusic return (0); 305*4463Smckusic } 306*4463Smckusic bno = alloccgblk(dev, fs, cgp, bpref); 307*4463Smckusic bpref = bno % fs->fs_fpg; 308*4463Smckusic for (i = frags; i < FRAG; i++) 309*4463Smckusic setbit(cgp->cg_free, bpref + i); 310*4463Smckusic i = FRAG - frags; 311*4463Smckusic cgp->cg_nffree += i; 312*4463Smckusic fs->fs_nffree += i; 313*4463Smckusic cgp->cg_frsum[i]++; 314*4463Smckusic bdwrite(bp); 315*4463Smckusic return (bno); 316*4463Smckusic } 317*4463Smckusic /* 318*4463Smckusic * find the fragment by searching through the free block 319*4463Smckusic * map for an appropriate bit pattern 320*4463Smckusic */ 321*4463Smckusic if (bpref) 322*4463Smckusic start = bpref % fs->fs_fpg / NBBY; 323*4463Smckusic else 324*4463Smckusic start = cgp->cg_frotor / NBBY; 325*4463Smckusic len = roundup(fs->fs_fpg - 1, NBBY) / NBBY - start; 326*4463Smckusic loc = scanc(len, &cgp->cg_free[start], fragtbl, 1 << (allocsiz - 1)); 327*4463Smckusic if (loc == 0) { 328*4463Smckusic len = start - 1; 329*4463Smckusic start = (cgdmin(cg, fs) - cgbase(cg, fs)) / NBBY; 330*4463Smckusic loc = scanc(len, &cgp->cg_free[start], fragtbl, 331*4463Smckusic 1 << (allocsiz - 1)); 332*4463Smckusic if (loc == 0) 333*4463Smckusic panic("alloccg: can't find frag"); 334*4463Smckusic } 335*4463Smckusic bno = (start + len - loc) * NBBY; 336*4463Smckusic cgp->cg_frotor = bno; 337*4463Smckusic /* 338*4463Smckusic * found the byte in the map 339*4463Smckusic * sift through the bits to find the selected frag 340*4463Smckusic */ 341*4463Smckusic for (i = 0; i < NBBY; i += FRAG) { 342*4463Smckusic blk = (cgp->cg_free[bno / NBBY] >> i) & (0xff >> NBBY - FRAG); 343*4463Smckusic blk <<= 1; 344*4463Smckusic field = around[allocsiz]; 345*4463Smckusic subfield = inside[allocsiz]; 346*4463Smckusic for (pos = 0; pos <= FRAG - allocsiz; pos++) { 347*4463Smckusic if ((blk & field) == subfield) { 348*4463Smckusic bno += i + pos; 349*4463Smckusic goto gotit; 350*4463Smckusic } 351*4463Smckusic field <<= 1; 352*4463Smckusic subfield <<= 1; 353*4463Smckusic } 354*4463Smckusic } 355*4463Smckusic panic("alloccg: frag not in block"); 356*4463Smckusic gotit: 357*4463Smckusic for (i = 0; i < frags; i++) 358*4463Smckusic clrbit(cgp->cg_free, bno + i); 359*4463Smckusic cgp->cg_nffree -= frags; 360*4463Smckusic fs->fs_nffree -= frags; 361*4463Smckusic cgp->cg_frsum[allocsiz]--; 362*4463Smckusic if (frags != allocsiz) 363*4463Smckusic cgp->cg_frsum[allocsiz - frags]++; 364*4463Smckusic bdwrite(bp); 365*4463Smckusic return (cg * fs->fs_fpg + bno); 366*4463Smckusic } 367*4463Smckusic 368*4463Smckusic daddr_t 369*4463Smckusic alloccgblk(dev, fs, cgp, bpref) 370*4463Smckusic dev_t dev; 371*4463Smckusic struct fs *fs; 372*4463Smckusic register struct cg *cgp; 373*4463Smckusic daddr_t bpref; 374*4463Smckusic { 375*4463Smckusic register int i; 376*4463Smckusic 3774359Smckusick if (bpref) { 378*4463Smckusic 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 } 393*4463Smckusic panic("alloccgblk: can't find a blk"); 3944359Smckusick return (0); 3954359Smckusick gotit: 396*4463Smckusic clrblock(cgp->cg_free, bpref/FRAG); 397*4463Smckusic cgp->cg_nbfree--; 398*4463Smckusic fs->fs_nbfree--; 399*4463Smckusic fs->fs_cs[cgp->cg_cgx].cs_nbfree--; 400*4463Smckusic i = bpref * NSPF; 401*4463Smckusic cgp->cg_b[i/fs->fs_spc][i%fs->fs_nsect*NRPOS/fs->fs_nsect]--; 4024359Smckusick fs->fs_fmod++; 403*4463Smckusic return (cgp->cg_cgx * fs->fs_fpg + bpref); 4044359Smckusick } 4054359Smckusick 4064359Smckusick long 4074359Smckusick ialloccg(dev, fs, cg, ipref, mode) 4084359Smckusick dev_t dev; 409*4463Smckusic register struct fs *fs; 4104359Smckusick int cg; 4114359Smckusick daddr_t ipref; 4124359Smckusick int mode; 4134359Smckusick { 414*4463Smckusic register struct buf *bp; 415*4463Smckusic 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; 465*4463Smckusic int cg, blk, frags, bbase; 466*4463Smckusic 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 { 489*4463Smckusic bbase = bno - (bno % FRAG); 490*4463Smckusic /* 491*4463Smckusic * decrement the counts associated with the old frags 492*4463Smckusic */ 493*4463Smckusic blk = ((cgp->cg_free[bbase / NBBY] >> (bbase % NBBY)) & 494*4463Smckusic (0xff >> (NBBY - FRAG))); 495*4463Smckusic fragacct(blk, cgp->cg_frsum, -1); 496*4463Smckusic /* 497*4463Smckusic * deallocate the fragment 498*4463Smckusic */ 499*4463Smckusic frags = size / FSIZE; 500*4463Smckusic 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 } 507*4463Smckusic /* 508*4463Smckusic * add back in counts associated with the new frags 509*4463Smckusic */ 510*4463Smckusic blk = ((cgp->cg_free[bbase / NBBY] >> (bbase % NBBY)) & 511*4463Smckusic (0xff >> (NBBY - FRAG))); 512*4463Smckusic fragacct(blk, cgp->cg_frsum, 1); 513*4463Smckusic /* 514*4463Smckusic * if a complete block has been reassembled, account for it 515*4463Smckusic */ 516*4463Smckusic 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++; 522*4463Smckusic 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 565*4463Smckusic /* 566*4463Smckusic * update the frsum fields to reflect addition or deletion 567*4463Smckusic * of some frags 568*4463Smckusic */ 569*4463Smckusic fragacct(fragmap, fraglist, cnt) 570*4463Smckusic char fragmap; 571*4463Smckusic short fraglist[]; 572*4463Smckusic int cnt; 573*4463Smckusic { 574*4463Smckusic int inblk; 575*4463Smckusic register int field, subfield; 576*4463Smckusic register int siz, pos; 577*4463Smckusic 578*4463Smckusic inblk = (int)(fragtbl[fragmap] << 1); 579*4463Smckusic fragmap <<= 1; 580*4463Smckusic for (siz = 1; siz < FRAG; siz++) { 581*4463Smckusic if (((1 << siz) & inblk) == 0) 582*4463Smckusic continue; 583*4463Smckusic field = around[siz]; 584*4463Smckusic subfield = inside[siz]; 585*4463Smckusic for (pos = siz; pos <= FRAG; pos++) { 586*4463Smckusic if ((fragmap & field) == subfield) { 587*4463Smckusic fraglist[siz] += cnt; 588*4463Smckusic pos += siz; 589*4463Smckusic field <<= siz; 590*4463Smckusic subfield <<= siz; 591*4463Smckusic } 592*4463Smckusic field <<= 1; 593*4463Smckusic subfield <<= 1; 594*4463Smckusic } 595*4463Smckusic } 596*4463Smckusic } 597*4463Smckusic 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