xref: /csrg-svn/sys/ufs/lfs/lfs_alloc.c (revision 4426)
14359Smckusick /* Copyright (c) 1981 Regents of the University of California */
24359Smckusick 
3*4426Smckusic static char vers[] = "@(#)lfs_alloc.c 1.3 09/22/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;
244359Smckusick 	struct inode *ip;
254359Smckusick 	daddr_t bpref;
264359Smckusick 	int size;
274359Smckusick {
284359Smckusick 	daddr_t bno;
294359Smckusick 	register struct fs *fs;
304359Smckusick 	struct buf *bp;
314359Smckusick 	int cg;
324359Smckusick 
334359Smckusick 	fs = getfs(dev);
344359Smckusick 	if (fs->fs_nbfree == 0 && size == BSIZE)
354359Smckusick 		goto nospace;
364359Smckusick 	if (bpref == 0)
374359Smckusick 		cg = itog(ip->i_number, fs);
384359Smckusick 	else
394359Smckusick 		cg = dtog(bpref, fs);
404359Smckusick 	bno = hashalloc(dev, fs, cg, (long)bpref, size, alloccg);
414359Smckusick 	if (bno == 0)
424359Smckusick 		goto nospace;
43*4426Smckusic 	bp = getblk(dev, bno, size);
444359Smckusick 	clrbuf(bp);
454359Smckusick 	return (bp);
464359Smckusick nospace:
474359Smckusick 	fserr(fs, "file system full");
484359Smckusick 	uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
494359Smckusick 	u.u_error = ENOSPC;
504359Smckusick 	return (NULL);
514359Smckusick }
524359Smckusick 
53*4426Smckusic struct buf *
54*4426Smckusic realloccg(dev, ip, bpref, osize, nsize)
55*4426Smckusic 	dev_t dev;
56*4426Smckusic 	struct inode *ip;
57*4426Smckusic 	daddr_t bpref;
58*4426Smckusic 	int osize, nsize;
59*4426Smckusic {
60*4426Smckusic 	daddr_t bno;
61*4426Smckusic 	register struct fs *fs;
62*4426Smckusic 	struct buf *bp;
63*4426Smckusic 	int cg;
64*4426Smckusic 
65*4426Smckusic 	fs = getfs(dev);
66*4426Smckusic 	if (bpref == 0)
67*4426Smckusic 		cg = itog(ip->i_number, fs);
68*4426Smckusic 	else
69*4426Smckusic 		cg = dtog(bpref, fs);
70*4426Smckusic 	bno = fragalloc(dev, fs, cg, (long)bpref, osize, nsize);
71*4426Smckusic 	if (bno == 0)
72*4426Smckusic 		goto nospace;
73*4426Smckusic 	bp = getblk(dev, bno, osize);
74*4426Smckusic 	bp->b_bcount += nsize - osize;
75*4426Smckusic 	blkclr(bp->b_un.b_addr + osize, nsize - osize);
76*4426Smckusic 	return (bp);
77*4426Smckusic nospace:
78*4426Smckusic 	fserr(fs, "file system full");
79*4426Smckusic 	uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
80*4426Smckusic 	u.u_error = ENOSPC;
81*4426Smckusic 	return (NULL);
82*4426Smckusic }
83*4426Smckusic 
844359Smckusick struct inode *
854359Smckusick ialloc(dev, ipref, mode)
864359Smckusick 	dev_t dev;
874359Smckusick 	ino_t ipref;
884359Smckusick 	int mode;
894359Smckusick {
904359Smckusick 	daddr_t ino;
914359Smckusick 	register struct fs *fs;
924359Smckusick 	register struct inode *ip;
934359Smckusick 	int cg;
944359Smckusick 
954359Smckusick 	fs = getfs(dev);
964359Smckusick 	if (fs->fs_nifree == 0)
974359Smckusick 		goto noinodes;
984359Smckusick 	cg = itog(ipref, fs);
994359Smckusick 	ino = hashalloc(dev, fs, cg, (long)ipref, mode, ialloccg);
1004359Smckusick 	if (ino == 0)
1014359Smckusick 		goto noinodes;
1024359Smckusick 	ip = iget(dev, ino);
1034359Smckusick 	if (ip == NULL) {
1044359Smckusick 		ifree(dev, ino);
1054359Smckusick 		return (NULL);
1064359Smckusick 	}
1074359Smckusick 	if (ip->i_mode)
1084359Smckusick 		panic("ialloc: dup alloc");
1094359Smckusick 	return (ip);
1104359Smckusick noinodes:
1114359Smckusick 	fserr(fs, "out of inodes");
1124359Smckusick 	uprintf("\n%s: create failed, no inodes free\n", fs->fs_fsmnt);
1134359Smckusick 	u.u_error = ENOSPC;
1144359Smckusick 	return (NULL);
1154359Smckusick }
1164359Smckusick 
1174359Smckusick dipref(dev)
1184359Smckusick 	dev_t dev;
1194359Smckusick {
1204359Smckusick 	register struct fs *fs;
1214359Smckusick 	int cg, minndir, mincg;
1224359Smckusick 
1234359Smckusick 	fs = getfs(dev);
1244359Smckusick 	minndir = fs->fs_cs[0].cs_ndir;
1254359Smckusick 	mincg = 0;
1264359Smckusick 	for (cg = 1; cg < fs->fs_ncg; cg++)
1274359Smckusick 		if (fs->fs_cs[cg].cs_ndir < minndir) {
1284359Smckusick 			mincg = cg;
1294359Smckusick 			minndir = fs->fs_cs[cg].cs_ndir;
1304359Smckusick 			if (minndir == 0)
1314359Smckusick 				break;
1324359Smckusick 		}
1334359Smckusick 	return (fs->fs_ipg * mincg);
1344359Smckusick }
1354359Smckusick 
1364359Smckusick long
1374359Smckusick hashalloc(dev, fs, cg, pref, size, allocator)
1384359Smckusick 	dev_t dev;
1394359Smckusick 	register struct fs *fs;
1404359Smckusick 	int cg;
1414359Smckusick 	long pref;
1424359Smckusick 	int size;	/* size for data blocks, mode for inodes */
1434359Smckusick 	long (*allocator)();
1444359Smckusick {
1454359Smckusick 	long result;
1464359Smckusick 	int i, icg = cg;
1474359Smckusick 
1484359Smckusick 	/*
1494359Smckusick 	 * 1: preferred cylinder group
1504359Smckusick 	 */
1514359Smckusick 	result = (*allocator)(dev, fs, cg, pref, size);
1524359Smckusick 	if (result)
1534359Smckusick 		return (result);
1544359Smckusick 	/*
1554359Smckusick 	 * 2: quadratic rehash
1564359Smckusick 	 */
1574359Smckusick 	for (i = 1; i < fs->fs_ncg; i *= 2) {
1584359Smckusick 		cg += i;
1594359Smckusick 		if (cg >= fs->fs_ncg)
1604359Smckusick 			cg -= fs->fs_ncg;
1614359Smckusick 		result = (*allocator)(dev, fs, cg, 0, size);
1624359Smckusick 		if (result)
1634359Smckusick 			return (result);
1644359Smckusick 	}
1654359Smckusick 	/*
1664359Smckusick 	 * 3: brute force search
1674359Smckusick 	 */
1684359Smckusick 	cg = icg;
1694359Smckusick 	for (i = 0; i < fs->fs_ncg; i++) {
1704359Smckusick 		result = (*allocator)(dev, fs, cg, 0, size);
1714359Smckusick 		if (result)
1724359Smckusick 			return (result);
1734359Smckusick 		cg++;
1744359Smckusick 		if (cg == fs->fs_ncg)
1754359Smckusick 			cg = 0;
1764359Smckusick 	}
1774359Smckusick 	return (0);
1784359Smckusick }
1794359Smckusick 
1804359Smckusick daddr_t
181*4426Smckusic fragalloc(dev, fs, cg, pref, osize, nsize)
182*4426Smckusic 	dev_t dev;
183*4426Smckusic 	register struct fs *fs;
184*4426Smckusic 	int cg;
185*4426Smckusic 	long pref;
186*4426Smckusic 	int osize, nsize;
187*4426Smckusic {
188*4426Smckusic 	struct buf *bp;
189*4426Smckusic 	struct cg *cgp;
190*4426Smckusic 	int i;
191*4426Smckusic 
192*4426Smckusic 	if ((unsigned)osize > BSIZE || osize % FSIZE != 0 ||
193*4426Smckusic 	    (unsigned)nsize > BSIZE || nsize % FSIZE != 0)
194*4426Smckusic 		panic("fragalloc: bad size");
195*4426Smckusic 	bp = bread(dev, cgtod(cg, fs), BSIZE);
196*4426Smckusic 	if (bp->b_flags & B_ERROR)
197*4426Smckusic 		return (0);
198*4426Smckusic 	cgp = bp->b_un.b_cg;
199*4426Smckusic 	if (pref) {
200*4426Smckusic 		pref %= fs->fs_fpg;
201*4426Smckusic 		for (i = osize / FSIZE; i < nsize / FSIZE; i++) {
202*4426Smckusic 			if (isclr(cgp->cg_free, pref + i))
203*4426Smckusic 				break;
204*4426Smckusic 		}
205*4426Smckusic 		if (i == nsize / FSIZE)
206*4426Smckusic 			goto extendit;
207*4426Smckusic 	}
208*4426Smckusic 	/*
209*4426Smckusic 	 * MUST FIND ALTERNATE LOCATION
210*4426Smckusic 	 */
211*4426Smckusic 	panic("fragalloc: reallocation too hard!");
212*4426Smckusic 	brelse(bp);
213*4426Smckusic 	return (0);
214*4426Smckusic extendit:
215*4426Smckusic 	for (i = osize / FSIZE; i < nsize / FSIZE; i++) {
216*4426Smckusic 		clrbit(cgp->cg_free, pref + i);
217*4426Smckusic 		cgp->cg_nffree--;
218*4426Smckusic 		fs->fs_nffree--;
219*4426Smckusic 	}
220*4426Smckusic 	fs->fs_fmod++;
221*4426Smckusic 	bdwrite(bp);
222*4426Smckusic 	return (cg * fs->fs_fpg + pref);
223*4426Smckusic }
224*4426Smckusic 
225*4426Smckusic daddr_t
2264359Smckusick alloccg(dev, fs, cg, bpref, size)
2274359Smckusick 	dev_t dev;
2284359Smckusick 	struct fs *fs;
2294359Smckusick 	int cg;
2304359Smckusick 	daddr_t bpref;
2314359Smckusick 	int size;
2324359Smckusick {
2334359Smckusick 	struct buf *bp;
2344359Smckusick 	struct cg *cgp;
2354359Smckusick 	int i;
2364359Smckusick 
237*4426Smckusic 	if ((unsigned)size > BSIZE || size % FSIZE != 0)
238*4426Smckusic 		panic("alloccg: bad size");
239*4426Smckusic 	bp = bread(dev, cgtod(cg, fs), BSIZE);
2404359Smckusick 	if (bp->b_flags & B_ERROR)
2414359Smckusick 		return (0);
2424359Smckusick 	cgp = bp->b_un.b_cg;
2434359Smckusick 	if (bpref) {
2444359Smckusick 		bpref %= fs->fs_fpg;
2454359Smckusick 		if (isblock(cgp->cg_free, bpref/FRAG))
2464359Smckusick 			goto gotit;
2474359Smckusick 	} else
2484359Smckusick 		bpref = cgp->cg_rotor;
2494359Smckusick 	for (i = 0; i < cgp->cg_ndblk; i += FRAG) {
2504359Smckusick 		bpref += FRAG;
2514359Smckusick 		if (bpref >= cgp->cg_ndblk)
2524359Smckusick 			bpref = 0;
2534359Smckusick 		if (isblock(cgp->cg_free, bpref/FRAG)) {
2544359Smckusick 			cgp->cg_rotor = bpref;
2554359Smckusick 			goto gotit;
2564359Smckusick 		}
2574359Smckusick 	}
2584359Smckusick 	brelse(bp);
2594359Smckusick 	return (0);
2604359Smckusick gotit:
261*4426Smckusic 	if (size == BSIZE) {
262*4426Smckusic 		clrblock(cgp->cg_free, bpref/FRAG);
263*4426Smckusic 		cgp->cg_nbfree--;
264*4426Smckusic 		fs->fs_nbfree--;
265*4426Smckusic 		fs->fs_cs[cg].cs_nbfree--;
266*4426Smckusic 		i = bpref * NSPF;
267*4426Smckusic 		cgp->cg_b[i/fs->fs_spc][i%fs->fs_nsect*NRPOS/fs->fs_nsect]--;
268*4426Smckusic 	} else {
269*4426Smckusic 		cgp->cg_nffree += FRAG;
270*4426Smckusic 		fs->fs_nffree += FRAG;
271*4426Smckusic 		for (i = 0; i < size / FSIZE; i++) {
272*4426Smckusic 			clrbit(cgp->cg_free, bpref + i);
273*4426Smckusic 			cgp->cg_nffree--;
274*4426Smckusic 			fs->fs_nffree--;
275*4426Smckusic 		}
276*4426Smckusic 		cgp->cg_nbfree--;
277*4426Smckusic 		fs->fs_nbfree--;
278*4426Smckusic 		fs->fs_cs[cg].cs_nbfree--;
279*4426Smckusic 		i = bpref * NSPF;
280*4426Smckusic 		cgp->cg_b[i/fs->fs_spc][i%fs->fs_nsect*NRPOS/fs->fs_nsect]--;
281*4426Smckusic 	}
2824359Smckusick 	fs->fs_fmod++;
2834359Smckusick 	bdwrite(bp);
2844359Smckusick 	return (cg * fs->fs_fpg + bpref);
2854359Smckusick }
2864359Smckusick 
2874359Smckusick long
2884359Smckusick ialloccg(dev, fs, cg, ipref, mode)
2894359Smckusick 	dev_t dev;
2904359Smckusick 	struct fs *fs;
2914359Smckusick 	int cg;
2924359Smckusick 	daddr_t ipref;
2934359Smckusick 	int mode;
2944359Smckusick {
2954359Smckusick 	struct buf *bp;
2964359Smckusick 	struct cg *cgp;
2974359Smckusick 	int i;
2984359Smckusick 
299*4426Smckusic 	bp = bread(dev, cgtod(cg, fs), BSIZE);
3004359Smckusick 	if (bp->b_flags & B_ERROR)
3014359Smckusick 		return (0);
3024359Smckusick 	cgp = bp->b_un.b_cg;
3034359Smckusick 	if (cgp->cg_nifree == 0) {
3044359Smckusick 		brelse(bp);
3054359Smckusick 		return (0);
3064359Smckusick 	}
3074359Smckusick 	if (ipref) {
3084359Smckusick 		ipref %= fs->fs_ipg;
3094359Smckusick 		if (isclr(cgp->cg_iused, ipref))
3104359Smckusick 			goto gotit;
3114359Smckusick 	} else
3124359Smckusick 		ipref = cgp->cg_irotor;
3134359Smckusick 	for (i = 0; i < fs->fs_ipg; i++) {
3144359Smckusick 		ipref++;
3154359Smckusick 		if (ipref >= fs->fs_ipg)
3164359Smckusick 			ipref = 0;
3174359Smckusick 		if (isclr(cgp->cg_iused, ipref)) {
3184359Smckusick 			cgp->cg_irotor = ipref;
3194359Smckusick 			goto gotit;
3204359Smckusick 		}
3214359Smckusick 	}
3224359Smckusick 	brelse(bp);
3234359Smckusick 	return (0);
3244359Smckusick gotit:
3254359Smckusick 	setbit(cgp->cg_iused, ipref);
3264359Smckusick 	cgp->cg_nifree--;
3274359Smckusick 	fs->fs_nifree--;
3284359Smckusick 	fs->fs_cs[cg].cs_nifree--;
3294359Smckusick 	fs->fs_fmod++;
3304359Smckusick 	if ((mode & IFMT) == IFDIR) {
3314359Smckusick 		cgp->cg_ndir++;
3324359Smckusick 		fs->fs_cs[cg].cs_ndir++;
3334359Smckusick 	}
3344359Smckusick 	bdwrite(bp);
3354359Smckusick 	return (cg * fs->fs_ipg + ipref);
3364359Smckusick }
3374359Smckusick 
3384359Smckusick fre(dev, bno, size)
3394359Smckusick 	dev_t dev;
3404359Smckusick 	daddr_t bno;
3414359Smckusick 	int size;
3424359Smckusick {
3434359Smckusick 	register struct fs *fs;
3444359Smckusick 	register struct cg *cgp;
3454359Smckusick 	register struct buf *bp;
3464359Smckusick 	int i;
3474359Smckusick 	int cg;
3484359Smckusick 
349*4426Smckusic 	if ((unsigned)size > BSIZE || size % FSIZE != 0)
350*4426Smckusic 		panic("free: bad size");
3514359Smckusick 	fs = getfs(dev);
3524359Smckusick 	cg = dtog(bno, fs);
3534359Smckusick 	if (badblock(fs, bno))
3544359Smckusick 		return;
355*4426Smckusic 	bp = bread(dev, cgtod(cg, fs), BSIZE);
3564359Smckusick 	if (bp->b_flags & B_ERROR)
3574359Smckusick 		return;
3584359Smckusick 	cgp = bp->b_un.b_cg;
3594359Smckusick 	bno %= fs->fs_fpg;
360*4426Smckusic 	if (size == BSIZE) {
361*4426Smckusic 		if (isblock(cgp->cg_free, bno/FRAG))
362*4426Smckusic 			panic("free: freeing free block");
363*4426Smckusic 		setblock(cgp->cg_free, bno/FRAG);
364*4426Smckusic 		cgp->cg_nbfree++;
365*4426Smckusic 		fs->fs_nbfree++;
366*4426Smckusic 		fs->fs_cs[cg].cs_nbfree++;
367*4426Smckusic 		i = bno * NSPF;
368*4426Smckusic 		cgp->cg_b[i/fs->fs_spc][i%fs->fs_nsect*NRPOS/fs->fs_nsect]++;
369*4426Smckusic 	} else {
370*4426Smckusic 		for (i = 0; i < size / FSIZE; i++) {
371*4426Smckusic 			if (isset(cgp->cg_free, bno + i))
372*4426Smckusic 				panic("free: freeing free frag");
373*4426Smckusic 			setbit(cgp->cg_free, bno + i);
374*4426Smckusic 			cgp->cg_nffree++;
375*4426Smckusic 			fs->fs_nffree++;
376*4426Smckusic 		}
377*4426Smckusic 		if (isblock(cgp->cg_free, (bno - bno % FRAG) / FRAG)) {
378*4426Smckusic 			cgp->cg_nffree -= FRAG;
379*4426Smckusic 			fs->fs_nffree -= FRAG;
380*4426Smckusic 			cgp->cg_nbfree++;
381*4426Smckusic 			fs->fs_nbfree++;
382*4426Smckusic 			fs->fs_cs[cg].cs_nbfree++;
383*4426Smckusic 			i = bno * NSPF;
384*4426Smckusic 			cgp->cg_b[i / fs->fs_spc]
385*4426Smckusic 				 [i % fs->fs_nsect * NRPOS / fs->fs_nsect]++;
386*4426Smckusic 		}
387*4426Smckusic 	}
3884359Smckusick 	fs->fs_fmod++;
3894359Smckusick 	bdwrite(bp);
3904359Smckusick }
3914359Smckusick 
3924359Smckusick ifree(dev, ino, mode)
3934359Smckusick 	dev_t dev;
3944359Smckusick 	ino_t ino;
3954359Smckusick 	int mode;
3964359Smckusick {
3974359Smckusick 	register struct fs *fs;
3984359Smckusick 	register struct cg *cgp;
3994359Smckusick 	register struct buf *bp;
4004359Smckusick 	int i;
4014359Smckusick 	int cg;
4024359Smckusick 
4034359Smckusick 	fs = getfs(dev);
4044359Smckusick 	if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg)
4054359Smckusick 		panic("ifree: range");
4064359Smckusick 	cg = itog(ino, fs);
407*4426Smckusic 	bp = bread(dev, cgtod(cg, fs), BSIZE);
4084359Smckusick 	if (bp->b_flags & B_ERROR)
4094359Smckusick 		return;
4104359Smckusick 	cgp = bp->b_un.b_cg;
4114359Smckusick 	ino %= fs->fs_ipg;
4124359Smckusick 	if (isclr(cgp->cg_iused, ino))
4134359Smckusick 		panic("ifree: freeing free inode");
4144359Smckusick 	clrbit(cgp->cg_iused, ino);
4154359Smckusick 	cgp->cg_nifree++;
4164359Smckusick 	fs->fs_nifree++;
4174359Smckusick 	fs->fs_cs[cg].cs_nifree++;
4184359Smckusick 	if ((mode & IFMT) == IFDIR) {
4194359Smckusick 		cgp->cg_ndir--;
4204359Smckusick 		fs->fs_cs[cg].cs_ndir--;
4214359Smckusick 	}
4224359Smckusick 	fs->fs_fmod++;
4234359Smckusick 	bdwrite(bp);
4244359Smckusick }
4254359Smckusick 
4264359Smckusick badblock(fs, bn)
4274359Smckusick 	register struct fs *fs;
4284359Smckusick 	daddr_t bn;
4294359Smckusick {
4304359Smckusick 
4314359Smckusick 	if ((unsigned)bn >= fs->fs_size || bn < cgdmin(dtog(bn, fs), fs)) {
4324359Smckusick 		fserr(fs, "bad block");
4334359Smckusick 		return (1);
4344359Smckusick 	}
4354359Smckusick 	return (0);
4364359Smckusick }
4374359Smckusick 
4384359Smckusick /*
4394359Smckusick  * getfs maps a device number into
4404359Smckusick  * a pointer to the incore super
4414359Smckusick  * block.  The algorithm is a linear
4424359Smckusick  * search through the mount table.
4434359Smckusick  * A consistency check of the
4444359Smckusick  * in core free-block and i-node
4454359Smckusick  * counts is performed.
4464359Smckusick  *
4474359Smckusick  * panic: no fs -- the device is not mounted.
4484359Smckusick  *	this "cannot happen"
4494359Smckusick  */
4504359Smckusick struct fs *
4514359Smckusick getfs(dev)
4524359Smckusick 	dev_t dev;
4534359Smckusick {
4544359Smckusick 	register struct mount *mp;
4554359Smckusick 	register struct fs *fs;
4564359Smckusick 
4574359Smckusick 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
4584359Smckusick 		if (mp->m_bufp != NULL && mp->m_dev == dev) {
4594359Smckusick 			fs = mp->m_bufp->b_un.b_fs;
4604359Smckusick 			if (fs->fs_magic != FS_MAGIC)
4614359Smckusick 				panic("getfs: bad magic");
4624359Smckusick 			return (fs);
4634359Smckusick 		}
4644359Smckusick 	panic("getfs: no fs");
4654359Smckusick 	return (NULL);
4664359Smckusick }
4674359Smckusick 
4684359Smckusick /*
4694359Smckusick  * Fserr prints the name of a file system
4704359Smckusick  * with an error diagnostic, in the form
4714359Smckusick  *	fs: error message
4724359Smckusick  */
4734359Smckusick fserr(fs, cp)
4744359Smckusick 	struct fs *fs;
4754359Smckusick 	char *cp;
4764359Smckusick {
4774359Smckusick 
4784359Smckusick 	printf("%s: %s\n", fs->fs_fsmnt, cp);
4794359Smckusick }
4804359Smckusick 
4814359Smckusick /*
4824359Smckusick  * Getfsx returns the index in the file system
4834359Smckusick  * table of the specified device.  The swap device
4844359Smckusick  * is also assigned a pseudo-index.  The index may
4854359Smckusick  * be used as a compressed indication of the location
4864359Smckusick  * of a block, recording
4874359Smckusick  *	<getfsx(dev),blkno>
4884359Smckusick  * rather than
4894359Smckusick  *	<dev, blkno>
4904359Smckusick  * provided the information need remain valid only
4914359Smckusick  * as long as the file system is mounted.
4924359Smckusick  */
4934359Smckusick getfsx(dev)
4944359Smckusick 	dev_t dev;
4954359Smckusick {
4964359Smckusick 	register struct mount *mp;
4974359Smckusick 
4984359Smckusick 	if (dev == swapdev)
4994359Smckusick 		return (MSWAPX);
5004359Smckusick 	for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
5014359Smckusick 		if (mp->m_dev == dev)
5024359Smckusick 			return (mp - &mount[0]);
5034359Smckusick 	return (-1);
5044359Smckusick }
5054359Smckusick 
5064359Smckusick /*
5074359Smckusick  * Update is the internal name of 'sync'.  It goes through the disk
5084359Smckusick  * queues to initiate sandbagged IO; goes through the inodes to write
5094359Smckusick  * modified nodes; and it goes through the mount table to initiate modified
5104359Smckusick  * super blocks.
5114359Smckusick  */
5124359Smckusick update()
5134359Smckusick {
5144359Smckusick 	register struct inode *ip;
5154359Smckusick 	register struct mount *mp;
5164359Smckusick 	register struct buf *bp;
5174359Smckusick 	struct fs *fs;
5184359Smckusick 	time_t tim;
5194359Smckusick 	int i;
5204359Smckusick 
5214359Smckusick 	if (updlock)
5224359Smckusick 		return;
5234359Smckusick 	updlock++;
5244359Smckusick 	/*
5254359Smckusick 	 * Write back modified superblocks.
5264359Smckusick 	 * Consistency check that the superblock
5274359Smckusick 	 * of each file system is still in the buffer cache.
5284359Smckusick 	 */
5294359Smckusick 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
5304359Smckusick 		if (mp->m_bufp != NULL) {
5314359Smckusick 			fs = mp->m_bufp->b_un.b_fs;
5324359Smckusick 			if (fs->fs_fmod == 0)
5334359Smckusick 				continue;
5344359Smckusick 			if (fs->fs_ronly != 0)
5354359Smckusick 				panic("update: rofs mod");
536*4426Smckusic 			bp = getblk(mp->m_dev, SBLOCK, BSIZE);
5374359Smckusick 			fs->fs_fmod = 0;
5384359Smckusick 			fs->fs_time = TIME;
5394359Smckusick 			if (bp->b_un.b_fs != fs)
5404359Smckusick 				panic("update: bad b_fs");
5414359Smckusick 			bwrite(bp);
5424359Smckusick 			for (i = 0; i < cssize(fs); i += BSIZE) {
543*4426Smckusic 				bp = getblk(mp->m_dev, csaddr(fs) + i / FSIZE,
544*4426Smckusic 					BSIZE);
5454359Smckusick 				bcopy(fs->fs_cs + i, bp->b_un.b_addr, BSIZE);
5464359Smckusick 				bwrite(bp);
5474359Smckusick 			}
5484359Smckusick 		}
5494359Smckusick 	/*
5504359Smckusick 	 * Write back each (modified) inode.
5514359Smckusick 	 */
5524359Smckusick 	for (ip = inode; ip < inodeNINODE; ip++)
5534359Smckusick 		if((ip->i_flag&ILOCK)==0 && ip->i_count) {
5544359Smckusick 			ip->i_flag |= ILOCK;
5554359Smckusick 			ip->i_count++;
5564359Smckusick 			tim = TIME;
5574359Smckusick 			iupdat(ip, &tim, &tim, 0);
5584359Smckusick 			iput(ip);
5594359Smckusick 		}
5604359Smckusick 	updlock = 0;
5614359Smckusick 	/*
5624359Smckusick 	 * Force stale buffer cache information to be flushed,
5634359Smckusick 	 * for all devices.
5644359Smckusick 	 */
5654359Smckusick 	bflush(NODEV);
5664359Smckusick }
567