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