devmulti.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #include "all.h"
  2. enum{
  3. MAXWREN = 7,
  4. };
  5. static char WMAGIC[] = "kfs wren device\n";
  6. static char MMAGIC[] = "kfs multi-wren device %4d/%4d\n";
  7. typedef struct Wren Wren;
  8. struct Wren{
  9. QLock;
  10. Device dev;
  11. ulong nblocks;
  12. int fd;
  13. };
  14. static char *wmagic = WMAGIC;
  15. static Wren *wrens;
  16. static int maxwren;
  17. char *wrenfile;
  18. int nwren;
  19. int badmagic;
  20. static Wren *
  21. wren(Device dev)
  22. {
  23. int i;
  24. for(i = 0; i < maxwren; i++)
  25. if(devcmp(dev, wrens[i].dev) == 0)
  26. return &wrens[i];
  27. panic("can't find wren for %D", dev);
  28. return 0;
  29. }
  30. /*
  31. * find out the length of a file
  32. * given the mesg version of a stat buffer
  33. * we call this because convM2D is different
  34. * for the file system than in the os
  35. */
  36. uvlong
  37. statlen(char *ap)
  38. {
  39. uchar *p;
  40. ulong ll, hl;
  41. p = (uchar*)ap;
  42. p += 3*NAMELEN+5*4;
  43. ll = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
  44. hl = p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24);
  45. return ll | ((uvlong) hl << 32);
  46. }
  47. static void
  48. wrenpartinit(Device dev, int k)
  49. {
  50. char buf[MAXBUFSIZE], d[DIRREC];
  51. char file[128], magic[64];
  52. Wren *w;
  53. int fd, i, nmagic;
  54. if(wrens == 0)
  55. wrens = ialloc(MAXWREN * sizeof *wrens);
  56. w = &wrens[maxwren];
  57. if(nwren > 0)
  58. sprint(file, "%s%d", wrenfile, k);
  59. else
  60. strcpy(file, wrenfile);
  61. fd = open(file, ORDWR);
  62. if(fd < 0)
  63. panic("can't open %s", file);
  64. if(fstat(fd, d) < 0)
  65. panic("can't stat %s\n", file);
  66. seek(fd, 0, 0);
  67. i = read(fd, buf, sizeof buf);
  68. if(i < sizeof buf)
  69. panic("can't read %s", file);
  70. badmagic = 0;
  71. RBUFSIZE = 1024;
  72. sprint(magic, wmagic, k, nwren);
  73. nmagic = strlen(magic);
  74. if(strncmp(buf+256, magic, nmagic) == 0){
  75. RBUFSIZE = atol(buf+256+nmagic);
  76. if(RBUFSIZE % 512){
  77. fprint(2, "kfs: bad buffersize(%d): assuming 1k blocks\n", RBUFSIZE);
  78. RBUFSIZE = 1024;
  79. }
  80. }else
  81. badmagic = 1;
  82. w->dev = dev;
  83. w->nblocks = statlen(d)/RBUFSIZE;
  84. if(k > 0)
  85. w->nblocks -= 1; /* don't count magic */
  86. w->fd = fd;
  87. maxwren++;
  88. }
  89. void
  90. wreninit(Device dev)
  91. {
  92. int i;
  93. if(nwren > 0)
  94. wmagic = MMAGIC;
  95. i = 0;
  96. do{
  97. wrenpartinit(dev, i);
  98. }while(++i < nwren);
  99. }
  100. static void
  101. wrenpartream(Device dev, int k)
  102. {
  103. Wren *w;
  104. char buf[MAXBUFSIZE], magic[64];
  105. int fd, i;
  106. if(RBUFSIZE % 512)
  107. panic("kfs: bad buffersize(%d): restart a multiple of 512\n", RBUFSIZE);
  108. print("kfs: reaming the file system using %d byte blocks\n", RBUFSIZE);
  109. w = wren(dev)+k;
  110. fd = w->fd;
  111. memset(buf, 0, sizeof buf);
  112. sprint(magic, wmagic, k, nwren);
  113. sprint(buf+256, "%s%d\n", magic, RBUFSIZE);
  114. qlock(w);
  115. i = seek(fd, 0, 0) < 0 || write(fd, buf, RBUFSIZE) != RBUFSIZE;
  116. qunlock(w);
  117. if(i < 0)
  118. panic("can't ream disk");
  119. }
  120. void
  121. wrenream(Device dev)
  122. {
  123. int i;
  124. i = 0;
  125. do{
  126. wrenpartream(dev, i);
  127. }while(++i < nwren);
  128. }
  129. static int
  130. wrentag(char *p, int tag, long qpath)
  131. {
  132. Tag *t;
  133. t = (Tag*)(p+BUFSIZE);
  134. return t->tag != tag || (qpath&~QPDIR) != t->path;
  135. }
  136. int
  137. wrencheck(Device dev)
  138. {
  139. char buf[MAXBUFSIZE];
  140. if(badmagic)
  141. return 1;
  142. if(RBUFSIZE > sizeof buf)
  143. panic("bufsize too big");
  144. if(wrenread(dev, wrensuper(dev), buf) || wrentag(buf, Tsuper, QPSUPER)
  145. || wrenread(dev, wrenroot(dev), buf) || wrentag(buf, Tdir, QPROOT))
  146. return 1;
  147. if(((Dentry *)buf)[0].mode & DALLOC)
  148. return 0;
  149. return 1;
  150. }
  151. long
  152. wrensize(Device dev)
  153. {
  154. Wren *w;
  155. int i, nb;
  156. w = wren(dev);
  157. nb = 0;
  158. i = 0;
  159. do{
  160. nb += w[i].nblocks;
  161. }while(++i < nwren);
  162. return nb;
  163. }
  164. long
  165. wrensuper(Device dev)
  166. {
  167. USED(dev);
  168. return 1;
  169. }
  170. long
  171. wrenroot(Device dev)
  172. {
  173. USED(dev);
  174. return 2;
  175. }
  176. int
  177. wrenread(Device dev, long addr, void *b)
  178. {
  179. Wren *w;
  180. int fd, i;
  181. w = wren(dev);
  182. for(i=0; i<nwren; i++){
  183. if(addr < w->nblocks)
  184. break;
  185. addr -= w->nblocks;
  186. ++w;
  187. }
  188. if(i > 0)
  189. addr++;
  190. fd = w->fd;
  191. qlock(w);
  192. i = seek(fd, (vlong)addr*RBUFSIZE, 0) == -1 || read(fd, b, RBUFSIZE) != RBUFSIZE;
  193. qunlock(w);
  194. return i;
  195. }
  196. int
  197. wrenwrite(Device dev, long addr, void *b)
  198. {
  199. Wren *w;
  200. int fd, i;
  201. w = wren(dev);
  202. for(i=0; i<nwren; i++){
  203. if(addr < w->nblocks)
  204. break;
  205. addr -= w->nblocks;
  206. ++w;
  207. }
  208. if(i > 0)
  209. addr++;
  210. fd = w->fd;
  211. qlock(w);
  212. i = seek(fd, (vlong)addr*RBUFSIZE, 0) == -1 || write(fd, b, RBUFSIZE) != RBUFSIZE;
  213. qunlock(w);
  214. return i;
  215. }