disk-io.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #define _XOPEN_SOURCE 500
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7. #include <unistd.h>
  8. #include "kerncompat.h"
  9. #include "radix-tree.h"
  10. #include "ctree.h"
  11. #include "disk-io.h"
  12. static int allocated_blocks = 0;
  13. static int check_tree_block(struct ctree_root *root, struct tree_buffer *buf)
  14. {
  15. if (buf->blocknr != buf->node.header.blocknr)
  16. BUG();
  17. if (root->node && buf->node.header.parentid != root->node->node.header.parentid)
  18. BUG();
  19. return 0;
  20. }
  21. struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr)
  22. {
  23. struct tree_buffer *buf;
  24. int ret;
  25. buf = malloc(sizeof(struct tree_buffer));
  26. if (!buf)
  27. return buf;
  28. allocated_blocks++;
  29. buf->blocknr = blocknr;
  30. buf->count = 1;
  31. radix_tree_preload(GFP_KERNEL);
  32. ret = radix_tree_insert(&root->cache_radix, blocknr, buf);
  33. radix_tree_preload_end();
  34. if (ret) {
  35. free(buf);
  36. return NULL;
  37. }
  38. return buf;
  39. }
  40. struct tree_buffer *find_tree_block(struct ctree_root *root, u64 blocknr)
  41. {
  42. struct tree_buffer *buf;
  43. buf = radix_tree_lookup(&root->cache_radix, blocknr);
  44. if (buf) {
  45. buf->count++;
  46. } else {
  47. buf = alloc_tree_block(root, blocknr);
  48. if (!buf) {
  49. BUG();
  50. return NULL;
  51. }
  52. }
  53. return buf;
  54. }
  55. struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr)
  56. {
  57. loff_t offset = blocknr * CTREE_BLOCKSIZE;
  58. struct tree_buffer *buf;
  59. int ret;
  60. buf = radix_tree_lookup(&root->cache_radix, blocknr);
  61. if (buf) {
  62. buf->count++;
  63. } else {
  64. buf = alloc_tree_block(root, blocknr);
  65. if (!buf)
  66. return NULL;
  67. ret = pread(root->fp, &buf->node, CTREE_BLOCKSIZE, offset);
  68. if (ret != CTREE_BLOCKSIZE) {
  69. free(buf);
  70. return NULL;
  71. }
  72. }
  73. if (check_tree_block(root, buf))
  74. BUG();
  75. return buf;
  76. }
  77. int write_tree_block(struct ctree_root *root, struct tree_buffer *buf)
  78. {
  79. u64 blocknr = buf->blocknr;
  80. loff_t offset = blocknr * CTREE_BLOCKSIZE;
  81. int ret;
  82. if (buf->blocknr != buf->node.header.blocknr)
  83. BUG();
  84. ret = pwrite(root->fp, &buf->node, CTREE_BLOCKSIZE, offset);
  85. if (ret != CTREE_BLOCKSIZE)
  86. return ret;
  87. return 0;
  88. }
  89. static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root,
  90. struct ctree_root_info *info, int fp)
  91. {
  92. root->fp = fp;
  93. root->node = NULL;
  94. root->node = read_tree_block(root, info->tree_root);
  95. root->extent_root = extent_root;
  96. return 0;
  97. }
  98. struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super)
  99. {
  100. struct ctree_root *root = malloc(sizeof(struct ctree_root));
  101. struct ctree_root *extent_root = malloc(sizeof(struct ctree_root));
  102. int fp;
  103. int ret;
  104. fp = open(filename, O_CREAT | O_RDWR, 0600);
  105. if (fp < 0) {
  106. free(root);
  107. return NULL;
  108. }
  109. INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL);
  110. INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL);
  111. ret = pread(fp, super, sizeof(struct ctree_super_block),
  112. CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
  113. if (ret == 0 || super->root_info.tree_root == 0) {
  114. printf("making new FS!\n");
  115. ret = mkfs(fp);
  116. if (ret)
  117. return NULL;
  118. ret = pread(fp, super, sizeof(struct ctree_super_block),
  119. CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
  120. if (ret != sizeof(struct ctree_super_block))
  121. return NULL;
  122. }
  123. BUG_ON(ret < 0);
  124. __setup_root(root, extent_root, &super->root_info, fp);
  125. __setup_root(extent_root, extent_root, &super->extent_info, fp);
  126. return root;
  127. }
  128. static int __update_root(struct ctree_root *root, struct ctree_root_info *info)
  129. {
  130. info->tree_root = root->node->blocknr;
  131. return 0;
  132. }
  133. int write_ctree_super(struct ctree_root *root, struct ctree_super_block *s)
  134. {
  135. int ret;
  136. __update_root(root, &s->root_info);
  137. __update_root(root->extent_root, &s->extent_info);
  138. ret = pwrite(root->fp, s, sizeof(*s), CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
  139. if (ret != sizeof(*s)) {
  140. fprintf(stderr, "failed to write new super block err %d\n", ret);
  141. return ret;
  142. }
  143. return 0;
  144. }
  145. int close_ctree(struct ctree_root *root)
  146. {
  147. close(root->fp);
  148. if (root->node)
  149. tree_block_release(root, root->node);
  150. if (root->extent_root->node)
  151. tree_block_release(root->extent_root, root->extent_root->node);
  152. free(root);
  153. printf("on close %d blocks are allocated\n", allocated_blocks);
  154. return 0;
  155. }
  156. void tree_block_release(struct ctree_root *root, struct tree_buffer *buf)
  157. {
  158. buf->count--;
  159. if (buf->count < 0)
  160. BUG();
  161. if (buf->count == 0) {
  162. if (!radix_tree_lookup(&root->cache_radix, buf->blocknr))
  163. BUG();
  164. radix_tree_delete(&root->cache_radix, buf->blocknr);
  165. memset(buf, 0, sizeof(*buf));
  166. free(buf);
  167. BUG_ON(allocated_blocks == 0);
  168. allocated_blocks--;
  169. }
  170. }