Skip to content

Commit

Permalink
Btrfs: Replace the transaction work queue with kthreads
Browse files Browse the repository at this point in the history
This creates one kthread for commits and one kthread for
deleting old snapshots.  All the work queues are removed.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
  • Loading branch information
Chris Mason committed Sep 25, 2008
1 parent 89ce8a6 commit a74a4b9
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 118 deletions.
5 changes: 4 additions & 1 deletion fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
free_extent_buffer(tmp);
goto again;
} else {
if (tmp)
free_extent_buffer(tmp);
b = read_node_slot(root, b, slot);
}
}
Expand Down Expand Up @@ -3048,7 +3050,8 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
free_extent_buffer(c);
path->nodes[level] = next;
path->slots[level] = 0;
path->locks[level] = 1;
if (!path->skip_locking)
path->locks[level] = 1;
if (!level)
break;
if (level == 1 && path->locks[1] && path->reada)
Expand Down
13 changes: 4 additions & 9 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/fs.h>
#include <linux/workqueue.h>
#include <linux/completion.h>
#include <linux/backing-dev.h>
#include <asm/kmap_types.h>
Expand Down Expand Up @@ -519,15 +518,14 @@ struct btrfs_fs_info {
struct backing_dev_info bdi;
spinlock_t hash_lock;
struct mutex trans_mutex;
struct mutex transaction_kthread_mutex;
struct mutex cleaner_mutex;
struct mutex alloc_mutex;
struct mutex chunk_mutex;
struct mutex drop_mutex;
struct list_head trans_list;
struct list_head hashers;
struct list_head dead_roots;
struct list_head end_io_work_list;
struct work_struct end_io_work;
spinlock_t end_io_work_lock;
atomic_t nr_async_submits;

/*
Expand All @@ -543,13 +541,10 @@ struct btrfs_fs_info {
struct btrfs_workers workers;
struct btrfs_workers endio_workers;
struct btrfs_workers submit_workers;
struct task_struct *transaction_kthread;
struct task_struct *cleaner_kthread;
int thread_pool_size;

#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
struct work_struct trans_work;
#else
struct delayed_work trans_work;
#endif
struct kobject super_kobj;
struct completion kobj_unregister;
int do_barriers;
Expand Down
116 changes: 107 additions & 9 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* Boston, MA 021110-1307, USA.
*/

#include <linux/version.h>
#include <linux/fs.h>
#include <linux/blkdev.h>
#include <linux/scatterlist.h>
Expand All @@ -24,6 +25,12 @@
#include <linux/writeback.h>
#include <linux/buffer_head.h> // for block_sync_page
#include <linux/workqueue.h>
#include <linux/kthread.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
# include <linux/freezer.h>
#else
# include <linux/sched.h>
#endif
#include "crc32c.h"
#include "ctree.h"
#include "disk-io.h"
Expand Down Expand Up @@ -1100,6 +1107,87 @@ static void end_workqueue_fn(struct btrfs_work *work)
#endif
}

static int cleaner_kthread(void *arg)
{
struct btrfs_root *root = arg;

do {
smp_mb();
if (root->fs_info->closing)
break;

vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);
mutex_lock(&root->fs_info->cleaner_mutex);
printk("cleaner awake\n");
btrfs_clean_old_snapshots(root);
printk("cleaner done\n");
mutex_unlock(&root->fs_info->cleaner_mutex);

if (freezing(current)) {
refrigerator();
} else {
smp_mb();
if (root->fs_info->closing)
break;
set_current_state(TASK_INTERRUPTIBLE);
schedule();
__set_current_state(TASK_RUNNING);
}
} while (!kthread_should_stop());
return 0;
}

static int transaction_kthread(void *arg)
{
struct btrfs_root *root = arg;
struct btrfs_trans_handle *trans;
struct btrfs_transaction *cur;
unsigned long now;
unsigned long delay;
int ret;

do {
smp_mb();
if (root->fs_info->closing)
break;

delay = HZ * 30;
vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);
mutex_lock(&root->fs_info->transaction_kthread_mutex);

mutex_lock(&root->fs_info->trans_mutex);
cur = root->fs_info->running_transaction;
if (!cur) {
mutex_unlock(&root->fs_info->trans_mutex);
goto sleep;
}
now = get_seconds();
if (now < cur->start_time || now - cur->start_time < 30) {
mutex_unlock(&root->fs_info->trans_mutex);
delay = HZ * 5;
goto sleep;
}
mutex_unlock(&root->fs_info->trans_mutex);
btrfs_defrag_dirty_roots(root->fs_info);
trans = btrfs_start_transaction(root, 1);
ret = btrfs_commit_transaction(trans, root);
sleep:
wake_up_process(root->fs_info->cleaner_kthread);
mutex_unlock(&root->fs_info->transaction_kthread_mutex);

if (freezing(current)) {
refrigerator();
} else {
if (root->fs_info->closing)
break;
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(delay);
__set_current_state(TASK_RUNNING);
}
} while (!kthread_should_stop());
return 0;
}

struct btrfs_root *open_ctree(struct super_block *sb,
struct btrfs_fs_devices *fs_devices,
char *options)
Expand Down Expand Up @@ -1189,11 +1277,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
fs_info->btree_inode->i_mapping, GFP_NOFS);
fs_info->do_barriers = 1;

#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
INIT_WORK(&fs_info->trans_work, btrfs_transaction_cleaner, fs_info);
#else
INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner);
#endif
BTRFS_I(fs_info->btree_inode)->root = tree_root;
memset(&BTRFS_I(fs_info->btree_inode)->location, 0,
sizeof(struct btrfs_key));
Expand All @@ -1204,6 +1287,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
mutex_init(&fs_info->drop_mutex);
mutex_init(&fs_info->alloc_mutex);
mutex_init(&fs_info->chunk_mutex);
mutex_init(&fs_info->transaction_kthread_mutex);
mutex_init(&fs_info->cleaner_mutex);

#if 0
ret = add_hasher(fs_info, "crc32c");
Expand Down Expand Up @@ -1247,7 +1332,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
btrfs_start_workers(&fs_info->submit_workers, 1);
btrfs_start_workers(&fs_info->endio_workers, fs_info->thread_pool_size);


err = -EINVAL;
if (btrfs_super_num_devices(disk_super) > fs_devices->open_devices) {
printk("Btrfs: wanted %llu devices, but found %llu\n",
Expand Down Expand Up @@ -1341,9 +1425,22 @@ struct btrfs_root *open_ctree(struct super_block *sb,
fs_info->data_alloc_profile = (u64)-1;
fs_info->metadata_alloc_profile = (u64)-1;
fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
"btrfs-cleaner");
if (!fs_info->cleaner_kthread)
goto fail_extent_root;

fs_info->transaction_kthread = kthread_run(transaction_kthread,
tree_root,
"btrfs-transaction");
if (!fs_info->transaction_kthread)
goto fail_trans_kthread;


return tree_root;

fail_trans_kthread:
kthread_stop(fs_info->cleaner_kthread);
fail_extent_root:
free_extent_buffer(extent_root->node);
fail_tree_root:
Expand Down Expand Up @@ -1562,8 +1659,11 @@ int close_ctree(struct btrfs_root *root)
fs_info->closing = 1;
smp_mb();

btrfs_transaction_flush_work(root);
kthread_stop(root->fs_info->transaction_kthread);
kthread_stop(root->fs_info->cleaner_kthread);

btrfs_defrag_dirty_roots(root->fs_info);
btrfs_clean_old_snapshots(root);
trans = btrfs_start_transaction(root, 1);
ret = btrfs_commit_transaction(trans, root);
/* run commit again to drop the original snapshot */
Expand All @@ -1574,8 +1674,6 @@ int close_ctree(struct btrfs_root *root)

write_ctree_super(NULL, root);

btrfs_transaction_flush_work(root);

if (fs_info->delalloc_bytes) {
printk("btrfs: at unmount delalloc count %Lu\n",
fs_info->delalloc_bytes);
Expand Down
10 changes: 5 additions & 5 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1216,15 +1216,16 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
if (ret == -ENOSPC) {
printk("space info full %Lu\n", flags);
space_info->full = 1;
goto out;
goto out_unlock;
}
BUG_ON(ret);

ret = btrfs_make_block_group(trans, extent_root, 0, flags,
BTRFS_FIRST_CHUNK_TREE_OBJECTID, start, num_bytes);
BUG_ON(ret);
out:
out_unlock:
mutex_unlock(&extent_root->fs_info->chunk_mutex);
out:
return 0;
}

Expand Down Expand Up @@ -2274,7 +2275,8 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
free_extent_buffer(next);
mutex_unlock(&root->fs_info->alloc_mutex);

reada_walk_down(root, cur, path->slots[*level]);
if (path->slots[*level] == 0)
reada_walk_down(root, cur, path->slots[*level]);

next = read_tree_block(root, bytenr, blocksize,
ptr_gen);
Expand Down Expand Up @@ -2446,8 +2448,6 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
break;
if (wret < 0)
ret = wret;
ret = -EAGAIN;
break;
}
for (i = 0; i <= orig_level; i++) {
if (path->nodes[i]) {
Expand Down
16 changes: 6 additions & 10 deletions fs/btrfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,6 @@ static int btrfs_fill_super(struct super_block * sb,
goto fail_close;

sb->s_root = root_dentry;
btrfs_transaction_queue_work(tree_root, HZ * 30);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
save_mount_options(sb, data);
Expand Down Expand Up @@ -416,9 +415,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
goto error_free_subvol_name;

bdev = fs_devices->latest_bdev;
btrfs_lock_volumes();
s = sget(fs_type, btrfs_test_super, set_anon_super, fs_devices);
btrfs_unlock_volumes();
if (IS_ERR(s))
goto error_s;

Expand Down Expand Up @@ -530,13 +527,15 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
static void btrfs_write_super_lockfs(struct super_block *sb)
{
struct btrfs_root *root = btrfs_sb(sb);
btrfs_transaction_flush_work(root);
mutex_lock(&root->fs_info->transaction_kthread_mutex);
mutex_lock(&root->fs_info->cleaner_mutex);
}

static void btrfs_unlockfs(struct super_block *sb)
{
struct btrfs_root *root = btrfs_sb(sb);
btrfs_transaction_queue_work(root, HZ * 30);
mutex_unlock(&root->fs_info->cleaner_mutex);
mutex_unlock(&root->fs_info->transaction_kthread_mutex);
}

static struct super_operations btrfs_super_ops = {
Expand Down Expand Up @@ -589,10 +588,9 @@ static int __init init_btrfs_fs(void)
if (err)
return err;

btrfs_init_transaction_sys();
err = btrfs_init_cachep();
if (err)
goto free_transaction_sys;
goto free_sysfs;

err = extent_io_init();
if (err)
Expand All @@ -618,15 +616,13 @@ static int __init init_btrfs_fs(void)
extent_io_exit();
free_cachep:
btrfs_destroy_cachep();
free_transaction_sys:
btrfs_exit_transaction_sys();
free_sysfs:
btrfs_exit_sysfs();
return err;
}

static void __exit exit_btrfs_fs(void)
{
btrfs_exit_transaction_sys();
btrfs_destroy_cachep();
extent_map_exit();
extent_io_exit();
Expand Down
Loading

0 comments on commit a74a4b9

Please sign in to comment.