diff options
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 30 |
1 files changed, 20 insertions, 10 deletions
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: |