All of lore.kernel.org
 help / color / mirror / Atom feed
From: NeilBrown <neilb@suse.de>
To: linux-kernel@vger.kernel.org
Subject: [PATCH 008 of 35] Introduce bi_iocnt to count requests sharing the one bio.
Date: Tue, 31 Jul 2007 12:16:29 +1000	[thread overview]
Message-ID: <1070731021629.25195@suse.de> (raw)
In-Reply-To: 20070731112539.22428.patches@notabene


This count is currently only used by raid5 (which used to use bi_phys_segments),
but it will be used more widely in future.

generic_make_request sets the count to 1, and bio_endio decrements it and
calls bi_end_io only when it hits zero.  A make_request_fn can do whatever
it likes if it doesn't call bio_endio directly.

As some bios do not come through generic_make_request (some are stuck on
the head of the request queue by scsi) we init bi_iocnt in bio_init too.

It now becomes important to call bi_endio exactly the right number of times,
so order_bio_endio can no-longer use it to call flush_dry_bio_endio.
So remove that function and opencode the effect inside ordered_bio_endio.

Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./block/ll_rw_blk.c   |   31 +++++++------------------------
 ./drivers/md/raid5.c  |   30 +++++++++++-------------------
 ./fs/bio.c            |    4 +++-
 ./include/linux/bio.h |    3 +++
 4 files changed, 24 insertions(+), 44 deletions(-)

diff .prev/block/ll_rw_blk.c ./block/ll_rw_blk.c
--- .prev/block/ll_rw_blk.c	2007-07-31 11:20:51.000000000 +1000
+++ ./block/ll_rw_blk.c	2007-07-31 11:20:52.000000000 +1000
@@ -527,44 +527,25 @@ int blk_do_ordered(struct request_queue 
 	return 1;
 }
 
-static void flush_dry_bio_endio(struct bio *bio, int error)
-{
-
-	/*
-	 * This is dry run, restore bio_sector and size.  We'll finish
-	 * this request again with the original bi_end_io after an
-	 * error occurs or post flush is complete.
-	 */
-
-	/* Reset bio */
-	set_bit(BIO_UPTODATE, &bio->bi_flags);
-}
-
 static int ordered_bio_endio(struct request *rq, struct bio *bio,
 			     int error)
 {
 	struct request_queue *q = rq->q;
-	bio_end_io_t *endio;
-	void *private;
 
 	if (&q->bar_rq != rq)
 		return 0;
 
 	/*
 	 * Okay, this is the barrier request in progress, dry finish it.
+	 *
+	 * We'll finish this request again with the original
+	 * bi_end_io after an error occurs or post flush is complete.
 	 */
+
 	if (error && !q->orderr)
 		q->orderr = error;
 
-	endio = bio->bi_end_io;
-	private = bio->bi_private;
-	bio->bi_end_io = flush_dry_bio_endio;
-	bio->bi_private = q;
-
-	bio_endio(bio, error);
-
-	bio->bi_end_io = endio;
-	bio->bi_private = private;
+	set_bit(BIO_UPTODATE, &bio->bi_flags);
 
 	return 1;
 }
@@ -3149,6 +3130,8 @@ static inline void __generic_make_reques
 	int ret, nr_sectors = bio_sectors(bio);
 	dev_t old_dev;
 
+	atomic_set(&bio->bi_iocnt, 1);
+
 	might_sleep();
 	/* Test device or partition size, when known. */
 	maxsector = bio->bi_bdev->bd_inode->i_size >> 9;

diff .prev/drivers/md/raid5.c ./drivers/md/raid5.c
--- .prev/drivers/md/raid5.c	2007-07-31 11:20:51.000000000 +1000
+++ ./drivers/md/raid5.c	2007-07-31 11:20:52.000000000 +1000
@@ -851,7 +851,7 @@ static void ops_complete_biofill(void *s
 				dev_q->sector + STRIPE_SECTORS) {
 				rbi2 = r5_next_bio(rbi, dev_q->sector);
 				spin_lock_irq(&conf->device_lock);
-				if (--rbi->bi_phys_segments == 0) {
+				if (atomic_dec_and_test(&rbi->bi_iocnt)) {
 					rbi->bi_next = return_bi;
 					return_bi = rbi;
 				}
@@ -2294,7 +2294,7 @@ static int add_queue_bio(struct stripe_q
 	if (*bip)
 		bi->bi_next = *bip;
 	*bip = bi;
-	bi->bi_phys_segments ++;
+	atomic_inc(&bi->bi_iocnt);
 	spin_unlock_irq(&conf->device_lock);
 	spin_unlock(&sq->lock);
 
@@ -2395,7 +2395,7 @@ handle_requests_to_failed_array(raid5_co
 			sq->dev[i].sector + STRIPE_SECTORS) {
 			struct bio *nextbi = r5_next_bio(bi, sq->dev[i].sector);
 			clear_bit(BIO_UPTODATE, &bi->bi_flags);
-			if (--bi->bi_phys_segments == 0) {
+			if (atomic_dec_and_test(&bi->bi_iocnt)) {
 				md_write_end(conf->mddev);
 				bi->bi_next = *return_bi;
 				*return_bi = bi;
@@ -2410,7 +2410,7 @@ handle_requests_to_failed_array(raid5_co
 		       sq->dev[i].sector + STRIPE_SECTORS) {
 			struct bio *bi2 = r5_next_bio(bi, sq->dev[i].sector);
 			clear_bit(BIO_UPTODATE, &bi->bi_flags);
-			if (--bi->bi_phys_segments == 0) {
+			if (atomic_dec_and_test(&bi->bi_iocnt)) {
 				md_write_end(conf->mddev);
 				bi->bi_next = *return_bi;
 				*return_bi = bi;
@@ -2435,7 +2435,7 @@ handle_requests_to_failed_array(raid5_co
 				struct bio *nextbi =
 					r5_next_bio(bi, sq->dev[i].sector);
 				clear_bit(BIO_UPTODATE, &bi->bi_flags);
-				if (--bi->bi_phys_segments == 0) {
+				if (atomic_dec_and_test(&bi->bi_iocnt)) {
 					bi->bi_next = *return_bi;
 					*return_bi = bi;
 				}
@@ -2640,7 +2640,7 @@ static void handle_completed_write_reque
 				while (wbi && wbi->bi_sector <
 					dev_q->sector + STRIPE_SECTORS) {
 					wbi2 = r5_next_bio(wbi, dev_q->sector);
-					if (--wbi->bi_phys_segments == 0) {
+					if (atomic_dec_and_test(&wbi->bi_iocnt)) {
 						md_write_end(conf->mddev);
 						wbi->bi_next = *return_bi;
 						*return_bi = wbi;
@@ -3426,7 +3426,7 @@ static void handle_stripe6(struct stripe
 				copy_data(0, rbi, dev->page, dev_q->sector);
 				rbi2 = r5_next_bio(rbi, dev_q->sector);
 				spin_lock_irq(&conf->device_lock);
-				if (--rbi->bi_phys_segments == 0) {
+				if (atomic_dec_and_test(&rbi->bi_iocnt)) {
 					rbi->bi_next = return_bi;
 					return_bi = rbi;
 				}
@@ -3870,7 +3870,7 @@ static struct bio *remove_bio_from_retry
 	if(bi) {
 		conf->retry_read_aligned_list = bi->bi_next;
 		bi->bi_next = NULL;
-		bi->bi_phys_segments = 1; /* biased count of active stripes */
+		atomic_set(&bi->bi_iocnt, 1);
 		bi->bi_hw_segments = 0; /* count of processed stripes */
 	}
 
@@ -4014,7 +4014,6 @@ static int make_request(struct request_q
 	sector_t logical_sector, last_sector;
 	struct stripe_queue *sq;
 	const int rw = bio_data_dir(bi);
-	int remaining;
 
 	if (unlikely(bio_barrier(bi))) {
 		bio_endio(bi, -EOPNOTSUPP);
@@ -4034,7 +4033,7 @@ static int make_request(struct request_q
 	logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
 	last_sector = bi->bi_sector + (bi->bi_size>>9);
 	bi->bi_next = NULL;
-	bi->bi_phys_segments = 1;	/* over-loaded to count active stripes */
+	atomic_set(&bi->bi_iocnt, 1);
 
 	for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
 		DEFINE_WAIT(w);
@@ -4131,10 +4130,7 @@ static int make_request(struct request_q
 		}
 			
 	}
-	spin_lock_irq(&conf->device_lock);
-	remaining = --bi->bi_phys_segments;
-	spin_unlock_irq(&conf->device_lock);
-	if (remaining == 0) {
+	if (atomic_dec_and_test(&bi->bi_iocnt)) {
 
 		if ( rw == WRITE )
 			md_write_end(mddev);
@@ -4408,7 +4404,6 @@ static int  retry_aligned_read(raid5_con
 	int dd_idx, pd_idx;
 	sector_t sector, logical_sector, last_sector;
 	int scnt = 0;
-	int remaining;
 	int handled = 0;
 	int disks = conf->raid_disks;
 	int data_disks = disks - conf->max_degraded;
@@ -4455,10 +4450,7 @@ static int  retry_aligned_read(raid5_con
 		handle_queue(sq, disks, data_disks);
 		handled++;
 	}
-	spin_lock_irq(&conf->device_lock);
-	remaining = --raid_bio->bi_phys_segments;
-	spin_unlock_irq(&conf->device_lock);
-	if (remaining == 0) {
+	if (atomic_dec_and_test(&raid_bio->bi_iocnt)) {
 
 		raid_bio->bi_end_io(raid_bio,
 			      test_bit(BIO_UPTODATE, &raid_bio->bi_flags)

diff .prev/fs/bio.c ./fs/bio.c
--- .prev/fs/bio.c	2007-07-31 11:20:51.000000000 +1000
+++ ./fs/bio.c	2007-07-31 11:20:52.000000000 +1000
@@ -141,6 +141,7 @@ void bio_init(struct bio *bio)
 	bio->bi_max_vecs = 0;
 	bio->bi_end_io = NULL;
 	atomic_set(&bio->bi_cnt, 1);
+	atomic_set(&bio->bi_iocnt, 1);
 	bio->bi_private = NULL;
 }
 
@@ -1013,7 +1014,8 @@ void bio_endio(struct bio *bio, int erro
 	if (error)
 		clear_bit(BIO_UPTODATE, &bio->bi_flags);
 
-	if (bio->bi_end_io)
+	if (atomic_dec_and_test(&bio->bi_iocnt) &&
+	    bio->bi_end_io)
 		bio->bi_end_io(bio, error);
 }
 

diff .prev/include/linux/bio.h ./include/linux/bio.h
--- .prev/include/linux/bio.h	2007-07-31 11:20:51.000000000 +1000
+++ ./include/linux/bio.h	2007-07-31 11:20:52.000000000 +1000
@@ -108,6 +108,9 @@ struct bio {
 
 	bio_end_io_t		*bi_end_io;
 	atomic_t		bi_cnt;		/* pin count */
+	atomic_t		bi_iocnt;	/* number of io requests
+						 * referring to this bio
+						 */
 
 	void			*bi_private;
 

  parent reply	other threads:[~2007-07-31  2:20 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-07-31  2:15 [PATCH 000 of 35] Refactor block layer to improve support for stacked devices NeilBrown
2007-07-31  2:15 ` [PATCH 001 of 35] Replace bio_data with blk_rq_data NeilBrown
2007-07-31  2:15 ` [PATCH 002 of 35] Replace bio_cur_sectors with blk_rq_cur_sectors NeilBrown
2007-07-31  2:16 ` [PATCH 003 of 35] Introduce rq_for_each_segment replacing rq_for_each_bio NeilBrown
2007-07-31  2:16 ` [PATCH 004 of 35] Merge blk_recount_segments into blk_recalc_rq_segments NeilBrown
2007-07-31  2:16 ` [PATCH 005 of 35] Stop updating bi_idx, bv_len, bv_offset when a request completes NeilBrown
2007-08-01 14:54   ` Tejun Heo
2007-07-31  2:16 ` [PATCH 006 of 35] Only call bi_end_io once for any bio NeilBrown
2007-07-31  2:16 ` [PATCH 007 of 35] Drop 'size' argument from bio_endio and bi_end_io NeilBrown
2007-08-01 15:17   ` Tejun Heo
2007-07-31  2:16 ` NeilBrown [this message]
2007-08-01 15:49   ` [PATCH 008 of 35] Introduce bi_iocnt to count requests sharing the one bio Tejun Heo
2007-07-31  2:16 ` [PATCH 009 of 35] Remove overloading of bi_hw_segments in raid5 NeilBrown
2007-07-31  2:16 ` [PATCH 010 of 35] New function blk_req_append_bio NeilBrown
2007-08-01 15:54   ` Christoph Hellwig
2007-07-31  2:16 ` [PATCH 011 of 35] Stop exporting blk_rq_bio_prep NeilBrown
2007-07-31  2:16 ` [PATCH 012 of 35] Share code between init_request_from_bio and blk_rq_bio_prep NeilBrown
2007-07-31  2:16 ` [PATCH 013 of 35] Don't update bi_hw_*_size if we aren't going to merge NeilBrown
2007-08-01 15:57   ` Tejun Heo
2007-08-02  3:37     ` Neil Brown
2007-07-31  2:17 ` [PATCH 014 of 35] Change blk_phys/hw_contig_segment to take requests, not bios NeilBrown
2007-07-31  2:17 ` [PATCH 015 of 35] Move hw_front_size and hw_back_size from bio to request NeilBrown
2007-07-31  2:17 ` [PATCH 016 of 35] Centralise setting for REQ_NOMERGE NeilBrown
2007-07-31  2:17 ` [PATCH 017 of 35] Fix various abuse of bio fields in umem.c NeilBrown
2007-07-31  2:17 ` [PATCH 018 of 35] Remove bi_idx NeilBrown
2007-07-31  2:17 ` [PATCH 019 of 35] Convert bio_for_each_segment to fill in a fresh bio_vec NeilBrown
2007-08-01 16:21   ` Tejun Heo
2007-07-31  2:17 ` [PATCH 020 of 35] Add bi_offset and allow a bio to reference only part of a bi_io_vec NeilBrown
2007-07-31  2:17 ` [PATCH 021 of 35] Teach umem.c about bi_offset and to limit to bi_size NeilBrown
2007-07-31  2:17 ` [PATCH 022 of 35] Teach dm-crypt to honour bi_offset and bi_size NeilBrown
2007-07-31  2:17 ` [PATCH 023 of 35] Teach pktcdvd.c " NeilBrown
2007-07-31  2:17 ` [PATCH 024 of 35] Allow request bio list not to end with NULL NeilBrown
2007-07-31  2:17 ` [PATCH 025 of 35] Treat rq->hard_nr_sectors as setting an overriding limit in the size of the request NeilBrown
2007-08-01 17:44   ` Tejun Heo
2007-08-02  3:31     ` Neil Brown
2007-08-02  5:03       ` Tejun Heo
2007-07-31  2:18 ` [PATCH 026 of 35] Split any large bios that arrive at __make_request NeilBrown
2007-08-01 17:56   ` Tejun Heo
2007-08-02  0:49     ` Neil Brown
2007-08-02  2:59       ` Tejun Heo
2007-08-02  3:16         ` Neil Brown
2007-07-31  2:18 ` [PATCH 028 of 35] Split arbitrarily large requests to md/raid0 and md/linear NeilBrown
2007-07-31  2:18 ` [PATCH 029 of 35] Teach md/raid10 to split arbitrarily large bios NeilBrown
2007-07-31  2:18 ` [PATCH 030 of 35] Teach raid5 to split incoming bios NeilBrown
2007-07-31  2:18 ` [PATCH 031 of 35] Use bio_multi_split to fully split bios for pktcdvd NeilBrown
2007-07-31  2:18 ` [PATCH 032 of 35] Remove blk_queue_merge_bvec and bio_split and related code NeilBrown
2007-07-31  2:18 ` [PATCH 033 of 35] Simplify stacking of IO restrictions NeilBrown
2007-07-31  2:18 ` [PATCH 034 of 35] Simplify bio_add_page and raid1/raid10 resync which use it NeilBrown
2007-07-31  2:18 ` [PATCH 035 of 35] Simplify bio splitting in dm NeilBrown
2007-07-31 15:28 ` [PATCH 000 of 35] Refactor block layer to improve support for stacked devices Avi Kivity
2007-08-01 14:37   ` Tejun Heo
2007-08-01 15:52     ` John Stoffel
2007-08-01 15:59       ` Tejun Heo
2007-08-02  3:43       ` Neil Brown

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=1070731021629.25195@suse.de \
    --to=neilb@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.