diff options
-rw-r--r-- | fs/btrfs/ctree.h | 4 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 4 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 30 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 3 |
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 { | |||
283 | struct crypto_hash; | 283 | struct crypto_hash; |
284 | 284 | ||
285 | struct btrfs_fs_info { | 285 | struct 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 | ||
16 | static void put_transaction(struct btrfs_transaction *transaction) | 15 | static 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 | ||
369 | printk("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); |
384 | printk("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); |
387 | out: | 397 | out: |
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 | ||
19 | struct btrfs_trans_handle { | 18 | struct 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 | ||