linux-raid.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [md PATCH 0/3] reshape bug fixes for 2.6.30
@ 2009-06-09  6:39 NeilBrown
  2009-06-09  6:39 ` [md PATCH 3/3] md/raid5: fix bug in reshape code when chunk_size decreases NeilBrown
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: NeilBrown @ 2009-06-09  6:39 UTC (permalink / raw)
  To: linux-raid

Hi,
 just for general information and review, I've nearly got
 mdadm to request and manage the new reshape modes and testing
 has revealed a few bugs in the kernel.
 So the following three are off to Linus shortly, hopefully in
 time for 2.6.30.

NeilBrown


---

NeilBrown (3):
      md/raid5: fix bug in reshape code when chunk_size decreases.
      md/raid5 - avoid deadlocks in get_active_stripe during reshape
      md/raid5: use conf->raid_disks in preference to mddev->raid_disk


 drivers/md/raid5.c |   28 ++++++++++++++--------------
 1 files changed, 14 insertions(+), 14 deletions(-)

-- 


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [md PATCH 1/3] md/raid5: use conf->raid_disks in preference to mddev->raid_disk
  2009-06-09  6:39 [md PATCH 0/3] reshape bug fixes for 2.6.30 NeilBrown
  2009-06-09  6:39 ` [md PATCH 3/3] md/raid5: fix bug in reshape code when chunk_size decreases NeilBrown
@ 2009-06-09  6:39 ` NeilBrown
  2009-06-09  6:39 ` [md PATCH 2/3] md/raid5 - avoid deadlocks in get_active_stripe during reshape NeilBrown
  2 siblings, 0 replies; 4+ messages in thread
From: NeilBrown @ 2009-06-09  6:39 UTC (permalink / raw)
  To: linux-raid; +Cc: NeilBrown

mddev->raid_disks can be changed and any time by a request from
user-space.  It is a suggestion as to what number of raid_disks is
desired.

conf->raid_disks can only be changed by the raid5 module with suitable
locks in place.  It is a statement as to the current number of
raid_disks.

There are two places where the latter should be used, but the former
is used.  This can lead to a crash when reshaping an array.

This patch changes to mddev-> to conf->

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

 drivers/md/raid5.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 5d400ae..75469e6 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3288,7 +3288,7 @@ static void unplug_slaves(mddev_t *mddev)
 	int i;
 
 	rcu_read_lock();
-	for (i=0; i<mddev->raid_disks; i++) {
+	for (i = 0; i < conf->raid_disks; i++) {
 		mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
 		if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) {
 			struct request_queue *r_queue = bdev_get_queue(rdev->bdev);
@@ -4034,7 +4034,7 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski
 	 * We don't need to check the 'failed' flag as when that gets set,
 	 * recovery aborts.
 	 */
-	for (i=0; i<mddev->raid_disks; i++)
+	for (i = 0; i < conf->raid_disks; i++)
 		if (conf->disks[i].rdev == NULL)
 			still_degraded = 1;
 



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [md PATCH 2/3] md/raid5 - avoid deadlocks in get_active_stripe during reshape
  2009-06-09  6:39 [md PATCH 0/3] reshape bug fixes for 2.6.30 NeilBrown
  2009-06-09  6:39 ` [md PATCH 3/3] md/raid5: fix bug in reshape code when chunk_size decreases NeilBrown
  2009-06-09  6:39 ` [md PATCH 1/3] md/raid5: use conf->raid_disks in preference to mddev->raid_disk NeilBrown
@ 2009-06-09  6:39 ` NeilBrown
  2 siblings, 0 replies; 4+ messages in thread
From: NeilBrown @ 2009-06-09  6:39 UTC (permalink / raw)
  To: linux-raid; +Cc: NeilBrown

md has functionality to 'quiesce' and array so that all pending
IO completed and no new IO starts.  This is used to achieve a
stable state before making internal changes.

Currently this quiescing applies equally to normal IO, resync
IO, and reshape IO.
However there is a problem with applying it to reshape IO.
Reshape can have multiple 'stripe_heads' that must be active together.
If the quiesce come between allocating the first and the last of
such a collection, then we deadlock, as the last will not be allocated
until the quiesce is lifted, the quiesce will not be lifted until the
first (which has been allocated) gets used, and that first cannot be
used until the last is allocated.

It is not necessary to inhibit reshape IO when a quiesce is
requested.  Those places in the code that require a full quiesce will
ensure the reshape thread is not running at all.

So allow reshape requests to get access to new stripe_heads without
being blocked by a 'quiesce'.

This only affects in-place reshapes (i.e. where the array does not
grow or shrink) and these are only newly supported.  So this patch is
not needed in earlier kernels.

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

 drivers/md/raid5.c |   22 +++++++++++-----------
 1 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 75469e6..59f2ec0 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -362,7 +362,7 @@ static void raid5_unplug_device(struct request_queue *q);
 
 static struct stripe_head *
 get_active_stripe(raid5_conf_t *conf, sector_t sector,
-		  int previous, int noblock)
+		  int previous, int noblock, int noquiesce)
 {
 	struct stripe_head *sh;
 
@@ -372,7 +372,7 @@ get_active_stripe(raid5_conf_t *conf, sector_t sector,
 
 	do {
 		wait_event_lock_irq(conf->wait_for_stripe,
-				    conf->quiesce == 0,
+				    conf->quiesce == 0 || noquiesce,
 				    conf->device_lock, /* nothing */);
 		sh = __find_stripe(conf, sector, conf->generation - previous);
 		if (!sh) {
@@ -2671,7 +2671,7 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh,
 			sector_t bn = compute_blocknr(sh, i, 1);
 			sector_t s = raid5_compute_sector(conf, bn, 0,
 							  &dd_idx, NULL);
-			sh2 = get_active_stripe(conf, s, 0, 1);
+			sh2 = get_active_stripe(conf, s, 0, 1, 1);
 			if (sh2 == NULL)
 				/* so far only the early blocks of this stripe
 				 * have been requested.  When later blocks
@@ -2944,7 +2944,7 @@ static bool handle_stripe5(struct stripe_head *sh)
 	/* Finish reconstruct operations initiated by the expansion process */
 	if (sh->reconstruct_state == reconstruct_state_result) {
 		struct stripe_head *sh2
-			= get_active_stripe(conf, sh->sector, 1, 1);
+			= get_active_stripe(conf, sh->sector, 1, 1, 1);
 		if (sh2 && test_bit(STRIPE_EXPAND_SOURCE, &sh2->state)) {
 			/* sh cannot be written until sh2 has been read.
 			 * so arrange for sh to be delayed a little
@@ -3189,7 +3189,7 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
 
 	if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
 		struct stripe_head *sh2
-			= get_active_stripe(conf, sh->sector, 1, 1);
+			= get_active_stripe(conf, sh->sector, 1, 1, 1);
 		if (sh2 && test_bit(STRIPE_EXPAND_SOURCE, &sh2->state)) {
 			/* sh cannot be written until sh2 has been read.
 			 * so arrange for sh to be delayed a little
@@ -3675,7 +3675,7 @@ static int make_request(struct request_queue *q, struct bio * bi)
 			(unsigned long long)logical_sector);
 
 		sh = get_active_stripe(conf, new_sector, previous,
-				       (bi->bi_rw&RWA_MASK));
+				       (bi->bi_rw&RWA_MASK), 0);
 		if (sh) {
 			if (unlikely(previous)) {
 				/* expansion might have moved on while waiting for a
@@ -3873,7 +3873,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
 	for (i = 0; i < reshape_sectors; i += STRIPE_SECTORS) {
 		int j;
 		int skipped = 0;
-		sh = get_active_stripe(conf, stripe_addr+i, 0, 0);
+		sh = get_active_stripe(conf, stripe_addr+i, 0, 0, 1);
 		set_bit(STRIPE_EXPANDING, &sh->state);
 		atomic_inc(&conf->reshape_stripes);
 		/* If any of this stripe is beyond the end of the old
@@ -3922,7 +3922,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
 	if (last_sector >= mddev->dev_sectors)
 		last_sector = mddev->dev_sectors - 1;
 	while (first_sector <= last_sector) {
-		sh = get_active_stripe(conf, first_sector, 1, 0);
+		sh = get_active_stripe(conf, first_sector, 1, 0, 1);
 		set_bit(STRIPE_EXPAND_SOURCE, &sh->state);
 		set_bit(STRIPE_HANDLE, &sh->state);
 		release_stripe(sh);
@@ -4022,9 +4022,9 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski
 
 	bitmap_cond_end_sync(mddev->bitmap, sector_nr);
 
-	sh = get_active_stripe(conf, sector_nr, 0, 1);
+	sh = get_active_stripe(conf, sector_nr, 0, 1, 0);
 	if (sh == NULL) {
-		sh = get_active_stripe(conf, sector_nr, 0, 0);
+		sh = get_active_stripe(conf, sector_nr, 0, 0, 0);
 		/* make sure we don't swamp the stripe cache if someone else
 		 * is trying to get access
 		 */
@@ -4086,7 +4086,7 @@ static int  retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
 			/* already done this stripe */
 			continue;
 
-		sh = get_active_stripe(conf, sector, 0, 1);
+		sh = get_active_stripe(conf, sector, 0, 1, 0);
 
 		if (!sh) {
 			/* failed to get a stripe - must wait */



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [md PATCH 3/3] md/raid5: fix bug in reshape code when chunk_size decreases.
  2009-06-09  6:39 [md PATCH 0/3] reshape bug fixes for 2.6.30 NeilBrown
@ 2009-06-09  6:39 ` NeilBrown
  2009-06-09  6:39 ` [md PATCH 1/3] md/raid5: use conf->raid_disks in preference to mddev->raid_disk NeilBrown
  2009-06-09  6:39 ` [md PATCH 2/3] md/raid5 - avoid deadlocks in get_active_stripe during reshape NeilBrown
  2 siblings, 0 replies; 4+ messages in thread
From: NeilBrown @ 2009-06-09  6:39 UTC (permalink / raw)
  To: linux-raid; +Cc: NeilBrown

Now that we support changing the chunksize, we calculate
"reshape_sectors" to be the max of number of sectors in old
and new chunk size.
However there is one please where we still use 'chunksize'
rather than 'reshape_sectors'.
This causes a reshape that reduces the size of chunks to freeze.

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

 drivers/md/raid5.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 59f2ec0..bb37fb1 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3916,7 +3916,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
 		raid5_compute_sector(conf, stripe_addr*(new_data_disks),
 				     1, &dd_idx, NULL);
 	last_sector =
-		raid5_compute_sector(conf, ((stripe_addr+conf->chunk_size/512)
+		raid5_compute_sector(conf, ((stripe_addr+reshape_sectors)
 					    *(new_data_disks) - 1),
 				     1, &dd_idx, NULL);
 	if (last_sector >= mddev->dev_sectors)



^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-06-09  6:39 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-06-09  6:39 [md PATCH 0/3] reshape bug fixes for 2.6.30 NeilBrown
2009-06-09  6:39 ` [md PATCH 3/3] md/raid5: fix bug in reshape code when chunk_size decreases NeilBrown
2009-06-09  6:39 ` [md PATCH 1/3] md/raid5: use conf->raid_disks in preference to mddev->raid_disk NeilBrown
2009-06-09  6:39 ` [md PATCH 2/3] md/raid5 - avoid deadlocks in get_active_stripe during reshape NeilBrown

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).