Linux RAID subsystem development
 help / color / mirror / Atom feed
* [PATCH] md - 3 of 8 - Allow an md personality to refuse a hot-remove request.
  2004-05-28  6:45 [PATCH] md - 0 of 8 - Introduction NeilBrown
                   ` (3 preceding siblings ...)
  2004-05-28  6:45 ` [PATCH] md - 8 of 8 - Support reshaping raid1 arrays - adding or removing drives NeilBrown
@ 2004-05-28  6:45 ` NeilBrown
  2004-05-28 18:35   ` 3ware 7506-8 and Tyan Thunder 2500, S1867, anyone? buggz
  2004-05-28  6:45 ` [PATCH] md - 1 of 8 - Rationalise device selection in md/multipath NeilBrown
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 14+ messages in thread
From: NeilBrown @ 2004-05-28  6:45 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-raid


This isn't really needed at the moment, but it is more consistant
with the interface and may be needed later.

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>

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

diff ./drivers/md/md.c~current~ ./drivers/md/md.c
--- ./drivers/md/md.c~current~	2004-05-28 15:48:47.000000000 +1000
+++ ./drivers/md/md.c	2004-05-28 15:48:47.000000000 +1000
@@ -3478,8 +3478,8 @@ void md_check_recovery(mddev_t *mddev)
 			if (rdev->raid_disk >= 0 &&
 			    rdev->faulty &&
 			    atomic_read(&rdev->nr_pending)==0) {
-				mddev->pers->hot_remove_disk(mddev, rdev->raid_disk);
-				rdev->raid_disk = -1;
+				if (mddev->pers->hot_remove_disk(mddev, rdev->raid_disk)==0)
+					rdev->raid_disk = -1;
 			}
 			if (!rdev->faulty && rdev->raid_disk >= 0 && !rdev->in_sync)
 				spares++;

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

* [PATCH] md - 4 of 8 - Make sure the size of a raid5/6 array is a multiple of the chunk size.
  2004-05-28  6:45 [PATCH] md - 0 of 8 - Introduction NeilBrown
  2004-05-28  6:45 ` [PATCH] md - 2 of 8 - Make sure md_check_recovery will remove a faulty device when ->nr_pending hits 0 NeilBrown
  2004-05-28  6:45 ` [PATCH] md - 6 of 8 - Abort the resync of raid1 there is only one device NeilBrown
@ 2004-05-28  6:45 ` NeilBrown
  2004-05-28  6:45 ` [PATCH] md - 8 of 8 - Support reshaping raid1 arrays - adding or removing drives NeilBrown
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: NeilBrown @ 2004-05-28  6:45 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-raid


Normally the size is chosen as a multiple of the chunk size,
but if the size is explicitly chosen, it might not be.
So we force it.

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>

 ----------- Diffstat output ------------
 ./drivers/md/raid5.c     |    3 +++
 ./drivers/md/raid6main.c |    3 +++
 2 files changed, 6 insertions(+)

diff ./drivers/md/raid5.c~current~ ./drivers/md/raid5.c
--- ./drivers/md/raid5.c~current~	2004-05-28 15:48:33.000000000 +1000
+++ ./drivers/md/raid5.c	2004-05-28 15:48:55.000000000 +1000
@@ -1611,6 +1611,9 @@ static int run (mddev_t *mddev)
 	conf->algorithm = mddev->layout;
 	conf->max_nr_stripes = NR_STRIPES;
 
+	/* device size must be a multiple of chunk size */
+	mddev->size &= ~(mddev->chunk_size/1024 -1);
+
 	if (!conf->chunk_size || conf->chunk_size % 4) {
 		printk(KERN_ERR "raid5: invalid chunk size %d for %s\n",
 			conf->chunk_size, mdname(mddev));

diff ./drivers/md/raid6main.c~current~ ./drivers/md/raid6main.c
--- ./drivers/md/raid6main.c~current~	2004-05-28 15:48:33.000000000 +1000
+++ ./drivers/md/raid6main.c	2004-05-28 15:48:55.000000000 +1000
@@ -1775,6 +1775,9 @@ static int run (mddev_t *mddev)
 	conf->algorithm = mddev->layout;
 	conf->max_nr_stripes = NR_STRIPES;
 
+	/* device size must be a multiple of chunk size */
+	mddev->size &= ~(mddev->chunk_size/1024 -1);
+
 	if (conf->raid_disks < 4) {
 		printk(KERN_ERR "raid6: not enough configured devices for %s (%d, minimum 4)\n",
 		       mdname(mddev), conf->raid_disks);

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

* [PATCH] md - 5 of 8 - Handle hot-add for arrays with non-persistent superblocks
  2004-05-28  6:45 [PATCH] md - 0 of 8 - Introduction NeilBrown
                   ` (5 preceding siblings ...)
  2004-05-28  6:45 ` [PATCH] md - 1 of 8 - Rationalise device selection in md/multipath NeilBrown
@ 2004-05-28  6:45 ` NeilBrown
  2004-05-28  6:45 ` [PATCH] md - 7 of 8 - Allow md arrays to be resized if devices are large enough NeilBrown
  7 siblings, 0 replies; 14+ messages in thread
From: NeilBrown @ 2004-05-28  6:45 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-raid



If the superblock isn't persistent, we shouldn't allow
room for it.

From: Paul Clements <Paul.Clements@SteelEye.com>
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>

 ----------- Diffstat output ------------
 ./drivers/md/md.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletion(-)

diff ./drivers/md/md.c~current~ ./drivers/md/md.c
--- ./drivers/md/md.c~current~	2004-05-28 15:48:47.000000000 +1000
+++ ./drivers/md/md.c	2004-05-28 15:49:25.000000000 +1000
@@ -2285,7 +2285,12 @@ static int hot_add_disk(mddev_t * mddev,
 		return -EINVAL;
 	}
 
-	rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
+	if (mddev->persistent)
+		rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
+	else
+		rdev->sb_offset =
+			rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
+
 	size = calc_dev_size(rdev, mddev->chunk_size);
 	rdev->size = size;
 

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

* [PATCH] md - 2 of 8 - Make sure md_check_recovery will remove a faulty device when ->nr_pending hits 0
  2004-05-28  6:45 [PATCH] md - 0 of 8 - Introduction NeilBrown
@ 2004-05-28  6:45 ` NeilBrown
  2004-05-28  6:45 ` [PATCH] md - 6 of 8 - Abort the resync of raid1 there is only one device NeilBrown
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: NeilBrown @ 2004-05-28  6:45 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-raid


md_check_recovery only locks a device and does stuff when it thinks there
is a real likelyhood that something needs doing.
So the test at the top must cover all possibilities.

But it didn't cover the possibility that the last outstanding request on
a failed device had finished and so the device needed to be removed.

As a result, a failed drive might not get removed from the personalities
perspective on the array, and so it could never be removed from the array as
a whole.

With this patch, whenever ->nr_pending hits zero on a faulty device,
MD_RECOVERY_NEEDED is set so that md_check_recovery will do stuff.

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>

 ----------- Diffstat output ------------
 ./drivers/md/multipath.c    |    2 +-
 ./drivers/md/raid1.c        |    8 ++++----
 ./drivers/md/raid5.c        |    4 ++--
 ./drivers/md/raid6main.c    |    4 ++--
 ./include/linux/raid/md_k.h |    8 ++++++++
 5 files changed, 17 insertions(+), 9 deletions(-)

diff ./drivers/md/multipath.c~current~ ./drivers/md/multipath.c
--- ./drivers/md/multipath.c~current~	2004-05-28 15:47:47.000000000 +1000
+++ ./drivers/md/multipath.c	2004-05-28 15:48:33.000000000 +1000
@@ -131,7 +131,7 @@ int multipath_end_request(struct bio *bi
 		       (unsigned long long)bio->bi_sector);
 		multipath_reschedule_retry(mp_bh);
 	}
-	atomic_dec(&rdev->nr_pending);
+	rdev_dec_pending(rdev, conf->mddev);
 	return 0;
 }
 

diff ./drivers/md/raid1.c~current~ ./drivers/md/raid1.c
--- ./drivers/md/raid1.c~current~	2004-05-28 15:48:33.000000000 +1000
+++ ./drivers/md/raid1.c	2004-05-28 15:48:33.000000000 +1000
@@ -296,7 +296,7 @@ static int raid1_end_read_request(struct
 		reschedule_retry(r1_bio);
 	}
 
-	atomic_dec(&conf->mirrors[mirror].rdev->nr_pending);
+	rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev); 
 	return 0;
 }
 
@@ -343,7 +343,7 @@ static int raid1_end_write_request(struc
 		raid_end_bio_io(r1_bio);
 	}
 
-	atomic_dec(&conf->mirrors[mirror].rdev->nr_pending);
+	rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
 	return 0;
 }
 
@@ -831,7 +831,7 @@ static int end_sync_read(struct bio *bio
 			 conf->mirrors[r1_bio->read_disk].rdev);
 	else
 		set_bit(R1BIO_Uptodate, &r1_bio->state);
-	atomic_dec(&conf->mirrors[r1_bio->read_disk].rdev->nr_pending);
+	rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
 	reschedule_retry(r1_bio);
 	return 0;
 }
@@ -861,7 +861,7 @@ static int end_sync_write(struct bio *bi
 		md_done_sync(mddev, r1_bio->sectors, uptodate);
 		put_buf(r1_bio);
 	}
-	atomic_dec(&conf->mirrors[mirror].rdev->nr_pending);
+	rdev_dec_pending(conf->mirrors[mirror].rdev, mddev);
 	return 0;
 }
 

diff ./drivers/md/raid5.c~current~ ./drivers/md/raid5.c
--- ./drivers/md/raid5.c~current~	2004-05-28 15:48:33.000000000 +1000
+++ ./drivers/md/raid5.c	2004-05-28 15:48:33.000000000 +1000
@@ -395,7 +395,7 @@ static int raid5_end_read_request (struc
 		md_error(conf->mddev, conf->disks[i].rdev);
 		clear_bit(R5_UPTODATE, &sh->dev[i].flags);
 	}
-	atomic_dec(&conf->disks[i].rdev->nr_pending);
+	rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
 #if 0
 	/* must restore b_page before unlocking buffer... */
 	if (sh->bh_page[i] != bh->b_page) {
@@ -438,7 +438,7 @@ static int raid5_end_write_request (stru
 	if (!uptodate)
 		md_error(conf->mddev, conf->disks[i].rdev);
 
-	atomic_dec(&conf->disks[i].rdev->nr_pending);
+	rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
 	
 	clear_bit(R5_LOCKED, &sh->dev[i].flags);
 	set_bit(STRIPE_HANDLE, &sh->state);

diff ./drivers/md/raid6main.c~current~ ./drivers/md/raid6main.c
--- ./drivers/md/raid6main.c~current~	2004-05-28 15:48:33.000000000 +1000
+++ ./drivers/md/raid6main.c	2004-05-28 15:48:33.000000000 +1000
@@ -414,7 +414,7 @@ static int raid6_end_read_request (struc
 		md_error(conf->mddev, conf->disks[i].rdev);
 		clear_bit(R5_UPTODATE, &sh->dev[i].flags);
 	}
-	atomic_dec(&conf->disks[i].rdev->nr_pending);
+	rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
 #if 0
 	/* must restore b_page before unlocking buffer... */
 	if (sh->bh_page[i] != bh->b_page) {
@@ -457,7 +457,7 @@ static int raid6_end_write_request (stru
 	if (!uptodate)
 		md_error(conf->mddev, conf->disks[i].rdev);
 
-	atomic_dec(&conf->disks[i].rdev->nr_pending);
+	rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
 
 	clear_bit(R5_LOCKED, &sh->dev[i].flags);
 	set_bit(STRIPE_HANDLE, &sh->state);

diff ./include/linux/raid/md_k.h~current~ ./include/linux/raid/md_k.h
--- ./include/linux/raid/md_k.h~current~	2004-05-28 15:48:33.000000000 +1000
+++ ./include/linux/raid/md_k.h	2004-05-28 15:48:33.000000000 +1000
@@ -255,6 +255,14 @@ struct mddev_s
 	struct list_head		all_mddevs;
 };
 
+
+static inline void rdev_dec_pending(mdk_rdev_t *rdev, mddev_t *mddev)
+{
+	int faulty = rdev->faulty;
+	if (atomic_dec_and_test(&rdev->nr_pending) && faulty)
+		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+}
+
 struct mdk_personality_s
 {
 	char *name;

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

* [PATCH] md - 8 of 8 - Support reshaping raid1 arrays - adding or removing drives.
  2004-05-28  6:45 [PATCH] md - 0 of 8 - Introduction NeilBrown
                   ` (2 preceding siblings ...)
  2004-05-28  6:45 ` [PATCH] md - 4 of 8 - Make sure the size of a raid5/6 array is a multiple of the chunk size NeilBrown
@ 2004-05-28  6:45 ` NeilBrown
  2004-05-28  7:31   ` Andrew Morton
  2004-05-28 13:32   ` Mario 'BitKoenig' Holbe
  2004-05-28  6:45 ` [PATCH] md - 3 of 8 - Allow an md personality to refuse a hot-remove request NeilBrown
                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 14+ messages in thread
From: NeilBrown @ 2004-05-28  6:45 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-raid

This allows the number of "raid_disks" in a raid1 to be changed.

This requires allocating a new pool of "r1bio" structures which a different
number of bios, suspending IO, and swapping the new pool in place of the old.
(and a few other related changes).

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>

 ----------- Diffstat output ------------
 ./drivers/md/md.c           |   31 +++++++-
 ./drivers/md/raid1.c        |  163 ++++++++++++++++++++++++++++++++++----------
 ./include/linux/raid/md_k.h |    1 
 3 files changed, 156 insertions(+), 39 deletions(-)

diff ./drivers/md/md.c~current~ ./drivers/md/md.c
--- ./drivers/md/md.c~current~	2004-05-28 16:29:57.000000000 +1000
+++ ./drivers/md/md.c	2004-05-28 16:29:57.000000000 +1000
@@ -2422,18 +2422,23 @@ static int set_array_info(mddev_t * mdde
 static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
 {
 	int rv = 0;
+	int cnt = 0;
 
 	if (mddev->major_version != info->major_version ||
 	    mddev->minor_version != info->minor_version ||
 /*	    mddev->patch_version != info->patch_version || */
 	    mddev->ctime         != info->ctime         ||
 	    mddev->level         != info->level         ||
-	    mddev->raid_disks    != info->raid_disks    ||
 	    mddev->layout        != info->layout        ||
 	    !mddev->persistent	 != info->not_persistent||
 	    mddev->chunk_size    != info->chunk_size    )
 		return -EINVAL;
-	/* that leaves only size */
+	/* Check there is only one change */
+	if (mddev->size != info->size) cnt++;
+	if (mddev->raid_disks != info->raid_disks) cnt++;
+	if (cnt == 0) return 0;
+	if (cnt > 1) return -EINVAL;
+
 	if (mddev->size != info->size) {
 		mdk_rdev_t * rdev;
 		struct list_head *tmp;
@@ -2477,6 +2482,28 @@ static int update_array_info(mddev_t *md
 			}
 		}
 	}
+	if (mddev->raid_disks    != info->raid_disks) {
+		/* change the number of raid disks */
+		if (mddev->pers->reshape == NULL)
+			return -EINVAL;
+		if (info->raid_disks <= 0 ||
+		    info->raid_disks >= mddev->max_disks)
+			return -EINVAL;
+		if (mddev->sync_thread)
+			return -EBUSY;
+		rv = mddev->pers->reshape(mddev, info->raid_disks);
+		if (!rv) {
+			struct block_device *bdev;
+
+			bdev = bdget_disk(mddev->gendisk, 0);
+			if (bdev) {
+				down(&bdev->bd_inode->i_sem);
+				i_size_write(bdev->bd_inode, mddev->array_size << 10);
+				up(&bdev->bd_inode->i_sem);
+				bdput(bdev);
+			}
+		}
+	}
 	md_update_sb(mddev);
 	return rv;
 }

diff ./drivers/md/raid1.c~current~ ./drivers/md/raid1.c
--- ./drivers/md/raid1.c~current~	2004-05-28 16:29:57.000000000 +1000
+++ ./drivers/md/raid1.c	2004-05-28 16:29:57.000000000 +1000
@@ -42,16 +42,17 @@ static void unplug_slaves(mddev_t *mddev
 
 static void * r1bio_pool_alloc(int gfp_flags, void *data)
 {
-	mddev_t *mddev = data;
+	struct pool_info *pi = data;
 	r1bio_t *r1_bio;
 
 	/* allocate a r1bio with room for raid_disks entries in the bios array */
-	r1_bio = kmalloc(sizeof(r1bio_t) + sizeof(struct bio*)*mddev->raid_disks,
+	r1_bio = kmalloc(sizeof(r1bio_t) + sizeof(struct bio*)*pi->raid_disks,
 			 gfp_flags);
 	if (r1_bio)
-		memset(r1_bio, 0, sizeof(*r1_bio) + sizeof(struct bio*)*mddev->raid_disks);
+		memset(r1_bio, 0, sizeof(*r1_bio) + 
+			       sizeof(struct bio*) * pi->raid_disks);
 	else
-		unplug_slaves(mddev);
+		unplug_slaves(pi->mddev);
 
 	return r1_bio;
 }
@@ -69,22 +70,22 @@ static void r1bio_pool_free(void *r1_bio
 
 static void * r1buf_pool_alloc(int gfp_flags, void *data)
 {
-	conf_t *conf = data;
+	struct pool_info *pi = data;
 	struct page *page;
 	r1bio_t *r1_bio;
 	struct bio *bio;
 	int i, j;
 
-	r1_bio = r1bio_pool_alloc(gfp_flags, conf->mddev);
+	r1_bio = r1bio_pool_alloc(gfp_flags, pi);
 	if (!r1_bio) {
-		unplug_slaves(conf->mddev);
+		unplug_slaves(pi->mddev);
 		return NULL;
 	}
 
 	/*
 	 * Allocate bios : 1 for reading, n-1 for writing
 	 */
-	for (j = conf->raid_disks ; j-- ; ) {
+	for (j = pi->raid_disks ; j-- ; ) {
 		bio = bio_alloc(gfp_flags, RESYNC_PAGES);
 		if (!bio)
 			goto out_free_bio;
@@ -111,16 +112,16 @@ out_free_pages:
 	for ( ; i > 0 ; i--)
 		__free_page(bio->bi_io_vec[i-1].bv_page);
 out_free_bio:
-	while ( ++j < conf->raid_disks )
+	while ( ++j < pi->raid_disks )
 		bio_put(r1_bio->bios[j]);
-	r1bio_pool_free(r1_bio, conf->mddev);
+	r1bio_pool_free(r1_bio, data);
 	return NULL;
 }
 
 static void r1buf_pool_free(void *__r1_bio, void *data)
 {
+	struct pool_info *pi = data;
 	int i;
-	conf_t *conf = data;
 	r1bio_t *r1bio = __r1_bio;
 	struct bio *bio = r1bio->bios[0];
 
@@ -128,10 +129,10 @@ static void r1buf_pool_free(void *__r1_b
 		__free_page(bio->bi_io_vec[i].bv_page);
 		bio->bi_io_vec[i].bv_page = NULL;
 	}
-	for (i=0 ; i < conf->raid_disks; i++)
+	for (i=0 ; i < pi->raid_disks; i++)
 		bio_put(r1bio->bios[i]);
 
-	r1bio_pool_free(r1bio, conf->mddev);
+	r1bio_pool_free(r1bio, data);
 }
 
 static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
@@ -536,7 +537,7 @@ static int make_request(request_queue_t 
 	mirror_info_t *mirror;
 	r1bio_t *r1_bio;
 	struct bio *read_bio;
-	int i, disks = conf->raid_disks;
+	int i, disks;
 
 	/*
 	 * Register the new request and wait if the reconstruction
@@ -596,6 +597,7 @@ static int make_request(request_queue_t 
 	 * inc refcount on their rdev.  Record them by setting
 	 * bios[x] to bio
 	 */
+	disks = conf->raid_disks;
 	spin_lock_irq(&conf->device_lock);
 	for (i = 0;  i < disks; i++) {
 		if (conf->mirrors[i].rdev &&
@@ -979,7 +981,8 @@ static int init_resync(conf_t *conf)
 	buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE;
 	if (conf->r1buf_pool)
 		BUG();
-	conf->r1buf_pool = mempool_create(buffs, r1buf_pool_alloc, r1buf_pool_free, conf);
+	conf->r1buf_pool = mempool_create(buffs, r1buf_pool_alloc, r1buf_pool_free,
+					  conf->poolinfo);
 	if (!conf->r1buf_pool)
 		return -ENOMEM;
 	conf->next_resync = 0;
@@ -1162,28 +1165,28 @@ static int run(mddev_t *mddev)
 	 */
 	conf = kmalloc(sizeof(conf_t), GFP_KERNEL);
 	mddev->private = conf;
-	if (!conf) {
-		printk(KERN_ERR "raid1: couldn't allocate memory for %s\n",
-			mdname(mddev));
-		goto out;
-	}
+	if (!conf)
+		goto out_no_mem;
+
 	memset(conf, 0, sizeof(*conf));
 	conf->mirrors = kmalloc(sizeof(struct mirror_info)*mddev->raid_disks, 
 				 GFP_KERNEL);
-	if (!conf->mirrors) {
-		printk(KERN_ERR "raid1: couldn't allocate memory for %s\n",
-		       mdname(mddev));
-		goto out_free_conf;
-	}
+	if (!conf->mirrors)
+		goto out_no_mem;
+
 	memset(conf->mirrors, 0, sizeof(struct mirror_info)*mddev->raid_disks);
 
+	conf->poolinfo = kmalloc(sizeof(*conf->poolinfo), GFP_KERNEL);
+	if (!conf->poolinfo)
+		goto out_no_mem;
+	conf->poolinfo->mddev = mddev;
+	conf->poolinfo->raid_disks = mddev->raid_disks;
 	conf->r1bio_pool = mempool_create(NR_RAID1_BIOS, r1bio_pool_alloc,
-						r1bio_pool_free, mddev);
-	if (!conf->r1bio_pool) {
-		printk(KERN_ERR "raid1: couldn't allocate memory for %s\n", 
-			mdname(mddev));
-		goto out_free_conf;
-	}
+					  r1bio_pool_free, 
+					  conf->poolinfo);
+	if (!conf->r1bio_pool)
+		goto out_no_mem;
+
 	mddev->queue->unplug_fn = raid1_unplug;
 
 	mddev->queue->issue_flush_fn = raid1_issue_flush;
@@ -1270,13 +1273,21 @@ static int run(mddev_t *mddev)
 
 	return 0;
 
+out_no_mem:
+	printk(KERN_ERR "raid1: couldn't allocate memory for %s\n",
+	       mdname(mddev));
+	
 out_free_conf:
-	if (conf->r1bio_pool)
-		mempool_destroy(conf->r1bio_pool);
-	if (conf->mirrors)
-		kfree(conf->mirrors);
-	kfree(conf);
-	mddev->private = NULL;
+	if (conf) {
+		if (conf->r1bio_pool)
+			mempool_destroy(conf->r1bio_pool);
+		if (conf->mirrors)
+			kfree(conf->mirrors);
+		if (conf->poolinfo)
+			kfree(conf->poolinfo);
+		kfree(conf);
+		mddev->private = NULL;
+	}
 out:
 	return -EIO;
 }
@@ -1291,6 +1302,8 @@ static int stop(mddev_t *mddev)
 		mempool_destroy(conf->r1bio_pool);
 	if (conf->mirrors)
 		kfree(conf->mirrors);
+	if (conf->poolinfo)
+		kfree(conf->poolinfo);
 	kfree(conf);
 	mddev->private = NULL;
 	return 0;
@@ -1316,6 +1329,81 @@ static int raid1_resize(mddev_t *mddev, 
 	return 0;
 }
 
+static int raid1_reshape(mddev_t *mddev, int raid_disks)
+{
+	/* We need to:
+	 * 1/ resize the r1bio_pool
+	 * 2/ resize conf->mirrors
+	 *
+	 * We allocate a new r1bio_pool if we can.
+	 * Then raise a device barrier and wait until all IO stops.
+	 * Then resize conf->mirrors and swap in the new r1bio pool.
+	 */
+	mempool_t *newpool, *oldpool;
+	struct pool_info *newpoolinfo;
+	mirror_info_t *newmirrors;
+	conf_t *conf = mddev_to_conf(mddev);
+	
+	int d;
+
+	for (d= raid_disks; d < conf->raid_disks; d++)
+		if (conf->mirrors[d].rdev)
+			return -EBUSY;
+	
+	newpoolinfo = kmalloc(sizeof(newpoolinfo), GFP_KERNEL);
+	if (!newpoolinfo)
+		return -ENOMEM;
+	newpoolinfo->mddev = mddev;
+	newpoolinfo->raid_disks = raid_disks;
+
+	newpool = mempool_create(NR_RAID1_BIOS, r1bio_pool_alloc,
+				 r1bio_pool_free, newpoolinfo);
+	if (!newpool) {
+		kfree(newpoolinfo);
+		return -ENOMEM;
+	}
+	newmirrors = kmalloc(sizeof(struct mirror_info) * raid_disks, GFP_KERNEL);
+	if (!newmirrors) {
+		kfree(newpoolinfo);
+		mempool_destroy(newpool);
+		return -ENOMEM;
+	}
+	memset(newmirrors, 0, sizeof(struct mirror_info)*raid_disks);
+
+	spin_lock_irq(&conf->resync_lock);
+	conf->barrier++;
+	wait_event_lock_irq(conf->wait_idle, !conf->nr_pending, 
+			    conf->resync_lock, unplug_slaves(mddev));
+	spin_unlock_irq(&conf->resync_lock);
+
+	/* ok, everything is stopped */
+	oldpool = conf->r1bio_pool;
+	conf->r1bio_pool = newpool;
+	for (d=0; d < raid_disks && d < conf->raid_disks; d++)
+		newmirrors[d] = conf->mirrors[d];
+	kfree(conf->mirrors);
+	conf->mirrors = newmirrors;
+	kfree(conf->poolinfo);
+	conf->poolinfo = newpoolinfo;
+	
+	mddev->degraded += (raid_disks - conf->raid_disks);
+	conf->raid_disks = mddev->raid_disks = raid_disks;
+
+	spin_lock_irq(&conf->resync_lock);
+	conf->barrier--;
+	spin_unlock_irq(&conf->resync_lock);
+	wake_up(&conf->wait_resume);
+	wake_up(&conf->wait_idle);
+
+
+	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+	md_wakeup_thread(mddev->thread);
+
+	mempool_destroy(oldpool);
+	return 0;
+}
+	
+
 static mdk_personality_t raid1_personality =
 {
 	.name		= "raid1",
@@ -1330,6 +1418,7 @@ static mdk_personality_t raid1_personali
 	.spare_active	= raid1_spare_active,
 	.sync_request	= sync_request,
 	.resize		= raid1_resize,
+	.reshape	= raid1_reshape,
 };
 
 static int __init raid_init(void)

diff ./include/linux/raid/md_k.h~current~ ./include/linux/raid/md_k.h
--- ./include/linux/raid/md_k.h~current~	2004-05-28 16:29:57.000000000 +1000
+++ ./include/linux/raid/md_k.h	2004-05-28 16:29:57.000000000 +1000
@@ -280,6 +280,7 @@ struct mdk_personality_s
 	int (*spare_active) (mddev_t *mddev);
 	int (*sync_request)(mddev_t *mddev, sector_t sector_nr, int go_faster);
 	int (*resize) (mddev_t *mddev, sector_t sectors);
+	int (*reshape) (mddev_t *mddev, int raid_disks);
 };
 
 

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

* [PATCH] md - 7 of 8 - Allow md arrays to be resized if devices are large enough.
  2004-05-28  6:45 [PATCH] md - 0 of 8 - Introduction NeilBrown
                   ` (6 preceding siblings ...)
  2004-05-28  6:45 ` [PATCH] md - 5 of 8 - Handle hot-add for arrays with non-persistent superblocks NeilBrown
@ 2004-05-28  6:45 ` NeilBrown
  7 siblings, 0 replies; 14+ messages in thread
From: NeilBrown @ 2004-05-28  6:45 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-raid


It is possible to have raid1/4/5/6 arrays that do not 
use all the space on the drive.
This can be done explicitly, or can happen info you,
one by one, replace all the drives with larger devices.

This patch extends the "SET_ARRAY_INFO" ioctl (which previously
invalid on active arrays) allow some attributes of the array
to be changed and implements changing of the "size" attribute.

"size" is the amount of each device that is actually used.
If "size" is increased, the new space will immediately be
"resynced".

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>

 ----------- Diffstat output ------------
 ./drivers/md/md.c           |  110 +++++++++++++++++++++++++++++++++++++-------
 ./drivers/md/raid1.c        |   21 ++++++++
 ./drivers/md/raid5.c        |   22 ++++++++
 ./drivers/md/raid6main.c    |   22 ++++++++
 ./include/linux/raid/md_k.h |    1 
 5 files changed, 160 insertions(+), 16 deletions(-)

diff ./drivers/md/md.c~current~ ./drivers/md/md.c
--- ./drivers/md/md.c~current~	2004-05-28 16:29:32.000000000 +1000
+++ ./drivers/md/md.c	2004-05-28 16:29:57.000000000 +1000
@@ -2411,6 +2411,76 @@ static int set_array_info(mddev_t * mdde
 	return 0;
 }
 
+/*
+ * update_array_info is used to change the configuration of an
+ * on-line array.
+ * The version, ctime,level,size,raid_disks,not_persistent, layout,chunk_size
+ * fields in the info are checked against the array.
+ * Any differences that cannot be handled will cause an error.
+ * Normally, only one change can be managed at a time.
+ */
+static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
+{
+	int rv = 0;
+
+	if (mddev->major_version != info->major_version ||
+	    mddev->minor_version != info->minor_version ||
+/*	    mddev->patch_version != info->patch_version || */
+	    mddev->ctime         != info->ctime         ||
+	    mddev->level         != info->level         ||
+	    mddev->raid_disks    != info->raid_disks    ||
+	    mddev->layout        != info->layout        ||
+	    !mddev->persistent	 != info->not_persistent||
+	    mddev->chunk_size    != info->chunk_size    )
+		return -EINVAL;
+	/* that leaves only size */
+	if (mddev->size != info->size) {
+		mdk_rdev_t * rdev;
+		struct list_head *tmp;
+		if (mddev->pers->resize == NULL)
+			return -EINVAL;
+		/* The "size" is the amount of each device that is used.
+		 * This can only make sense for arrays with redundancy.
+		 * linear and raid0 always use whatever space is available
+		 * We can only consider changing the size of no resync
+		 * or reconstruction is happening, and if the new size
+		 * is acceptable. It must fit before the sb_offset or,
+		 * if that is <data_offset, it must fit before the
+		 * size of each device.
+		 * If size is zero, we find the largest size that fits.
+		 */
+		if (mddev->sync_thread)
+			return -EBUSY;
+		ITERATE_RDEV(mddev,rdev,tmp) {
+			sector_t avail;
+			int fit = (info->size == 0);
+			if (rdev->sb_offset > rdev->data_offset)
+				avail = (rdev->sb_offset*2) - rdev->data_offset;
+			else
+				avail = get_capacity(rdev->bdev->bd_disk)
+					- rdev->data_offset;
+			if (fit && (info->size == 0 || info->size > avail/2))
+				info->size = avail/2;
+			if (avail < ((sector_t)info->size << 1))
+				return -ENOSPC;
+		}
+		rv = mddev->pers->resize(mddev, (sector_t)info->size *2);
+		if (!rv) {
+			struct block_device *bdev;
+
+			bdev = bdget_disk(mddev->gendisk, 0);
+			if (bdev) {
+				down(&bdev->bd_inode->i_sem);
+				i_size_write(bdev->bd_inode, mddev->array_size << 10);
+				up(&bdev->bd_inode->i_sem);
+				bdput(bdev);
+			}
+		}
+	}
+	md_update_sb(mddev);
+	return rv;
+}
+
 static int set_disk_faulty(mddev_t *mddev, dev_t dev)
 {
 	mdk_rdev_t *rdev;
@@ -2502,21 +2572,6 @@ static int md_ioctl(struct inode *inode,
 	switch (cmd)
 	{
 		case SET_ARRAY_INFO:
-
-			if (!list_empty(&mddev->disks)) {
-				printk(KERN_WARNING 
-					"md: array %s already has disks!\n",
-					mdname(mddev));
-				err = -EBUSY;
-				goto abort_unlock;
-			}
-			if (mddev->raid_disks) {
-				printk(KERN_WARNING 
-					"md: array %s already initialised!\n",
-					mdname(mddev));
-				err = -EBUSY;
-				goto abort_unlock;
-			}
 			{
 				mdu_array_info_t info;
 				if (!arg)
@@ -2525,10 +2580,33 @@ static int md_ioctl(struct inode *inode,
 					err = -EFAULT;
 					goto abort_unlock;
 				}
+				if (mddev->pers) {
+					err = update_array_info(mddev, &info);
+					if (err) {
+						printk(KERN_WARNING "md: couldn't update"
+						       " array info. %d\n", err);
+						goto abort_unlock;
+					}
+					goto done_unlock;
+				}
+				if (!list_empty(&mddev->disks)) {
+					printk(KERN_WARNING 
+					       "md: array %s already has disks!\n",
+					       mdname(mddev));
+					err = -EBUSY;
+					goto abort_unlock;
+				}
+				if (mddev->raid_disks) {
+					printk(KERN_WARNING 
+					       "md: array %s already initialised!\n",
+					       mdname(mddev));
+					err = -EBUSY;
+					goto abort_unlock;
+				}
 				err = set_array_info(mddev, &info);
 				if (err) {
 					printk(KERN_WARNING "md: couldn't set"
-						" array info. %d\n", err);
+					       " array info. %d\n", err);
 					goto abort_unlock;
 				}
 			}

diff ./drivers/md/raid1.c~current~ ./drivers/md/raid1.c
--- ./drivers/md/raid1.c~current~	2004-05-28 16:28:18.000000000 +1000
+++ ./drivers/md/raid1.c	2004-05-28 16:29:57.000000000 +1000
@@ -1296,6 +1296,26 @@ static int stop(mddev_t *mddev)
 	return 0;
 }
 
+static int raid1_resize(mddev_t *mddev, sector_t sectors)
+{
+	/* no resync is happening, and there is enough space 
+	 * on all devices, so we can resize.
+	 * We need to make sure resync covers any new space.
+	 * If the array is shrinking we should possibly wait until
+	 * any io in the removed space completes, but it hardly seems
+	 * worth it.
+	 */
+	mddev->array_size = sectors>>1;
+	set_capacity(mddev->gendisk, mddev->array_size << 1);
+	mddev->changed = 1;
+	if (mddev->array_size > mddev->size && mddev->recovery_cp == MaxSector) {
+		mddev->recovery_cp = mddev->size << 1;
+		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+	}
+	mddev->size = mddev->array_size;
+	return 0;
+}
+
 static mdk_personality_t raid1_personality =
 {
 	.name		= "raid1",
@@ -1309,6 +1329,7 @@ static mdk_personality_t raid1_personali
 	.hot_remove_disk= raid1_remove_disk,
 	.spare_active	= raid1_spare_active,
 	.sync_request	= sync_request,
+	.resize		= raid1_resize,
 };
 
 static int __init raid_init(void)

diff ./drivers/md/raid5.c~current~ ./drivers/md/raid5.c
--- ./drivers/md/raid5.c~current~	2004-05-28 16:28:13.000000000 +1000
+++ ./drivers/md/raid5.c	2004-05-28 16:29:57.000000000 +1000
@@ -1865,6 +1865,27 @@ static int raid5_add_disk(mddev_t *mddev
 	return found;
 }
 
+static int raid5_resize(mddev_t *mddev, sector_t sectors)
+{
+	/* no resync is happening, and there is enough space 
+	 * on all devices, so we can resize.
+	 * We need to make sure resync covers any new space.
+	 * If the array is shrinking we should possibly wait until
+	 * any io in the removed space completes, but it hardly seems
+	 * worth it.
+	 */
+	sectors &= ~((sector_t)mddev->chunk_size/512 - 1);
+	mddev->array_size = (sectors * (mddev->raid_disks-1))>>1;
+	set_capacity(mddev->gendisk, mddev->array_size << 1);
+	mddev->changed = 1;
+	if (sectors/2  > mddev->size && mddev->recovery_cp == MaxSector) {
+		mddev->recovery_cp = mddev->size << 1;
+		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+	}
+	mddev->size = sectors /2;
+	return 0;
+}
+
 static mdk_personality_t raid5_personality=
 {
 	.name		= "raid5",
@@ -1878,6 +1899,7 @@ static mdk_personality_t raid5_personali
 	.hot_remove_disk= raid5_remove_disk,
 	.spare_active	= raid5_spare_active,
 	.sync_request	= sync_request,
+	.resize		= raid5_resize,
 };
 
 static int __init raid5_init (void)

diff ./drivers/md/raid6main.c~current~ ./drivers/md/raid6main.c
--- ./drivers/md/raid6main.c~current~	2004-05-28 16:28:13.000000000 +1000
+++ ./drivers/md/raid6main.c	2004-05-28 16:29:57.000000000 +1000
@@ -2034,6 +2034,27 @@ static int raid6_add_disk(mddev_t *mddev
 	return found;
 }
 
+static int raid6_resize(mddev_t *mddev, sector_t sectors)
+{
+	/* no resync is happening, and there is enough space 
+	 * on all devices, so we can resize.
+	 * We need to make sure resync covers any new space.
+	 * If the array is shrinking we should possibly wait until
+	 * any io in the removed space completes, but it hardly seems
+	 * worth it.
+	 */
+	sectors &= ~((sector_t)mddev->chunk_size/512 - 1);
+	mddev->array_size = (sectors * (mddev->raid_disks-2))>>1;
+	set_capacity(mddev->gendisk, mddev->array_size << 1);
+	mddev->changed = 1;
+	if (sectors/2  > mddev->size && mddev->recovery_cp == MaxSector) {
+		mddev->recovery_cp = mddev->size << 1;
+		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+	}
+	mddev->size = sectors /2;
+	return 0;
+}
+
 static mdk_personality_t raid6_personality=
 {
 	.name		= "raid6",
@@ -2047,6 +2068,7 @@ static mdk_personality_t raid6_personali
 	.hot_remove_disk= raid6_remove_disk,
 	.spare_active	= raid6_spare_active,
 	.sync_request	= sync_request,
+	.resize		= raid6_resize,
 };
 
 static int __init raid6_init (void)

diff ./include/linux/raid/md_k.h~current~ ./include/linux/raid/md_k.h
--- ./include/linux/raid/md_k.h~current~	2004-05-28 16:28:13.000000000 +1000
+++ ./include/linux/raid/md_k.h	2004-05-28 16:29:57.000000000 +1000
@@ -279,6 +279,7 @@ struct mdk_personality_s
 	int (*hot_remove_disk) (mddev_t *mddev, int number);
 	int (*spare_active) (mddev_t *mddev);
 	int (*sync_request)(mddev_t *mddev, sector_t sector_nr, int go_faster);
+	int (*resize) (mddev_t *mddev, sector_t sectors);
 };
 
 

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

* [PATCH] md - 0 of 8 - Introduction
@ 2004-05-28  6:45 NeilBrown
  2004-05-28  6:45 ` [PATCH] md - 2 of 8 - Make sure md_check_recovery will remove a faulty device when ->nr_pending hits 0 NeilBrown
                   ` (7 more replies)
  0 siblings, 8 replies; 14+ messages in thread
From: NeilBrown @ 2004-05-28  6:45 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-raid

Following are 8 patches for md in 2.6.7-rc1-mm1

The first 6 a ready to go to Linus.
The last two are sufficiently new that maybe they should wait a while,
but I don't have any serious concerns about them and have tested them quite a bit.

1 - tidy up some multipath code
2 - fix a bug which stopped failed drives from being removable
    in some cases.
3 - rationalise use of ->hot_remove_disk method.
4 - double check that size in a multiple of chunksize of raid5/6
    (needed for a subsequent patch)
5 - Fix problem with hot-adding to array with non-persistant superblocks.
6 - Get raid1 to cope sensible with a device failure during rebuild.

and the new functionality.

7 - support resizing of devices in raid1/4/5/6.  If the devices are replaced
    with larger ones, the array can grow while online to use the extra space
8 - support adding and removing active drives for raid1.  i.e change a raid1 
    array that used 2 drives so that it uses 3 drives, or vice-versa.

I will release a new mdadm in a few days that provide "--grow" for using
this functionality.

NeilBrown


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

* [PATCH] md - 1 of 8 - Rationalise device selection in md/multipath.
  2004-05-28  6:45 [PATCH] md - 0 of 8 - Introduction NeilBrown
                   ` (4 preceding siblings ...)
  2004-05-28  6:45 ` [PATCH] md - 3 of 8 - Allow an md personality to refuse a hot-remove request NeilBrown
@ 2004-05-28  6:45 ` NeilBrown
  2004-05-28  6:45 ` [PATCH] md - 5 of 8 - Handle hot-add for arrays with non-persistent superblocks NeilBrown
  2004-05-28  6:45 ` [PATCH] md - 7 of 8 - Allow md arrays to be resized if devices are large enough NeilBrown
  7 siblings, 0 replies; 14+ messages in thread
From: NeilBrown @ 2004-05-28  6:45 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-raid


md/multipath has two separate pieces of code for choosing a device
to use, one when a request is first made and the other when a
request is being re-tried after failure.
This patch discards multipath_read_balance and uses multipath_map
in both situations.

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>

 ----------- Diffstat output ------------
 ./drivers/md/multipath.c |   45 ++++++++++++---------------------------------
 1 files changed, 12 insertions(+), 33 deletions(-)

diff ./drivers/md/multipath.c~current~ ./drivers/md/multipath.c
--- ./drivers/md/multipath.c~current~	2004-05-28 15:47:47.000000000 +1000
+++ ./drivers/md/multipath.c	2004-05-28 15:47:47.000000000 +1000
@@ -54,9 +54,8 @@ static void mp_pool_free(void *mpb, void
 	kfree(mpb);
 }
 
-static int multipath_map (mddev_t *mddev, mdk_rdev_t **rdevp)
+static int multipath_map (multipath_conf_t *conf)
 {
-	multipath_conf_t *conf = mddev_to_conf(mddev);
 	int i, disks = conf->raid_disks;
 
 	/*
@@ -68,10 +67,9 @@ static int multipath_map (mddev_t *mddev
 	for (i = 0; i < disks; i++) {
 		mdk_rdev_t *rdev = conf->multipaths[i].rdev;
 		if (rdev && rdev->in_sync) {
-			*rdevp = rdev;
 			atomic_inc(&rdev->nr_pending);
 			spin_unlock_irq(&conf->device_lock);
-			return 0;
+			return i;
 		}
 	}
 	spin_unlock_irq(&conf->device_lock);
@@ -137,24 +135,6 @@ int multipath_end_request(struct bio *bi
 	return 0;
 }
 
-/*
- * This routine returns the disk from which the requested read should
- * be done.
- */
-
-static int multipath_read_balance (multipath_conf_t *conf)
-{
-	int disk;
-
-	for (disk = 0; disk < conf->raid_disks; disk++) {
-		mdk_rdev_t *rdev = conf->multipaths[disk].rdev;
-		if (rdev && rdev->in_sync)
-			return disk;
-	}
-	BUG();
-	return 0;
-}
-
 static void unplug_slaves(mddev_t *mddev)
 {
 	multipath_conf_t *conf = mddev_to_conf(mddev);
@@ -204,14 +184,14 @@ static int multipath_make_request (reque
 		disk_stat_inc(mddev->gendisk, reads);
 		disk_stat_add(mddev->gendisk, read_sectors, bio_sectors(bio));
 	}
-	/*
-	 * read balancing logic:
-	 */
-	spin_lock_irq(&conf->device_lock);
-	mp_bh->path = multipath_read_balance(conf);
+
+	mp_bh->path = multipath_map(conf);
+	if (mp_bh->path < 0) {
+		bio_endio(bio, bio->bi_size, -EIO);
+		mempool_free(mp_bh, conf->pool);
+		return 0;
+	}
 	multipath = conf->multipaths + mp_bh->path;
-	atomic_inc(&multipath->rdev->nr_pending);
-	spin_unlock_irq(&conf->device_lock);
 
 	mp_bh->bio = *bio;
 	mp_bh->bio.bi_bdev = multipath->rdev->bdev;
@@ -400,7 +380,7 @@ static void multipathd (mddev_t *mddev)
 	struct multipath_bh *mp_bh;
 	struct bio *bio;
 	unsigned long flags;
-	mdk_rdev_t *rdev;
+	multipath_conf_t *conf = mddev_to_conf(mddev);
 
 	md_check_recovery(mddev);
 	for (;;) {
@@ -416,8 +396,7 @@ static void multipathd (mddev_t *mddev)
 		bio = &mp_bh->bio;
 		bio->bi_sector = mp_bh->master_bio->bi_sector;
 		
-		rdev = NULL;
-		if (multipath_map (mddev, &rdev)<0) {
+		if ((mp_bh->path = multipath_map (conf))<0) {
 			printk(KERN_ALERT "multipath: %s: unrecoverable IO read"
 				" error for block %llu\n",
 				bdevname(bio->bi_bdev,b),
@@ -428,7 +407,7 @@ static void multipathd (mddev_t *mddev)
 				" to another IO path\n",
 				bdevname(bio->bi_bdev,b),
 				(unsigned long long)bio->bi_sector);
-			bio->bi_bdev = rdev->bdev;
+			bio->bi_bdev = conf->multipaths[mp_bh->path].rdev->bdev;
 			generic_make_request(bio);
 		}
 	}

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

* [PATCH] md - 6 of 8 - Abort the resync of raid1 there is only one device.
  2004-05-28  6:45 [PATCH] md - 0 of 8 - Introduction NeilBrown
  2004-05-28  6:45 ` [PATCH] md - 2 of 8 - Make sure md_check_recovery will remove a faulty device when ->nr_pending hits 0 NeilBrown
@ 2004-05-28  6:45 ` NeilBrown
  2004-05-28  6:45 ` [PATCH] md - 4 of 8 - Make sure the size of a raid5/6 array is a multiple of the chunk size NeilBrown
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: NeilBrown @ 2004-05-28  6:45 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-raid


If raid1 decides it needs to resync it will do so even if
there is only one working device.  This is pointless.

With this patch we abort resync if there is nowhere to write to.

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>

 ----------- Diffstat output ------------
 ./drivers/md/md.c    |    2 +-
 ./drivers/md/raid1.c |   13 +++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff ./drivers/md/md.c~current~ ./drivers/md/md.c
--- ./drivers/md/md.c~current~	2004-05-28 16:28:13.000000000 +1000
+++ ./drivers/md/md.c	2004-05-28 16:29:32.000000000 +1000
@@ -3317,7 +3317,7 @@ static void md_do_sync(mddev_t *mddev)
 		j += sectors;
 		if (j>1) mddev->curr_resync = j;
 
-		if (last_check + window > j)
+		if (last_check + window > j || j == max_sectors)
 			continue;
 
 		last_check = j;

diff ./drivers/md/raid1.c~current~ ./drivers/md/raid1.c
--- ./drivers/md/raid1.c~current~	2004-05-28 16:28:13.000000000 +1000
+++ ./drivers/md/raid1.c	2004-05-28 16:28:18.000000000 +1000
@@ -1005,6 +1005,7 @@ static int sync_request(mddev_t *mddev, 
 	sector_t max_sector, nr_sectors;
 	int disk;
 	int i;
+	int write_targets = 0;
 
 	if (!conf->r1buf_pool)
 		if (init_resync(conf))
@@ -1081,12 +1082,24 @@ static int sync_request(mddev_t *mddev, 
 			    sector_nr + RESYNC_SECTORS > mddev->recovery_cp)) {
 			bio->bi_rw = WRITE;
 			bio->bi_end_io = end_sync_write;
+			write_targets ++;
 		} else
 			continue;
 		bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset;
 		bio->bi_bdev = conf->mirrors[i].rdev->bdev;
 		bio->bi_private = r1_bio;
 	}
+	if (write_targets == 0) {
+		/* There is nowhere to write, so all non-sync
+		 * drives must be failed - so we are finished
+		 */
+		int rv = max_sector - sector_nr;
+		md_done_sync(mddev, rv, 1);
+		put_buf(r1_bio);
+		atomic_dec(&conf->mirrors[disk].rdev->nr_pending);
+		return rv;
+	}
+
 	nr_sectors = 0;
 	do {
 		struct page *page;

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

* Re: [PATCH] md - 8 of 8 - Support reshaping raid1 arrays - adding or removing drives.
  2004-05-28  6:45 ` [PATCH] md - 8 of 8 - Support reshaping raid1 arrays - adding or removing drives NeilBrown
@ 2004-05-28  7:31   ` Andrew Morton
  2004-05-28  8:41     ` Neil Brown
  2004-05-28 13:32   ` Mario 'BitKoenig' Holbe
  1 sibling, 1 reply; 14+ messages in thread
From: Andrew Morton @ 2004-05-28  7:31 UTC (permalink / raw)
  To: NeilBrown; +Cc: linux-raid

NeilBrown <neilb@cse.unsw.edu.au> wrote:
>
> This requires allocating a new pool of "r1bio" structures which a different
>  number of bios, suspending IO, and swapping the new pool in place of the old.
>  (and a few other related changes).

Wanna send me the missing hunk?


drivers/md/raid1.c: In function `r1bio_pool_alloc':
drivers/md/raid1.c:49: dereferencing pointer to incomplete type
drivers/md/raid1.c:53: dereferencing pointer to incomplete type
drivers/md/raid1.c:53: dereferencing pointer to incomplete type
drivers/md/raid1.c:53: dereferencing pointer to incomplete type
drivers/md/raid1.c:53: dereferencing pointer to incomplete type
drivers/md/raid1.c:53: dereferencing pointer to incomplete type
drivers/md/raid1.c:53: dereferencing pointer to incomplete type
drivers/md/raid1.c:55: dereferencing pointer to incomplete type
drivers/md/raid1.c: In function `r1buf_pool_alloc':
drivers/md/raid1.c:81: dereferencing pointer to incomplete type
drivers/md/raid1.c:88: dereferencing pointer to incomplete type
drivers/md/raid1.c:115: dereferencing pointer to incomplete type
drivers/md/raid1.c:77: warning: `j' might be used uninitialized in this function
drivers/md/raid1.c: In function `r1buf_pool_free':
drivers/md/raid1.c:132: dereferencing pointer to incomplete type
drivers/md/raid1.c: In function `init_resync':
drivers/md/raid1.c:985: structure has no member named `poolinfo'
drivers/md/raid1.c: In function `run':
drivers/md/raid1.c:1179: structure has no member named `poolinfo'
drivers/md/raid1.c:1179: structure has no member named `poolinfo'
drivers/md/raid1.c:1180: structure has no member named `poolinfo'
drivers/md/raid1.c:1182: structure has no member named `poolinfo'
drivers/md/raid1.c:1183: structure has no member named `poolinfo'
drivers/md/raid1.c:1186: structure has no member named `poolinfo'
drivers/md/raid1.c:1286: structure has no member named `poolinfo'
drivers/md/raid1.c:1287: structure has no member named `poolinfo'
drivers/md/raid1.c: In function `stop':
drivers/md/raid1.c:1305: structure has no member named `poolinfo'
drivers/md/raid1.c:1306: structure has no member named `poolinfo'
drivers/md/raid1.c: In function `raid1_reshape':
drivers/md/raid1.c:1356: dereferencing pointer to incomplete type
drivers/md/raid1.c:1357: dereferencing pointer to incomplete type
drivers/md/raid1.c:1386: structure has no member named `poolinfo'
drivers/md/raid1.c:1387: structure has no member named `poolinfo'

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

* Re: [PATCH] md - 8 of 8 - Support reshaping raid1 arrays - adding or removing drives.
  2004-05-28  7:31   ` Andrew Morton
@ 2004-05-28  8:41     ` Neil Brown
  0 siblings, 0 replies; 14+ messages in thread
From: Neil Brown @ 2004-05-28  8:41 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-raid

On Friday May 28, akpm@osdl.org wrote:
> NeilBrown <neilb@cse.unsw.edu.au> wrote:
> >
> > This requires allocating a new pool of "r1bio" structures which a different
> >  number of bios, suspending IO, and swapping the new pool in place of the old.
> >  (and a few other related changes).
> 
> Wanna send me the missing hunk?
> 

Blush. thats what you get for writing your own patch management
software...




diff ./include/linux/raid/raid1.h~current~ ./include/linux/raid/raid1.h
--- ./include/linux/raid/raid1.h~current~	2004-05-28 18:30:13.000000000 +1000
+++ ./include/linux/raid/raid1.h	2004-05-28 18:36:52.000000000 +1000
@@ -10,6 +10,20 @@ struct mirror_info {
 	sector_t	head_position;
 };
 
+/*
+ * memory pools need a pointer to the mddev, so they can force an unplug
+ * when memory is tight, and a count of the number of drives that the
+ * pool was allocated for, so they know how much to allocate and free.
+ * mddev->raid_disks cannot be used, as it can change while a pool is active
+ * These two datums are stored in a kmalloced struct.
+ */
+
+struct pool_info {
+	mddev_t *mddev;
+	int	raid_disks;
+};
+
+
 typedef struct r1bio_s r1bio_t;
 
 struct r1_private_data_s {
@@ -31,6 +45,8 @@ struct r1_private_data_s {
 	wait_queue_head_t	wait_idle;
 	wait_queue_head_t	wait_resume;
 
+	struct pool_info	*poolinfo;
+
 	mempool_t *r1bio_pool;
 	mempool_t *r1buf_pool;
 };


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

* Re: [PATCH] md - 8 of 8 - Support reshaping raid1 arrays - adding or removing drives.
  2004-05-28  6:45 ` [PATCH] md - 8 of 8 - Support reshaping raid1 arrays - adding or removing drives NeilBrown
  2004-05-28  7:31   ` Andrew Morton
@ 2004-05-28 13:32   ` Mario 'BitKoenig' Holbe
  2004-05-28 22:47     ` Neil Brown
  1 sibling, 1 reply; 14+ messages in thread
From: Mario 'BitKoenig' Holbe @ 2004-05-28 13:32 UTC (permalink / raw)
  To: linux-raid

NeilBrown <neilb@cse.unsw.edu.au> wrote:
> This requires allocating a new pool of "r1bio" structures which a different
> number of bios, suspending IO, and swapping the new pool in place of the old.
> (and a few other related changes).

Hmmm, I'm not really familiar with the md-code, but doesn't
do memory allocation at runtime re-introduce the 2.2. swap-
on-raid-problems?
Afair, they were due to swap out -> md driver allocates
something -> no ram -> swap out -> md driver allocates ...


regards,
   Mario
-- 
[mod_nessus for iauth]
<delta> "scanning your system...found depreciated OS...found
        hole...installing new OS...please reboot and reconnect now"


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

* 3ware 7506-8 and Tyan Thunder 2500, S1867, anyone?
  2004-05-28  6:45 ` [PATCH] md - 3 of 8 - Allow an md personality to refuse a hot-remove request NeilBrown
@ 2004-05-28 18:35   ` buggz
  0 siblings, 0 replies; 14+ messages in thread
From: buggz @ 2004-05-28 18:35 UTC (permalink / raw)
  To: linux-raid

Has anyone gotten this combination to work?
I cannot.
I get BLANK video, NO BIOS screens, NOTHING, whenever I have the 3ware
card installed.
I am using a Creative TNT2Ultra AGP video card.  I have tried ALL 6 PCI slots,
I have tried myrid array of BIOS settings.
I have even tried a PCI video card, ALL to same effect, NO VIDEO w/ the
3ware card installed.
I finally installed this card in a DEC Alpha PC164SX mb, I then get video
w/ the 3ware card installed!
Sigh...
I'm wondering now, can this card be used successfully on the Alpha mb?  If
so, I guess I will go that route and try Gentoo.
I am being told from Tyan that these 3ware cards were all built out of
PCI spec, a known standing problem.  Anyone know about that?



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

* Re: [PATCH] md - 8 of 8 - Support reshaping raid1 arrays - adding or removing drives.
  2004-05-28 13:32   ` Mario 'BitKoenig' Holbe
@ 2004-05-28 22:47     ` Neil Brown
  0 siblings, 0 replies; 14+ messages in thread
From: Neil Brown @ 2004-05-28 22:47 UTC (permalink / raw)
  To: Mario 'BitKoenig' Holbe; +Cc: linux-raid

On Friday May 28, Mario.Holbe@RZ.TU-Ilmenau.DE wrote:
> NeilBrown <neilb@cse.unsw.edu.au> wrote:
> > This requires allocating a new pool of "r1bio" structures which a different
> > number of bios, suspending IO, and swapping the new pool in place of the old.
> > (and a few other related changes).
> 
> Hmmm, I'm not really familiar with the md-code, but doesn't
> do memory allocation at runtime re-introduce the 2.2. swap-
> on-raid-problems?

No.

> Afair, they were due to swap out -> md driver allocates
> something -> no ram -> swap out -> md driver allocates ...
> 

This was not the problem.
When the md driver allocated memory in the write-out path it always
does it with a flag that say "don't trigger any write-out to while
trying to satisfy this request".  It also manages memory in  such a
way (using mempools) that if a memory request fails, it can just wait
for some pending requests to complete and it is certain to get some
memory soon.

Further, the "allocation a new pool" mentioned above is not in the
write-out path for raid1 so it has no bearing on these issues.

It allocates a new pool quite separately for the normally running of
raid1.  If all the needed allocations succeed, it blocks further
requests, swaps the new pool in place of the old and makes other
changes to reshape the array, and the allows further requests to
proceed.

The problem in 2.2 was only during resync.  Because of how buffers
were managed, swap could write out to a block that we in the process
of being re-synced, and the resync process would overwrite the new
swap data.  The buffer management is now completely different and this
is not a problem.

I hope this makes it a tiny bit clearer.

NeilBrown


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

end of thread, other threads:[~2004-05-28 22:47 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-05-28  6:45 [PATCH] md - 0 of 8 - Introduction NeilBrown
2004-05-28  6:45 ` [PATCH] md - 2 of 8 - Make sure md_check_recovery will remove a faulty device when ->nr_pending hits 0 NeilBrown
2004-05-28  6:45 ` [PATCH] md - 6 of 8 - Abort the resync of raid1 there is only one device NeilBrown
2004-05-28  6:45 ` [PATCH] md - 4 of 8 - Make sure the size of a raid5/6 array is a multiple of the chunk size NeilBrown
2004-05-28  6:45 ` [PATCH] md - 8 of 8 - Support reshaping raid1 arrays - adding or removing drives NeilBrown
2004-05-28  7:31   ` Andrew Morton
2004-05-28  8:41     ` Neil Brown
2004-05-28 13:32   ` Mario 'BitKoenig' Holbe
2004-05-28 22:47     ` Neil Brown
2004-05-28  6:45 ` [PATCH] md - 3 of 8 - Allow an md personality to refuse a hot-remove request NeilBrown
2004-05-28 18:35   ` 3ware 7506-8 and Tyan Thunder 2500, S1867, anyone? buggz
2004-05-28  6:45 ` [PATCH] md - 1 of 8 - Rationalise device selection in md/multipath NeilBrown
2004-05-28  6:45 ` [PATCH] md - 5 of 8 - Handle hot-add for arrays with non-persistent superblocks NeilBrown
2004-05-28  6:45 ` [PATCH] md - 7 of 8 - Allow md arrays to be resized if devices are large enough NeilBrown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox