kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Minchan Kim <minchan@kernel.org>
To: Rusty Russell <rusty@rustcorp.com.au>
Cc: Chris Wright <chrisw@sous-sol.org>, Jens Axboe <axboe@kernel.dk>,
	Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>,
	kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	Christoph Hellwig <hch@infradead.org>,
	Minchan Kim <minchan@kernel.org>,
	Minchan Kim <minchan@redhat.com>
Subject: [PATCH 6/6] virtio-blk: Emulate Flush/FUA
Date: Wed, 21 Dec 2011 10:00:54 +0900	[thread overview]
Message-ID: <1324429254-28383-7-git-send-email-minchan@kernel.org> (raw)
In-Reply-To: <1324429254-28383-1-git-send-email-minchan@kernel.org>

This patch emulates flush/fua on virtio-blk and pass xfstest on ext4.
But it needs more reviews.

Signed-off-by: Minchan Kim <minchan@redhat.com>
---
 drivers/block/virtio_blk.c |   89 ++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 86 insertions(+), 3 deletions(-)

diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index e32c69e..6721b9d 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -12,7 +12,6 @@
 #include <linux/idr.h>
 
 #define PART_BITS 4
-static int use_make_request = 1;
 
 static int major;
 static DEFINE_IDA(vd_index_ida);
@@ -77,6 +76,7 @@ struct virtblk_req
 	u8 kind;
 #define VIRTIO_BLK_REQUEST	0x00
 #define VIRTIO_BLK_BIO		0x01
+#define VIRTIO_BLK_BIO_FLUSH	0x02
 	u8 status;
 
 	struct scatterlist sg[];
@@ -160,6 +160,9 @@ static void blk_done(struct virtqueue *vq)
 			 */
         		blk_start_queue(vblk->disk->queue);
 			break;
+		case VIRTIO_BLK_BIO_FLUSH:
+			complete(vbr->private);
+			break;
 		case VIRTIO_BLK_BIO:
 			if (head) {
 				tail->next = vbr;
@@ -526,6 +529,59 @@ static void virtblk_add_buf_wait(struct virtio_blk *vblk,
         finish_wait(&vblk->queue_wait, &wait);
 }
 
+static int virtblk_flush(struct virtio_blk *vblk,
+			struct virtblk_req *vbr, struct bio *bio)
+{
+	int error;
+	bool retry, notify;
+	DECLARE_COMPLETION_ONSTACK(done);
+
+	vbr->private = &done;
+	vbr->next = NULL;
+	vbr->kind = VIRTIO_BLK_BIO_FLUSH;
+
+	vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH;
+	vbr->out_hdr.sector = 0;
+	if (bio)
+		vbr->out_hdr.ioprio = bio_prio(bio);
+	else
+		vbr->out_hdr.ioprio = 0;
+
+	sg_set_buf(&vbr->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr));
+	sg_set_buf(&vbr->sg[1], &vbr->status, sizeof(vbr->status));
+
+	spin_lock_irq(&vblk->lock);
+	if (virtqueue_add_buf(vblk->vq, vbr->sg, 1, 1, vbr) < 0) {
+		retry = true;
+	} else {
+		retry = false;
+	}
+
+	notify = virtqueue_kick_prepare(vblk->vq);
+	spin_unlock_irq(&vblk->lock);
+
+	if (notify && !virtblk_plugged(vblk))
+		virtqueue_notify(vblk->vq);
+
+	if (retry)
+		virtblk_add_buf_wait(vblk, vbr, 1, 1);
+
+	wait_for_completion(&done);
+	error = virtblk_result(vbr);
+	return error;
+}
+
+void bq_flush(struct bio_queue *bq)
+{
+	int cpu;
+	for_each_possible_cpu(cpu) {
+		struct per_cpu_bio __percpu *pcbio = per_cpu_ptr(bq->pcbio, cpu);
+		queue_work_on(cpu,
+			virtblk_wq, &pcbio->dwork.work);
+		flush_work_sync(&pcbio->dwork.work);
+	}
+}
+
 bool full_segment(struct per_cpu_bio __percpu *pcbio, struct bio *bio,
 		unsigned int max)
 {
@@ -616,9 +672,36 @@ static void virtblk_make_request(struct request_queue *q, struct bio *bio)
 {
 	struct virtio_blk *vblk = q->queuedata;
 	struct per_cpu_bio __percpu *pcbio;
+	bool pre_flush, post_flush;
 
 	BUG_ON(bio->bi_phys_segments + 2 > vblk->sg_elems);
-	BUG_ON(bio->bi_rw & (REQ_FLUSH | REQ_FUA));
+
+	pre_flush = bio->bi_rw & REQ_FLUSH;
+	post_flush = bio->bi_rw & REQ_FUA;
+
+	if (pre_flush) {
+		struct virtblk_req *dummy_vbr;
+		bq_flush(&vblk->bq);
+
+		dummy_vbr = alloc_virtblk_req(vblk, GFP_NOIO);
+		virtblk_flush(vblk, dummy_vbr, NULL);
+		mempool_free(dummy_vbr, vblk->pool);
+
+		if (bio->bi_sector && post_flush) {
+			int error;
+			struct virtblk_req *vbr;
+			vbr = alloc_virtblk_req(vblk, GFP_NOIO);
+			error = virtblk_flush(vblk, vbr, bio);
+			mempool_free(vbr, vblk->pool);
+
+			dummy_vbr = alloc_virtblk_req(vblk, GFP_NOIO);
+			virtblk_flush(vblk, dummy_vbr, NULL);
+			mempool_free(dummy_vbr, vblk->pool);
+
+			bio_endio(bio, error);
+			return;
+		}
+	}
 retry:
 	preempt_disable();
 	pcbio = this_cpu_ptr(vblk->bq.pcbio);
@@ -918,7 +1001,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
 	vblk->index = index;
 
 	/* configure queue flush support */
-	if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH) && !use_make_request)
+	if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH))
 		blk_queue_flush(q, REQ_FLUSH);
 
 	/* If disk is read-only in the host, the guest should obey */
-- 
1.7.6.4


  parent reply	other threads:[~2011-12-21  1:01 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-12-21  1:00 [PATCH 0/6][RFC] virtio-blk: Change I/O path from request to BIO Minchan Kim
2011-12-21  1:00 ` [PATCH 1/6] block: add bio_map_sg Minchan Kim
2011-12-21  1:00 ` [PATCH 2/6] virtio: support unlocked queue kick Minchan Kim
2011-12-21  1:00 ` [PATCH 3/6] virtio-blk: remove the unused list of pending requests Minchan Kim
2011-12-21  1:00 ` [PATCH 4/6] virtio-blk: implement ->make_request Minchan Kim
2011-12-22 12:20   ` Stefan Hajnoczi
2011-12-22 20:28     ` Christoph Hellwig
2011-12-21  1:00 ` [PATCH 5/6] virtio-blk: Support batch I/O for enhancing sequential IO Minchan Kim
2011-12-21  1:00 ` Minchan Kim [this message]
2011-12-21  5:08 ` [PATCH 0/6][RFC] virtio-blk: Change I/O path from request to BIO Rusty Russell
2011-12-21  5:56   ` Minchan Kim
2011-12-21  8:28 ` Sasha Levin
2011-12-21  8:17   ` Minchan Kim
2011-12-21 19:11 ` Vivek Goyal
2011-12-22  1:05   ` Minchan Kim
2011-12-22 15:45     ` Vivek Goyal
2011-12-22 23:26       ` Minchan Kim
2011-12-22 12:57 ` Stefan Hajnoczi
2011-12-22 23:41   ` Minchan Kim
2012-01-01 16:45     ` Stefan Hajnoczi
2012-01-02  7:48       ` Dor Laor
2012-01-02 16:12       ` Paolo Bonzini
2012-01-02 16:15         ` Christoph Hellwig
2012-01-02 16:18           ` Paolo Bonzini
2012-01-02 16:23             ` Christoph Hellwig
2012-01-02 16:18       ` Christoph Hellwig
2012-01-02 16:21         ` Avi Kivity

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1324429254-28383-7-git-send-email-minchan@kernel.org \
    --to=minchan@kernel.org \
    --cc=axboe@kernel.dk \
    --cc=chrisw@sous-sol.org \
    --cc=hch@infradead.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=minchan@redhat.com \
    --cc=rusty@rustcorp.com.au \
    --cc=stefanha@linux.vnet.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).