From patchwork Mon Feb 23 19:23:00 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikulas Patocka X-Patchwork-Id: 8497 X-Patchwork-Delegate: agk@redhat.com Received: from hormel.redhat.com (hormel1.redhat.com [209.132.177.33]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n1NJN6FD030072 for ; Mon, 23 Feb 2009 19:23:06 GMT Received: from listman.util.phx.redhat.com (listman.util.phx.redhat.com [10.8.4.110]) by hormel.redhat.com (Postfix) with ESMTP id 53D56619FB2; Mon, 23 Feb 2009 14:23:05 -0500 (EST) Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by listman.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id n1NJN3wR011755 for ; Mon, 23 Feb 2009 14:23:03 -0500 Received: from hs20-bc2-1.build.redhat.com (hs20-bc2-1.build.redhat.com [10.10.28.34]) by int-mx1.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n1NJN35B030601 for ; Mon, 23 Feb 2009 14:23:03 -0500 Received: from hs20-bc2-1.build.redhat.com (localhost.localdomain [127.0.0.1]) by hs20-bc2-1.build.redhat.com (8.13.1/8.13.1) with ESMTP id n1NJN0UD025527 for ; Mon, 23 Feb 2009 14:23:00 -0500 Received: from localhost (mpatocka@localhost) by hs20-bc2-1.build.redhat.com (8.13.1/8.13.1/Submit) with ESMTP id n1NJN0He025521 for ; Mon, 23 Feb 2009 14:23:00 -0500 X-Authentication-Warning: hs20-bc2-1.build.redhat.com: mpatocka owned process doing -bs Date: Mon, 23 Feb 2009 14:23:00 -0500 (EST) From: Mikulas Patocka X-X-Sender: mpatocka@hs20-bc2-1.build.redhat.com To: dm-devel@redhat.com Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.58 on 172.16.52.254 X-loop: dm-devel@redhat.com Subject: [dm-devel] [PATCH 14/14] barriers X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.5 Precedence: junk Reply-To: device-mapper development List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com Barrier support. Barriers are submitted to a worker thread that issues them in-order. __process_bio functions is modified that when it sees a barrier request, it waits for all pending IO before the request, then submits the barrier and waits for it. DM_ENDIO_REQUEUE doesn't work and I doubt that it can be made work with barriers. Signed-off-by: Mikulas Patocka --- drivers/md/dm.c | 75 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 14 deletions(-) -- dm-devel mailing list dm-devel@redhat.com https://www.redhat.com/mailman/listinfo/dm-devel Index: linux-2.6.29-rc6-devel/drivers/md/dm.c =================================================================== --- linux-2.6.29-rc6-devel.orig/drivers/md/dm.c 2009-02-23 17:55:37.000000000 +0100 +++ linux-2.6.29-rc6-devel/drivers/md/dm.c 2009-02-23 17:55:45.000000000 +0100 @@ -125,6 +125,11 @@ struct mapped_device { spinlock_t deferred_lock; /* + * An error from the barrier request currently being processed. + */ + int barrier_error; + + /* * Processing queue (flush/barriers) */ struct workqueue_struct *wq; @@ -425,6 +430,10 @@ static void end_io_acct(struct dm_io *io part_stat_add(cpu, &dm_disk(md)->part0, ticks[rw], duration); part_stat_unlock(); + /* + * after this is decremented, the bio must not be touched if it is + * barrier bio + */ dm_disk(md)->part0.in_flight = pending = atomic_dec_return(&md->pending); @@ -525,19 +534,29 @@ static void dec_pending(struct dm_io *io */ spin_lock_irqsave(&io->md->deferred_lock, flags); if (__noflush_suspending(io->md)) - bio_list_add(&io->md->deferred, io->bio); + bio_list_add_head(&io->md->deferred, io->bio); else /* noflush suspend was interrupted. */ io->error = -EIO; spin_unlock_irqrestore(&io->md->deferred_lock, flags); } - end_io_acct(io); + if (bio_barrier(io->bio)) { + /* + * There could be just one barrier request, so we use + * per-device variable for error reporting is OK. + * Note that you can't touch the bio after end_io_acct + */ + io->md->barrier_error = io->error; + end_io_acct(io); + } else { + end_io_acct(io); - if (io->error != DM_ENDIO_REQUEUE) { - trace_block_bio_complete(io->md->queue, io->bio); + if (io->error != DM_ENDIO_REQUEUE) { + trace_block_bio_complete(io->md->queue, io->bio); - bio_endio(io->bio, io->error); + bio_endio(io->bio, io->error); + } } free_io(io->md, io); @@ -682,7 +701,7 @@ static struct bio *split_bvec(struct bio clone->bi_sector = sector; clone->bi_bdev = bio->bi_bdev; - clone->bi_rw = bio->bi_rw; + clone->bi_rw = bio->bi_rw & ~(1 << BIO_RW_BARRIER); clone->bi_vcnt = 1; clone->bi_size = to_bytes(len); clone->bi_io_vec->bv_offset = offset; @@ -703,6 +722,7 @@ static struct bio *clone_bio(struct bio clone = bio_alloc_bioset(GFP_NOIO, bio->bi_max_vecs, bs); __bio_clone(clone, bio); + clone->bi_rw &= ~(1 << BIO_RW_BARRIER); clone->bi_destructor = dm_bio_destructor; clone->bi_sector = sector; clone->bi_idx = idx; @@ -823,7 +843,10 @@ static void __process_bio(struct mapped_ ci.map = dm_get_table(md); if (unlikely(!ci.map)) { - bio_io_error(bio); + if (!bio_barrier(bio)) + bio_io_error(bio); + else + md->barrier_error = -EIO; return; } @@ -911,11 +934,6 @@ static int dm_request(struct request_que * There is no use in forwarding any barrier request since we can't * guarantee it is (or can be) handled by the targets correctly. */ - if (unlikely(bio_barrier(bio))) { - bio_endio(bio, -EOPNOTSUPP); - return 0; - } - down_read(&md->io_lock); cpu = part_stat_lock(); @@ -927,7 +945,8 @@ static int dm_request(struct request_que * If we're suspended we have to queue * this io for later. */ - if (unlikely(test_bit(DMF_BLOCK_IO, &md->flags))) { + if (unlikely(test_bit(DMF_BLOCK_IO, &md->flags)) || + unlikely(bio_barrier(bio))) { up_read(&md->io_lock); if (unlikely(test_bit(DMF_BLOCK_FOR_SUSPEND, &md->flags)) && @@ -1392,6 +1411,12 @@ static int dm_wait_for_completion(struct return r; } +static int dm_flush(struct mapped_device *md) +{ + dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE); + return 0; +} + /* * Process the deferred bios */ @@ -1413,8 +1438,30 @@ static void dm_wq_work(struct work_struc } up_write(&md->io_lock); - __process_bio(md, c); + if (!bio_barrier(c)) + __process_bio(md, c); + else { + int error = dm_flush(md); + if (unlikely(error)) { + bio_endio(c, error); + goto next_bio; + } + if (bio_empty_barrier(c)) { + bio_endio(c, 0); + goto next_bio; + } + + __process_bio(md, c); + + error = dm_flush(md); + if (!error && md->barrier_error) + error = md->barrier_error; + + if (md->barrier_error != DM_ENDIO_REQUEUE) + bio_endio(c, error); + } +next_bio: down_write(&md->io_lock); }