All of lore.kernel.org
 help / color / mirror / Atom feed
From: NeilBrown <neilb@suse.de>
To: linux-raid@vger.kernel.org
Subject: [md PATCH 15/16] md/raid1: clear bad-block record when write succeeds.
Date: Mon, 07 Jun 2010 10:07:56 +1000	[thread overview]
Message-ID: <20100607000756.13302.33760.stgit@notabene.brown> (raw)
In-Reply-To: <20100606235833.13302.60932.stgit@notabene.brown>

If we succeed in writing to a block that was recorded as
being bad, we clear the bad-block record.

This requires some delayed handling as the bad-block-list update has
to happen in process-context.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/raid1.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++------
 drivers/md/raid1.h |   13 +++++++++++-
 2 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index d240d58..e23ec40 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -175,7 +175,7 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
 
 	for (i = 0; i < conf->raid_disks; i++) {
 		struct bio **bio = r1_bio->bios + i;
-		if (*bio && *bio != IO_BLOCKED)
+		if (!BIO_SPECIAL(*bio))
 			bio_put(*bio);
 		*bio = NULL;
 	}
@@ -348,7 +348,7 @@ static void raid1_end_write_request(struct bio *bio, int error)
 			md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
 			/* an I/O failed, we can't clear the bitmap */
 			set_bit(R1BIO_Degraded, &r1_bio->state);
-		} else
+		} else {
 			/*
 			 * Set R1BIO_Uptodate in our master bio, so that
 			 * we will return a good error code for to the higher
@@ -360,6 +360,15 @@ static void raid1_end_write_request(struct bio *bio, int error)
 			 */
 			set_bit(R1BIO_Uptodate, &r1_bio->state);
 
+			/* Maybe we can clear some bad blocks. */
+			if (is_badblock(conf->mirrors[mirror].rdev,
+					r1_bio->sector, r1_bio->sectors,
+					NULL, NULL)) {
+				r1_bio->bios[mirror] = IO_MADE_GOOD;
+				set_bit(R1BIO_MadeGood, &r1_bio->state);
+			}
+		}
+
 		update_head_pos(mirror, r1_bio);
 
 		if (behind) {
@@ -384,7 +393,9 @@ static void raid1_end_write_request(struct bio *bio, int error)
 				}
 			}
 		}
-		rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
+		if (r1_bio->bios[mirror] == NULL)
+			rdev_dec_pending(conf->mirrors[mirror].rdev,
+					 conf->mddev);
 	}
 	/*
 	 *
@@ -408,7 +419,10 @@ static void raid1_end_write_request(struct bio *bio, int error)
 					!test_bit(R1BIO_Degraded, &r1_bio->state),
 					behind);
 			md_write_end(r1_bio->mddev);
-			raid_end_bio_io(r1_bio);
+			if (test_bit(R1BIO_MadeGood, &r1_bio->state))
+				reschedule_retry(r1_bio);
+			else
+				raid_end_bio_io(r1_bio);
 		}
 	}
 
@@ -1451,7 +1465,11 @@ static void end_sync_write(struct bio *bio, int error)
 			sectors_to_go -= sync_blocks;
 		} while (sectors_to_go > 0);
 		md_error(mddev, conf->mirrors[mirror].rdev);
-	}
+	} else if (is_badblock(conf->mirrors[mirror].rdev,
+			       r1_bio->sector,
+			       r1_bio->sectors,
+			       NULL, NULL))
+		set_bit(R1BIO_MadeGood, &r1_bio->state);
 
 	update_head_pos(mirror, r1_bio);
 
@@ -1812,8 +1830,34 @@ static void raid1d(mddev_t *mddev)
 		mddev = r1_bio->mddev;
 		conf = mddev->private;
 		if (test_bit(R1BIO_IsSync, &r1_bio->state)) {
-			sync_request_write(mddev, r1_bio);
-			unplug = 1;
+			if (test_bit(R1BIO_MadeGood, &r1_bio->state)) {
+				int m;
+				for (m = 0; m < conf->raid_disks ; m++)
+					if (!BIO_SPECIAL(r1_bio->bios[m]) &&
+					    test_bit(BIO_UPTODATE,
+						     &r1_bio->bios[m]->bi_flags)) {
+						md_clear_badblocks(
+							&conf->mirrors[m].rdev->badblocks,
+							r1_bio->sector,
+							r1_bio->sectors);
+					}
+				put_buf(r1_bio);
+			} else {
+				sync_request_write(mddev, r1_bio);
+				unplug = 1;
+			}
+		} else if (test_bit(R1BIO_MadeGood, &r1_bio->state)) {
+			int m;
+			for (m = 0; m < conf->raid_disks ; m++)
+				if (r1_bio->bios[m] == IO_MADE_GOOD) {
+					md_clear_badblocks(
+						&conf->mirrors[m].rdev->badblocks,
+						r1_bio->sector,
+						r1_bio->sectors);
+					rdev_dec_pending(conf->mirrors[m].rdev,
+							 mddev);
+				}
+			raid_end_bio_io(r1_bio);
 		} else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) {
 			/* some requests in the r1bio were BIO_RW_BARRIER
 			 * requests which failed with -EOPNOTSUPP.  Hohumm..
diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h
index 5f2d443..c91c736 100644
--- a/drivers/md/raid1.h
+++ b/drivers/md/raid1.h
@@ -110,7 +110,14 @@ struct r1bio_s {
  * correct the read error.  To keep track of bad blocks on a per-bio
  * level, we store IO_BLOCKED in the appropriate 'bios' pointer
  */
-#define IO_BLOCKED ((struct bio*)1)
+#define IO_BLOCKED ((struct bio *)1)
+/* When we successfully write to a known bad-block, we need to remove the
+ * bad-block marking which must be done from process context.  So we record
+ * the success by setting bios[n] to IO_MADE_GOOD
+ */
+#define IO_MADE_GOOD ((struct bio *)2)
+
+#define BIO_SPECIAL(bio) ((unsigned long)bio <= 2)
 
 /* bits for r1bio.state */
 #define	R1BIO_Uptodate	0
@@ -127,5 +134,9 @@ struct r1bio_s {
  * Record that bi_end_io was called with this flag...
  */
 #define	R1BIO_Returned 6
+/* If a write for this request means we can clear some
+ * known-bad-block records, we set this flag
+ */
+#define R1BIO_MadeGood 7
 
 #endif



  parent reply	other threads:[~2010-06-07  0:07 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-06-07  0:07 [md PATCH 00/16] bad block list management for md and RAID1 NeilBrown
2010-06-07  0:07 ` [md PATCH 01/16] md: beginnings of bad block management NeilBrown
2010-06-07  0:07 ` [md PATCH 02/16] md/bad-block-log: add sysfs interface for accessing bad-block-log NeilBrown
2010-06-07  0:07 ` [md PATCH 05/16] md: reject devices with bad blocks and v0.90 metadata NeilBrown
2010-06-07  0:07 ` [md PATCH 04/16] md: load/store badblock list from v1.x metadata NeilBrown
2010-06-07  0:07 ` [md PATCH 06/16] md/raid1: clean up read_balance NeilBrown
2010-06-07  0:07 ` [md PATCH 07/16] md: simplify raid10 read_balance NeilBrown
2010-06-07  0:07 ` [md PATCH 03/16] md: don't allow arrays to contain devices with bad blocks NeilBrown
2010-06-07  0:07 ` [md PATCH 12/16] md: make error_handler functions more uniform and correct NeilBrown
2010-06-07  0:07 ` [md PATCH 10/16] md: add 'write_error' flag to component devices NeilBrown
2010-06-07  0:07 ` [md PATCH 11/16] md/multipath: discard ->working_disks in favour of ->degraded NeilBrown
2010-06-07  0:07 ` [md PATCH 08/16] md/raid1: avoid reading from known bad blocks NeilBrown
2010-06-07  0:07 ` [md PATCH 09/16] md/raid1: avoid reading known bad blocks during resync NeilBrown
2010-06-07  0:07 ` NeilBrown [this message]
2010-06-07  0:07 ` [md PATCH 16/16] md/raid1: Handle write errors by updating badblock log NeilBrown
2010-06-07  0:07 ` [md PATCH 13/16] md: make it easier to wait for bad blocks to be acknowledged NeilBrown
2010-06-07  0:07 ` [md PATCH 14/16] md/raid1: avoid writing to known-bad blocks on known-bad drives NeilBrown
2010-06-07  0:28 ` [md PATCH 00/16] bad block list management for md and RAID1 Berkey B Walker
2010-06-07 22:18   ` Stefan /*St0fF*/ Hübner
2010-06-17 12:48 ` Brett Russ
2010-06-17 15:53   ` Graham Mitchell
2010-06-18  3:58     ` Neil Brown
2010-06-18  4:30       ` Graham Mitchell
2010-06-18  3:23   ` Neil Brown
     [not found]     ` <4C1BABC4.3020008@tmr.com>
2010-06-29  5:06       ` Neil Brown
2010-06-29 16:54         ` Bill Davidsen

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=20100607000756.13302.33760.stgit@notabene.brown \
    --to=neilb@suse.de \
    --cc=linux-raid@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.