iobuf.c 2.8 KB

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