transaction.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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. static void put_transaction(struct btrfs_transaction *transaction)
  8. {
  9. transaction->use_count--;
  10. if (transaction->use_count == 0) {
  11. WARN_ON(total_trans == 0);
  12. total_trans--;
  13. kfree(transaction);
  14. }
  15. }
  16. static int join_transaction(struct btrfs_root *root)
  17. {
  18. struct btrfs_transaction *cur_trans;
  19. cur_trans = root->fs_info->running_transaction;
  20. if (!cur_trans) {
  21. cur_trans = kmalloc(sizeof(*cur_trans), GFP_NOFS);
  22. total_trans++;
  23. BUG_ON(!cur_trans);
  24. root->fs_info->running_transaction = cur_trans;
  25. cur_trans->num_writers = 0;
  26. cur_trans->transid = root->root_key.offset + 1;
  27. init_waitqueue_head(&cur_trans->writer_wait);
  28. init_waitqueue_head(&cur_trans->commit_wait);
  29. cur_trans->in_commit = 0;
  30. cur_trans->use_count = 1;
  31. cur_trans->commit_done = 0;
  32. }
  33. cur_trans->num_writers++;
  34. return 0;
  35. }
  36. struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
  37. int num_blocks)
  38. {
  39. struct btrfs_trans_handle *h = kmalloc(sizeof(*h), GFP_NOFS);
  40. int ret;
  41. mutex_lock(&root->fs_info->trans_mutex);
  42. ret = join_transaction(root);
  43. BUG_ON(ret);
  44. h->transid = root->fs_info->running_transaction->transid;
  45. h->transaction = root->fs_info->running_transaction;
  46. h->blocks_reserved = num_blocks;
  47. h->blocks_used = 0;
  48. root->fs_info->running_transaction->use_count++;
  49. mutex_unlock(&root->fs_info->trans_mutex);
  50. return h;
  51. }
  52. int btrfs_end_transaction(struct btrfs_trans_handle *trans,
  53. struct btrfs_root *root)
  54. {
  55. struct btrfs_transaction *cur_trans;
  56. mutex_lock(&root->fs_info->trans_mutex);
  57. cur_trans = root->fs_info->running_transaction;
  58. WARN_ON(cur_trans->num_writers < 1);
  59. if (waitqueue_active(&cur_trans->writer_wait))
  60. wake_up(&cur_trans->writer_wait);
  61. cur_trans->num_writers--;
  62. put_transaction(cur_trans);
  63. mutex_unlock(&root->fs_info->trans_mutex);
  64. kfree(trans);
  65. return 0;
  66. }
  67. int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
  68. struct btrfs_root *root)
  69. {
  70. filemap_write_and_wait(root->fs_info->sb->s_bdev->bd_inode->i_mapping);
  71. return 0;
  72. }
  73. int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
  74. struct btrfs_root *root)
  75. {
  76. int ret;
  77. u64 old_extent_block;
  78. struct btrfs_fs_info *fs_info = root->fs_info;
  79. struct btrfs_root *tree_root = fs_info->tree_root;
  80. struct btrfs_root *extent_root = fs_info->extent_root;
  81. struct btrfs_root *inode_root = fs_info->inode_root;
  82. btrfs_set_root_blocknr(&inode_root->root_item,
  83. inode_root->node->b_blocknr);
  84. ret = btrfs_update_root(trans, tree_root,
  85. &inode_root->root_key,
  86. &inode_root->root_item);
  87. BUG_ON(ret);
  88. while(1) {
  89. old_extent_block = btrfs_root_blocknr(&extent_root->root_item);
  90. if (old_extent_block == extent_root->node->b_blocknr)
  91. break;
  92. btrfs_set_root_blocknr(&extent_root->root_item,
  93. extent_root->node->b_blocknr);
  94. ret = btrfs_update_root(trans, tree_root,
  95. &extent_root->root_key,
  96. &extent_root->root_item);
  97. BUG_ON(ret);
  98. }
  99. return 0;
  100. }
  101. static int wait_for_commit(struct btrfs_root *root,
  102. struct btrfs_transaction *commit)
  103. {
  104. DEFINE_WAIT(wait);
  105. while(!commit->commit_done) {
  106. prepare_to_wait(&commit->commit_wait, &wait,
  107. TASK_UNINTERRUPTIBLE);
  108. if (commit->commit_done)
  109. break;
  110. mutex_unlock(&root->fs_info->trans_mutex);
  111. schedule();
  112. mutex_lock(&root->fs_info->trans_mutex);
  113. }
  114. finish_wait(&commit->commit_wait, &wait);
  115. return 0;
  116. }
  117. int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
  118. struct btrfs_root *root)
  119. {
  120. int ret = 0;
  121. struct buffer_head *snap;
  122. struct btrfs_key snap_key;
  123. struct btrfs_transaction *cur_trans;
  124. DEFINE_WAIT(wait);
  125. mutex_lock(&root->fs_info->trans_mutex);
  126. if (trans->transaction->in_commit) {
  127. cur_trans = trans->transaction;
  128. trans->transaction->use_count++;
  129. btrfs_end_transaction(trans, root);
  130. ret = wait_for_commit(root, cur_trans);
  131. BUG_ON(ret);
  132. put_transaction(cur_trans);
  133. mutex_unlock(&root->fs_info->trans_mutex);
  134. return 0;
  135. }
  136. while (trans->transaction->num_writers > 1) {
  137. prepare_to_wait(&trans->transaction->writer_wait, &wait,
  138. TASK_UNINTERRUPTIBLE);
  139. if (trans->transaction->num_writers <= 1)
  140. break;
  141. mutex_unlock(&root->fs_info->trans_mutex);
  142. schedule();
  143. mutex_lock(&root->fs_info->trans_mutex);
  144. }
  145. finish_wait(&trans->transaction->writer_wait, &wait);
  146. if (root->node != root->commit_root) {
  147. memcpy(&snap_key, &root->root_key, sizeof(snap_key));
  148. root->root_key.offset++;
  149. }
  150. if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) {
  151. btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr);
  152. ret = btrfs_insert_root(trans, root->fs_info->tree_root,
  153. &root->root_key, &root->root_item);
  154. BUG_ON(ret);
  155. }
  156. ret = btrfs_commit_tree_roots(trans, root);
  157. BUG_ON(ret);
  158. cur_trans = root->fs_info->running_transaction;
  159. root->fs_info->running_transaction = NULL;
  160. mutex_unlock(&root->fs_info->trans_mutex);
  161. ret = btrfs_write_and_wait_transaction(trans, root);
  162. BUG_ON(ret);
  163. write_ctree_super(trans, root);
  164. btrfs_finish_extent_commit(trans, root);
  165. mutex_lock(&root->fs_info->trans_mutex);
  166. put_transaction(cur_trans);
  167. put_transaction(cur_trans);
  168. mutex_unlock(&root->fs_info->trans_mutex);
  169. kfree(trans);
  170. if (root->node != root->commit_root) {
  171. trans = btrfs_start_transaction(root, 1);
  172. snap = root->commit_root;
  173. root->commit_root = root->node;
  174. get_bh(root->node);
  175. ret = btrfs_drop_snapshot(trans, root, snap);
  176. BUG_ON(ret);
  177. ret = btrfs_del_root(trans, root->fs_info->tree_root,
  178. &snap_key);
  179. BUG_ON(ret); root->fs_info->generation = root->root_key.offset + 1; ret = btrfs_end_transaction(trans, root); BUG_ON(ret);
  180. printk("at free, total trans %d\n", total_trans);
  181. }
  182. return ret;
  183. }