Btrfs: still corruption hunting

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 84c4e27..72b52e1 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -5,13 +5,20 @@
 #include "transaction.h"
 
 static int total_trans = 0;
+extern struct kmem_cache *btrfs_trans_handle_cachep;
+extern struct kmem_cache *btrfs_transaction_cachep;
+
+#define TRANS_MAGIC 0xE1E10E
 static void put_transaction(struct btrfs_transaction *transaction)
 {
+	WARN_ON(transaction->use_count == 0);
 	transaction->use_count--;
+	WARN_ON(transaction->magic != TRANS_MAGIC);
 	if (transaction->use_count == 0) {
 		WARN_ON(total_trans == 0);
 		total_trans--;
-		kfree(transaction);
+		memset(transaction, 0, sizeof(*transaction));
+		kmem_cache_free(btrfs_transaction_cachep, transaction);
 	}
 }
 
@@ -20,7 +27,8 @@
 	struct btrfs_transaction *cur_trans;
 	cur_trans = root->fs_info->running_transaction;
 	if (!cur_trans) {
-		cur_trans = kmalloc(sizeof(*cur_trans), GFP_NOFS);
+		cur_trans = kmem_cache_alloc(btrfs_transaction_cachep,
+					     GFP_NOFS);
 		total_trans++;
 		BUG_ON(!cur_trans);
 		root->fs_info->running_transaction = cur_trans;
@@ -28,6 +36,7 @@
 		cur_trans->transid = root->root_key.offset + 1;
 		init_waitqueue_head(&cur_trans->writer_wait);
 		init_waitqueue_head(&cur_trans->commit_wait);
+		cur_trans->magic = TRANS_MAGIC;
 		cur_trans->in_commit = 0;
 		cur_trans->use_count = 1;
 		cur_trans->commit_done = 0;
@@ -39,7 +48,8 @@
 struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
 						   int num_blocks)
 {
-	struct btrfs_trans_handle *h = kmalloc(sizeof(*h), GFP_NOFS);
+	struct btrfs_trans_handle *h =
+		kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
 	int ret;
 
 	mutex_lock(&root->fs_info->trans_mutex);
@@ -51,6 +61,7 @@
 	h->blocks_used = 0;
 	root->fs_info->running_transaction->use_count++;
 	mutex_unlock(&root->fs_info->trans_mutex);
+	h->magic = h->magic2 = TRANS_MAGIC;
 	return h;
 }
 
@@ -58,6 +69,8 @@
 			  struct btrfs_root *root)
 {
 	struct btrfs_transaction *cur_trans;
+	WARN_ON(trans->magic != TRANS_MAGIC);
+	WARN_ON(trans->magic2 != TRANS_MAGIC);
 	mutex_lock(&root->fs_info->trans_mutex);
 	cur_trans = root->fs_info->running_transaction;
 	WARN_ON(cur_trans->num_writers < 1);
@@ -67,7 +80,7 @@
 	put_transaction(cur_trans);
 	mutex_unlock(&root->fs_info->trans_mutex);
 	memset(trans, 0, sizeof(*trans));
-	kfree(trans);
+	kmem_cache_free(btrfs_trans_handle_cachep, trans);
 	return 0;
 }
 
@@ -75,7 +88,7 @@
 int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
 				     struct btrfs_root *root)
 {
-	filemap_write_and_wait(root->fs_info->btree_inode->i_mapping);
+	filemap_write_and_wait(root->fs_info->sb->s_bdev->bd_inode->i_mapping);
 	return 0;
 }
 
@@ -137,6 +150,7 @@
 
 	mutex_lock(&root->fs_info->trans_mutex);
 	if (trans->transaction->in_commit) {
+printk("already in commit!, waiting\n");
 		cur_trans = trans->transaction;
 		trans->transaction->use_count++;
 		btrfs_end_transaction(trans, root);
@@ -146,7 +160,10 @@
 		mutex_unlock(&root->fs_info->trans_mutex);
 		return 0;
 	}
+	cur_trans = trans->transaction;
+	trans->transaction->in_commit = 1;
 	while (trans->transaction->num_writers > 1) {
+		WARN_ON(cur_trans != trans->transaction);
 		prepare_to_wait(&trans->transaction->writer_wait, &wait,
 				TASK_UNINTERRUPTIBLE);
 		if (trans->transaction->num_writers <= 1)
@@ -154,15 +171,15 @@
 		mutex_unlock(&root->fs_info->trans_mutex);
 		schedule();
 		mutex_lock(&root->fs_info->trans_mutex);
+		finish_wait(&trans->transaction->writer_wait, &wait);
 	}
 	finish_wait(&trans->transaction->writer_wait, &wait);
-
+	WARN_ON(cur_trans != trans->transaction);
 	if (root->node != root->commit_root) {
 		memcpy(&snap_key, &root->root_key, sizeof(snap_key));
 		root->root_key.offset++;
 	}
 
-
 	if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) {
 		btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr);
 		ret = btrfs_insert_root(trans, root->fs_info->tree_root,
@@ -172,22 +189,21 @@
 
 	ret = btrfs_commit_tree_roots(trans, root);
 	BUG_ON(ret);
-
 	cur_trans = root->fs_info->running_transaction;
 	root->fs_info->running_transaction = NULL;
 	mutex_unlock(&root->fs_info->trans_mutex);
-
 	ret = btrfs_write_and_wait_transaction(trans, root);
 	BUG_ON(ret);
 
 	write_ctree_super(trans, root);
 	btrfs_finish_extent_commit(trans, root);
 	mutex_lock(&root->fs_info->trans_mutex);
+	cur_trans->commit_done = 1;
+	wake_up(&cur_trans->commit_wait);
 	put_transaction(cur_trans);
 	put_transaction(cur_trans);
 	mutex_unlock(&root->fs_info->trans_mutex);
-	kfree(trans);
-
+	kmem_cache_free(btrfs_trans_handle_cachep, trans);
 	if (root->node != root->commit_root) {
 		trans = btrfs_start_transaction(root, 1);
 		snap = root->commit_root;
@@ -203,7 +219,6 @@
 		ret = btrfs_end_transaction(trans, root);
 		BUG_ON(ret);
 	}
-
 	return ret;
 }