kfsboot.c 5.1 KB

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