transaction.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #include <linux/module.h>
  2. #include <linux/fs.h>
  3. #include "ctree.h"
  4. #include "disk-io.h"
  5. #include "transaction.h"
  6. static int total_trans = 0;
  7. extern struct kmem_cache *btrfs_trans_handle_cachep;
  8. extern struct kmem_cache *btrfs_transaction_cachep;
  9. #define TRANS_MAGIC 0xE1E10E
  10. static void put_transaction(struct btrfs_transaction *transaction)
  11. {
  12. WARN_ON(transaction->use_count == 0);
  13. transaction->use_count--;
  14. WARN_ON(transaction->magic != TRANS_MAGIC);
  15. if (transaction->use_count == 0) {
  16. WARN_ON(total_trans == 0);
  17. total_trans--;
  18. memset(transaction, 0, sizeof(*transaction));
  19. kmem_cache_free(btrfs_transaction_cachep, transaction);
  20. }
  21. }
  22. static int join_transaction(struct btrfs_root *root)
  23. {
  24. struct btrfs_transaction *cur_trans;
  25. cur_trans = root->fs_info->running_transaction;
  26. if (!cur_trans) {
  27. cur_trans = kmem_cache_alloc(btrfs_transaction_cachep,
  28. GFP_NOFS);
  29. total_trans++;
  30. BUG_ON(!cur_trans);
  31. root->fs_info->running_transaction = cur_trans;
  32. cur_trans->num_writers = 0;
  33. cur_trans->transid = root->root_key.offset + 1;
  34. init_waitqueue_head(&cur_trans->writer_wait);
  35. init_waitqueue_head(&cur_trans->commit_wait);
  36. cur_trans->magic = TRANS_MAGIC;
  37. cur_trans->in_commit = 0;
  38. cur_trans->use_count = 1;
  39. cur_trans->commit_done = 0;
  40. }
  41. cur_trans->num_writers++;
  42. return 0;
  43. }
  44. struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
  45. int num_blocks)
  46. {
  47. struct btrfs_trans_handle *h =
  48. kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
  49. int ret;
  50. /* FIXME, use the right root */
  51. root = root->fs_info->fs_root;
  52. mutex_lock(&root->fs_info->trans_mutex);
  53. ret = join_transaction(root);
  54. BUG_ON(ret);
  55. h->transid = root->fs_info->running_transaction->transid;
  56. h->transaction = root->fs_info->running_transaction;
  57. h->blocks_reserved = num_blocks;
  58. h->blocks_used = 0;
  59. root->fs_info->running_transaction->use_count++;
  60. mutex_unlock(&root->fs_info->trans_mutex);
  61. h->magic = h->magic2 = TRANS_MAGIC;
  62. return h;
  63. }
  64. int btrfs_end_transaction(struct btrfs_trans_handle *trans,
  65. struct btrfs_root *root)
  66. {
  67. struct btrfs_transaction *cur_trans;
  68. /* FIXME, use the right root */
  69. root = root->fs_info->fs_root;
  70. WARN_ON(trans->magic != TRANS_MAGIC);
  71. WARN_ON(trans->magic2 != TRANS_MAGIC);
  72. mutex_lock(&root->fs_info->trans_mutex);
  73. cur_trans = root->fs_info->running_transaction;
  74. WARN_ON(cur_trans->num_writers < 1);
  75. if (waitqueue_active(&cur_trans->writer_wait))
  76. wake_up(&cur_trans->writer_wait);
  77. cur_trans->num_writers--;
  78. put_transaction(cur_trans);
  79. mutex_unlock(&root->fs_info->trans_mutex);
  80. memset(trans, 0, sizeof(*trans));
  81. kmem_cache_free(btrfs_trans_handle_cachep, trans);
  82. return 0;
  83. }
  84. int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
  85. struct btrfs_root *root)
  86. {
  87. filemap_write_and_wait(root->fs_info->btree_inode->i_mapping);
  88. return 0;
  89. }
  90. int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
  91. struct btrfs_root *root)
  92. {
  93. int ret;
  94. u64 old_extent_block;
  95. struct btrfs_fs_info *fs_info = root->fs_info;
  96. struct btrfs_root *tree_root = fs_info->tree_root;
  97. struct btrfs_root *extent_root = fs_info->extent_root;
  98. struct btrfs_root *inode_root = fs_info->inode_root;
  99. btrfs_set_root_blocknr(&inode_root->root_item,
  100. inode_root->node->b_blocknr);
  101. ret = btrfs_update_root(trans, tree_root,
  102. &inode_root->root_key,
  103. &inode_root->root_item);
  104. BUG_ON(ret);
  105. while(1) {
  106. old_extent_block = btrfs_root_blocknr(&extent_root->root_item);
  107. if (old_extent_block == extent_root->node->b_blocknr)
  108. break;
  109. btrfs_set_root_blocknr(&extent_root->root_item,
  110. extent_root->node->b_blocknr);
  111. ret = btrfs_update_root(trans, tree_root,
  112. &extent_root->root_key,
  113. &extent_root->root_item);
  114. BUG_ON(ret);
  115. }
  116. return 0;
  117. }
  118. static int wait_for_commit(struct btrfs_root *root,
  119. struct btrfs_transaction *commit)
  120. {
  121. DEFINE_WAIT(wait);
  122. while(!commit->commit_done) {
  123. prepare_to_wait(&commit->commit_wait, &wait,
  124. TASK_UNINTERRUPTIBLE);
  125. if (commit->commit_done)
  126. break;
  127. mutex_unlock(&root->fs_info->trans_mutex);
  128. schedule();
  129. mutex_lock(&root->fs_info->trans_mutex);
  130. }
  131. finish_wait(&commit->commit_wait, &wait);
  132. return 0;
  133. }
  134. int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
  135. struct btrfs_root *root)
  136. {
  137. int ret = 0;
  138. struct buffer_head *snap;
  139. struct btrfs_key snap_key;
  140. struct btrfs_transaction *cur_trans;
  141. DEFINE_WAIT(wait);
  142. /* FIXME, use the right root */
  143. root = root->fs_info->fs_root;
  144. mutex_lock(&root->fs_info->trans_mutex);
  145. if (trans->transaction->in_commit) {
  146. printk("already in commit!, waiting\n");
  147. cur_trans = trans->transaction;
  148. trans->transaction->use_count++;
  149. btrfs_end_transaction(trans, root);
  150. ret = wait_for_commit(root, cur_trans);
  151. BUG_ON(ret);
  152. put_transaction(cur_trans);
  153. mutex_unlock(&root->fs_info->trans_mutex);
  154. return 0;
  155. }
  156. cur_trans = trans->transaction;
  157. trans->transaction->in_commit = 1;
  158. while (trans->transaction->num_writers > 1) {
  159. WARN_ON(cur_trans != trans->transaction);
  160. prepare_to_wait(&trans->transaction->writer_wait, &wait,
  161. TASK_UNINTERRUPTIBLE);
  162. if (trans->transaction->num_writers <= 1)
  163. break;
  164. mutex_unlock(&root->fs_info->trans_mutex);
  165. schedule();
  166. mutex_lock(&root->fs_info->trans_mutex);
  167. finish_wait(&trans->transaction->writer_wait, &wait);
  168. }
  169. finish_wait(&trans->transaction->writer_wait, &wait);
  170. WARN_ON(cur_trans != trans->transaction);
  171. if (root->node != root->commit_root) {
  172. memcpy(&snap_key, &root->root_key, sizeof(snap_key));
  173. root->root_key.offset++;
  174. }
  175. if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) {
  176. btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr);
  177. ret = btrfs_insert_root(trans, root->fs_info->tree_root,
  178. &root->root_key, &root->root_item);
  179. BUG_ON(ret);
  180. }
  181. ret = btrfs_commit_tree_roots(trans, root);
  182. BUG_ON(ret);
  183. cur_trans = root->fs_info->running_transaction;
  184. root->fs_info->running_transaction = NULL;
  185. mutex_unlock(&root->fs_info->trans_mutex);
  186. ret = btrfs_write_and_wait_transaction(trans, root);
  187. BUG_ON(ret);
  188. write_ctree_super(trans, root);
  189. btrfs_finish_extent_commit(trans, root);
  190. mutex_lock(&root->fs_info->trans_mutex);
  191. cur_trans->commit_done = 1;
  192. wake_up(&cur_trans->commit_wait);
  193. put_transaction(cur_trans);
  194. put_transaction(cur_trans);
  195. mutex_unlock(&root->fs_info->trans_mutex);
  196. kmem_cache_free(btrfs_trans_handle_cachep, trans);
  197. if (root->node != root->commit_root) {
  198. trans = btrfs_start_transaction(root, 1);
  199. snap = root->commit_root;
  200. root->commit_root = root->node;
  201. get_bh(root->node);
  202. ret = btrfs_drop_snapshot(trans, root, snap);
  203. BUG_ON(ret);
  204. ret = btrfs_del_root(trans, root->fs_info->tree_root,
  205. &snap_key);
  206. BUG_ON(ret);
  207. root->fs_info->generation = root->root_key.offset + 1;
  208. ret = btrfs_end_transaction(trans, root);
  209. BUG_ON(ret);
  210. }
  211. return ret;
  212. }