aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-04-09 16:28:12 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:01 -0400
commit22c599485b1fdd95e4476a4752596a6cf6c6629a (patch)
treef34285bfb545cf7abed9be6ad12a61e80dbb4bb5 /fs/btrfs/disk-io.c
parentce9adaa5a792c2099a83246265eb4055bc38b6b8 (diff)
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>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 82109204788c..94ff87d0eae4 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -54,6 +54,7 @@ struct end_io_wq {
54 void *private; 54 void *private;
55 struct btrfs_fs_info *info; 55 struct btrfs_fs_info *info;
56 int error; 56 int error;
57 int metadata;
57 struct list_head list; 58 struct list_head list;
58}; 59};
59 60
@@ -308,29 +309,40 @@ static int end_workqueue_bio(struct bio *bio,
308#endif 309#endif
309} 310}
310 311
311static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio) 312int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio,
313 int metadata)
312{ 314{
313 struct btrfs_root *root = BTRFS_I(inode)->root;
314 struct end_io_wq *end_io_wq; 315 struct end_io_wq *end_io_wq;
315 u64 offset;
316 offset = bio->bi_sector << 9;
317
318 if (rw & (1 << BIO_RW)) {
319 return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio);
320 }
321
322 end_io_wq = kmalloc(sizeof(*end_io_wq), GFP_NOFS); 316 end_io_wq = kmalloc(sizeof(*end_io_wq), GFP_NOFS);
323 if (!end_io_wq) 317 if (!end_io_wq)
324 return -ENOMEM; 318 return -ENOMEM;
325 319
326 end_io_wq->private = bio->bi_private; 320 end_io_wq->private = bio->bi_private;
327 end_io_wq->end_io = bio->bi_end_io; 321 end_io_wq->end_io = bio->bi_end_io;
328 end_io_wq->info = root->fs_info; 322 end_io_wq->info = info;
329 end_io_wq->error = 0; 323 end_io_wq->error = 0;
330 end_io_wq->bio = bio; 324 end_io_wq->bio = bio;
325 end_io_wq->metadata = metadata;
331 326
332 bio->bi_private = end_io_wq; 327 bio->bi_private = end_io_wq;
333 bio->bi_end_io = end_workqueue_bio; 328 bio->bi_end_io = end_workqueue_bio;
329 return 0;
330}
331
332static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio)
333{
334 struct btrfs_root *root = BTRFS_I(inode)->root;
335 u64 offset;
336 int ret;
337
338 offset = bio->bi_sector << 9;
339
340 if (rw & (1 << BIO_RW)) {
341 return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio);
342 }
343
344 ret = btrfs_bio_wq_end_io(root->fs_info, bio, 1);
345 BUG_ON(ret);
334 346
335 if (offset == BTRFS_SUPER_INFO_OFFSET) { 347 if (offset == BTRFS_SUPER_INFO_OFFSET) {
336 bio->bi_bdev = root->fs_info->sb->s_bdev; 348 bio->bi_bdev = root->fs_info->sb->s_bdev;
@@ -880,7 +892,7 @@ void btrfs_end_io_csum(struct work_struct *work)
880 end_io_wq = list_entry(next, struct end_io_wq, list); 892 end_io_wq = list_entry(next, struct end_io_wq, list);
881 893
882 bio = end_io_wq->bio; 894 bio = end_io_wq->bio;
883 if (!bio_ready_for_csum(bio)) { 895 if (end_io_wq->metadata && !bio_ready_for_csum(bio)) {
884 spin_lock_irqsave(&fs_info->end_io_work_lock, flags); 896 spin_lock_irqsave(&fs_info->end_io_work_lock, flags);
885 was_empty = list_empty(&fs_info->end_io_work_list); 897 was_empty = list_empty(&fs_info->end_io_work_list);
886 list_add_tail(&end_io_wq->list, 898 list_add_tail(&end_io_wq->list,