mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-04 16:15:11 +00:00
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: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
ce9adaa5a7
commit
22c599485b
3 changed files with 28 additions and 12 deletions
|
@ -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,
|
||||||
#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)
|
||||||
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);
|
||||||
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)
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue