Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+23 −11
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ struct end_io_wq {
	void *private;
	struct btrfs_fs_info *info;
	int error;
	int metadata;
	struct list_head list;
};

@@ -308,29 +309,40 @@ static int end_workqueue_bio(struct bio *bio,
#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;
	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);
	if (!end_io_wq)
		return -ENOMEM;

	end_io_wq->private = bio->bi_private;
	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->bio = bio;
	end_io_wq->metadata = metadata;

	bio->bi_private = end_io_wq;
	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) {
		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);

		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);
			was_empty = list_empty(&fs_info->end_io_work_list);
			list_add_tail(&end_io_wq->list,
+2 −0
Original line number Diff line number Diff line
@@ -71,4 +71,6 @@ void btrfs_throttle(struct btrfs_root *root);
int btrfs_open_device(struct btrfs_device *dev);
int btrfs_verify_block_csum(struct btrfs_root *root,
			    struct extent_buffer *buf);
int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio,
			int metadata);
#endif
+3 −1
Original line number Diff line number Diff line
@@ -328,7 +328,9 @@ int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio)
	struct btrfs_trans_handle *trans;
	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;
	}