Commit 22c59948 authored by Chris Mason's avatar Chris Mason

Btrfs: Handle data block end_io through the async work queue

Before it was done by the bio end_io routine, the work queue code is able
to scale much better with faster IO subsystems.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent ce9adaa5
...@@ -54,6 +54,7 @@ struct end_io_wq { ...@@ -54,6 +54,7 @@ struct end_io_wq {
void *private; void *private;
struct btrfs_fs_info *info; struct btrfs_fs_info *info;
int error; int error;
int metadata;
struct list_head list; struct list_head list;
}; };
...@@ -308,29 +309,40 @@ static int end_workqueue_bio(struct bio *bio, ...@@ -308,29 +309,40 @@ static int end_workqueue_bio(struct bio *bio,
#endif #endif
} }
static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio) int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio,
int metadata)
{ {
struct btrfs_root *root = BTRFS_I(inode)->root;
struct end_io_wq *end_io_wq; struct end_io_wq *end_io_wq;
u64 offset;
offset = bio->bi_sector << 9;
if (rw & (1 << BIO_RW)) {
return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio);
}
end_io_wq = kmalloc(sizeof(*end_io_wq), GFP_NOFS); end_io_wq = kmalloc(sizeof(*end_io_wq), GFP_NOFS);
if (!end_io_wq) if (!end_io_wq)
return -ENOMEM; return -ENOMEM;
end_io_wq->private = bio->bi_private; end_io_wq->private = bio->bi_private;
end_io_wq->end_io = bio->bi_end_io; end_io_wq->end_io = bio->bi_end_io;
end_io_wq->info = root->fs_info; end_io_wq->info = info;
end_io_wq->error = 0; end_io_wq->error = 0;
end_io_wq->bio = bio; end_io_wq->bio = bio;
end_io_wq->metadata = metadata;
bio->bi_private = end_io_wq; bio->bi_private = end_io_wq;
bio->bi_end_io = end_workqueue_bio; bio->bi_end_io = end_workqueue_bio;
return 0;
}
static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
u64 offset;
int ret;
offset = bio->bi_sector << 9;
if (rw & (1 << BIO_RW)) {
return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio);
}
ret = btrfs_bio_wq_end_io(root->fs_info, bio, 1);
BUG_ON(ret);
if (offset == BTRFS_SUPER_INFO_OFFSET) { if (offset == BTRFS_SUPER_INFO_OFFSET) {
bio->bi_bdev = root->fs_info->sb->s_bdev; bio->bi_bdev = root->fs_info->sb->s_bdev;
...@@ -880,7 +892,7 @@ void btrfs_end_io_csum(struct work_struct *work) ...@@ -880,7 +892,7 @@ void btrfs_end_io_csum(struct work_struct *work)
end_io_wq = list_entry(next, struct end_io_wq, list); end_io_wq = list_entry(next, struct end_io_wq, list);
bio = end_io_wq->bio; bio = end_io_wq->bio;
if (!bio_ready_for_csum(bio)) { if (end_io_wq->metadata && !bio_ready_for_csum(bio)) {
spin_lock_irqsave(&fs_info->end_io_work_lock, flags); spin_lock_irqsave(&fs_info->end_io_work_lock, flags);
was_empty = list_empty(&fs_info->end_io_work_list); was_empty = list_empty(&fs_info->end_io_work_list);
list_add_tail(&end_io_wq->list, list_add_tail(&end_io_wq->list,
......
...@@ -71,4 +71,6 @@ void btrfs_throttle(struct btrfs_root *root); ...@@ -71,4 +71,6 @@ void btrfs_throttle(struct btrfs_root *root);
int btrfs_open_device(struct btrfs_device *dev); int btrfs_open_device(struct btrfs_device *dev);
int btrfs_verify_block_csum(struct btrfs_root *root, int btrfs_verify_block_csum(struct btrfs_root *root,
struct extent_buffer *buf); struct extent_buffer *buf);
int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio,
int metadata);
#endif #endif
...@@ -328,7 +328,9 @@ int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio) ...@@ -328,7 +328,9 @@ int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio)
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
int ret = 0; int ret = 0;
if (rw != WRITE) { if (!(rw & (1 << BIO_RW))) {
ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0);
BUG_ON(ret);
goto mapit; goto mapit;
} }
......
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