aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/disk-io.c4
-rw-r--r--fs/btrfs/transaction.c30
-rw-r--r--fs/btrfs/transaction.h3
4 files changed, 27 insertions, 14 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 74e6aadf6bb7..e93ba1a5c812 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -283,6 +283,7 @@ struct btrfs_block_group_cache {
283struct crypto_hash; 283struct crypto_hash;
284 284
285struct btrfs_fs_info { 285struct btrfs_fs_info {
286 spinlock_t hash_lock;
286 struct btrfs_root *extent_root; 287 struct btrfs_root *extent_root;
287 struct btrfs_root *tree_root; 288 struct btrfs_root *tree_root;
288 struct btrfs_root *dev_root; 289 struct btrfs_root *dev_root;
@@ -308,10 +309,11 @@ struct btrfs_fs_info {
308 struct mutex trans_mutex; 309 struct mutex trans_mutex;
309 struct mutex fs_mutex; 310 struct mutex fs_mutex;
310 struct list_head trans_list; 311 struct list_head trans_list;
312 struct list_head dead_roots;
311 struct crypto_hash *hash_tfm; 313 struct crypto_hash *hash_tfm;
312 struct delayed_work trans_work; 314 struct delayed_work trans_work;
313 spinlock_t hash_lock;
314 int do_barriers; 315 int do_barriers;
316 int closing;
315}; 317};
316 318
317/* 319/*
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 048282f06afb..751069c0e9f5 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -563,6 +563,7 @@ struct btrfs_root *open_ctree(struct super_block *sb)
563 INIT_RADIX_TREE(&fs_info->block_group_radix, GFP_KERNEL); 563 INIT_RADIX_TREE(&fs_info->block_group_radix, GFP_KERNEL);
564 INIT_RADIX_TREE(&fs_info->block_group_data_radix, GFP_KERNEL); 564 INIT_RADIX_TREE(&fs_info->block_group_data_radix, GFP_KERNEL);
565 INIT_LIST_HEAD(&fs_info->trans_list); 565 INIT_LIST_HEAD(&fs_info->trans_list);
566 INIT_LIST_HEAD(&fs_info->dead_roots);
566 sb_set_blocksize(sb, 4096); 567 sb_set_blocksize(sb, 4096);
567 fs_info->running_transaction = NULL; 568 fs_info->running_transaction = NULL;
568 fs_info->tree_root = tree_root; 569 fs_info->tree_root = tree_root;
@@ -577,6 +578,8 @@ struct btrfs_root *open_ctree(struct super_block *sb)
577 fs_info->do_barriers = 1; 578 fs_info->do_barriers = 1;
578 fs_info->extent_tree_insert_nr = 0; 579 fs_info->extent_tree_insert_nr = 0;
579 fs_info->extent_tree_prealloc_nr = 0; 580 fs_info->extent_tree_prealloc_nr = 0;
581 fs_info->closing = 0;
582
580 INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner); 583 INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner);
581 BTRFS_I(fs_info->btree_inode)->root = tree_root; 584 BTRFS_I(fs_info->btree_inode)->root = tree_root;
582 memset(&BTRFS_I(fs_info->btree_inode)->location, 0, 585 memset(&BTRFS_I(fs_info->btree_inode)->location, 0,
@@ -746,6 +749,7 @@ int close_ctree(struct btrfs_root *root)
746 struct btrfs_trans_handle *trans; 749 struct btrfs_trans_handle *trans;
747 struct btrfs_fs_info *fs_info = root->fs_info; 750 struct btrfs_fs_info *fs_info = root->fs_info;
748 751
752 fs_info->closing = 1;
749 btrfs_transaction_flush_work(root); 753 btrfs_transaction_flush_work(root);
750 mutex_lock(&fs_info->fs_mutex); 754 mutex_lock(&fs_info->fs_mutex);
751 trans = btrfs_start_transaction(root, 1); 755 trans = btrfs_start_transaction(root, 1);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index bf7eef67ba0b..b859db395fd5 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -12,12 +12,10 @@ static struct workqueue_struct *trans_wq;
12 12
13#define BTRFS_ROOT_TRANS_TAG 0 13#define BTRFS_ROOT_TRANS_TAG 0
14 14
15#define TRANS_MAGIC 0xE1E10E
16static void put_transaction(struct btrfs_transaction *transaction) 15static void put_transaction(struct btrfs_transaction *transaction)
17{ 16{
18 WARN_ON(transaction->use_count == 0); 17 WARN_ON(transaction->use_count == 0);
19 transaction->use_count--; 18 transaction->use_count--;
20 WARN_ON(transaction->magic != TRANS_MAGIC);
21 if (transaction->use_count == 0) { 19 if (transaction->use_count == 0) {
22 WARN_ON(total_trans == 0); 20 WARN_ON(total_trans == 0);
23 total_trans--; 21 total_trans--;
@@ -42,7 +40,6 @@ static int join_transaction(struct btrfs_root *root)
42 cur_trans->transid = root->fs_info->generation; 40 cur_trans->transid = root->fs_info->generation;
43 init_waitqueue_head(&cur_trans->writer_wait); 41 init_waitqueue_head(&cur_trans->writer_wait);
44 init_waitqueue_head(&cur_trans->commit_wait); 42 init_waitqueue_head(&cur_trans->commit_wait);
45 cur_trans->magic = TRANS_MAGIC;
46 cur_trans->in_commit = 0; 43 cur_trans->in_commit = 0;
47 cur_trans->use_count = 1; 44 cur_trans->use_count = 1;
48 cur_trans->commit_done = 0; 45 cur_trans->commit_done = 0;
@@ -83,7 +80,6 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
83 h->block_group = NULL; 80 h->block_group = NULL;
84 root->fs_info->running_transaction->use_count++; 81 root->fs_info->running_transaction->use_count++;
85 mutex_unlock(&root->fs_info->trans_mutex); 82 mutex_unlock(&root->fs_info->trans_mutex);
86 h->magic = h->magic2 = TRANS_MAGIC;
87 return h; 83 return h;
88} 84}
89 85
@@ -92,8 +88,6 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans,
92{ 88{
93 struct btrfs_transaction *cur_trans; 89 struct btrfs_transaction *cur_trans;
94 90
95 WARN_ON(trans->magic != TRANS_MAGIC);
96 WARN_ON(trans->magic2 != TRANS_MAGIC);
97 mutex_lock(&root->fs_info->trans_mutex); 91 mutex_lock(&root->fs_info->trans_mutex);
98 cur_trans = root->fs_info->running_transaction; 92 cur_trans = root->fs_info->running_transaction;
99 WARN_ON(cur_trans->num_writers < 1); 93 WARN_ON(cur_trans->num_writers < 1);
@@ -257,8 +251,8 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
257 struct dirty_root *dirty; 251 struct dirty_root *dirty;
258 struct btrfs_trans_handle *trans; 252 struct btrfs_trans_handle *trans;
259 int ret; 253 int ret;
260
261 while(!list_empty(list)) { 254 while(!list_empty(list)) {
255 mutex_lock(&tree_root->fs_info->fs_mutex);
262 dirty = list_entry(list->next, struct dirty_root, list); 256 dirty = list_entry(list->next, struct dirty_root, list);
263 list_del_init(&dirty->list); 257 list_del_init(&dirty->list);
264 trans = btrfs_start_transaction(tree_root, 1); 258 trans = btrfs_start_transaction(tree_root, 1);
@@ -271,6 +265,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
271 ret = btrfs_end_transaction(trans, tree_root); 265 ret = btrfs_end_transaction(trans, tree_root);
272 BUG_ON(ret); 266 BUG_ON(ret);
273 kfree(dirty); 267 kfree(dirty);
268 mutex_unlock(&tree_root->fs_info->fs_mutex);
274 } 269 }
275 return 0; 270 return 0;
276} 271}
@@ -346,10 +341,18 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
346 wake_up(&cur_trans->commit_wait); 341 wake_up(&cur_trans->commit_wait);
347 put_transaction(cur_trans); 342 put_transaction(cur_trans);
348 put_transaction(cur_trans); 343 put_transaction(cur_trans);
344 if (root->fs_info->closing)
345 list_splice_init(&root->fs_info->dead_roots, &dirty_fs_roots);
346 else
347 list_splice_init(&dirty_fs_roots, &root->fs_info->dead_roots);
349 mutex_unlock(&root->fs_info->trans_mutex); 348 mutex_unlock(&root->fs_info->trans_mutex);
350 kmem_cache_free(btrfs_trans_handle_cachep, trans); 349 kmem_cache_free(btrfs_trans_handle_cachep, trans);
351 350
352 drop_dirty_roots(root->fs_info->tree_root, &dirty_fs_roots); 351 if (root->fs_info->closing) {
352 mutex_unlock(&root->fs_info->fs_mutex);
353 drop_dirty_roots(root->fs_info->tree_root, &dirty_fs_roots);
354 mutex_lock(&root->fs_info->fs_mutex);
355 }
353 return ret; 356 return ret;
354} 357}
355 358
@@ -362,11 +365,19 @@ void btrfs_transaction_cleaner(struct work_struct *work)
362 struct btrfs_root *root = fs_info->tree_root; 365 struct btrfs_root *root = fs_info->tree_root;
363 struct btrfs_transaction *cur; 366 struct btrfs_transaction *cur;
364 struct btrfs_trans_handle *trans; 367 struct btrfs_trans_handle *trans;
368 struct list_head dirty_roots;
365 unsigned long now; 369 unsigned long now;
366 unsigned long delay = HZ * 30; 370 unsigned long delay = HZ * 30;
367 int ret; 371 int ret;
368 372
369printk("btrfs transaction cleaner\n"); 373 INIT_LIST_HEAD(&dirty_roots);
374 mutex_lock(&root->fs_info->trans_mutex);
375 list_splice_init(&root->fs_info->dead_roots, &dirty_roots);
376 mutex_unlock(&root->fs_info->trans_mutex);
377
378 if (!list_empty(&dirty_roots)) {
379 drop_dirty_roots(root, &dirty_roots);
380 }
370 mutex_lock(&root->fs_info->fs_mutex); 381 mutex_lock(&root->fs_info->fs_mutex);
371 mutex_lock(&root->fs_info->trans_mutex); 382 mutex_lock(&root->fs_info->trans_mutex);
372 cur = root->fs_info->running_transaction; 383 cur = root->fs_info->running_transaction;
@@ -381,7 +392,6 @@ printk("btrfs transaction cleaner\n");
381 goto out; 392 goto out;
382 } 393 }
383 mutex_unlock(&root->fs_info->trans_mutex); 394 mutex_unlock(&root->fs_info->trans_mutex);
384printk("forcing commit\n");
385 trans = btrfs_start_transaction(root, 1); 395 trans = btrfs_start_transaction(root, 1);
386 ret = btrfs_commit_transaction(trans, root); 396 ret = btrfs_commit_transaction(trans, root);
387out: 397out:
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 0b08208be853..f25b4900db45 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -8,7 +8,6 @@ struct btrfs_transaction {
8 int in_commit; 8 int in_commit;
9 int use_count; 9 int use_count;
10 int commit_done; 10 int commit_done;
11 int magic;
12 struct list_head list; 11 struct list_head list;
13 struct radix_tree_root dirty_pages; 12 struct radix_tree_root dirty_pages;
14 unsigned long start_time; 13 unsigned long start_time;
@@ -17,13 +16,11 @@ struct btrfs_transaction {
17}; 16};
18 17
19struct btrfs_trans_handle { 18struct btrfs_trans_handle {
20 int magic;
21 u64 transid; 19 u64 transid;
22 unsigned long blocks_reserved; 20 unsigned long blocks_reserved;
23 unsigned long blocks_used; 21 unsigned long blocks_used;
24 struct btrfs_transaction *transaction; 22 struct btrfs_transaction *transaction;
25 struct btrfs_block_group_cache *block_group; 23 struct btrfs_block_group_cache *block_group;
26 int magic2;
27}; 24};
28 25
29 26