xref: /csrg-svn/sys/ufs/lfs/lfs_alloc.c (revision 5361)
14359Smckusick /* Copyright (c) 1981 Regents of the University of California */
24359Smckusick 
3*5361Smckusic static char vers[] = "@(#)lfs_alloc.c 1.13 01/10/82";
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 
175212Smckusic extern u_long		hashalloc();
185212Smckusic extern ino_t		ialloccg();
194651Smckusic extern daddr_t		alloccg();
204651Smckusic extern daddr_t		alloccgblk();
214651Smckusic extern daddr_t		fragextend();
224651Smckusic extern daddr_t		blkpref();
234651Smckusic extern daddr_t		mapsearch();
244607Smckusic extern int		inside[], around[];
255322Smckusic extern unsigned char	*fragtbl[];
264359Smckusick 
274359Smckusick struct buf *
284359Smckusick alloc(dev, ip, bpref, size)
294359Smckusick 	dev_t dev;
304463Smckusic 	register struct inode *ip;
314359Smckusick 	daddr_t bpref;
324359Smckusick 	int size;
334359Smckusick {
344359Smckusick 	daddr_t bno;
354359Smckusick 	register struct fs *fs;
364463Smckusic 	register struct buf *bp;
374359Smckusick 	int cg;
384359Smckusick 
395322Smckusic 	fs = getfs(dev);
405322Smckusic 	if ((unsigned)size > fs->fs_bsize || size % fs->fs_fsize != 0)
414463Smckusic 		panic("alloc: bad size");
425322Smckusic 	if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0)
434359Smckusick 		goto nospace;
444792Smckusic 	if (u.u_uid != 0 &&
455322Smckusic 	    fs->fs_cstotal.cs_nbfree * fs->fs_frag + fs->fs_cstotal.cs_nffree <
465322Smckusic 	      fs->fs_dsize * fs->fs_minfree / 100)
474792Smckusic 		goto nospace;
484948Smckusic 	if (bpref >= fs->fs_size)
494948Smckusic 		bpref = 0;
504359Smckusick 	if (bpref == 0)
514359Smckusick 		cg = itog(ip->i_number, fs);
524359Smckusick 	else
534359Smckusick 		cg = dtog(bpref, fs);
545212Smckusic 	bno = (daddr_t)hashalloc(dev, fs, cg, (long)bpref, size, alloccg);
554359Smckusick 	if (bno == 0)
564359Smckusick 		goto nospace;
575322Smckusic 	bp = getblk(dev, fsbtodb(fs, bno), size);
584359Smckusick 	clrbuf(bp);
594359Smckusick 	return (bp);
604359Smckusick nospace:
614359Smckusick 	fserr(fs, "file system full");
624359Smckusick 	uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
634359Smckusick 	u.u_error = ENOSPC;
644359Smckusick 	return (NULL);
654359Smckusick }
664359Smckusick 
674426Smckusic struct buf *
685212Smckusic realloccg(dev, bprev, bpref, osize, nsize)
694426Smckusic 	dev_t dev;
704651Smckusic 	daddr_t bprev, bpref;
714426Smckusic 	int osize, nsize;
724426Smckusic {
734426Smckusic 	daddr_t bno;
744426Smckusic 	register struct fs *fs;
754463Smckusic 	register struct buf *bp, *obp;
764463Smckusic 	caddr_t cp;
774426Smckusic 	int cg;
784426Smckusic 
795322Smckusic 	fs = getfs(dev);
805322Smckusic 	if ((unsigned)osize > fs->fs_bsize || osize % fs->fs_fsize != 0 ||
815322Smckusic 	    (unsigned)nsize > fs->fs_bsize || nsize % fs->fs_fsize != 0)
824463Smckusic 		panic("realloccg: bad size");
834792Smckusic 	if (u.u_uid != 0 &&
845322Smckusic 	    fs->fs_cstotal.cs_nbfree * fs->fs_frag + fs->fs_cstotal.cs_nffree <
855322Smckusic 	      fs->fs_dsize * fs->fs_minfree / 100)
864792Smckusic 		goto nospace;
874463Smckusic 	if (bprev == 0)
884463Smckusic 		panic("realloccg: bad bprev");
894426Smckusic 	else
904463Smckusic 		cg = dtog(bprev, fs);
914463Smckusic 	bno = fragextend(dev, fs, cg, (long)bprev, osize, nsize);
924463Smckusic 	if (bno != 0) {
935322Smckusic 		bp = bread(dev, fsbtodb(fs, bno), osize);
94*5361Smckusic 		if (bp->b_flags & B_ERROR)
95*5361Smckusic 			return (0);
964463Smckusic 		bp->b_bcount = nsize;
974463Smckusic 		blkclr(bp->b_un.b_addr + osize, nsize - osize);
984463Smckusic 		return (bp);
994463Smckusic 	}
1004948Smckusic 	if (bpref >= fs->fs_size)
1014948Smckusic 		bpref = 0;
1025212Smckusic 	bno = (daddr_t)hashalloc(dev, fs, cg, (long)bpref, nsize, alloccg);
1034463Smckusic 	if (bno != 0) {
1044463Smckusic 		/*
1054463Smckusic 		 * make a new copy
1064463Smckusic 		 */
1075322Smckusic 		obp = bread(dev, fsbtodb(fs, bprev), osize);
108*5361Smckusic 		if (obp->b_flags & B_ERROR)
109*5361Smckusic 			return (0);
1105322Smckusic 		bp = getblk(dev, fsbtodb(fs, bno), nsize);
1114463Smckusic 		cp = bp->b_un.b_addr;
1124463Smckusic 		bp->b_un.b_addr = obp->b_un.b_addr;
1134463Smckusic 		obp->b_un.b_addr = cp;
1144463Smckusic 		obp->b_flags |= B_INVAL;
1154463Smckusic 		brelse(obp);
1165212Smckusic 		fre(dev, bprev, (off_t)osize);
1174463Smckusic 		blkclr(bp->b_un.b_addr + osize, nsize - osize);
1184463Smckusic 		return(bp);
1194463Smckusic 	}
1204792Smckusic nospace:
1214463Smckusic 	/*
1224463Smckusic 	 * no space available
1234463Smckusic 	 */
1244426Smckusic 	fserr(fs, "file system full");
1254426Smckusic 	uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
1264426Smckusic 	u.u_error = ENOSPC;
1274426Smckusic 	return (NULL);
1284426Smckusic }
1294426Smckusic 
1304359Smckusick struct inode *
1314359Smckusick ialloc(dev, ipref, mode)
1324359Smckusick 	dev_t dev;
1334359Smckusick 	ino_t ipref;
1344359Smckusick 	int mode;
1354359Smckusick {
1365212Smckusic 	ino_t ino;
1374359Smckusick 	register struct fs *fs;
1384359Smckusick 	register struct inode *ip;
1394359Smckusick 	int cg;
1404359Smckusick 
1414359Smckusick 	fs = getfs(dev);
1424792Smckusic 	if (fs->fs_cstotal.cs_nifree == 0)
1434359Smckusick 		goto noinodes;
1444948Smckusic 	if (ipref >= fs->fs_ncg * fs->fs_ipg)
1454948Smckusic 		ipref = 0;
1464359Smckusick 	cg = itog(ipref, fs);
1475212Smckusic 	ino = (ino_t)hashalloc(dev, fs, cg, (long)ipref, mode, ialloccg);
1484359Smckusick 	if (ino == 0)
1494359Smckusick 		goto noinodes;
1504359Smckusick 	ip = iget(dev, ino);
1514359Smckusick 	if (ip == NULL) {
1525212Smckusic 		ifree(dev, ino, 0);
1534359Smckusick 		return (NULL);
1544359Smckusick 	}
1554359Smckusick 	if (ip->i_mode)
1564359Smckusick 		panic("ialloc: dup alloc");
1574359Smckusick 	return (ip);
1584359Smckusick noinodes:
1594359Smckusick 	fserr(fs, "out of inodes");
1604359Smckusick 	uprintf("\n%s: create failed, no inodes free\n", fs->fs_fsmnt);
1614359Smckusick 	u.u_error = ENOSPC;
1624359Smckusick 	return (NULL);
1634359Smckusick }
1644359Smckusick 
1654651Smckusic /*
1664651Smckusic  * find a cylinder to place a directory
1674651Smckusic  */
1684651Smckusic dirpref(dev)
1694359Smckusick 	dev_t dev;
1704359Smckusick {
1714359Smckusick 	register struct fs *fs;
1724651Smckusic 	int cg, minndir, mincg, avgifree;
1734359Smckusick 
1744359Smckusick 	fs = getfs(dev);
1754792Smckusic 	avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg;
1764651Smckusic 	minndir = fs->fs_ipg;
1774359Smckusick 	mincg = 0;
1784651Smckusic 	for (cg = 0; cg < fs->fs_ncg; cg++)
1795322Smckusic 		if (fs->fs_cs(fs, cg).cs_ndir < minndir &&
1805322Smckusic 		    fs->fs_cs(fs, cg).cs_nifree >= avgifree) {
1814359Smckusick 			mincg = cg;
1825322Smckusic 			minndir = fs->fs_cs(fs, cg).cs_ndir;
1834359Smckusick 		}
1844359Smckusick 	return (fs->fs_ipg * mincg);
1854359Smckusick }
1864359Smckusick 
1874651Smckusic /*
1884651Smckusic  * select a cylinder to place a large block of data
1894651Smckusic  */
1905212Smckusic daddr_t
1914651Smckusic blkpref(dev)
1924651Smckusic 	dev_t dev;
1934651Smckusic {
1944651Smckusic 	register struct fs *fs;
1954651Smckusic 	int cg, avgbfree;
1964651Smckusic 
1974651Smckusic 	fs = getfs(dev);
1984792Smckusic 	avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
1994651Smckusic 	for (cg = fs->fs_cgrotor + 1; cg < fs->fs_ncg; cg++)
2005322Smckusic 		if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
2014651Smckusic 			fs->fs_cgrotor = cg;
2025322Smckusic 			return (fs->fs_fpg * cg + fs->fs_frag);
2034651Smckusic 		}
2044651Smckusic 	for (cg = 0; cg <= fs->fs_cgrotor; cg++)
2055322Smckusic 		if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
2064651Smckusic 			fs->fs_cgrotor = cg;
2075322Smckusic 			return (fs->fs_fpg * cg + fs->fs_frag);
2084651Smckusic 		}
2094651Smckusic 	return (0);
2104651Smckusic }
2114651Smckusic 
2125212Smckusic /*VARARGS5*/
2135212Smckusic u_long
2144359Smckusick hashalloc(dev, fs, cg, pref, size, allocator)
2154359Smckusick 	dev_t dev;
2164359Smckusick 	register struct fs *fs;
2174359Smckusick 	int cg;
2184359Smckusick 	long pref;
2194359Smckusick 	int size;	/* size for data blocks, mode for inodes */
2205212Smckusic 	u_long (*allocator)();
2214359Smckusick {
2224359Smckusick 	long result;
2234359Smckusick 	int i, icg = cg;
2244359Smckusick 
2254359Smckusick 	/*
2264359Smckusick 	 * 1: preferred cylinder group
2274359Smckusick 	 */
2284359Smckusick 	result = (*allocator)(dev, fs, cg, pref, size);
2294359Smckusick 	if (result)
2304359Smckusick 		return (result);
2314359Smckusick 	/*
2324359Smckusick 	 * 2: quadratic rehash
2334359Smckusick 	 */
2344359Smckusick 	for (i = 1; i < fs->fs_ncg; i *= 2) {
2354359Smckusick 		cg += i;
2364359Smckusick 		if (cg >= fs->fs_ncg)
2374359Smckusick 			cg -= fs->fs_ncg;
2384359Smckusick 		result = (*allocator)(dev, fs, cg, 0, size);
2394359Smckusick 		if (result)
2404359Smckusick 			return (result);
2414359Smckusick 	}
2424359Smckusick 	/*
2434359Smckusick 	 * 3: brute force search
2444359Smckusick 	 */
2454359Smckusick 	cg = icg;
2464359Smckusick 	for (i = 0; i < fs->fs_ncg; i++) {
2474359Smckusick 		result = (*allocator)(dev, fs, cg, 0, size);
2484359Smckusick 		if (result)
2494359Smckusick 			return (result);
2504359Smckusick 		cg++;
2514359Smckusick 		if (cg == fs->fs_ncg)
2524359Smckusick 			cg = 0;
2534359Smckusick 	}
2544359Smckusick 	return (0);
2554359Smckusick }
2564359Smckusick 
2574359Smckusick daddr_t
2584463Smckusic fragextend(dev, fs, cg, bprev, osize, nsize)
2594426Smckusic 	dev_t dev;
2604426Smckusic 	register struct fs *fs;
2614426Smckusic 	int cg;
2624463Smckusic 	long bprev;
2634426Smckusic 	int osize, nsize;
2644426Smckusic {
2654463Smckusic 	register struct buf *bp;
2664463Smckusic 	register struct cg *cgp;
2674463Smckusic 	long bno;
2684463Smckusic 	int frags, bbase;
2694426Smckusic 	int i;
2704426Smckusic 
2715322Smckusic 	frags = nsize / fs->fs_fsize;
2725322Smckusic 	bbase = bprev % fs->fs_frag;
2735322Smckusic 	if (bbase > (bprev + frags - 1) % fs->fs_frag) {
2744463Smckusic 		/* cannot extend across a block boundry */
2754463Smckusic 		return (0);
2764463Smckusic 	}
2775322Smckusic 	bp = bread(dev, fsbtodb(fs, cgtod(cg, fs)), fs->fs_bsize);
2784426Smckusic 	if (bp->b_flags & B_ERROR)
2794426Smckusic 		return (0);
2804426Smckusic 	cgp = bp->b_un.b_cg;
2814463Smckusic 	bno = bprev % fs->fs_fpg;
282*5361Smckusic 	for (i = osize / fs->fs_fsize; i < frags; i++)
283*5361Smckusic 		if (isclr(cgp->cg_free, bno + i)) {
284*5361Smckusic 			brelse(bp);
285*5361Smckusic 			return (0);
286*5361Smckusic 		}
287*5361Smckusic 	/*
288*5361Smckusic 	 * the current fragment can be extended
289*5361Smckusic 	 * deduct the count on fragment being extended into
290*5361Smckusic 	 * increase the count on the remaining fragment (if any)
291*5361Smckusic 	 * allocate the extended piece
292*5361Smckusic 	 */
293*5361Smckusic 	for (i = frags; i < fs->fs_frag - bbase; i++)
2944463Smckusic 		if (isclr(cgp->cg_free, bno + i))
2954463Smckusic 			break;
296*5361Smckusic 	cgp->cg_frsum[i - osize / fs->fs_fsize]--;
297*5361Smckusic 	if (i != frags)
298*5361Smckusic 		cgp->cg_frsum[i - frags]++;
299*5361Smckusic 	for (i = osize / fs->fs_fsize; i < frags; i++) {
300*5361Smckusic 		clrbit(cgp->cg_free, bno + i);
301*5361Smckusic 		cgp->cg_cs.cs_nffree--;
302*5361Smckusic 		fs->fs_cstotal.cs_nffree--;
303*5361Smckusic 		fs->fs_cs(fs, cg).cs_nffree--;
3044463Smckusic 	}
305*5361Smckusic 	fs->fs_fmod++;
306*5361Smckusic 	bdwrite(bp);
307*5361Smckusic 	return (bprev);
3084426Smckusic }
3094426Smckusic 
3104426Smckusic daddr_t
3114359Smckusick alloccg(dev, fs, cg, bpref, size)
3124359Smckusick 	dev_t dev;
3134463Smckusic 	register struct fs *fs;
3144359Smckusick 	int cg;
3154359Smckusick 	daddr_t bpref;
3164359Smckusick 	int size;
3174359Smckusick {
3184463Smckusic 	register struct buf *bp;
3194463Smckusic 	register struct cg *cgp;
3204463Smckusic 	int bno, frags;
3214463Smckusic 	int allocsiz;
3224463Smckusic 	register int i;
3234359Smckusick 
3245322Smckusic 	if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize)
3254792Smckusic 		return (0);
3265322Smckusic 	bp = bread(dev, fsbtodb(fs, cgtod(cg, fs)), fs->fs_bsize);
3274359Smckusick 	if (bp->b_flags & B_ERROR)
3284359Smckusick 		return (0);
3294359Smckusick 	cgp = bp->b_un.b_cg;
3305322Smckusic 	if (size == fs->fs_bsize) {
3315212Smckusic 		bno = alloccgblk(fs, cgp, bpref);
3324463Smckusic 		bdwrite(bp);
3334463Smckusic 		return (bno);
3344463Smckusic 	}
3354463Smckusic 	/*
3364463Smckusic 	 * check to see if any fragments are already available
3374463Smckusic 	 * allocsiz is the size which will be allocated, hacking
3384463Smckusic 	 * it down to a smaller size if necessary
3394463Smckusic 	 */
3405322Smckusic 	frags = size / fs->fs_fsize;
3415322Smckusic 	for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++)
3424463Smckusic 		if (cgp->cg_frsum[allocsiz] != 0)
3434463Smckusic 			break;
3445322Smckusic 	if (allocsiz == fs->fs_frag) {
3454463Smckusic 		/*
3464463Smckusic 		 * no fragments were available, so a block will be
3474463Smckusic 		 * allocated, and hacked up
3484463Smckusic 		 */
3494792Smckusic 		if (cgp->cg_cs.cs_nbfree == 0) {
3504463Smckusic 			brelse(bp);
3514463Smckusic 			return (0);
3524463Smckusic 		}
3535212Smckusic 		bno = alloccgblk(fs, cgp, bpref);
3544463Smckusic 		bpref = bno % fs->fs_fpg;
3555322Smckusic 		for (i = frags; i < fs->fs_frag; i++)
3564463Smckusic 			setbit(cgp->cg_free, bpref + i);
3575322Smckusic 		i = fs->fs_frag - frags;
3584792Smckusic 		cgp->cg_cs.cs_nffree += i;
3594792Smckusic 		fs->fs_cstotal.cs_nffree += i;
3605322Smckusic 		fs->fs_cs(fs, cg).cs_nffree += i;
3614463Smckusic 		cgp->cg_frsum[i]++;
3624463Smckusic 		bdwrite(bp);
3634463Smckusic 		return (bno);
3644463Smckusic 	}
3654651Smckusic 	bno = mapsearch(fs, cgp, bpref, allocsiz);
3664651Smckusic 	if (bno == 0)
3674651Smckusic 		return (0);
3684463Smckusic 	for (i = 0; i < frags; i++)
3694463Smckusic 		clrbit(cgp->cg_free, bno + i);
3704792Smckusic 	cgp->cg_cs.cs_nffree -= frags;
3714792Smckusic 	fs->fs_cstotal.cs_nffree -= frags;
3725322Smckusic 	fs->fs_cs(fs, cg).cs_nffree -= frags;
3734463Smckusic 	cgp->cg_frsum[allocsiz]--;
3744463Smckusic 	if (frags != allocsiz)
3754463Smckusic 		cgp->cg_frsum[allocsiz - frags]++;
3764463Smckusic 	bdwrite(bp);
3774463Smckusic 	return (cg * fs->fs_fpg + bno);
3784463Smckusic }
3794463Smckusic 
3804463Smckusic daddr_t
3815212Smckusic alloccgblk(fs, cgp, bpref)
3824463Smckusic 	struct fs *fs;
3834463Smckusic 	register struct cg *cgp;
3844463Smckusic 	daddr_t bpref;
3854463Smckusic {
3864651Smckusic 	daddr_t bno;
3874651Smckusic 	int cylno, pos;
3884651Smckusic 	short *cylbp;
389*5361Smckusic 	register int i;
3904463Smckusic 
3914651Smckusic 	if (bpref == 0) {
3924651Smckusic 		bpref = cgp->cg_rotor;
393*5361Smckusic 		goto norot;
394*5361Smckusic 	}
395*5361Smckusic 	bpref &= ~(fs->fs_frag - 1);
396*5361Smckusic 	bpref %= fs->fs_fpg;
397*5361Smckusic 	/*
398*5361Smckusic 	 * if the requested block is available, use it
399*5361Smckusic 	 */
400*5361Smckusic 	if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) {
401*5361Smckusic 		bno = bpref;
402*5361Smckusic 		goto gotit;
403*5361Smckusic 	}
404*5361Smckusic 	if (fs->fs_cpc == 0)
405*5361Smckusic 		goto norot;
406*5361Smckusic 	/*
407*5361Smckusic 	 * check for a block available on the same cylinder
408*5361Smckusic 	 * beginning with one which is rotationally optimal
409*5361Smckusic 	 */
410*5361Smckusic 	cylno = cbtocylno(fs, bpref);
411*5361Smckusic 	cylbp = cgp->cg_b[cylno];
412*5361Smckusic 	if (fs->fs_rotdelay == 0) {
413*5361Smckusic 		pos = cbtorpos(fs, bpref);
4144651Smckusic 	} else {
4154651Smckusic 		/*
416*5361Smckusic 		 * here we convert ms of delay to frags as:
417*5361Smckusic 		 * (frags) = (ms) * (rev/sec) * (sect/rev) /
418*5361Smckusic 		 *	((sect/frag) * (ms/sec))
419*5361Smckusic 		 * then round up to the next rotational position
4204651Smckusic 		 */
421*5361Smckusic 		bpref += fs->fs_rotdelay * fs->fs_rps * fs->fs_nsect /
422*5361Smckusic 		    (NSPF(fs) * 1000);
423*5361Smckusic 		pos = cbtorpos(fs, bpref);
424*5361Smckusic 		pos = (pos + 1) % NRPOS;
425*5361Smckusic 	}
426*5361Smckusic 	/*
427*5361Smckusic 	 * check the summary information to see if a block is
428*5361Smckusic 	 * available in the requested cylinder starting at the
429*5361Smckusic 	 * optimal rotational position and proceeding around.
430*5361Smckusic 	 */
431*5361Smckusic 	for (i = pos; i < NRPOS; i++)
432*5361Smckusic 		if (cylbp[i] > 0)
433*5361Smckusic 			break;
434*5361Smckusic 	if (i == NRPOS)
435*5361Smckusic 		for (i = 0; i < pos; i++)
436*5361Smckusic 			if (cylbp[i] > 0)
437*5361Smckusic 				break;
438*5361Smckusic 	if (cylbp[i] > 0) {
4394651Smckusic 		/*
440*5361Smckusic 		 * found a rotational position, now find the actual
441*5361Smckusic 		 * block. A panic if none is actually there.
4424651Smckusic 		 */
443*5361Smckusic 		pos = cylno % fs->fs_cpc;
444*5361Smckusic 		bno = (cylno - pos) * fs->fs_spc / NSPB(fs);
445*5361Smckusic 		if (fs->fs_postbl[pos][i] == -1)
446*5361Smckusic 			panic("alloccgblk: cyl groups corrupted");
447*5361Smckusic 		for (i = fs->fs_postbl[pos][i]; ; i += fs->fs_rotbl[i]) {
448*5361Smckusic 			if (isblock(fs, cgp->cg_free, bno + i)) {
449*5361Smckusic 				bno = (bno + i) * fs->fs_frag;
450*5361Smckusic 				goto gotit;
451*5361Smckusic 			}
452*5361Smckusic 			if (fs->fs_rotbl[i] == 0)
4534651Smckusic 				break;
4544651Smckusic 		}
455*5361Smckusic 		panic("alloccgblk: can't find blk in cyl");
4564359Smckusick 	}
457*5361Smckusic norot:
458*5361Smckusic 	/*
459*5361Smckusic 	 * no blocks in the requested cylinder, so take next
460*5361Smckusic 	 * available one in this cylinder group.
461*5361Smckusic 	 */
4625322Smckusic 	bno = mapsearch(fs, cgp, bpref, fs->fs_frag);
4634651Smckusic 	if (bno == 0)
4644651Smckusic 		return (0);
4654651Smckusic 	cgp->cg_rotor = bno;
4664359Smckusick gotit:
4675322Smckusic 	clrblock(fs, cgp->cg_free, bno/fs->fs_frag);
4684792Smckusic 	cgp->cg_cs.cs_nbfree--;
4694792Smckusic 	fs->fs_cstotal.cs_nbfree--;
4705322Smckusic 	fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--;
471*5361Smckusic 	cgp->cg_b[cbtocylno(fs, bno)][cbtorpos(fs, bno)]--;
4724359Smckusick 	fs->fs_fmod++;
4734651Smckusic 	return (cgp->cg_cgx * fs->fs_fpg + bno);
4744359Smckusick }
4754359Smckusick 
4765212Smckusic ino_t
4774359Smckusick ialloccg(dev, fs, cg, ipref, mode)
4784359Smckusick 	dev_t dev;
4794463Smckusic 	register struct fs *fs;
4804359Smckusick 	int cg;
4814359Smckusick 	daddr_t ipref;
4824359Smckusick 	int mode;
4834359Smckusick {
4844463Smckusic 	register struct buf *bp;
4854463Smckusic 	register struct cg *cgp;
4864359Smckusick 	int i;
4874359Smckusick 
4885322Smckusic 	if (fs->fs_cs(fs, cg).cs_nifree == 0)
4894792Smckusic 		return (0);
4905322Smckusic 	bp = bread(dev, fsbtodb(fs, cgtod(cg, fs)), fs->fs_bsize);
4914359Smckusick 	if (bp->b_flags & B_ERROR)
4924359Smckusick 		return (0);
4934359Smckusick 	cgp = bp->b_un.b_cg;
4944359Smckusick 	if (ipref) {
4954359Smckusick 		ipref %= fs->fs_ipg;
4964359Smckusick 		if (isclr(cgp->cg_iused, ipref))
4974359Smckusick 			goto gotit;
4984359Smckusick 	} else
4994359Smckusick 		ipref = cgp->cg_irotor;
5004359Smckusick 	for (i = 0; i < fs->fs_ipg; i++) {
5014359Smckusick 		ipref++;
5024359Smckusick 		if (ipref >= fs->fs_ipg)
5034359Smckusick 			ipref = 0;
5044359Smckusick 		if (isclr(cgp->cg_iused, ipref)) {
5054359Smckusick 			cgp->cg_irotor = ipref;
5064359Smckusick 			goto gotit;
5074359Smckusick 		}
5084359Smckusick 	}
5094359Smckusick 	brelse(bp);
5104359Smckusick 	return (0);
5114359Smckusick gotit:
5124359Smckusick 	setbit(cgp->cg_iused, ipref);
5134792Smckusic 	cgp->cg_cs.cs_nifree--;
5144792Smckusic 	fs->fs_cstotal.cs_nifree--;
5155322Smckusic 	fs->fs_cs(fs, cg).cs_nifree--;
5164359Smckusick 	fs->fs_fmod++;
5174359Smckusick 	if ((mode & IFMT) == IFDIR) {
5184792Smckusic 		cgp->cg_cs.cs_ndir++;
5194792Smckusic 		fs->fs_cstotal.cs_ndir++;
5205322Smckusic 		fs->fs_cs(fs, cg).cs_ndir++;
5214359Smckusick 	}
5224359Smckusick 	bdwrite(bp);
5234359Smckusick 	return (cg * fs->fs_ipg + ipref);
5244359Smckusick }
5254359Smckusick 
5264359Smckusick fre(dev, bno, size)
5274359Smckusick 	dev_t dev;
5284359Smckusick 	daddr_t bno;
5295212Smckusic 	off_t size;
5304359Smckusick {
5314359Smckusick 	register struct fs *fs;
5324359Smckusick 	register struct cg *cgp;
5334359Smckusick 	register struct buf *bp;
5344463Smckusic 	int cg, blk, frags, bbase;
5354463Smckusic 	register int i;
5364359Smckusick 
5375322Smckusic 	fs = getfs(dev);
5385322Smckusic 	if ((unsigned)size > fs->fs_bsize || size % fs->fs_fsize != 0)
5394426Smckusic 		panic("free: bad size");
5404359Smckusick 	cg = dtog(bno, fs);
5414359Smckusick 	if (badblock(fs, bno))
5424359Smckusick 		return;
5435322Smckusic 	bp = bread(dev, fsbtodb(fs, cgtod(cg, fs)), fs->fs_bsize);
5444359Smckusick 	if (bp->b_flags & B_ERROR)
5454359Smckusick 		return;
5464359Smckusick 	cgp = bp->b_un.b_cg;
5474359Smckusick 	bno %= fs->fs_fpg;
5485322Smckusic 	if (size == fs->fs_bsize) {
5495322Smckusic 		if (isblock(fs, cgp->cg_free, bno/fs->fs_frag))
5504426Smckusic 			panic("free: freeing free block");
5515322Smckusic 		setblock(fs, cgp->cg_free, bno/fs->fs_frag);
5524792Smckusic 		cgp->cg_cs.cs_nbfree++;
5534792Smckusic 		fs->fs_cstotal.cs_nbfree++;
5545322Smckusic 		fs->fs_cs(fs, cg).cs_nbfree++;
555*5361Smckusic 		cgp->cg_b[cbtocylno(fs, bno)][cbtorpos(fs, bno)]++;
5564426Smckusic 	} else {
5575322Smckusic 		bbase = bno - (bno % fs->fs_frag);
5584463Smckusic 		/*
5594463Smckusic 		 * decrement the counts associated with the old frags
5604463Smckusic 		 */
5614463Smckusic 		blk = ((cgp->cg_free[bbase / NBBY] >> (bbase % NBBY)) &
5625322Smckusic 		       (0xff >> (NBBY - fs->fs_frag)));
5635322Smckusic 		fragacct(fs, blk, cgp->cg_frsum, -1);
5644463Smckusic 		/*
5654463Smckusic 		 * deallocate the fragment
5664463Smckusic 		 */
5675322Smckusic 		frags = size / fs->fs_fsize;
5684463Smckusic 		for (i = 0; i < frags; i++) {
5694426Smckusic 			if (isset(cgp->cg_free, bno + i))
5704426Smckusic 				panic("free: freeing free frag");
5714426Smckusic 			setbit(cgp->cg_free, bno + i);
5724792Smckusic 			cgp->cg_cs.cs_nffree++;
5734792Smckusic 			fs->fs_cstotal.cs_nffree++;
5745322Smckusic 			fs->fs_cs(fs, cg).cs_nffree++;
5754426Smckusic 		}
5764463Smckusic 		/*
5774463Smckusic 		 * add back in counts associated with the new frags
5784463Smckusic 		 */
5794463Smckusic 		blk = ((cgp->cg_free[bbase / NBBY] >> (bbase % NBBY)) &
5805322Smckusic 		       (0xff >> (NBBY - fs->fs_frag)));
5815322Smckusic 		fragacct(fs, blk, cgp->cg_frsum, 1);
5824463Smckusic 		/*
5834463Smckusic 		 * if a complete block has been reassembled, account for it
5844463Smckusic 		 */
5855322Smckusic 		if (isblock(fs, cgp->cg_free, bbase / fs->fs_frag)) {
5865322Smckusic 			cgp->cg_cs.cs_nffree -= fs->fs_frag;
5875322Smckusic 			fs->fs_cstotal.cs_nffree -= fs->fs_frag;
5885322Smckusic 			fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag;
5894792Smckusic 			cgp->cg_cs.cs_nbfree++;
5904792Smckusic 			fs->fs_cstotal.cs_nbfree++;
5915322Smckusic 			fs->fs_cs(fs, cg).cs_nbfree++;
592*5361Smckusic 			cgp->cg_b[cbtocylno(fs, bbase)][cbtorpos(fs, bbase)]++;
5934426Smckusic 		}
5944426Smckusic 	}
5954359Smckusick 	fs->fs_fmod++;
5964359Smckusick 	bdwrite(bp);
5974359Smckusick }
5984359Smckusick 
5994359Smckusick ifree(dev, ino, mode)
6004359Smckusick 	dev_t dev;
6014359Smckusick 	ino_t ino;
6024359Smckusick 	int mode;
6034359Smckusick {
6044359Smckusick 	register struct fs *fs;
6054359Smckusick 	register struct cg *cgp;
6064359Smckusick 	register struct buf *bp;
6074359Smckusick 	int cg;
6084359Smckusick 
6094359Smckusick 	fs = getfs(dev);
6104359Smckusick 	if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg)
6114359Smckusick 		panic("ifree: range");
6124359Smckusick 	cg = itog(ino, fs);
6135322Smckusic 	bp = bread(dev, fsbtodb(fs, cgtod(cg, fs)), fs->fs_bsize);
6144359Smckusick 	if (bp->b_flags & B_ERROR)
6154359Smckusick 		return;
6164359Smckusick 	cgp = bp->b_un.b_cg;
6174359Smckusick 	ino %= fs->fs_ipg;
6184359Smckusick 	if (isclr(cgp->cg_iused, ino))
6194359Smckusick 		panic("ifree: freeing free inode");
6204359Smckusick 	clrbit(cgp->cg_iused, ino);
6214792Smckusic 	cgp->cg_cs.cs_nifree++;
6224792Smckusic 	fs->fs_cstotal.cs_nifree++;
6235322Smckusic 	fs->fs_cs(fs, cg).cs_nifree++;
6244359Smckusick 	if ((mode & IFMT) == IFDIR) {
6254792Smckusic 		cgp->cg_cs.cs_ndir--;
6264792Smckusic 		fs->fs_cstotal.cs_ndir--;
6275322Smckusic 		fs->fs_cs(fs, cg).cs_ndir--;
6284359Smckusick 	}
6294359Smckusick 	fs->fs_fmod++;
6304359Smckusick 	bdwrite(bp);
6314359Smckusick }
6324359Smckusick 
6334463Smckusic /*
6344651Smckusic  * find a block of the specified size in the specified cylinder group
6354651Smckusic  * It is a panic if a request is made to find a block if none are
6364651Smckusic  * available.
6374651Smckusic  */
6384651Smckusic daddr_t
6394651Smckusic mapsearch(fs, cgp, bpref, allocsiz)
6404651Smckusic 	register struct fs *fs;
6414651Smckusic 	register struct cg *cgp;
6424651Smckusic 	daddr_t bpref;
6434651Smckusic 	int allocsiz;
6444651Smckusic {
6454651Smckusic 	daddr_t bno;
6464651Smckusic 	int start, len, loc, i;
6474651Smckusic 	int blk, field, subfield, pos;
6484651Smckusic 
6494651Smckusic 	/*
6504651Smckusic 	 * find the fragment by searching through the free block
6514651Smckusic 	 * map for an appropriate bit pattern
6524651Smckusic 	 */
6534651Smckusic 	if (bpref)
6544651Smckusic 		start = bpref % fs->fs_fpg / NBBY;
6554651Smckusic 	else
6564651Smckusic 		start = cgp->cg_frotor / NBBY;
6574651Smckusic 	len = roundup(fs->fs_fpg - 1, NBBY) / NBBY - start;
6585322Smckusic 	loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag],
6595322Smckusic 		1 << (allocsiz - 1));
6604651Smckusic 	if (loc == 0) {
6614651Smckusic 		len = start - 1;
6624651Smckusic 		start = (cgdmin(cgp->cg_cgx, fs) -
6634651Smckusic 			 cgbase(cgp->cg_cgx, fs)) / NBBY;
6645322Smckusic 		loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag],
6654651Smckusic 			1 << (allocsiz - 1));
6664651Smckusic 		if (loc == 0) {
6674651Smckusic 			panic("alloccg: map corrupted");
6684651Smckusic 			return (0);
6694651Smckusic 		}
6704651Smckusic 	}
6714651Smckusic 	bno = (start + len - loc) * NBBY;
6724651Smckusic 	cgp->cg_frotor = bno;
6734651Smckusic 	/*
6744651Smckusic 	 * found the byte in the map
6754651Smckusic 	 * sift through the bits to find the selected frag
6764651Smckusic 	 */
6775322Smckusic 	for (i = 0; i < NBBY; i += fs->fs_frag) {
6785322Smckusic 		blk = (cgp->cg_free[bno / NBBY] >> i) &
6795322Smckusic 		      (0xff >> NBBY - fs->fs_frag);
6804651Smckusic 		blk <<= 1;
6814651Smckusic 		field = around[allocsiz];
6824651Smckusic 		subfield = inside[allocsiz];
6835322Smckusic 		for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) {
6844651Smckusic 			if ((blk & field) == subfield) {
6854651Smckusic 				return (bno + i + pos);
6864651Smckusic 			}
6874651Smckusic 			field <<= 1;
6884651Smckusic 			subfield <<= 1;
6894651Smckusic 		}
6904651Smckusic 	}
6914651Smckusic 	panic("alloccg: block not in map");
6924651Smckusic 	return (0);
6934651Smckusic }
6944651Smckusic 
6954651Smckusic /*
6964463Smckusic  * update the frsum fields to reflect addition or deletion
6974463Smckusic  * of some frags
6984463Smckusic  */
6995322Smckusic fragacct(fs, fragmap, fraglist, cnt)
7005322Smckusic 	struct fs *fs;
7014472Smckusic 	int fragmap;
7024792Smckusic 	long fraglist[];
7034463Smckusic 	int cnt;
7044463Smckusic {
7054463Smckusic 	int inblk;
7064463Smckusic 	register int field, subfield;
7074463Smckusic 	register int siz, pos;
7084463Smckusic 
7095322Smckusic 	inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
7104463Smckusic 	fragmap <<= 1;
7115322Smckusic 	for (siz = 1; siz < fs->fs_frag; siz++) {
7124463Smckusic 		if (((1 << siz) & inblk) == 0)
7134463Smckusic 			continue;
7144463Smckusic 		field = around[siz];
7154463Smckusic 		subfield = inside[siz];
7165322Smckusic 		for (pos = siz; pos <= fs->fs_frag; pos++) {
7174463Smckusic 			if ((fragmap & field) == subfield) {
7184463Smckusic 				fraglist[siz] += cnt;
7194463Smckusic 				pos += siz;
7204463Smckusic 				field <<= siz;
7214463Smckusic 				subfield <<= siz;
7224463Smckusic 			}
7234463Smckusic 			field <<= 1;
7244463Smckusic 			subfield <<= 1;
7254463Smckusic 		}
7264463Smckusic 	}
7274463Smckusic }
7284463Smckusic 
7294359Smckusick badblock(fs, bn)
7304359Smckusick 	register struct fs *fs;
7314359Smckusick 	daddr_t bn;
7324359Smckusick {
7334359Smckusick 
7344359Smckusick 	if ((unsigned)bn >= fs->fs_size || bn < cgdmin(dtog(bn, fs), fs)) {
7354359Smckusick 		fserr(fs, "bad block");
7364359Smckusick 		return (1);
7374359Smckusick 	}
7384359Smckusick 	return (0);
7394359Smckusick }
7404359Smckusick 
7414359Smckusick /*
7424359Smckusick  * getfs maps a device number into
7434359Smckusick  * a pointer to the incore super
7444359Smckusick  * block.  The algorithm is a linear
7454359Smckusick  * search through the mount table.
7464359Smckusick  * A consistency check of the
7474359Smckusick  * in core free-block and i-node
7484359Smckusick  * counts is performed.
7494359Smckusick  *
7504359Smckusick  * panic: no fs -- the device is not mounted.
7514359Smckusick  *	this "cannot happen"
7524359Smckusick  */
7534359Smckusick struct fs *
7544359Smckusick getfs(dev)
7554359Smckusick 	dev_t dev;
7564359Smckusick {
7574359Smckusick 	register struct mount *mp;
7584359Smckusick 	register struct fs *fs;
7594359Smckusick 
7604359Smckusick 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
7614359Smckusick 		if (mp->m_bufp != NULL && mp->m_dev == dev) {
7624359Smckusick 			fs = mp->m_bufp->b_un.b_fs;
7634359Smckusick 			if (fs->fs_magic != FS_MAGIC)
7644359Smckusick 				panic("getfs: bad magic");
7654359Smckusick 			return (fs);
7664359Smckusick 		}
7674359Smckusick 	panic("getfs: no fs");
7684359Smckusick 	return (NULL);
7694359Smckusick }
7704359Smckusick 
7714359Smckusick /*
7724359Smckusick  * Fserr prints the name of a file system
7734359Smckusick  * with an error diagnostic, in the form
7744359Smckusick  *	fs: error message
7754359Smckusick  */
7764359Smckusick fserr(fs, cp)
7774359Smckusick 	struct fs *fs;
7784359Smckusick 	char *cp;
7794359Smckusick {
7804359Smckusick 
7814359Smckusick 	printf("%s: %s\n", fs->fs_fsmnt, cp);
7824359Smckusick }
7834359Smckusick 
7844359Smckusick /*
7854359Smckusick  * Getfsx returns the index in the file system
7864359Smckusick  * table of the specified device.  The swap device
7874359Smckusick  * is also assigned a pseudo-index.  The index may
7884359Smckusick  * be used as a compressed indication of the location
7894359Smckusick  * of a block, recording
7904359Smckusick  *	<getfsx(dev),blkno>
7914359Smckusick  * rather than
7924359Smckusick  *	<dev, blkno>
7934359Smckusick  * provided the information need remain valid only
7944359Smckusick  * as long as the file system is mounted.
7954359Smckusick  */
7964359Smckusick getfsx(dev)
7974359Smckusick 	dev_t dev;
7984359Smckusick {
7994359Smckusick 	register struct mount *mp;
8004359Smckusick 
8014359Smckusick 	if (dev == swapdev)
8024359Smckusick 		return (MSWAPX);
8034359Smckusick 	for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
8044359Smckusick 		if (mp->m_dev == dev)
8054359Smckusick 			return (mp - &mount[0]);
8064359Smckusick 	return (-1);
8074359Smckusick }
8084359Smckusick 
8094359Smckusick /*
8104359Smckusick  * Update is the internal name of 'sync'.  It goes through the disk
8114359Smckusick  * queues to initiate sandbagged IO; goes through the inodes to write
8124359Smckusick  * modified nodes; and it goes through the mount table to initiate modified
8134359Smckusick  * super blocks.
8144359Smckusick  */
8154359Smckusick update()
8164359Smckusick {
8174359Smckusick 	register struct inode *ip;
8184359Smckusick 	register struct mount *mp;
8194359Smckusick 	register struct buf *bp;
8204359Smckusick 	struct fs *fs;
8214359Smckusick 	time_t tim;
8224651Smckusic 	int i, blks;
8234359Smckusick 
8244359Smckusick 	if (updlock)
8254359Smckusick 		return;
8264359Smckusick 	updlock++;
8274359Smckusick 	/*
8284359Smckusick 	 * Write back modified superblocks.
8294359Smckusick 	 * Consistency check that the superblock
8304359Smckusick 	 * of each file system is still in the buffer cache.
8314359Smckusick 	 */
8324359Smckusick 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
8334359Smckusick 		if (mp->m_bufp != NULL) {
8344359Smckusick 			fs = mp->m_bufp->b_un.b_fs;
8354359Smckusick 			if (fs->fs_fmod == 0)
8364359Smckusick 				continue;
8374359Smckusick 			if (fs->fs_ronly != 0)
8384359Smckusick 				panic("update: rofs mod");
8395344Smckusic 			bp = getblk(mp->m_dev, SBLOCK, SBSIZE);
8404359Smckusick 			fs->fs_fmod = 0;
8414359Smckusick 			fs->fs_time = TIME;
8424359Smckusick 			if (bp->b_un.b_fs != fs)
8434359Smckusick 				panic("update: bad b_fs");
8444359Smckusick 			bwrite(bp);
8455322Smckusic 			blks = howmany(fs->fs_cssize, fs->fs_bsize);
8464651Smckusic 			for (i = 0; i < blks; i++) {
8475322Smckusic 				bp = getblk(mp->m_dev,
8485322Smckusic 				    fsbtodb(fs, fs->fs_csaddr + (i * fs->fs_frag)),
8495322Smckusic 				    fs->fs_bsize);
8504359Smckusick 				bwrite(bp);
8514359Smckusick 			}
8524359Smckusick 		}
8534359Smckusick 	/*
8544359Smckusick 	 * Write back each (modified) inode.
8554359Smckusick 	 */
8564359Smckusick 	for (ip = inode; ip < inodeNINODE; ip++)
8574359Smckusick 		if((ip->i_flag&ILOCK)==0 && ip->i_count) {
8584359Smckusick 			ip->i_flag |= ILOCK;
8594359Smckusick 			ip->i_count++;
8604359Smckusick 			tim = TIME;
8614359Smckusick 			iupdat(ip, &tim, &tim, 0);
8624359Smckusick 			iput(ip);
8634359Smckusick 		}
8644359Smckusick 	updlock = 0;
8654359Smckusick 	/*
8664359Smckusick 	 * Force stale buffer cache information to be flushed,
8674359Smckusick 	 * for all devices.
8684359Smckusick 	 */
8694359Smckusick 	bflush(NODEV);
8704359Smckusick }
8715322Smckusic 
8725322Smckusic /*
8735322Smckusic  * block macros
8745322Smckusic  */
8755322Smckusic 
8765322Smckusic isblock(fs, cp, h)
8775322Smckusic 	struct fs *fs;
8785322Smckusic 	unsigned char *cp;
8795322Smckusic 	int h;
8805322Smckusic {
8815322Smckusic 	unsigned char mask;
8825322Smckusic 
8835322Smckusic 	switch (fs->fs_frag) {
8845322Smckusic 	case 8:
8855322Smckusic 		return (cp[h] == 0xff);
8865322Smckusic 	case 4:
8875322Smckusic 		mask = 0x0f << ((h & 0x1) << 2);
8885322Smckusic 		return ((cp[h >> 1] & mask) == mask);
8895322Smckusic 	case 2:
8905322Smckusic 		mask = 0x03 << ((h & 0x3) << 1);
8915322Smckusic 		return ((cp[h >> 2] & mask) == mask);
8925322Smckusic 	case 1:
8935322Smckusic 		mask = 0x01 << (h & 0x7);
8945322Smckusic 		return ((cp[h >> 3] & mask) == mask);
8955322Smckusic 	default:
8965322Smckusic 		panic("isblock bad fs_frag");
8975322Smckusic 		return;
8985322Smckusic 	}
8995322Smckusic }
9005322Smckusic clrblock(fs, cp, h)
9015322Smckusic 	struct fs *fs;
9025322Smckusic 	unsigned char *cp;
9035322Smckusic 	int h;
9045322Smckusic {
9055322Smckusic 	switch ((fs)->fs_frag) {
9065322Smckusic 	case 8:
9075322Smckusic 		cp[h] = 0;
9085322Smckusic 		return;
9095322Smckusic 	case 4:
9105322Smckusic 		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
9115322Smckusic 		return;
9125322Smckusic 	case 2:
9135322Smckusic 		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
9145322Smckusic 		return;
9155322Smckusic 	case 1:
9165322Smckusic 		cp[h >> 3] &= ~(0x01 << (h & 0x7));
9175322Smckusic 		return;
9185322Smckusic 	default:
9195322Smckusic 		panic("clrblock bad fs_frag");
9205322Smckusic 		return;
9215322Smckusic 	}
9225322Smckusic }
9235322Smckusic setblock(fs, cp, h)
9245322Smckusic 	struct fs *fs;
9255322Smckusic 	unsigned char *cp;
9265322Smckusic 	int h;
9275322Smckusic {
9285322Smckusic 	switch (fs->fs_frag) {
9295322Smckusic 	case 8:
9305322Smckusic 		cp[h] = 0xff;
9315322Smckusic 		return;
9325322Smckusic 	case 4:
9335322Smckusic 		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
9345322Smckusic 		return;
9355322Smckusic 	case 2:
9365322Smckusic 		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
9375322Smckusic 		return;
9385322Smckusic 	case 1:
9395322Smckusic 		cp[h >> 3] |= (0x01 << (h & 0x7));
9405322Smckusic 		return;
9415322Smckusic 	default:
9425322Smckusic 		panic("setblock bad fs_frag");
9435322Smckusic 		return;
9445322Smckusic 	}
9455322Smckusic }
946