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