Commit facda1e7 authored by Chris Mason's avatar Chris Mason Committed by David Woodhouse

Btrfs: get forced transaction commits via workqueue

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 08607c1b
...@@ -283,6 +283,7 @@ struct btrfs_block_group_cache { ...@@ -283,6 +283,7 @@ struct btrfs_block_group_cache {
struct crypto_hash; struct crypto_hash;
struct btrfs_fs_info { struct btrfs_fs_info {
spinlock_t hash_lock;
struct btrfs_root *extent_root; struct btrfs_root *extent_root;
struct btrfs_root *tree_root; struct btrfs_root *tree_root;
struct btrfs_root *dev_root; struct btrfs_root *dev_root;
...@@ -308,10 +309,11 @@ struct btrfs_fs_info { ...@@ -308,10 +309,11 @@ struct btrfs_fs_info {
struct mutex trans_mutex; struct mutex trans_mutex;
struct mutex fs_mutex; struct mutex fs_mutex;
struct list_head trans_list; struct list_head trans_list;
struct list_head dead_roots;
struct crypto_hash *hash_tfm; struct crypto_hash *hash_tfm;
struct delayed_work trans_work; struct delayed_work trans_work;
spinlock_t hash_lock;
int do_barriers; int do_barriers;
int closing;
}; };
/* /*
......
...@@ -563,6 +563,7 @@ struct btrfs_root *open_ctree(struct super_block *sb) ...@@ -563,6 +563,7 @@ struct btrfs_root *open_ctree(struct super_block *sb)
INIT_RADIX_TREE(&fs_info->block_group_radix, GFP_KERNEL); INIT_RADIX_TREE(&fs_info->block_group_radix, GFP_KERNEL);
INIT_RADIX_TREE(&fs_info->block_group_data_radix, GFP_KERNEL); INIT_RADIX_TREE(&fs_info->block_group_data_radix, GFP_KERNEL);
INIT_LIST_HEAD(&fs_info->trans_list); INIT_LIST_HEAD(&fs_info->trans_list);
INIT_LIST_HEAD(&fs_info->dead_roots);
sb_set_blocksize(sb, 4096); sb_set_blocksize(sb, 4096);
fs_info->running_transaction = NULL; fs_info->running_transaction = NULL;
fs_info->tree_root = tree_root; fs_info->tree_root = tree_root;
...@@ -577,6 +578,8 @@ struct btrfs_root *open_ctree(struct super_block *sb) ...@@ -577,6 +578,8 @@ struct btrfs_root *open_ctree(struct super_block *sb)
fs_info->do_barriers = 1; fs_info->do_barriers = 1;
fs_info->extent_tree_insert_nr = 0; fs_info->extent_tree_insert_nr = 0;
fs_info->extent_tree_prealloc_nr = 0; fs_info->extent_tree_prealloc_nr = 0;
fs_info->closing = 0;
INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner); INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner);
BTRFS_I(fs_info->btree_inode)->root = tree_root; BTRFS_I(fs_info->btree_inode)->root = tree_root;
memset(&BTRFS_I(fs_info->btree_inode)->location, 0, memset(&BTRFS_I(fs_info->btree_inode)->location, 0,
...@@ -746,6 +749,7 @@ int close_ctree(struct btrfs_root *root) ...@@ -746,6 +749,7 @@ int close_ctree(struct btrfs_root *root)
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_fs_info *fs_info = root->fs_info;
fs_info->closing = 1;
btrfs_transaction_flush_work(root); btrfs_transaction_flush_work(root);
mutex_lock(&fs_info->fs_mutex); mutex_lock(&fs_info->fs_mutex);
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
......
...@@ -12,12 +12,10 @@ static struct workqueue_struct *trans_wq; ...@@ -12,12 +12,10 @@ static struct workqueue_struct *trans_wq;
#define BTRFS_ROOT_TRANS_TAG 0 #define BTRFS_ROOT_TRANS_TAG 0
#define TRANS_MAGIC 0xE1E10E
static void put_transaction(struct btrfs_transaction *transaction) static void put_transaction(struct btrfs_transaction *transaction)
{ {
WARN_ON(transaction->use_count == 0); WARN_ON(transaction->use_count == 0);
transaction->use_count--; transaction->use_count--;
WARN_ON(transaction->magic != TRANS_MAGIC);
if (transaction->use_count == 0) { if (transaction->use_count == 0) {
WARN_ON(total_trans == 0); WARN_ON(total_trans == 0);
total_trans--; total_trans--;
...@@ -42,7 +40,6 @@ static int join_transaction(struct btrfs_root *root) ...@@ -42,7 +40,6 @@ static int join_transaction(struct btrfs_root *root)
cur_trans->transid = root->fs_info->generation; cur_trans->transid = root->fs_info->generation;
init_waitqueue_head(&cur_trans->writer_wait); init_waitqueue_head(&cur_trans->writer_wait);
init_waitqueue_head(&cur_trans->commit_wait); init_waitqueue_head(&cur_trans->commit_wait);
cur_trans->magic = TRANS_MAGIC;
cur_trans->in_commit = 0; cur_trans->in_commit = 0;
cur_trans->use_count = 1; cur_trans->use_count = 1;
cur_trans->commit_done = 0; cur_trans->commit_done = 0;
...@@ -83,7 +80,6 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, ...@@ -83,7 +80,6 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
h->block_group = NULL; h->block_group = NULL;
root->fs_info->running_transaction->use_count++; root->fs_info->running_transaction->use_count++;
mutex_unlock(&root->fs_info->trans_mutex); mutex_unlock(&root->fs_info->trans_mutex);
h->magic = h->magic2 = TRANS_MAGIC;
return h; return h;
} }
...@@ -92,8 +88,6 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, ...@@ -92,8 +88,6 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans,
{ {
struct btrfs_transaction *cur_trans; struct btrfs_transaction *cur_trans;
WARN_ON(trans->magic != TRANS_MAGIC);
WARN_ON(trans->magic2 != TRANS_MAGIC);
mutex_lock(&root->fs_info->trans_mutex); mutex_lock(&root->fs_info->trans_mutex);
cur_trans = root->fs_info->running_transaction; cur_trans = root->fs_info->running_transaction;
WARN_ON(cur_trans->num_writers < 1); WARN_ON(cur_trans->num_writers < 1);
...@@ -257,8 +251,8 @@ static int drop_dirty_roots(struct btrfs_root *tree_root, ...@@ -257,8 +251,8 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
struct dirty_root *dirty; struct dirty_root *dirty;
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
int ret; int ret;
while(!list_empty(list)) { while(!list_empty(list)) {
mutex_lock(&tree_root->fs_info->fs_mutex);
dirty = list_entry(list->next, struct dirty_root, list); dirty = list_entry(list->next, struct dirty_root, list);
list_del_init(&dirty->list); list_del_init(&dirty->list);
trans = btrfs_start_transaction(tree_root, 1); trans = btrfs_start_transaction(tree_root, 1);
...@@ -271,6 +265,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root, ...@@ -271,6 +265,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
ret = btrfs_end_transaction(trans, tree_root); ret = btrfs_end_transaction(trans, tree_root);
BUG_ON(ret); BUG_ON(ret);
kfree(dirty); kfree(dirty);
mutex_unlock(&tree_root->fs_info->fs_mutex);
} }
return 0; return 0;
} }
...@@ -346,10 +341,18 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ...@@ -346,10 +341,18 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
wake_up(&cur_trans->commit_wait); wake_up(&cur_trans->commit_wait);
put_transaction(cur_trans); put_transaction(cur_trans);
put_transaction(cur_trans); put_transaction(cur_trans);
if (root->fs_info->closing)
list_splice_init(&root->fs_info->dead_roots, &dirty_fs_roots);
else
list_splice_init(&dirty_fs_roots, &root->fs_info->dead_roots);
mutex_unlock(&root->fs_info->trans_mutex); mutex_unlock(&root->fs_info->trans_mutex);
kmem_cache_free(btrfs_trans_handle_cachep, trans); kmem_cache_free(btrfs_trans_handle_cachep, trans);
if (root->fs_info->closing) {
mutex_unlock(&root->fs_info->fs_mutex);
drop_dirty_roots(root->fs_info->tree_root, &dirty_fs_roots); drop_dirty_roots(root->fs_info->tree_root, &dirty_fs_roots);
mutex_lock(&root->fs_info->fs_mutex);
}
return ret; return ret;
} }
...@@ -362,11 +365,19 @@ void btrfs_transaction_cleaner(struct work_struct *work) ...@@ -362,11 +365,19 @@ void btrfs_transaction_cleaner(struct work_struct *work)
struct btrfs_root *root = fs_info->tree_root; struct btrfs_root *root = fs_info->tree_root;
struct btrfs_transaction *cur; struct btrfs_transaction *cur;
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
struct list_head dirty_roots;
unsigned long now; unsigned long now;
unsigned long delay = HZ * 30; unsigned long delay = HZ * 30;
int ret; int ret;
printk("btrfs transaction cleaner\n"); INIT_LIST_HEAD(&dirty_roots);
mutex_lock(&root->fs_info->trans_mutex);
list_splice_init(&root->fs_info->dead_roots, &dirty_roots);
mutex_unlock(&root->fs_info->trans_mutex);
if (!list_empty(&dirty_roots)) {
drop_dirty_roots(root, &dirty_roots);
}
mutex_lock(&root->fs_info->fs_mutex); mutex_lock(&root->fs_info->fs_mutex);
mutex_lock(&root->fs_info->trans_mutex); mutex_lock(&root->fs_info->trans_mutex);
cur = root->fs_info->running_transaction; cur = root->fs_info->running_transaction;
...@@ -381,7 +392,6 @@ printk("btrfs transaction cleaner\n"); ...@@ -381,7 +392,6 @@ printk("btrfs transaction cleaner\n");
goto out; goto out;
} }
mutex_unlock(&root->fs_info->trans_mutex); mutex_unlock(&root->fs_info->trans_mutex);
printk("forcing commit\n");
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
ret = btrfs_commit_transaction(trans, root); ret = btrfs_commit_transaction(trans, root);
out: out:
......
...@@ -8,7 +8,6 @@ struct btrfs_transaction { ...@@ -8,7 +8,6 @@ struct btrfs_transaction {
int in_commit; int in_commit;
int use_count; int use_count;
int commit_done; int commit_done;
int magic;
struct list_head list; struct list_head list;
struct radix_tree_root dirty_pages; struct radix_tree_root dirty_pages;
unsigned long start_time; unsigned long start_time;
...@@ -17,13 +16,11 @@ struct btrfs_transaction { ...@@ -17,13 +16,11 @@ struct btrfs_transaction {
}; };
struct btrfs_trans_handle { struct btrfs_trans_handle {
int magic;
u64 transid; u64 transid;
unsigned long blocks_reserved; unsigned long blocks_reserved;
unsigned long blocks_used; unsigned long blocks_used;
struct btrfs_transaction *transaction; struct btrfs_transaction *transaction;
struct btrfs_block_group_cache *block_group; struct btrfs_block_group_cache *block_group;
int magic2;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment