Btrfs: get forced transaction commits via workqueue
authorChris Mason <chris.mason@oracle.com>
Fri, 8 Jun 2007 22:11:48 +0000 (18:11 -0400)
committerDavid Woodhouse <dwmw2@hera.kernel.org>
Fri, 8 Jun 2007 22:11:48 +0000 (18:11 -0400)
Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h

index 74e6aadf6bb71f18695da7355202bd349dbcd23b..e93ba1a5c812ced98c089a21b0347f9e4c2f6a3e 100644 (file)
@@ -283,6 +283,7 @@ struct btrfs_block_group_cache {
 struct crypto_hash;
 
 struct btrfs_fs_info {
+       spinlock_t hash_lock;
        struct btrfs_root *extent_root;
        struct btrfs_root *tree_root;
        struct btrfs_root *dev_root;
@@ -308,10 +309,11 @@ struct btrfs_fs_info {
        struct mutex trans_mutex;
        struct mutex fs_mutex;
        struct list_head trans_list;
+       struct list_head dead_roots;
        struct crypto_hash *hash_tfm;
        struct delayed_work trans_work;
-       spinlock_t hash_lock;
        int do_barriers;
+       int closing;
 };
 
 /*
index 048282f06afb63c68bf47f4b6f6ddda9704cb944..751069c0e9f57318e38b696cbcd5ea1e4352bb2f 100644 (file)
@@ -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_data_radix, GFP_KERNEL);
        INIT_LIST_HEAD(&fs_info->trans_list);
+       INIT_LIST_HEAD(&fs_info->dead_roots);
        sb_set_blocksize(sb, 4096);
        fs_info->running_transaction = NULL;
        fs_info->tree_root = tree_root;
@@ -577,6 +578,8 @@ struct btrfs_root *open_ctree(struct super_block *sb)
        fs_info->do_barriers = 1;
        fs_info->extent_tree_insert_nr = 0;
        fs_info->extent_tree_prealloc_nr = 0;
+       fs_info->closing = 0;
+
        INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner);
        BTRFS_I(fs_info->btree_inode)->root = tree_root;
        memset(&BTRFS_I(fs_info->btree_inode)->location, 0,
@@ -746,6 +749,7 @@ int close_ctree(struct btrfs_root *root)
        struct btrfs_trans_handle *trans;
        struct btrfs_fs_info *fs_info = root->fs_info;
 
+       fs_info->closing = 1;
        btrfs_transaction_flush_work(root);
        mutex_lock(&fs_info->fs_mutex);
        trans = btrfs_start_transaction(root, 1);
index bf7eef67ba0b4ecf231baddf9fca55fdfeccec4c..b859db395fd56d941a9a982890c24642fad6d022 100644 (file)
@@ -12,12 +12,10 @@ static struct workqueue_struct *trans_wq;
 
 #define BTRFS_ROOT_TRANS_TAG 0
 
-#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--;
@@ -42,7 +40,6 @@ static int join_transaction(struct btrfs_root *root)
                cur_trans->transid = root->fs_info->generation;
                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;
@@ -83,7 +80,6 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
        h->block_group = NULL;
        root->fs_info->running_transaction->use_count++;
        mutex_unlock(&root->fs_info->trans_mutex);
-       h->magic = h->magic2 = TRANS_MAGIC;
        return h;
 }
 
@@ -92,8 +88,6 @@ int btrfs_end_transaction(struct btrfs_trans_handle *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);
        cur_trans = root->fs_info->running_transaction;
        WARN_ON(cur_trans->num_writers < 1);
@@ -257,8 +251,8 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
        struct dirty_root *dirty;
        struct btrfs_trans_handle *trans;
        int ret;
-
        while(!list_empty(list)) {
+               mutex_lock(&tree_root->fs_info->fs_mutex);
                dirty = list_entry(list->next, struct dirty_root, list);
                list_del_init(&dirty->list);
                trans = btrfs_start_transaction(tree_root, 1);
@@ -271,6 +265,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
                ret = btrfs_end_transaction(trans, tree_root);
                BUG_ON(ret);
                kfree(dirty);
+               mutex_unlock(&tree_root->fs_info->fs_mutex);
        }
        return 0;
 }
@@ -346,10 +341,18 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
        wake_up(&cur_trans->commit_wait);
        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);
        kmem_cache_free(btrfs_trans_handle_cachep, trans);
 
-       drop_dirty_roots(root->fs_info->tree_root, &dirty_fs_roots);
+       if (root->fs_info->closing) {
+               mutex_unlock(&root->fs_info->fs_mutex);
+               drop_dirty_roots(root->fs_info->tree_root, &dirty_fs_roots);
+               mutex_lock(&root->fs_info->fs_mutex);
+       }
        return ret;
 }
 
@@ -362,11 +365,19 @@ void btrfs_transaction_cleaner(struct work_struct *work)
        struct btrfs_root *root = fs_info->tree_root;
        struct btrfs_transaction *cur;
        struct btrfs_trans_handle *trans;
+       struct list_head dirty_roots;
        unsigned long now;
        unsigned long delay = HZ * 30;
        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->trans_mutex);
        cur = root->fs_info->running_transaction;
@@ -381,7 +392,6 @@ printk("btrfs transaction cleaner\n");
                goto out;
        }
        mutex_unlock(&root->fs_info->trans_mutex);
-printk("forcing commit\n");
        trans = btrfs_start_transaction(root, 1);
        ret = btrfs_commit_transaction(trans, root);
 out:
index 0b08208be85358a468f178c3fd8cd0d7cbbd5dda..f25b4900db45186299d6d61f2423934417fd5495 100644 (file)
@@ -8,7 +8,6 @@ struct btrfs_transaction {
        int in_commit;
        int use_count;
        int commit_done;
-       int magic;
        struct list_head list;
        struct radix_tree_root dirty_pages;
        unsigned long start_time;
@@ -17,13 +16,11 @@ struct btrfs_transaction {
 };
 
 struct btrfs_trans_handle {
-       int magic;
        u64 transid;
        unsigned long blocks_reserved;
        unsigned long blocks_used;
        struct btrfs_transaction *transaction;
        struct btrfs_block_group_cache *block_group;
-       int magic2;
 };