kfsboot.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #include "u.h"
  2. #include "lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "fs.h"
  7. typedef struct Tag Tag;
  8. /*
  9. * tags on block
  10. */
  11. enum
  12. {
  13. Tnone = 0,
  14. Tsuper, /* the super block */
  15. Tdir, /* directory contents */
  16. Tind1, /* points to blocks */
  17. Tind2, /* points to Tind1 */
  18. Tfile, /* file contents */
  19. Tfree, /* in free list */
  20. Tbuck, /* cache fs bucket */
  21. Tvirgo, /* fake worm virgin bits */
  22. Tcache, /* cw cache things */
  23. MAXTAG
  24. };
  25. #define QPDIR 0x80000000L
  26. #define QPNONE 0
  27. #define QPROOT 1
  28. #define QPSUPER 2
  29. /* DONT TOUCH, this is the disk structure */
  30. struct Tag
  31. {
  32. short pad;
  33. short tag;
  34. long path;
  35. };
  36. static int thisblock = -1;
  37. static Fs *thisfs;
  38. static uchar *block;
  39. /*
  40. * we end up reading 2x or 3x the number of blocks we need to read.
  41. * this is okay because we need to read so few. if it wasn't okay, we could
  42. * have getblock return a pointer to a block, and keep a cache of the last
  43. * three read blocks. that would get us down to the minimum.
  44. * but this is fine.
  45. */
  46. static int
  47. getblock(Fs *fs, ulong n)
  48. {
  49. if(!block)
  50. block = malloc(16384);
  51. if(thisblock == n && thisfs == fs)
  52. return 0;
  53. thisblock = -1;
  54. if(fs->diskseek(fs, (vlong)n*fs->kfs.RBUFSIZE) < 0)
  55. return -1;
  56. if(fs->diskread(fs, block, fs->kfs.RBUFSIZE) != fs->kfs.RBUFSIZE)
  57. return -1;
  58. thisblock = n;
  59. thisfs = fs;
  60. return 1;
  61. }
  62. static int
  63. checktag(Fs *fs, uchar *block, int tag, long qpath)
  64. {
  65. Tag *t;
  66. t = (Tag*)(block+fs->kfs.BUFSIZE);
  67. if(t->tag != tag)
  68. return -1;
  69. if(qpath != QPNONE && (qpath&~QPDIR) != t->path)
  70. return -1;
  71. return 1;
  72. }
  73. static int
  74. getblocktag(Fs *fs, ulong n, int tag, long qpath)
  75. {
  76. if(getblock(fs, n) < 0 || checktag(fs, block, tag, qpath) < 0)
  77. return -1;
  78. return 1;
  79. }
  80. static int
  81. readinfo(Fs *fs)
  82. {
  83. fs->kfs.RBUFSIZE = 512;
  84. if(getblock(fs, 0) < 0)
  85. return -1;
  86. if(memcmp(block+256, "kfs wren device\n", 16) != 0)
  87. return -1;
  88. fs->kfs.RBUFSIZE = atoi((char*)block+256+16);
  89. if(!fs->kfs.RBUFSIZE || (fs->kfs.RBUFSIZE&(fs->kfs.RBUFSIZE-1)))
  90. return -1;
  91. fs->kfs.BUFSIZE = fs->kfs.RBUFSIZE - sizeof(Tag);
  92. fs->kfs.DIRPERBUF = fs->kfs.BUFSIZE / sizeof(Dentry);
  93. fs->kfs.INDPERBUF = fs->kfs.BUFSIZE / sizeof(long);
  94. fs->kfs.INDPERBUF2 = fs->kfs.INDPERBUF * fs->kfs.INDPERBUF;
  95. return 1;
  96. }
  97. static int
  98. readroot(Fs *fs, Dentry *d)
  99. {
  100. Dentry *d2;
  101. if(getblocktag(fs, 2, Tdir, QPROOT) < 0)
  102. return -1;
  103. d2 = (Dentry*)block;
  104. if(strcmp(d2->name, "/") != 0)
  105. return -1;
  106. *d = *(Dentry*)block;
  107. return 1;
  108. }
  109. static long
  110. indfetch(Fs *fs, long addr, long off, int tag, long path)
  111. {
  112. if(getblocktag(fs, addr, tag, path) < 0)
  113. return -1;
  114. return ((long*)block)[off];
  115. }
  116. static long
  117. rel2abs(Fs *fs, Dentry *d, long a)
  118. {
  119. long addr;
  120. if(a < NDBLOCK)
  121. return d->dblock[a];
  122. a -= NDBLOCK;
  123. if(a < fs->kfs.INDPERBUF){
  124. if(d->iblock == 0)
  125. return 0;
  126. addr = indfetch(fs, d->iblock, a, Tind1, d->qid.path);
  127. if(addr == 0)
  128. print("rel2abs indfetch 0 %s %ld\n", d->name, a);
  129. return addr;
  130. }
  131. a -= fs->kfs.INDPERBUF;
  132. if(a < fs->kfs.INDPERBUF2){
  133. if(d->diblock == 0)
  134. return 0;
  135. addr = indfetch(fs, d->diblock, a/fs->kfs.INDPERBUF, Tind2, d->qid.path);
  136. if(addr == 0){
  137. print("rel2abs indfetch 0 %s %ld\n", d->name, a/fs->kfs.INDPERBUF);
  138. return 0;
  139. }
  140. addr = indfetch(fs, addr, a%fs->kfs.INDPERBUF, Tind1, d->qid.path);
  141. return addr;
  142. }
  143. print("rel2abs trip ind %s %ld\n", d->name, a);
  144. return -1;
  145. }
  146. static int
  147. readdentry(Fs *fs, Dentry *d, int n, Dentry *e)
  148. {
  149. long addr, m;
  150. m = n/fs->kfs.DIRPERBUF;
  151. if((addr = rel2abs(fs, d, m)) <= 0)
  152. return addr;
  153. if(getblocktag(fs, addr, Tdir, d->qid.path) < 0)
  154. return -1;
  155. *e = *(Dentry*)(block+(n%fs->kfs.DIRPERBUF)*sizeof(Dentry));
  156. return 1;
  157. }
  158. static int
  159. getdatablock(Fs *fs, Dentry *d, long a)
  160. {
  161. long addr;
  162. if((addr = rel2abs(fs, d, a)) == 0)
  163. return -1;
  164. return getblocktag(fs, addr, Tfile, QPNONE);
  165. }
  166. static int
  167. walk(Fs *fs, Dentry *d, char *name, Dentry *e)
  168. {
  169. int i, n;
  170. Dentry x;
  171. for(i=0;; i++){
  172. if((n=readdentry(fs, d, i, &x)) <= 0)
  173. return n;
  174. if(strcmp(x.name, name) == 0){
  175. *e = x;
  176. return 1;
  177. }
  178. }
  179. }
  180. static long
  181. kfsread(File *f, void *va, long len)
  182. {
  183. uchar *a;
  184. long tot, off, o, n;
  185. Fs *fs;
  186. a = va;
  187. fs = f->fs;
  188. off = f->kfs.off;
  189. tot = 0;
  190. while(tot < len){
  191. if(getdatablock(fs, &f->kfs, off/fs->kfs.BUFSIZE) < 0)
  192. return -1;
  193. o = off%fs->kfs.BUFSIZE;
  194. n = fs->kfs.BUFSIZE - o;
  195. if(n > len-tot)
  196. n = len-tot;
  197. memmove(a+tot, block+o, n);
  198. off += n;
  199. tot += n;
  200. }
  201. f->kfs.off = off;
  202. return tot;
  203. }
  204. static int
  205. kfswalk(File *f, char *name)
  206. {
  207. int n;
  208. n = walk(f->fs, &f->kfs, name, &f->kfs);
  209. if(n < 0)
  210. return -1;
  211. f->kfs.off = 0;
  212. return 1;
  213. }
  214. int
  215. kfsinit(Fs *fs)
  216. {
  217. if(readinfo(fs) < 0 || readroot(fs, &fs->root.kfs) < 0)
  218. return -1;
  219. fs->root.fs = fs;
  220. fs->read = kfsread;
  221. fs->walk = kfswalk;
  222. return 0;
  223. }