iotrack.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. #include <u.h>
  2. #include <libc.h>
  3. #include "iotrack.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #define HIOB 31 /* a prime */
  7. #define NIOBUF 80
  8. static Iotrack hiob[HIOB+1]; /* hash buckets + lru list */
  9. static Iotrack iobuf[NIOBUF]; /* the real ones */
  10. #define UNLINK(p, nx, pr) ((p)->pr->nx = (p)->nx, (p)->nx->pr = (p)->pr)
  11. #define LINK(h, p, nx, pr) ((p)->nx = (h)->nx, (p)->pr = (h), \
  12. (h)->nx->pr = (p), (h)->nx = (p))
  13. #define HTOFRONT(h, p) ((h)->hnext != (p) && (UNLINK(p,hnext,hprev), LINK(h,p,hnext,hprev)))
  14. #define TOFRONT(h, p) ((h)->next != (p) && (UNLINK(p, next, prev), LINK(h,p, next, prev)))
  15. Iosect *
  16. getsect(Xfs *xf, long addr)
  17. {
  18. return getiosect(xf, addr, 1);
  19. }
  20. Iosect *
  21. getosect(Xfs *xf, long addr)
  22. {
  23. return getiosect(xf, addr, 0);
  24. }
  25. Iosect *
  26. getiosect(Xfs *xf, long addr, int rflag)
  27. {
  28. Iotrack *t;
  29. long taddr;
  30. int toff;
  31. Iosect *p;
  32. toff = addr % Sect2trk;
  33. taddr = addr - toff;
  34. t = getiotrack(xf, taddr);
  35. if(rflag && (t->flags&BSTALE)){
  36. if(tread(t) < 0){
  37. unmlock(&t->lock);
  38. return 0;
  39. }
  40. t->flags &= ~BSTALE;
  41. }
  42. t->ref++;
  43. p = t->tp->p[toff];
  44. if(p == 0){
  45. p = newsect();
  46. t->tp->p[toff] = p;
  47. p->flags = t->flags&BSTALE;
  48. p->lock.key = 0;
  49. p->t = t;
  50. p->iobuf = t->tp->buf[toff];
  51. }
  52. unmlock(&t->lock);
  53. mlock(&p->lock);
  54. return p;
  55. }
  56. void
  57. putsect(Iosect *p)
  58. {
  59. Iotrack *t;
  60. if(canmlock(&p->lock))
  61. panic("putsect");
  62. t = p->t;
  63. mlock(&t->lock);
  64. t->flags |= p->flags;
  65. p->flags = 0;
  66. t->ref--;
  67. if(t->flags & BIMM){
  68. if(t->flags & BMOD)
  69. twrite(t);
  70. t->flags &= ~(BMOD|BIMM);
  71. }
  72. unmlock(&t->lock);
  73. unmlock(&p->lock);
  74. }
  75. Iotrack *
  76. getiotrack(Xfs *xf, long addr)
  77. {
  78. Iotrack *hp, *p;
  79. Iotrack *mp = &hiob[HIOB];
  80. long h;
  81. /*
  82. * chat("iotrack %d,%d...", dev, addr);
  83. */
  84. h = (xf->dev<<24) ^ addr;
  85. if(h < 0)
  86. h = ~h;
  87. h %= HIOB;
  88. hp = &hiob[h];
  89. loop:
  90. /*
  91. * look for it in the active list
  92. */
  93. mlock(&hp->lock);
  94. for(p=hp->hnext; p != hp; p=p->hnext){
  95. if(p->addr != addr || p->xf != xf)
  96. continue;
  97. unmlock(&hp->lock);
  98. mlock(&p->lock);
  99. if(p->addr == addr && p->xf == xf)
  100. goto out;
  101. unmlock(&p->lock);
  102. goto loop;
  103. }
  104. unmlock(&hp->lock);
  105. /*
  106. * not found
  107. * take oldest unref'd entry
  108. */
  109. mlock(&mp->lock);
  110. for(p=mp->prev; p != mp; p=p->prev)
  111. if(p->ref == 0 && canmlock(&p->lock)){
  112. if(p->ref == 0)
  113. break;
  114. unmlock(&p->lock);
  115. }
  116. unmlock(&mp->lock);
  117. if(p == mp){
  118. print("iotrack all ref'd\n");
  119. goto loop;
  120. }
  121. if(p->flags & BMOD){
  122. twrite(p);
  123. p->flags &= ~(BMOD|BIMM);
  124. unmlock(&p->lock);
  125. goto loop;
  126. }
  127. purgetrack(p);
  128. p->addr = addr;
  129. p->xf = xf;
  130. p->flags = BSTALE;
  131. out:
  132. mlock(&hp->lock);
  133. HTOFRONT(hp, p);
  134. unmlock(&hp->lock);
  135. mlock(&mp->lock);
  136. TOFRONT(mp, p);
  137. unmlock(&mp->lock);
  138. return p;
  139. }
  140. void
  141. purgetrack(Iotrack *t)
  142. {
  143. int i, ref = Sect2trk;
  144. Iosect *p;
  145. for(i=0; i<Sect2trk; i++){
  146. p = t->tp->p[i];
  147. if(p == 0){
  148. --ref;
  149. continue;
  150. }
  151. if(canmlock(&p->lock)){
  152. freesect(p);
  153. --ref;
  154. t->tp->p[i] = 0;
  155. }
  156. }
  157. if(t->ref != ref)
  158. panic("purgetrack");
  159. }
  160. int
  161. twrite(Iotrack *t)
  162. {
  163. int i, ref;
  164. chat("[twrite %ld...", t->addr);
  165. if(t->flags & BSTALE){
  166. for(ref=0,i=0; i<Sect2trk; i++)
  167. if(t->tp->p[i])
  168. ++ref;
  169. if(ref < Sect2trk){
  170. if(tread(t) < 0){
  171. chat("error]");
  172. return -1;
  173. }
  174. }else
  175. t->flags &= ~BSTALE;
  176. }
  177. if(devwrite(t->xf, t->addr, t->tp->buf, Trksize) < 0){
  178. chat("error]");
  179. return -1;
  180. }
  181. chat(" done]");
  182. return 0;
  183. }
  184. int
  185. tread(Iotrack *t)
  186. {
  187. int i, ref = 0;
  188. uchar buf[Sect2trk][Sectorsize];
  189. for(i=0; i<Sect2trk; i++)
  190. if(t->tp->p[i])
  191. ++ref;
  192. chat("[tread %ld+%ld...", t->addr, t->xf->offset);
  193. if(ref == 0){
  194. if(devread(t->xf, t->addr, t->tp->buf, Trksize) < 0){
  195. chat("error]");
  196. return -1;
  197. }
  198. chat("done]");
  199. t->flags &= ~BSTALE;
  200. return 0;
  201. }
  202. if(devread(t->xf, t->addr, buf, Trksize) < 0){
  203. chat("error]");
  204. return -1;
  205. }
  206. for(i=0; i<Sect2trk; i++)
  207. if(t->tp->p[i] == 0){
  208. memmove(t->tp->buf[i], buf[i], Sectorsize);
  209. chat("%d ", i);
  210. }
  211. chat("done]");
  212. t->flags &= ~BSTALE;
  213. return 0;
  214. }
  215. void
  216. purgebuf(Xfs *xf)
  217. {
  218. Iotrack *p;
  219. for(p=&iobuf[0]; p<&iobuf[NIOBUF]; p++){
  220. if(p->xf != xf)
  221. continue;
  222. mlock(&p->lock);
  223. if(p->xf == xf){
  224. if(p->flags & BMOD)
  225. twrite(p);
  226. p->flags = BSTALE;
  227. purgetrack(p);
  228. }
  229. unmlock(&p->lock);
  230. }
  231. }
  232. void
  233. sync(void)
  234. {
  235. Iotrack *p;
  236. for(p=&iobuf[0]; p<&iobuf[NIOBUF]; p++){
  237. if(!(p->flags & BMOD))
  238. continue;
  239. mlock(&p->lock);
  240. if(p->flags & BMOD){
  241. twrite(p);
  242. p->flags &= ~(BMOD|BIMM);
  243. }
  244. unmlock(&p->lock);
  245. }
  246. }
  247. void
  248. iotrack_init(void)
  249. {
  250. Iotrack *mp, *p;
  251. for (mp=&hiob[0]; mp<&hiob[HIOB]; mp++)
  252. mp->hprev = mp->hnext = mp;
  253. mp->prev = mp->next = mp;
  254. for (p=&iobuf[0]; p<&iobuf[NIOBUF]; p++) {
  255. p->hprev = p->hnext = p;
  256. p->prev = p->next = p;
  257. TOFRONT(mp, p);
  258. p->tp = sbrk(sizeof(Track));
  259. memset(p->tp->p, 0, sizeof p->tp->p);
  260. }
  261. }
  262. static MLock freelock;
  263. static Iosect * freelist;
  264. Iosect *
  265. newsect(void)
  266. {
  267. Iosect *p;
  268. mlock(&freelock);
  269. if(p = freelist) /* assign = */
  270. freelist = p->next;
  271. else
  272. p = malloc(sizeof(Iosect));
  273. unmlock(&freelock);
  274. p->next = 0;
  275. return p;
  276. }
  277. void
  278. freesect(Iosect *p)
  279. {
  280. mlock(&freelock);
  281. p->next = freelist;
  282. freelist = p;
  283. unmlock(&freelock);
  284. }