xref: /plan9/sys/src/cmd/cfs/inode.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include "cformat.h"
43e12c5d1SDavid du Colombier #include "lru.h"
53e12c5d1SDavid du Colombier #include "bcache.h"
63e12c5d1SDavid du Colombier #include "disk.h"
73e12c5d1SDavid du Colombier #include "inode.h"
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier /*
103e12c5d1SDavid du Colombier  *  read the inode blocks and make sure they
113e12c5d1SDavid du Colombier  *  haven't been trashed.
123e12c5d1SDavid du Colombier  *
133e12c5d1SDavid du Colombier  *  make the in-core table of qid to inode mappings.
143e12c5d1SDavid du Colombier  *	N.B. this is just an array. we need a linear search to find
153e12c5d1SDavid du Colombier  *	     a particular inode. this could be done faster.
163e12c5d1SDavid du Colombier  *
173e12c5d1SDavid du Colombier  *  nab is the first inode block.
183e12c5d1SDavid du Colombier  */
193e12c5d1SDavid du Colombier int
203e12c5d1SDavid du Colombier iinit(Icache *ic, int f, int psize)
213e12c5d1SDavid du Colombier {
223e12c5d1SDavid du Colombier 	Ibuf *b;
233e12c5d1SDavid du Colombier 	Imap *m;
243e12c5d1SDavid du Colombier 	ulong ino;
253e12c5d1SDavid du Colombier 	Bbuf *bb;
263e12c5d1SDavid du Colombier 	Dinode *bi;
273e12c5d1SDavid du Colombier 
283e12c5d1SDavid du Colombier 	/*
293e12c5d1SDavid du Colombier 	 *  get basic sizes and allocation info from disk
303e12c5d1SDavid du Colombier 	 */
313e12c5d1SDavid du Colombier 	if(dinit(ic, f, psize) < 0)
323e12c5d1SDavid du Colombier 		return -1;
333e12c5d1SDavid du Colombier 
343e12c5d1SDavid du Colombier 	/*
353e12c5d1SDavid du Colombier 	 *  read first inode block to get number of inodes
363e12c5d1SDavid du Colombier 	 */
373e12c5d1SDavid du Colombier 	bb = bcread(ic, ic->nab);
383e12c5d1SDavid du Colombier 	if(bb == 0){
393e12c5d1SDavid du Colombier 		fprint(2, "iinit: can't read disk\n");
403e12c5d1SDavid du Colombier 		return -1;
413e12c5d1SDavid du Colombier 	}
423e12c5d1SDavid du Colombier 	bi = (Dinode*)bb->data;
433e12c5d1SDavid du Colombier 	if(bi->nino==0 || bi->nino>2048){
443e12c5d1SDavid du Colombier 		fprint(2, "iinit: bad nino\n");
453e12c5d1SDavid du Colombier 		return -1;
463e12c5d1SDavid du Colombier 	}
473e12c5d1SDavid du Colombier 	ic->nino = bi->nino;
483e12c5d1SDavid du Colombier 
493e12c5d1SDavid du Colombier 	/*
503e12c5d1SDavid du Colombier 	 *  set up sizing constants
513e12c5d1SDavid du Colombier 	 */
523e12c5d1SDavid du Colombier 	ic->i2b = (ic->bsize - sizeof(Dihdr))/sizeof(Inode);
533e12c5d1SDavid du Colombier 	ic->nib = (ic->nino + ic->i2b - 1)/ic->i2b;
543e12c5d1SDavid du Colombier 
553e12c5d1SDavid du Colombier 	/*
563e12c5d1SDavid du Colombier 	 *  allocate the in-core qid/inode map, build it's lru
573e12c5d1SDavid du Colombier 	 */
583e12c5d1SDavid du Colombier 	if(ic->map)
593e12c5d1SDavid du Colombier 		free(ic->map);
603e12c5d1SDavid du Colombier 	ic->map = malloc(sizeof(Imap)*ic->nino);
613e12c5d1SDavid du Colombier 	if(ic->map == 0){
623e12c5d1SDavid du Colombier 		fprint(2, "iinit: can't alloc map\n");
633e12c5d1SDavid du Colombier 		return -1;
643e12c5d1SDavid du Colombier 	}
653e12c5d1SDavid du Colombier 	lruinit(&ic->mlru);
663e12c5d1SDavid du Colombier 	for(m = ic->map; m < &ic->map[ic->nino]; m++){
673e12c5d1SDavid du Colombier 		m->inuse = 0;
683e12c5d1SDavid du Colombier 		m->b = 0;
693e12c5d1SDavid du Colombier 		lruadd(&ic->mlru, m);
703e12c5d1SDavid du Colombier 	}
713e12c5d1SDavid du Colombier 
723e12c5d1SDavid du Colombier 	/*
733e12c5d1SDavid du Colombier 	 *  mark all cache buffers as empty, put them on the lru list
743e12c5d1SDavid du Colombier 	 */
753e12c5d1SDavid du Colombier 	lruinit(&ic->blru);
763e12c5d1SDavid du Colombier 	for(b = ic->ib; b < &ic->ib[Nicache]; b++){
773e12c5d1SDavid du Colombier 		b->inuse = 0;
783e12c5d1SDavid du Colombier 		lruadd(&ic->blru, b);
793e12c5d1SDavid du Colombier 	}
803e12c5d1SDavid du Colombier 
813e12c5d1SDavid du Colombier 	/*
823e12c5d1SDavid du Colombier 	 *  Read all inodes and
833e12c5d1SDavid du Colombier 	 *  build the in-core qid/inode map
843e12c5d1SDavid du Colombier 	 */
853e12c5d1SDavid du Colombier 	for(ino = 0; ino < ic->nino; ino++){
863e12c5d1SDavid du Colombier 		b = iread(ic, ino);
873e12c5d1SDavid du Colombier 		if(b == 0){
883e12c5d1SDavid du Colombier 			fprint(2, "iinit: can't read inode %ld\n", ino);
893e12c5d1SDavid du Colombier 			return -1;
903e12c5d1SDavid du Colombier 		}
913e12c5d1SDavid du Colombier 		if(b->inode.inuse){
923e12c5d1SDavid du Colombier 			m = &ic->map[ino];
933e12c5d1SDavid du Colombier 			m->inuse = 1;
943e12c5d1SDavid du Colombier 			m->qid = b->inode.qid;
953e12c5d1SDavid du Colombier 			lruref(&ic->mlru, m);
963e12c5d1SDavid du Colombier 		}
973e12c5d1SDavid du Colombier 	}
983e12c5d1SDavid du Colombier 	return 0;
993e12c5d1SDavid du Colombier }
1003e12c5d1SDavid du Colombier 
1013e12c5d1SDavid du Colombier /*
1023e12c5d1SDavid du Colombier  *  format the inode blocks
1033e12c5d1SDavid du Colombier  */
1043e12c5d1SDavid du Colombier int
1053e12c5d1SDavid du Colombier iformat(Icache *ic, int f, ulong nino, char *name, int bsize, int psize)
1063e12c5d1SDavid du Colombier {
1073e12c5d1SDavid du Colombier 	Bbuf *bb;
1083e12c5d1SDavid du Colombier 	Dinode *bi;
1093e12c5d1SDavid du Colombier 	ulong bno;
1103e12c5d1SDavid du Colombier 	ulong i;
1113e12c5d1SDavid du Colombier 	ulong i2b;
1123e12c5d1SDavid du Colombier 	int nib;
1133e12c5d1SDavid du Colombier 
1143e12c5d1SDavid du Colombier 	/*
1153e12c5d1SDavid du Colombier 	 *  first format disk allocation
1163e12c5d1SDavid du Colombier 	 */
1173e12c5d1SDavid du Colombier 	if(dformat(ic, f, name, bsize, psize) < 0)
1183e12c5d1SDavid du Colombier 		return -1;
1193e12c5d1SDavid du Colombier 
120*219b2ee8SDavid du Colombier 	fprint(2, "formatting inodes\n");
1213e12c5d1SDavid du Colombier 
1223e12c5d1SDavid du Colombier 	i2b = (bsize - sizeof(Dihdr))/sizeof(Inode);
1233e12c5d1SDavid du Colombier 	nib = (nino + i2b - 1)/i2b;
1243e12c5d1SDavid du Colombier 
1253e12c5d1SDavid du Colombier 	for(bno = ic->nab; bno < ic->nab + nib; bno++){
1263e12c5d1SDavid du Colombier 		if(dalloc(ic, 0) == Notabno){
1273e12c5d1SDavid du Colombier 			fprint(2, "iformat: balloc failed\n");
1283e12c5d1SDavid du Colombier 			return -1;
1293e12c5d1SDavid du Colombier 		}
1303e12c5d1SDavid du Colombier 		bb = bcalloc(ic, bno);
1313e12c5d1SDavid du Colombier 		if(bb == 0){
1323e12c5d1SDavid du Colombier 			fprint(2, "iformat: bcalloc failed\n");
1333e12c5d1SDavid du Colombier 			return -1;
1343e12c5d1SDavid du Colombier 		}
1353e12c5d1SDavid du Colombier 		bi = (Dinode*)bb->data;
1363e12c5d1SDavid du Colombier 		bi->magic = Imagic;
1373e12c5d1SDavid du Colombier 		bi->nino = nino;
1383e12c5d1SDavid du Colombier 		for(i = 0; i < i2b; i++)
1393e12c5d1SDavid du Colombier 			bi->inode[i].inuse = 0;
1403e12c5d1SDavid du Colombier 		bcmark(ic, bb);
1413e12c5d1SDavid du Colombier 	}
1423e12c5d1SDavid du Colombier 
1433e12c5d1SDavid du Colombier 	bcsync(ic);
1443e12c5d1SDavid du Colombier 
1453e12c5d1SDavid du Colombier 	return iinit(ic, f, psize);
1463e12c5d1SDavid du Colombier }
1473e12c5d1SDavid du Colombier 
1483e12c5d1SDavid du Colombier /*
1493e12c5d1SDavid du Colombier  *  allocate a cache buffer, use least recently used
1503e12c5d1SDavid du Colombier  */
1513e12c5d1SDavid du Colombier Ibuf*
1523e12c5d1SDavid du Colombier ialloc(Icache *ic, ulong ino)
1533e12c5d1SDavid du Colombier {
1543e12c5d1SDavid du Colombier 	Imap *m;
1553e12c5d1SDavid du Colombier 	Ibuf *b;
1563e12c5d1SDavid du Colombier 
1573e12c5d1SDavid du Colombier 	b = (Ibuf*)ic->blru.lnext;
1583e12c5d1SDavid du Colombier 	if(b->inuse)
1593e12c5d1SDavid du Colombier 		ic->map[b->ino].b = 0;
1603e12c5d1SDavid du Colombier 	b->ino = ino;
1613e12c5d1SDavid du Colombier 	b->inuse = 1;
1623e12c5d1SDavid du Colombier 	m = &ic->map[ino];
1633e12c5d1SDavid du Colombier 	m->b = b;
1643e12c5d1SDavid du Colombier 	return b;
1653e12c5d1SDavid du Colombier }
1663e12c5d1SDavid du Colombier 
1673e12c5d1SDavid du Colombier /*
1683e12c5d1SDavid du Colombier  *  free a cache buffer
1693e12c5d1SDavid du Colombier  */
1703e12c5d1SDavid du Colombier void
1713e12c5d1SDavid du Colombier ifree(Icache *ic, Ibuf *b)
1723e12c5d1SDavid du Colombier {
1733e12c5d1SDavid du Colombier 	b->inuse = 0;
1743e12c5d1SDavid du Colombier 	if(b->inuse)
1753e12c5d1SDavid du Colombier 		ic->map[b->ino].b = 0;
1763e12c5d1SDavid du Colombier 	lruderef(&ic->blru, b);
1773e12c5d1SDavid du Colombier }
1783e12c5d1SDavid du Colombier 
1793e12c5d1SDavid du Colombier /*
1803e12c5d1SDavid du Colombier  *  get an inode into the cache.  if no inode exists for this qid, create one
1813e12c5d1SDavid du Colombier  *  from an unused qid/inode map.
1823e12c5d1SDavid du Colombier  */
1833e12c5d1SDavid du Colombier Ibuf *
1843e12c5d1SDavid du Colombier iget(Icache *ic, Qid qid)
1853e12c5d1SDavid du Colombier {
1863e12c5d1SDavid du Colombier 	Imap *m, *me;
1873e12c5d1SDavid du Colombier 	Ibuf *b;
1883e12c5d1SDavid du Colombier 
1893e12c5d1SDavid du Colombier 	/*
1903e12c5d1SDavid du Colombier 	 *  find map entry with same qid.path
1913e12c5d1SDavid du Colombier 	 */
1923e12c5d1SDavid du Colombier 	for(m = ic->map, me = &ic->map[ic->nino]; m < me; m++){
1933e12c5d1SDavid du Colombier 		if(m->inuse && m->qid.path==qid.path){
1943e12c5d1SDavid du Colombier 			if(m->qid.vers != qid.vers){
1953e12c5d1SDavid du Colombier 				/*
1963e12c5d1SDavid du Colombier 				 *  our info is old, forget it
1973e12c5d1SDavid du Colombier 				 */
1983e12c5d1SDavid du Colombier 				DPRINT(2, "updating old file %lud.%lud\n",
1993e12c5d1SDavid du Colombier 					qid.path, qid.vers);
2003e12c5d1SDavid du Colombier 				m->qid = qid;
2013e12c5d1SDavid du Colombier 				iupdate(ic, m - ic->map, qid);
2023e12c5d1SDavid du Colombier 			}
2033e12c5d1SDavid du Colombier 			break;
2043e12c5d1SDavid du Colombier 		}
2053e12c5d1SDavid du Colombier 	}
2063e12c5d1SDavid du Colombier 
2073e12c5d1SDavid du Colombier 	/*
2083e12c5d1SDavid du Colombier  	 *  if an already existing inode, just get it
2093e12c5d1SDavid du Colombier 	 */
2103e12c5d1SDavid du Colombier 	if(m != me)
2113e12c5d1SDavid du Colombier 		return iread(ic, m - ic->map);
2123e12c5d1SDavid du Colombier 
2133e12c5d1SDavid du Colombier 	/*
2143e12c5d1SDavid du Colombier 	 *  create a new inode, throw out the least recently used inode
2153e12c5d1SDavid du Colombier 	 *  if necessary
2163e12c5d1SDavid du Colombier 	 */
2173e12c5d1SDavid du Colombier 	m = (Imap*)ic->mlru.lnext;
2183e12c5d1SDavid du Colombier 	if(m->inuse){
2193e12c5d1SDavid du Colombier 		DPRINT(2, "superceding file %ld.%ld by %ld.%ld\n", m->qid.path,
2203e12c5d1SDavid du Colombier 			m->qid.vers, qid.path, qid.vers);
2213e12c5d1SDavid du Colombier 		if(iremove(ic, m - ic->map) < 0)
2223e12c5d1SDavid du Colombier 			return 0;
2233e12c5d1SDavid du Colombier 	}
2243e12c5d1SDavid du Colombier 
2253e12c5d1SDavid du Colombier 	/*
2263e12c5d1SDavid du Colombier 	 *  init inode and write to disk
2273e12c5d1SDavid du Colombier 	 */
2283e12c5d1SDavid du Colombier 	DPRINT(2, "new file %ld.%ld ino %ld\n", qid.path, qid.vers, m - ic->map);
2293e12c5d1SDavid du Colombier 	b = ialloc(ic, m - ic->map);
2303e12c5d1SDavid du Colombier 	b->inode.inuse = m->inuse = 1;
2313e12c5d1SDavid du Colombier 	b->inode.qid = qid;
2323e12c5d1SDavid du Colombier 	m->qid = qid;
2333e12c5d1SDavid du Colombier 	b->inode.ptr.bno = Notabno;
2343e12c5d1SDavid du Colombier 	iwrite(ic, b);
2353e12c5d1SDavid du Colombier 	return b;
2363e12c5d1SDavid du Colombier }
2373e12c5d1SDavid du Colombier 
2383e12c5d1SDavid du Colombier /*
2393e12c5d1SDavid du Colombier  *  read an inode into the cache
2403e12c5d1SDavid du Colombier  *
2413e12c5d1SDavid du Colombier  *  ASSUMPTION: the inode is valid
2423e12c5d1SDavid du Colombier  */
2433e12c5d1SDavid du Colombier Ibuf*
2443e12c5d1SDavid du Colombier iread(Icache *ic, ulong ino)
2453e12c5d1SDavid du Colombier {
2463e12c5d1SDavid du Colombier 	Ibuf *b;
2473e12c5d1SDavid du Colombier 	Imap *m;
2483e12c5d1SDavid du Colombier 	ulong bno;
2493e12c5d1SDavid du Colombier 	Bbuf *bb;
2503e12c5d1SDavid du Colombier 	Dinode *bi;
2513e12c5d1SDavid du Colombier 
2523e12c5d1SDavid du Colombier 	/*
2533e12c5d1SDavid du Colombier 	 *  first see if we already have it in a cache entry
2543e12c5d1SDavid du Colombier 	 */
2553e12c5d1SDavid du Colombier 	m = &ic->map[ino];
2563e12c5d1SDavid du Colombier 	if(m->inuse && m->b){
2573e12c5d1SDavid du Colombier 		b = m->b;
2583e12c5d1SDavid du Colombier 		goto out;
2593e12c5d1SDavid du Colombier 	}
2603e12c5d1SDavid du Colombier 
2613e12c5d1SDavid du Colombier 	/*
2623e12c5d1SDavid du Colombier 	 *  read it
2633e12c5d1SDavid du Colombier 	 */
2643e12c5d1SDavid du Colombier 	b = ialloc(ic, ino);
2653e12c5d1SDavid du Colombier 	bno = ic->nab + ino/ic->i2b;
2663e12c5d1SDavid du Colombier 	bb = bcread(ic, bno);
2673e12c5d1SDavid du Colombier 	if(bb == 0){
2683e12c5d1SDavid du Colombier 		ifree(ic, b);
2693e12c5d1SDavid du Colombier 		return 0;
2703e12c5d1SDavid du Colombier 	}
2713e12c5d1SDavid du Colombier 	bi = (Dinode*)bb->data;
2723e12c5d1SDavid du Colombier 	b->inode = bi->inode[ino % ic->i2b];
2733e12c5d1SDavid du Colombier 
2743e12c5d1SDavid du Colombier 	/*
2753e12c5d1SDavid du Colombier 	 *  consistency check
2763e12c5d1SDavid du Colombier 	 */
2773e12c5d1SDavid du Colombier 	if(bi->nino!=ic->nino || bi->magic!=Imagic){
2783e12c5d1SDavid du Colombier 		fprint(2, "iread: inconsistent inode block\n");
2793e12c5d1SDavid du Colombier 		ifree(ic, b);
2803e12c5d1SDavid du Colombier 		return 0;
2813e12c5d1SDavid du Colombier 	}
2823e12c5d1SDavid du Colombier out:
2833e12c5d1SDavid du Colombier 	b->inuse = 1;
2843e12c5d1SDavid du Colombier 	m->b = b;
2853e12c5d1SDavid du Colombier 	if(b->inode.inuse)
2863e12c5d1SDavid du Colombier 		lruref(&ic->mlru, m);
2873e12c5d1SDavid du Colombier 	lruref(&ic->blru, b);
2883e12c5d1SDavid du Colombier 	return b;
2893e12c5d1SDavid du Colombier }
2903e12c5d1SDavid du Colombier 
2913e12c5d1SDavid du Colombier /*
2923e12c5d1SDavid du Colombier  *  write an inode back to disk
2933e12c5d1SDavid du Colombier  */
2943e12c5d1SDavid du Colombier int
2953e12c5d1SDavid du Colombier iwrite(Icache *ic, Ibuf *b)
2963e12c5d1SDavid du Colombier {
2973e12c5d1SDavid du Colombier 	ulong bno;
2983e12c5d1SDavid du Colombier 	Bbuf *bb;
2993e12c5d1SDavid du Colombier 	Dinode *bi;
3003e12c5d1SDavid du Colombier 
3013e12c5d1SDavid du Colombier 	bno = ic->nab + b->ino/ic->i2b;
3023e12c5d1SDavid du Colombier 	bb = bcread(ic, bno);
3033e12c5d1SDavid du Colombier 	if(bb == 0)
3043e12c5d1SDavid du Colombier 		return 0;
3053e12c5d1SDavid du Colombier 	bi = (Dinode*)bb->data;
3063e12c5d1SDavid du Colombier 	bi->inode[b->ino % ic->i2b] = b->inode;
3073e12c5d1SDavid du Colombier 	bcmark(ic, bb);
3083e12c5d1SDavid du Colombier 	lruref(&ic->mlru, &ic->map[b->ino]);
3093e12c5d1SDavid du Colombier 	lruref(&ic->blru, b);
3103e12c5d1SDavid du Colombier 	return 0;
3113e12c5d1SDavid du Colombier }
3123e12c5d1SDavid du Colombier 
3133e12c5d1SDavid du Colombier /*
3143e12c5d1SDavid du Colombier  *  Forget what we know about an inode without removing it
3153e12c5d1SDavid du Colombier  *
3163e12c5d1SDavid du Colombier  *	N.B: ordering of iwrite and dfree is important
3173e12c5d1SDavid du Colombier  */
3183e12c5d1SDavid du Colombier int
3193e12c5d1SDavid du Colombier iupdate(Icache *ic, ulong ino, Qid qid)
3203e12c5d1SDavid du Colombier {
3213e12c5d1SDavid du Colombier 	Ibuf *b;
3223e12c5d1SDavid du Colombier 	Imap *m;
3233e12c5d1SDavid du Colombier 	Dptr d;
3243e12c5d1SDavid du Colombier 
3253e12c5d1SDavid du Colombier 	b = iread(ic, ino);
3263e12c5d1SDavid du Colombier 	if(b == 0)
3273e12c5d1SDavid du Colombier 		return -1;
3283e12c5d1SDavid du Colombier 
3293e12c5d1SDavid du Colombier 	/*
3303e12c5d1SDavid du Colombier 	 *  update inode and map
3313e12c5d1SDavid du Colombier 	 */
3323e12c5d1SDavid du Colombier 	b->inode.qid = qid;
3333e12c5d1SDavid du Colombier 	m = &ic->map[ino];
3343e12c5d1SDavid du Colombier 	m->qid = qid;
3353e12c5d1SDavid du Colombier 
3363e12c5d1SDavid du Colombier 	/*
3373e12c5d1SDavid du Colombier 	 *  the free is not done if the write fails!
3383e12c5d1SDavid du Colombier 	 *  this is important
3393e12c5d1SDavid du Colombier 	 */
3403e12c5d1SDavid du Colombier 	d = b->inode.ptr;
3413e12c5d1SDavid du Colombier 	b->inode.ptr.bno = Notabno;
3423e12c5d1SDavid du Colombier 	if(iwrite(ic, b) < 0)
3433e12c5d1SDavid du Colombier 		return -1;
3443e12c5d1SDavid du Colombier 	dfree(ic, &d);
3453e12c5d1SDavid du Colombier 	return 0;
3463e12c5d1SDavid du Colombier }
3473e12c5d1SDavid du Colombier 
3483e12c5d1SDavid du Colombier /*
3493e12c5d1SDavid du Colombier  *  remove an inode
3503e12c5d1SDavid du Colombier  *
3513e12c5d1SDavid du Colombier  *	N.B: ordering of iwrite and dfree is important
3523e12c5d1SDavid du Colombier  */
3533e12c5d1SDavid du Colombier int
3543e12c5d1SDavid du Colombier iremove(Icache *ic, ulong ino)
3553e12c5d1SDavid du Colombier {
3563e12c5d1SDavid du Colombier 	Ibuf *b;
3573e12c5d1SDavid du Colombier 	Imap *m;
3583e12c5d1SDavid du Colombier 
3593e12c5d1SDavid du Colombier 	m = &ic->map[ino];
3603e12c5d1SDavid du Colombier 
3613e12c5d1SDavid du Colombier 	/*
3623e12c5d1SDavid du Colombier 	 *  read in inode
3633e12c5d1SDavid du Colombier 	 */
3643e12c5d1SDavid du Colombier 	b = iread(ic, ino);
3653e12c5d1SDavid du Colombier 	if(b == 0)
3663e12c5d1SDavid du Colombier 		return -1;
3673e12c5d1SDavid du Colombier 
3683e12c5d1SDavid du Colombier 	/*
3693e12c5d1SDavid du Colombier 	 *  mark it unused on disk
3703e12c5d1SDavid du Colombier 	 */
3713e12c5d1SDavid du Colombier 	b->inode.inuse = 0;
3723e12c5d1SDavid du Colombier 	if(iwrite(ic, b) < 0)
3733e12c5d1SDavid du Colombier 		return -1;
3743e12c5d1SDavid du Colombier 
3753e12c5d1SDavid du Colombier 	/*
3763e12c5d1SDavid du Colombier 	 *  throw out it's data pages
3773e12c5d1SDavid du Colombier 	 */
3783e12c5d1SDavid du Colombier 	dfree(ic, &b->inode.ptr);
3793e12c5d1SDavid du Colombier 
3803e12c5d1SDavid du Colombier 	/*
3813e12c5d1SDavid du Colombier 	 *  free the inode buffer
3823e12c5d1SDavid du Colombier 	 */
3833e12c5d1SDavid du Colombier 	ifree(ic, b);
3843e12c5d1SDavid du Colombier 
3853e12c5d1SDavid du Colombier 	/*
3863e12c5d1SDavid du Colombier 	 *  make map entry least recently used
3873e12c5d1SDavid du Colombier 	 */
3883e12c5d1SDavid du Colombier 	lruderef(&ic->mlru, m);
3893e12c5d1SDavid du Colombier 	return 0;
3903e12c5d1SDavid du Colombier }
3913e12c5d1SDavid du Colombier 
3923e12c5d1SDavid du Colombier /*
3933e12c5d1SDavid du Colombier  *  increment our version number
3943e12c5d1SDavid du Colombier  */
3953e12c5d1SDavid du Colombier void
3963e12c5d1SDavid du Colombier iinc(Icache *ic, Ibuf *b)
3973e12c5d1SDavid du Colombier {
3983e12c5d1SDavid du Colombier 	b->inode.qid.vers++;
3993e12c5d1SDavid du Colombier 	ic->map[b->ino].qid = b->inode.qid;
4003e12c5d1SDavid du Colombier 	iwrite(ic, b);
4013e12c5d1SDavid du Colombier }
402