1 #include <u.h> 2 #include <libc.h> 3 #include <fcall.h> 4 #include <thread.h> 5 #include <9p.h> 6 #include "dat.h" 7 #include "fns.h" 8 9 #define NIOBUF 100 10 #define HIOB (NIOBUF/3) 11 12 static Iobuf* hiob[HIOB]; /* hash buckets */ 13 static Iobuf iobuf[NIOBUF]; /* buffer headers */ 14 static Iobuf* iohead; 15 static Iobuf* iotail; 16 17 Iobuf* 18 getbuf(Xfs *dev, long addr) 19 { 20 Iobuf *p, *h, **l, **f; 21 22 l = &hiob[addr%HIOB]; 23 for(p = *l; p; p = p->hash) { 24 if(p->addr == addr && p->dev == dev) { 25 p->busy++; 26 return p; 27 } 28 } 29 /* Find a non-busy buffer from the tail */ 30 for(p = iotail; p && (p->busy > 0); p = p->prev) 31 ; 32 if(!p) 33 panic("all buffers busy"); 34 if(p->dirty){ 35 xwrite(p); 36 p->dirty = 0; 37 } 38 39 if( xread(dev, p, addr) < 0) 40 return 0; 41 /* Delete from hash chain */ 42 f = &hiob[p->addr%HIOB]; 43 if( *f == p ) 44 *f = p->hash; 45 else { 46 for(h = *f; h ; h = h->hash) 47 if( h->hash == p ){ 48 h->hash = p->hash; 49 break; 50 } 51 } 52 /* Fill and hash */ 53 p->hash = *l; 54 *l = p; 55 p->addr = addr; 56 p->dev = dev; 57 p->busy=1; 58 59 return p; 60 } 61 void 62 putbuf(Iobuf *p) 63 { 64 if(p->busy <= 0) 65 panic("putbuf"); 66 p->busy--; 67 68 /* Link onto head for lru */ 69 if(p == iohead) 70 return; 71 if( p == iotail ){ 72 p->prev->next = 0; 73 iotail = p->prev; 74 }else{ 75 p->prev->next = p->next; 76 p->next->prev = p->prev; 77 } 78 79 p->prev = 0; 80 p->next = iohead; 81 iohead->prev = p; 82 iohead = p; 83 } 84 void 85 dirtybuf(Iobuf *p) 86 { 87 if(p->busy <=0) 88 panic("dirtybuf"); 89 p->dirty = 1; 90 } 91 void 92 syncbuf(void) 93 { 94 Iobuf *p; 95 96 for(p=&iobuf[0] ; p<&iobuf[NIOBUF]; p++) 97 if( p->dirty ){ 98 xwrite(p); 99 p->dirty = 0; 100 } 101 } 102 void 103 purgebuf(Xfs *dev) 104 { 105 Iobuf *p; 106 107 for(p=&iobuf[0]; p<&iobuf[NIOBUF]; p++) 108 if(p->dev == dev) 109 p->busy = 0; 110 111 /* Blow hash chains */ 112 memset(hiob, 0, sizeof(hiob)); 113 } 114 void 115 iobuf_init(void) 116 { 117 Iobuf *p; 118 119 iohead = iobuf; 120 iotail = iobuf+NIOBUF-1; 121 122 for(p = iobuf; p <= iotail; p++) { 123 p->next = p+1; 124 p->prev = p-1; 125 126 p->iobuf = (char *)malloc(EXT2_MAX_BLOCK_SIZE); 127 if(p->iobuf == 0) 128 panic("iobuf_init"); 129 } 130 131 iohead->prev = 0; 132 iotail->next = 0; 133 } 134 int 135 xread(Xfs *dev, Iobuf *p, long addr) 136 { 137 /*chat("xread %d,%d...", dev->dev, addr);*/ 138 139 seek(dev->dev, (vlong)addr*dev->block_size, 0); 140 if(read(dev->dev, p->iobuf, dev->block_size) != dev->block_size){ 141 chat("xread %d, block=%d failed ...", dev->dev, addr); 142 errno = Eio; 143 return -1; 144 } 145 /*chat("xread ok...");*/ 146 return 0; 147 } 148 void 149 xwrite(Iobuf *p) 150 { 151 Xfs *dev; 152 long addr; 153 154 dev = p->dev; 155 addr = p->addr; 156 /*chat("xwrite %d,%d...", dev->dev, addr);*/ 157 158 seek(dev->dev, (vlong)addr*dev->block_size, 0); 159 if(write(dev->dev, p->iobuf, dev->block_size) != dev->block_size){ 160 chat("xwrite %d, block=%d failed ...", dev->dev, addr); 161 errno = Eio; 162 return; 163 } 164 /*chat("xwrite ok...");*/ 165 } 166 void 167 dumpbuf(void) 168 { 169 Iobuf *p; 170 171 for(p = iotail; p ; p = p->prev) 172 if( p->busy ) 173 mchat("\nHi ERROR buf(%x, %d, %d)\n", p, p->addr, p->busy); 174 } 175