linux-raid.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [md PATCH 00/28] md patches destined for -next and the next merge window
@ 2010-04-15  6:21 NeilBrown
  2010-04-15  6:21 ` [md PATCH 01/28] md: remove some dead fields from mddev_s NeilBrown
                   ` (28 more replies)
  0 siblings, 29 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

Hi all,
 I thought it was time I posted my patch queue for review to be sure
 it would be ready for the next merge window.

 Apart from sundry bug fixes and minor improvements there are two big
 themes here
 1/ enhancements to level conversion so e.g. we can now convert RAID0
    to RAID5 or RAID10 (near-2 only) and back.
 2/ general refactoring of bits of md code - some functions
    (e.g. do_md_stop) had become really big and were just a mess of
    stuff that all had to be done at much the same time.  It is now
    broken into somewhat meaningful parts.  There is a deeper reason
    for doing this refactoring .... you'll find out soon. :-)

 This is all available at
    git://neil.brown.name/md for-next
 and should be in linux-next in a day or two.


 All review, testing, and comments most welcome.

 Unfortunately it doesn't contain a fix for
   https://bugzilla.kernel.org/show_bug.cgi?id=15464

 I stared at that for some time and haven't made any headway.

NeilBrown

---

H Hartley Sweeten (1):
      drivers/md: Remove unnecessary casts of void *

Maciej Trela (2):
      md: Correctly handle device removal via sysfs
      md: notify level changes through sysfs.

NeilBrown (21):
      md: remove some dead fields from mddev_s
      md: discard StateChanged device flag.
      md: don't use mddev->raid_disks in raid0 or raid10 while array is active.
      md: Relax checks on ->max_disks when external metadata handling is used.
      md: remove unneeded sysfs files more promptly
      md: manage redundancy group in sysfs when changing level.
      md: add support for raid5 to raid4 conversion
      md/raid5: small tidyup in raid5_align_endio
      md: move io accounting out of personalities into md_make_request
      md: don't reference gendisk in getgeo
      md: remove ->changed and related code.
      md: factor do_md_run to separate accesses to ->gendisk
      md: start to refactor do_md_stop
      md: factor md_stop_writes out of do_md_stop.
      md: split md_set_readonly out of do_md_stop
      md: call md_stop_writes from md_stop
      md: pass mddev to make_request functions rather than request_queue
      md: factor out init code for an mddev
      md: don't unregister the thread in mddev_suspend
      md/raid1: fix confusing 'redirect sector' message.
      md/raid1: delay reads that could overtake behind-writes.

Paul Clements (1):
      md: expose max value of behind writes counter

Trela Maciej (1):
      md:Add support for Raid0->Raid5 takeover

Trela, Maciej (2):
      md: Add support for Raid5->Raid0 and Raid10->Raid0 takeover
      md: Add support for Raid0->Raid10 takeover


 drivers/md/bitmap.c    |   41 ++++-
 drivers/md/bitmap.h    |    2 
 drivers/md/faulty.c    |    9 -
 drivers/md/linear.c    |   15 --
 drivers/md/md.c        |  437 +++++++++++++++++++++++++++++-------------------
 drivers/md/md.h        |   10 -
 drivers/md/multipath.c |   13 -
 drivers/md/raid0.c     |  155 ++++++++++++++---
 drivers/md/raid0.h     |    3 
 drivers/md/raid1.c     |   52 +++---
 drivers/md/raid10.c    |  231 +++++++++++++++++--------
 drivers/md/raid10.h    |   12 +
 drivers/md/raid5.c     |   78 ++++++---
 13 files changed, 699 insertions(+), 359 deletions(-)

-- 
Signature


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

* [md PATCH 01/28] md: remove some dead fields from mddev_s
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 06/28] md:Add support for Raid0->Raid5 takeover NeilBrown
                   ` (27 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

These fields have never been used.
commit 4b6d287f627b5fb6a49f78f9e81649ff98c62bb7
added them, but also added identical files to bitmap_super_s,
and only used the latter.

So remove these unused fields.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.h |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/drivers/md/md.h b/drivers/md/md.h
index 8e4c75c..4dc6252 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -279,9 +279,6 @@ struct mddev_s
 	atomic_t			writes_pending; 
 	struct request_queue		*queue;	/* for plugging ... */
 
-	atomic_t                        write_behind; /* outstanding async IO */
-	unsigned int                    max_write_behind; /* 0 = sync */
-
 	struct bitmap                   *bitmap; /* the bitmap for the device */
 	struct {
 		struct file		*file; /* the bitmap file */



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

* [md PATCH 03/28] drivers/md: Remove unnecessary casts of void *
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (5 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 04/28] md: discard StateChanged device flag NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 07/28] md: Add support for Raid5->Raid0 and Raid10->Raid0 takeover NeilBrown
                   ` (21 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid; +Cc: H Hartley Sweeten

From: H Hartley Sweeten <hartleys@visionengravers.com>

void pointers do not need to be cast to other pointer types.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/bitmap.c    |    8 ++++----
 drivers/md/faulty.c    |    6 +++---
 drivers/md/multipath.c |    2 +-
 drivers/md/raid1.c     |    8 ++++----
 drivers/md/raid10.c    |    8 ++++----
 drivers/md/raid5.c     |   10 +++++-----
 6 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 6279393..49d6080 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -505,7 +505,7 @@ void bitmap_update_sb(struct bitmap *bitmap)
 		return;
 	}
 	spin_unlock_irqrestore(&bitmap->lock, flags);
-	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
+	sb = kmap_atomic(bitmap->sb_page, KM_USER0);
 	sb->events = cpu_to_le64(bitmap->mddev->events);
 	if (bitmap->mddev->events < bitmap->events_cleared) {
 		/* rocking back to read-only */
@@ -526,7 +526,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
 
 	if (!bitmap || !bitmap->sb_page)
 		return;
-	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
+	sb = kmap_atomic(bitmap->sb_page, KM_USER0);
 	printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));
 	printk(KERN_DEBUG "         magic: %08x\n", le32_to_cpu(sb->magic));
 	printk(KERN_DEBUG "       version: %d\n", le32_to_cpu(sb->version));
@@ -575,7 +575,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
 		return err;
 	}
 
-	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
+	sb = kmap_atomic(bitmap->sb_page, KM_USER0);
 
 	chunksize = le32_to_cpu(sb->chunksize);
 	daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ;
@@ -661,7 +661,7 @@ static int bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
 		return 0;
 	}
 	spin_unlock_irqrestore(&bitmap->lock, flags);
-	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
+	sb = kmap_atomic(bitmap->sb_page, KM_USER0);
 	old = le32_to_cpu(sb->state) & bits;
 	switch (op) {
 		case MASK_SET: sb->state |= cpu_to_le32(bits);
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index 713acd0..608a8d3 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -171,7 +171,7 @@ static void add_sector(conf_t *conf, sector_t start, int mode)
 static int make_request(struct request_queue *q, struct bio *bio)
 {
 	mddev_t *mddev = q->queuedata;
-	conf_t *conf = (conf_t*)mddev->private;
+	conf_t *conf = mddev->private;
 	int failit = 0;
 
 	if (bio_data_dir(bio) == WRITE) {
@@ -224,7 +224,7 @@ static int make_request(struct request_queue *q, struct bio *bio)
 
 static void status(struct seq_file *seq, mddev_t *mddev)
 {
-	conf_t *conf = (conf_t*)mddev->private;
+	conf_t *conf = mddev->private;
 	int n;
 
 	if ((n=atomic_read(&conf->counters[WriteTransient])) != 0)
@@ -327,7 +327,7 @@ static int run(mddev_t *mddev)
 
 static int stop(mddev_t *mddev)
 {
-	conf_t *conf = (conf_t *)mddev->private;
+	conf_t *conf = mddev->private;
 
 	kfree(conf);
 	mddev->private = NULL;
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 5558ebc..97befd5 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -84,7 +84,7 @@ static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err)
 static void multipath_end_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	struct multipath_bh * mp_bh = (struct multipath_bh *)(bio->bi_private);
+	struct multipath_bh *mp_bh = bio->bi_private;
 	multipath_conf_t *conf = mp_bh->mddev->private;
 	mdk_rdev_t *rdev = conf->multipaths[mp_bh->path].rdev;
 
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index f741f77..ff6f97b 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -262,7 +262,7 @@ static inline void update_head_pos(int disk, r1bio_t *r1_bio)
 static void raid1_end_read_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
+	r1bio_t *r1_bio = bio->bi_private;
 	int mirror;
 	conf_t *conf = r1_bio->mddev->private;
 
@@ -307,7 +307,7 @@ static void raid1_end_read_request(struct bio *bio, int error)
 static void raid1_end_write_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
+	r1bio_t *r1_bio = bio->bi_private;
 	int mirror, behind = test_bit(R1BIO_BehindIO, &r1_bio->state);
 	conf_t *conf = r1_bio->mddev->private;
 	struct bio *to_put = NULL;
@@ -1222,7 +1222,7 @@ abort:
 
 static void end_sync_read(struct bio *bio, int error)
 {
-	r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
+	r1bio_t *r1_bio = bio->bi_private;
 	int i;
 
 	for (i=r1_bio->mddev->raid_disks; i--; )
@@ -1245,7 +1245,7 @@ static void end_sync_read(struct bio *bio, int error)
 static void end_sync_write(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
+	r1bio_t *r1_bio = bio->bi_private;
 	mddev_t *mddev = r1_bio->mddev;
 	conf_t *conf = mddev->private;
 	int i;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index b4ba41e..b90fef6 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -254,7 +254,7 @@ static inline void update_head_pos(int slot, r10bio_t *r10_bio)
 static void raid10_end_read_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
+	r10bio_t *r10_bio = bio->bi_private;
 	int slot, dev;
 	conf_t *conf = r10_bio->mddev->private;
 
@@ -295,7 +295,7 @@ static void raid10_end_read_request(struct bio *bio, int error)
 static void raid10_end_write_request(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
+	r10bio_t *r10_bio = bio->bi_private;
 	int slot, dev;
 	conf_t *conf = r10_bio->mddev->private;
 
@@ -1223,7 +1223,7 @@ abort:
 
 static void end_sync_read(struct bio *bio, int error)
 {
-	r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
+	r10bio_t *r10_bio = bio->bi_private;
 	conf_t *conf = r10_bio->mddev->private;
 	int i,d;
 
@@ -1260,7 +1260,7 @@ static void end_sync_read(struct bio *bio, int error)
 static void end_sync_write(struct bio *bio, int error)
 {
 	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
+	r10bio_t *r10_bio = bio->bi_private;
 	mddev_t *mddev = r10_bio->mddev;
 	conf_t *conf = mddev->private;
 	int i,d;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 70ffbd0..04139d9 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1618,7 +1618,7 @@ static void raid5_build_block(struct stripe_head *sh, int i, int previous)
 static void error(mddev_t *mddev, mdk_rdev_t *rdev)
 {
 	char b[BDEVNAME_SIZE];
-	raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
+	raid5_conf_t *conf = mddev->private;
 	pr_debug("raid5: error called\n");
 
 	if (!test_bit(Faulty, &rdev->flags)) {
@@ -4057,7 +4057,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
 	 * As the reads complete, handle_stripe will copy the data
 	 * into the destination stripe and release that stripe.
 	 */
-	raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
+	raid5_conf_t *conf = mddev->private;
 	struct stripe_head *sh;
 	sector_t first_sector, last_sector;
 	int raid_disks = conf->previous_raid_disks;
@@ -4266,7 +4266,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
 /* FIXME go_faster isn't used */
 static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
-	raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
+	raid5_conf_t *conf = mddev->private;
 	struct stripe_head *sh;
 	sector_t max_sector = mddev->dev_sectors;
 	int sync_blocks;
@@ -5130,7 +5130,7 @@ abort:
 
 static int stop(mddev_t *mddev)
 {
-	raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
+	raid5_conf_t *conf = mddev->private;
 
 	md_unregister_thread(mddev->thread);
 	mddev->thread = NULL;
@@ -5178,7 +5178,7 @@ static void printall(struct seq_file *seq, raid5_conf_t *conf)
 
 static void status(struct seq_file *seq, mddev_t *mddev)
 {
-	raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
+	raid5_conf_t *conf = mddev->private;
 	int i;
 
 	seq_printf(seq, " level %d, %dk chunk, algorithm %d", mddev->level,



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

* [md PATCH 02/28] md: expose max value of behind writes counter
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
  2010-04-15  6:21 ` [md PATCH 01/28] md: remove some dead fields from mddev_s NeilBrown
  2010-04-15  6:21 ` [md PATCH 06/28] md:Add support for Raid0->Raid5 takeover NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 05/28] md: don't use mddev->raid_disks in raid0 or raid10 while array is active NeilBrown
                   ` (25 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid; +Cc: Paul Clements

From: Paul Clements <paul.clements@steeleye.com>

Keep track of the maximum number of concurrent write-behind requests
for an md array and exposed this number in sysfs at
   md/bitmap/max_backlog_used

Writing any value to this file will clear it.

This allows userspace to be involved in tuning bitmap/backlog.

Signed-off-by: Paul Clements <paul.clements@steeleye.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/bitmap.c |   29 ++++++++++++++++++++++++++++-
 drivers/md/bitmap.h |    1 +
 2 files changed, 29 insertions(+), 1 deletions(-)

diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 26ac8aa..6279393 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -1292,9 +1292,14 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
 	if (!bitmap) return 0;
 
 	if (behind) {
+		int bw;
 		atomic_inc(&bitmap->behind_writes);
+		bw = atomic_read(&bitmap->behind_writes);
+		if (bw > bitmap->behind_writes_used)
+			bitmap->behind_writes_used = bw;
+
 		PRINTK(KERN_DEBUG "inc write-behind count %d/%d\n",
-		  atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
+		       bw, bitmap->max_write_behind);
 	}
 
 	while (sectors) {
@@ -2006,6 +2011,27 @@ static ssize_t can_clear_store(mddev_t *mddev, const char *buf, size_t len)
 static struct md_sysfs_entry bitmap_can_clear =
 __ATTR(can_clear, S_IRUGO|S_IWUSR, can_clear_show, can_clear_store);
 
+static ssize_t
+behind_writes_used_show(mddev_t *mddev, char *page)
+{
+	if (mddev->bitmap == NULL)
+		return sprintf(page, "0\n");
+	return sprintf(page, "%lu\n",
+		       mddev->bitmap->behind_writes_used);
+}
+
+static ssize_t
+behind_writes_used_reset(mddev_t *mddev, const char *buf, size_t len)
+{
+	if (mddev->bitmap)
+		mddev->bitmap->behind_writes_used = 0;
+	return len;
+}
+
+static struct md_sysfs_entry max_backlog_used =
+__ATTR(max_backlog_used, S_IRUGO | S_IWUSR,
+       behind_writes_used_show, behind_writes_used_reset);
+
 static struct attribute *md_bitmap_attrs[] = {
 	&bitmap_location.attr,
 	&bitmap_timeout.attr,
@@ -2013,6 +2039,7 @@ static struct attribute *md_bitmap_attrs[] = {
 	&bitmap_chunksize.attr,
 	&bitmap_metadata.attr,
 	&bitmap_can_clear.attr,
+	&max_backlog_used.attr,
 	NULL
 };
 struct attribute_group md_bitmap_group = {
diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h
index cb821d7..aa82b7c 100644
--- a/drivers/md/bitmap.h
+++ b/drivers/md/bitmap.h
@@ -227,6 +227,7 @@ struct bitmap {
 	int allclean;
 
 	atomic_t behind_writes;
+	unsigned long behind_writes_used; /* highest actual value at runtime */
 
 	/*
 	 * the bitmap daemon - periodically wakes up and sweeps the bitmap



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

* [md PATCH 04/28] md: discard StateChanged device flag.
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (4 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 08/28] md: Add support for Raid0->Raid10 takeover NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 03/28] drivers/md: Remove unnecessary casts of void * NeilBrown
                   ` (22 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

This was needed when sysfs files could only be 'notified'
from process context.  Now that we have sys_notify_direct,
we can call it directly from an interrupt.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c |    7 +------
 drivers/md/md.h |    3 ---
 2 files changed, 1 insertions(+), 9 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index a20a71e..509a5e4 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -5899,7 +5899,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
 	mddev->pers->error_handler(mddev,rdev);
 	if (mddev->degraded)
 		set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
-	set_bit(StateChanged, &rdev->flags);
+	sysfs_notify_dirent(rdev->sysfs_state);
 	set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
@@ -6891,11 +6891,6 @@ void md_check_recovery(mddev_t *mddev)
 		if (mddev->flags)
 			md_update_sb(mddev, 0);
 
-		list_for_each_entry(rdev, &mddev->disks, same_set)
-			if (test_and_clear_bit(StateChanged, &rdev->flags))
-				sysfs_notify_dirent(rdev->sysfs_state);
-
-
 		if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
 		    !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) {
 			/* resync/recovery still happening */
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 4dc6252..b9dc3ea 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -74,9 +74,6 @@ struct mdk_rdev_s
 #define Blocked		8		/* An error occured on an externally
 					 * managed array, don't allow writes
 					 * until it is cleared */
-#define StateChanged	9		/* Faulty or Blocked has changed during
-					 * interrupt, so it needs to be
-					 * notified by the thread */
 	wait_queue_head_t blocked_wait;
 
 	int desc_nr;			/* descriptor index in the superblock */



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

* [md PATCH 05/28] md: don't use mddev->raid_disks in raid0 or raid10 while array is active.
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (2 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 02/28] md: expose max value of behind writes counter NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 08/28] md: Add support for Raid0->Raid10 takeover NeilBrown
                   ` (24 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

In a subsequent patch we will make it possible to change
mddev->raid_disks while a RAID0 or RAID10 array is active.  This is
part of the process of reshaping such an array.

This means that we cannot use this value while processes requests
(it is OK to use it during initialisation as we are locked against
changes then).
Both RAID0 and RAID10 have the same value stored in the private data
structure, so use that value instead.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/raid0.c  |   15 ++++++++++-----
 drivers/md/raid10.c |   16 ++++++++--------
 2 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 377cf2a..c2e0d1d 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -28,9 +28,10 @@ static void raid0_unplug(struct request_queue *q)
 	mddev_t *mddev = q->queuedata;
 	raid0_conf_t *conf = mddev->private;
 	mdk_rdev_t **devlist = conf->devlist;
+	int raid_disks = conf->strip_zone[0].nb_dev;
 	int i;
 
-	for (i=0; i<mddev->raid_disks; i++) {
+	for (i=0; i < raid_disks; i++) {
 		struct request_queue *r_queue = bdev_get_queue(devlist[i]->bdev);
 
 		blk_unplug(r_queue);
@@ -42,12 +43,13 @@ static int raid0_congested(void *data, int bits)
 	mddev_t *mddev = data;
 	raid0_conf_t *conf = mddev->private;
 	mdk_rdev_t **devlist = conf->devlist;
+	int raid_disks = conf->strip_zone[0].nb_dev;
 	int i, ret = 0;
 
 	if (mddev_congested(mddev, bits))
 		return 1;
 
-	for (i = 0; i < mddev->raid_disks && !ret ; i++) {
+	for (i = 0; i < raid_disks && !ret ; i++) {
 		struct request_queue *q = bdev_get_queue(devlist[i]->bdev);
 
 		ret |= bdi_congested(&q->backing_dev_info, bits);
@@ -65,6 +67,7 @@ static void dump_zones(mddev_t *mddev)
 	sector_t zone_start = 0;
 	char b[BDEVNAME_SIZE];
 	raid0_conf_t *conf = mddev->private;
+	int raid_disks = conf->strip_zone[0].nb_dev;
 	printk(KERN_INFO "******* %s configuration *********\n",
 		mdname(mddev));
 	h = 0;
@@ -72,7 +75,7 @@ static void dump_zones(mddev_t *mddev)
 		printk(KERN_INFO "zone%d=[", j);
 		for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
 			printk("%s/",
-			bdevname(conf->devlist[j*mddev->raid_disks
+			bdevname(conf->devlist[j*raid_disks
 						+ k]->bdev, b));
 		printk("]\n");
 
@@ -401,6 +404,7 @@ static mdk_rdev_t *map_sector(mddev_t *mddev, struct strip_zone *zone,
 	unsigned int sect_in_chunk;
 	sector_t chunk;
 	raid0_conf_t *conf = mddev->private;
+	int raid_disks = conf->strip_zone[0].nb_dev;
 	unsigned int chunk_sects = mddev->chunk_sectors;
 
 	if (is_power_of_2(chunk_sects)) {
@@ -423,7 +427,7 @@ static mdk_rdev_t *map_sector(mddev_t *mddev, struct strip_zone *zone,
 	*	+ the position in the chunk
 	*/
 	*sector_offset = (chunk * chunk_sects) + sect_in_chunk;
-	return conf->devlist[(zone - conf->strip_zone)*mddev->raid_disks
+	return conf->devlist[(zone - conf->strip_zone)*raid_disks
 			     + sector_div(sector, zone->nb_dev)];
 }
 
@@ -518,6 +522,7 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev)
 	int j, k, h;
 	char b[BDEVNAME_SIZE];
 	raid0_conf_t *conf = mddev->private;
+	int raid_disks = conf->strip_zone[0].nb_dev;
 
 	sector_t zone_size;
 	sector_t zone_start = 0;
@@ -528,7 +533,7 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev)
 		seq_printf(seq, "=[");
 		for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
 			seq_printf(seq, "%s/", bdevname(
-				conf->devlist[j*mddev->raid_disks + k]
+				conf->devlist[j*raid_disks + k]
 						->bdev, b));
 
 		zone_size  = conf->strip_zone[j].zone_end - zone_start;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index b90fef6..044c115 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -600,7 +600,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->mirrors[i].rdev);
 		if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) {
 			struct request_queue *r_queue = bdev_get_queue(rdev->bdev);
@@ -634,7 +634,7 @@ static int raid10_congested(void *data, int bits)
 	if (mddev_congested(mddev, bits))
 		return 1;
 	rcu_read_lock();
-	for (i = 0; i < mddev->raid_disks && ret == 0; i++) {
+	for (i = 0; i < conf->raid_disks && ret == 0; i++) {
 		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
 		if (rdev && !test_bit(Faulty, &rdev->flags)) {
 			struct request_queue *q = bdev_get_queue(rdev->bdev);
@@ -1131,7 +1131,7 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 	int mirror;
 	mirror_info_t *p;
 	int first = 0;
-	int last = mddev->raid_disks - 1;
+	int last = conf->raid_disks - 1;
 
 	if (mddev->recovery_cp < MaxSector)
 		/* only hot-add to in-sync arrays, as recovery is
@@ -2139,7 +2139,7 @@ raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks)
 	conf_t *conf = mddev->private;
 
 	if (!raid_disks)
-		raid_disks = mddev->raid_disks;
+		raid_disks = conf->raid_disks;
 	if (!sectors)
 		sectors = mddev->dev_sectors;
 
@@ -2250,7 +2250,7 @@ static int run(mddev_t *mddev)
 
 	list_for_each_entry(rdev, &mddev->disks, same_set) {
 		disk_idx = rdev->raid_disk;
-		if (disk_idx >= mddev->raid_disks
+		if (disk_idx >= conf->raid_disks
 		    || disk_idx < 0)
 			continue;
 		disk = conf->mirrors + disk_idx;
@@ -2311,8 +2311,8 @@ static int run(mddev_t *mddev)
 		       mdname(mddev));
 	printk(KERN_INFO
 		"raid10: raid set %s active with %d out of %d devices\n",
-		mdname(mddev), mddev->raid_disks - mddev->degraded,
-		mddev->raid_disks);
+		mdname(mddev), conf->raid_disks - mddev->degraded,
+		conf->raid_disks);
 	/*
 	 * Ok, everything is just fine now
 	 */
@@ -2335,7 +2335,7 @@ static int run(mddev_t *mddev)
 			mddev->queue->backing_dev_info.ra_pages = 2* stripe;
 	}
 
-	if (conf->near_copies < mddev->raid_disks)
+	if (conf->near_copies < conf->raid_disks)
 		blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec);
 	md_integrity_register(mddev);
 	return 0;



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

* [md PATCH 06/28] md:Add support for Raid0->Raid5 takeover
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
  2010-04-15  6:21 ` [md PATCH 01/28] md: remove some dead fields from mddev_s NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 02/28] md: expose max value of behind writes counter NeilBrown
                   ` (26 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid; +Cc: Maciej Trela

From: Trela Maciej <Maciej.Trela@intel.com>

Signed-off-by: Maciej Trela <maciej.trela@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c    |   13 +++++++++++++
 drivers/md/raid5.c |   26 ++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 509a5e4..ccfbd4a 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2973,6 +2973,19 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
 	/* Looks like we have a winner */
 	mddev_suspend(mddev);
 	mddev->pers->stop(mddev);
+	if (mddev->pers->sync_request == NULL &&
+	    mddev->external) {
+		/* We are converting from a no-redundancy array
+		 * to a redundancy array and metadata is managed
+		 * externally so we need to be sure that writes
+		 * won't block due to a need to transition
+		 *      clean->dirty
+		 * until external management is started.
+		 */
+		mddev->in_sync = 0;
+		mddev->safemode_delay = 0;
+		mddev->safemode = 0;
+	}
 	module_put(mddev->pers->owner);
 	/* Invalidate devices that are now superfluous */
 	list_for_each_entry(rdev, &mddev->disks, same_set)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 04139d9..c54ddbc 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -52,6 +52,7 @@
 #include <linux/cpu.h>
 #include "md.h"
 #include "raid5.h"
+#include "raid0.h"
 #include "bitmap.h"
 
 /*
@@ -5616,6 +5617,21 @@ static void raid5_quiesce(mddev_t *mddev, int state)
 }
 
 
+static void *raid5_takeover_raid0(mddev_t *mddev)
+{
+
+	mddev->new_level = 5;
+	mddev->new_layout = ALGORITHM_PARITY_N;
+	mddev->new_chunk_sectors = mddev->chunk_sectors;
+	mddev->raid_disks += 1;
+	mddev->delta_disks = 1;
+	/* make sure it will be not marked as dirty */
+	mddev->recovery_cp = MaxSector;
+
+	return setup_conf(mddev);
+}
+
+
 static void *raid5_takeover_raid1(mddev_t *mddev)
 {
 	int chunksect;
@@ -5745,6 +5761,16 @@ static void *raid5_takeover(mddev_t *mddev)
 	 *  raid4 - trivial - just use a raid4 layout.
 	 *  raid6 - Providing it is a *_6 layout
 	 */
+	if (mddev->level == 0) {
+		/* for raid0 takeover only one zone is supported */
+		struct raid0_private_data *raid0_priv
+			= mddev->private;
+		if (raid0_priv->nr_strip_zones > 1) {
+			printk(KERN_ERR "md: cannot takeover raid 0 with more than one zone.\n");
+			return ERR_PTR(-EINVAL);
+		}
+		return raid5_takeover_raid0(mddev);
+	}
 
 	if (mddev->level == 1)
 		return raid5_takeover_raid1(mddev);



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

* [md PATCH 07/28] md: Add support for Raid5->Raid0 and Raid10->Raid0 takeover
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (6 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 03/28] drivers/md: Remove unnecessary casts of void * NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 27/28] md/raid1: fix confusing 'redirect sector' message NeilBrown
                   ` (20 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid; +Cc: Maciej Trela

From: Trela, Maciej <Maciej.Trela@intel.com>

Signed-off-by: Maciej Trela <maciej.trela@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c    |    7 +++
 drivers/md/raid0.c |  125 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 drivers/md/raid0.h |    3 +
 3 files changed, 129 insertions(+), 6 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index ccfbd4a..be16462 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -3000,6 +3000,13 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
 	mddev->layout = mddev->new_layout;
 	mddev->chunk_sectors = mddev->new_chunk_sectors;
 	mddev->delta_disks = 0;
+	if (mddev->pers->sync_request == NULL) {
+		/* this is now an array without redundancy, so
+		 * it must always be in_sync
+		 */
+		mddev->in_sync = 1;
+		del_timer_sync(&mddev->safemode_timer);
+	}
 	pers->run(mddev);
 	mddev_resume(mddev);
 	set_bit(MD_CHANGE_DEVS, &mddev->flags);
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index c2e0d1d..afddf62 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -22,6 +22,7 @@
 #include <linux/seq_file.h>
 #include "md.h"
 #include "raid0.h"
+#include "raid5.h"
 
 static void raid0_unplug(struct request_queue *q)
 {
@@ -90,7 +91,7 @@ static void dump_zones(mddev_t *mddev)
 	printk(KERN_INFO "**********************************\n\n");
 }
 
-static int create_strip_zones(mddev_t *mddev)
+static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf)
 {
 	int i, c, err;
 	sector_t curr_zone_end, sectors;
@@ -164,6 +165,10 @@ static int create_strip_zones(mddev_t *mddev)
 	list_for_each_entry(rdev1, &mddev->disks, same_set) {
 		int j = rdev1->raid_disk;
 
+		if (mddev->level == 10)
+			/* taking over a raid10-n2 array */
+			j /= 2;
+
 		if (j < 0 || j >= mddev->raid_disks) {
 			printk(KERN_ERR "raid0: bad disk number %d - "
 				"aborting!\n", j);
@@ -264,13 +269,14 @@ static int create_strip_zones(mddev_t *mddev)
 			 (mddev->chunk_sectors << 9) * mddev->raid_disks);
 
 	printk(KERN_INFO "raid0: done.\n");
-	mddev->private = conf;
+	*private_conf = conf;
+
 	return 0;
 abort:
 	kfree(conf->strip_zone);
 	kfree(conf->devlist);
 	kfree(conf);
-	mddev->private = NULL;
+	*private_conf = NULL;
 	return err;
 }
 
@@ -321,6 +327,7 @@ static sector_t raid0_size(mddev_t *mddev, sector_t sectors, int raid_disks)
 
 static int raid0_run(mddev_t *mddev)
 {
+	raid0_conf_t *conf;
 	int ret;
 
 	if (mddev->chunk_sectors == 0) {
@@ -332,9 +339,20 @@ static int raid0_run(mddev_t *mddev)
 	blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
 	mddev->queue->queue_lock = &mddev->queue->__queue_lock;
 
-	ret = create_strip_zones(mddev);
-	if (ret < 0)
-		return ret;
+	/* if private is not null, we are here after takeover */
+	if (mddev->private == NULL) {
+		ret = create_strip_zones(mddev, &conf);
+		if (ret < 0)
+			return ret;
+		mddev->private = conf;
+	}
+	conf = mddev->private;
+	if (conf->scale_raid_disks) {
+		int i;
+		for (i=0; i < conf->strip_zone[0].nb_dev; i++)
+			conf->devlist[i]->raid_disk /= conf->scale_raid_disks;
+		/* FIXME update sysfs rd links */
+	}
 
 	/* calculate array device size */
 	md_set_array_sectors(mddev, raid0_size(mddev, 0, 0));
@@ -548,6 +566,99 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev)
 	return;
 }
 
+static void *raid0_takeover_raid5(mddev_t *mddev)
+{
+	mdk_rdev_t *rdev;
+	raid0_conf_t *priv_conf;
+
+	if (mddev->degraded != 1) {
+		printk(KERN_ERR "md: raid5 must be degraded! Degraded disks: %d\n",
+		       mddev->degraded);
+		return ERR_PTR(-EINVAL);
+	}
+
+	list_for_each_entry(rdev, &mddev->disks, same_set) {
+		/* check slot number for a disk */
+		if (rdev->raid_disk == mddev->raid_disks-1) {
+			printk(KERN_ERR "md: raid5 must have missing parity disk!\n");
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	/* Set new parameters */
+	mddev->new_level = 0;
+	mddev->new_chunk_sectors = mddev->chunk_sectors;
+	mddev->raid_disks--;
+	mddev->delta_disks = -1;
+	/* make sure it will be not marked as dirty */
+	mddev->recovery_cp = MaxSector;
+
+	create_strip_zones(mddev, &priv_conf);
+	return priv_conf;
+}
+
+static void *raid0_takeover_raid10(mddev_t *mddev)
+{
+	raid0_conf_t *priv_conf;
+
+	/* Check layout:
+	 *  - far_copies must be 1
+	 *  - near_copies must be 2
+	 *  - disks number must be even
+	 *  - all mirrors must be already degraded
+	 */
+	if (mddev->layout != ((1 << 8) + 2)) {
+		printk(KERN_ERR "md: Raid0 cannot takover layout: %x\n",
+		       mddev->layout);
+		return ERR_PTR(-EINVAL);
+	}
+	if (mddev->raid_disks & 1) {
+		printk(KERN_ERR "md: Raid0 cannot takover Raid10 with odd disk number.\n");
+		return ERR_PTR(-EINVAL);
+	}
+	if (mddev->degraded != (mddev->raid_disks>>1)) {
+		printk(KERN_ERR "md: All mirrors must be already degraded!\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* Set new parameters */
+	mddev->new_level = 0;
+	mddev->new_chunk_sectors = mddev->chunk_sectors;
+	mddev->delta_disks = - mddev->raid_disks / 2;
+	mddev->raid_disks += mddev->delta_disks;
+	mddev->degraded = 0;
+	/* make sure it will be not marked as dirty */
+	mddev->recovery_cp = MaxSector;
+
+	create_strip_zones(mddev, &priv_conf);
+	priv_conf->scale_raid_disks = 2;
+	return priv_conf;
+}
+
+static void *raid0_takeover(mddev_t *mddev)
+{
+	/* raid0 can take over:
+	 *  raid5 - providing it is Raid4 layout and one disk is faulty
+	 *  raid10 - assuming we have all necessary active disks
+	 */
+	if (mddev->level == 5) {
+		if (mddev->layout == ALGORITHM_PARITY_N)
+			return raid0_takeover_raid5(mddev);
+
+		printk(KERN_ERR "md: Raid can only takeover Raid5 with layout: %d\n",
+		       ALGORITHM_PARITY_N);
+	}
+
+	if (mddev->level == 10)
+		return raid0_takeover_raid10(mddev);
+
+	return ERR_PTR(-EINVAL);
+}
+
+static void raid0_quiesce(mddev_t *mddev, int state)
+{
+}
+
 static struct mdk_personality raid0_personality=
 {
 	.name		= "raid0",
@@ -558,6 +669,8 @@ static struct mdk_personality raid0_personality=
 	.stop		= raid0_stop,
 	.status		= raid0_status,
 	.size		= raid0_size,
+	.takeover	= raid0_takeover,
+	.quiesce	= raid0_quiesce,
 };
 
 static int __init raid0_init (void)
diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h
index 91f8e87..d724e66 100644
--- a/drivers/md/raid0.h
+++ b/drivers/md/raid0.h
@@ -13,6 +13,9 @@ struct raid0_private_data
 	struct strip_zone *strip_zone;
 	mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */
 	int nr_strip_zones;
+	int scale_raid_disks; /* divide rdev->raid_disks by this in run()
+			       * to handle conversion from raid10
+			       */
 };
 
 typedef struct raid0_private_data raid0_conf_t;



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

* [md PATCH 08/28] md: Add support for Raid0->Raid10 takeover
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (3 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 05/28] md: don't use mddev->raid_disks in raid0 or raid10 while array is active NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 04/28] md: discard StateChanged device flag NeilBrown
                   ` (23 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid; +Cc: Maciej Trela

From: Trela, Maciej <Maciej.Trela@intel.com>

Signed-off-by: Maciej Trela <maciej.trela@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/raid10.c |  193 ++++++++++++++++++++++++++++++++++++++-------------
 drivers/md/raid10.h |   12 +++
 2 files changed, 154 insertions(+), 51 deletions(-)

diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 044c115..beab7f6 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -23,6 +23,7 @@
 #include <linux/seq_file.h>
 #include "md.h"
 #include "raid10.h"
+#include "raid0.h"
 #include "bitmap.h"
 
 /*
@@ -2141,7 +2142,7 @@ raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks)
 	if (!raid_disks)
 		raid_disks = conf->raid_disks;
 	if (!sectors)
-		sectors = mddev->dev_sectors;
+		sectors = conf->dev_sectors;
 
 	size = sectors >> conf->chunk_shift;
 	sector_div(size, conf->far_copies);
@@ -2151,62 +2152,60 @@ raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks)
 	return size << conf->chunk_shift;
 }
 
-static int run(mddev_t *mddev)
+
+static conf_t *setup_conf(mddev_t *mddev)
 {
-	conf_t *conf;
-	int i, disk_idx, chunk_size;
-	mirror_info_t *disk;
-	mdk_rdev_t *rdev;
+	conf_t *conf = NULL;
 	int nc, fc, fo;
 	sector_t stride, size;
+	int err = -EINVAL;
 
 	if (mddev->chunk_sectors < (PAGE_SIZE >> 9) ||
 	    !is_power_of_2(mddev->chunk_sectors)) {
 		printk(KERN_ERR "md/raid10: chunk size must be "
 		       "at least PAGE_SIZE(%ld) and be a power of 2.\n", PAGE_SIZE);
-		return -EINVAL;
+		goto out;
 	}
 
 	nc = mddev->layout & 255;
 	fc = (mddev->layout >> 8) & 255;
 	fo = mddev->layout & (1<<16);
+
 	if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
 	    (mddev->layout >> 17)) {
 		printk(KERN_ERR "raid10: %s: unsupported raid10 layout: 0x%8x\n",
 		       mdname(mddev), mddev->layout);
 		goto out;
 	}
-	/*
-	 * copy the already verified devices into our private RAID10
-	 * bookkeeping area. [whatever we allocate in run(),
-	 * should be freed in stop()]
-	 */
+
+	err = -ENOMEM;
 	conf = kzalloc(sizeof(conf_t), GFP_KERNEL);
-	mddev->private = conf;
-	if (!conf) {
-		printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
-			mdname(mddev));
+	if (!conf)
 		goto out;
-	}
+
 	conf->mirrors = kzalloc(sizeof(struct mirror_info)*mddev->raid_disks,
-				 GFP_KERNEL);
-	if (!conf->mirrors) {
-		printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
-		       mdname(mddev));
-		goto out_free_conf;
-	}
+				GFP_KERNEL);
+	if (!conf->mirrors)
+		goto out;
 
 	conf->tmppage = alloc_page(GFP_KERNEL);
 	if (!conf->tmppage)
-		goto out_free_conf;
+		goto out;
+
 
 	conf->raid_disks = mddev->raid_disks;
 	conf->near_copies = nc;
 	conf->far_copies = fc;
 	conf->copies = nc*fc;
 	conf->far_offset = fo;
-	conf->chunk_mask = mddev->chunk_sectors - 1;
-	conf->chunk_shift = ffz(~mddev->chunk_sectors);
+	conf->chunk_mask = mddev->new_chunk_sectors - 1;
+	conf->chunk_shift = ffz(~mddev->new_chunk_sectors);
+
+	conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc,
+					   r10bio_pool_free, conf);
+	if (!conf->r10bio_pool)
+		goto out;
+
 	size = mddev->dev_sectors >> conf->chunk_shift;
 	sector_div(size, fc);
 	size = size * conf->raid_disks;
@@ -2220,7 +2219,8 @@ static int run(mddev_t *mddev)
 	 */
 	stride += conf->raid_disks - 1;
 	sector_div(stride, conf->raid_disks);
-	mddev->dev_sectors = stride << conf->chunk_shift;
+
+	conf->dev_sectors = stride << conf->chunk_shift;
 
 	if (fo)
 		stride = 1;
@@ -2228,18 +2228,63 @@ static int run(mddev_t *mddev)
 		sector_div(stride, fc);
 	conf->stride = stride << conf->chunk_shift;
 
-	conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc,
-						r10bio_pool_free, conf);
-	if (!conf->r10bio_pool) {
-		printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
-			mdname(mddev));
-		goto out_free_conf;
-	}
 
-	conf->mddev = mddev;
 	spin_lock_init(&conf->device_lock);
+	INIT_LIST_HEAD(&conf->retry_list);
+
+	spin_lock_init(&conf->resync_lock);
+	init_waitqueue_head(&conf->wait_barrier);
+
+	conf->thread = md_register_thread(raid10d, mddev, NULL);
+	if (!conf->thread)
+		goto out;
+
+	conf->scale_disks = 0;
+	conf->mddev = mddev;
+	return conf;
+
+ out:
+	printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
+	       mdname(mddev));
+	if (conf) {
+		if (conf->r10bio_pool)
+			mempool_destroy(conf->r10bio_pool);
+		kfree(conf->mirrors);
+		safe_put_page(conf->tmppage);
+		kfree(conf);
+	}
+	return ERR_PTR(err);
+}
+
+static int run(mddev_t *mddev)
+{
+	conf_t *conf;
+	int i, disk_idx, chunk_size;
+	mirror_info_t *disk;
+	mdk_rdev_t *rdev;
+	sector_t size;
+
+	/*
+	 * copy the already verified devices into our private RAID10
+	 * bookkeeping area. [whatever we allocate in run(),
+	 * should be freed in stop()]
+	 */
+
+	if (mddev->private == NULL) {
+		conf = setup_conf(mddev);
+		if (IS_ERR(conf))
+			return PTR_ERR(conf);
+		mddev->private = conf;
+	}
+	conf = mddev->private;
+	if (!conf)
+		goto out;
+
 	mddev->queue->queue_lock = &conf->device_lock;
 
+	mddev->thread = conf->thread;
+	conf->thread = NULL;
+
 	chunk_size = mddev->chunk_sectors << 9;
 	blk_queue_io_min(mddev->queue, chunk_size);
 	if (conf->raid_disks % conf->near_copies)
@@ -2253,6 +2298,11 @@ static int run(mddev_t *mddev)
 		if (disk_idx >= conf->raid_disks
 		    || disk_idx < 0)
 			continue;
+		if (conf->scale_disks) {
+			disk_idx *= conf->scale_disks;
+			rdev->raid_disk = disk_idx;
+			/* MOVE 'rd%d' link !! */
+		}
 		disk = conf->mirrors + disk_idx;
 
 		disk->rdev = rdev;
@@ -2270,11 +2320,6 @@ static int run(mddev_t *mddev)
 
 		disk->head_position = 0;
 	}
-	INIT_LIST_HEAD(&conf->retry_list);
-
-	spin_lock_init(&conf->resync_lock);
-	init_waitqueue_head(&conf->wait_barrier);
-
 	/* need to check that every block has at least one working mirror */
 	if (!enough(conf)) {
 		printk(KERN_ERR "raid10: not enough operational mirrors for %s\n",
@@ -2296,15 +2341,6 @@ static int run(mddev_t *mddev)
 		}
 	}
 
-
-	mddev->thread = md_register_thread(raid10d, mddev, NULL);
-	if (!mddev->thread) {
-		printk(KERN_ERR
-		       "raid10: couldn't allocate thread for %s\n",
-		       mdname(mddev));
-		goto out_free_conf;
-	}
-
 	if (mddev->recovery_cp != MaxSector)
 		printk(KERN_NOTICE "raid10: %s is not clean"
 		       " -- starting background reconstruction\n",
@@ -2316,8 +2352,9 @@ static int run(mddev_t *mddev)
 	/*
 	 * Ok, everything is just fine now
 	 */
-	md_set_array_sectors(mddev, raid10_size(mddev, 0, 0));
-	mddev->resync_max_sectors = raid10_size(mddev, 0, 0);
+	mddev->dev_sectors = conf->dev_sectors;
+	size = raid10_size(mddev, 0, 0);
+	md_set_array_sectors(mddev, size);
 
 	mddev->queue->unplug_fn = raid10_unplug;
 	mddev->queue->backing_dev_info.congested_fn = raid10_congested;
@@ -2347,6 +2384,7 @@ out_free_conf:
 	kfree(conf->mirrors);
 	kfree(conf);
 	mddev->private = NULL;
+	md_unregister_thread(mddev->thread);
 out:
 	return -EIO;
 }
@@ -2383,6 +2421,58 @@ static void raid10_quiesce(mddev_t *mddev, int state)
 	}
 }
 
+static void *raid10_takeover_raid0(mddev_t *mddev)
+{
+	mdk_rdev_t *rdev;
+	conf_t *conf;
+
+	if (mddev->degraded > 0) {
+		printk(KERN_ERR "error: degraded raid0!\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* Update slot numbers to obtain
+	 * degraded raid10 with missing mirrors
+	 */
+	list_for_each_entry(rdev, &mddev->disks, same_set) {
+		rdev->raid_disk *= 2;
+	}
+
+	/* Set new parameters */
+	mddev->new_level = 10;
+	/* new layout: far_copies = 1, near_copies = 2 */
+	mddev->new_layout = (1<<8) + 2;
+	mddev->new_chunk_sectors = mddev->chunk_sectors;
+	mddev->delta_disks = mddev->raid_disks;
+	mddev->degraded = mddev->raid_disks;
+	mddev->raid_disks *= 2;
+	/* make sure it will be not marked as dirty */
+	mddev->recovery_cp = MaxSector;
+
+	conf = setup_conf(mddev);
+	conf->scale_disks = 2;
+	return conf;
+}
+
+static void *raid10_takeover(mddev_t *mddev)
+{
+	struct raid0_private_data *raid0_priv;
+
+	/* raid10 can take over:
+	 *  raid0 - providing it has only two drives
+	 */
+	if (mddev->level == 0) {
+		/* for raid0 takeover only one zone is supported */
+		raid0_priv = mddev->private;
+		if (raid0_priv->nr_strip_zones > 1) {
+			printk(KERN_ERR "md: cannot takeover raid 0 with more than one zone.\n");
+			return ERR_PTR(-EINVAL);
+		}
+		return raid10_takeover_raid0(mddev);
+	}
+	return ERR_PTR(-EINVAL);
+}
+
 static struct mdk_personality raid10_personality =
 {
 	.name		= "raid10",
@@ -2399,6 +2489,7 @@ static struct mdk_personality raid10_personality =
 	.sync_request	= sync_request,
 	.quiesce	= raid10_quiesce,
 	.size		= raid10_size,
+	.takeover	= raid10_takeover,
 };
 
 static int __init raid_init(void)
diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h
index 59cd1ef..3824a08 100644
--- a/drivers/md/raid10.h
+++ b/drivers/md/raid10.h
@@ -33,9 +33,16 @@ struct r10_private_data_s {
 					       * 1 stripe.
 					       */
 
+	sector_t		dev_sectors;  /* temp copy of mddev->dev_sectors */
+
 	int chunk_shift; /* shift from chunks to sectors */
 	sector_t chunk_mask;
 
+	int			scale_disks;  /* When starting array, multiply
+					       * each ->raid_disk by this.
+					       * Need for raid0->raid10 migration
+					       */
+
 	struct list_head	retry_list;
 	/* queue pending writes and submit them on unplug */
 	struct bio_list		pending_bio_list;
@@ -57,6 +64,11 @@ struct r10_private_data_s {
 	mempool_t *r10bio_pool;
 	mempool_t *r10buf_pool;
 	struct page		*tmppage;
+
+	/* When taking over an array from a different personality, we store
+	 * the new thread here until we fully activate the array.
+	 */
+	struct mdk_thread_s	*thread;
 };
 
 typedef struct r10_private_data_s conf_t;



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

* [md PATCH 09/28] md: Correctly handle device removal via sysfs
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (10 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 26/28] md: don't unregister the thread in mddev_suspend NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 20/28] md: start to refactor do_md_stop NeilBrown
                   ` (16 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid; +Cc: Maciej Trela

From: Maciej Trela <Maciej.Trela@intel.com>

Writing "none" to "../md/dev-xx/slot" removes that device
from being an active part of the array, but it didn't
set ->raid_disk to -1 to record this fact.


Signed-off-by: Maciej Trela <Maciej.Trela@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index be16462..30389bc 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2358,6 +2358,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
 			return err;
 		sprintf(nm, "rd%d", rdev->raid_disk);
 		sysfs_remove_link(&rdev->mddev->kobj, nm);
+		rdev->raid_disk = -1;
 		set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
 		md_wakeup_thread(rdev->mddev->thread);
 	} else if (rdev->mddev->pers) {



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

* [md PATCH 10/28] md: Relax checks on ->max_disks when external metadata handling is used.
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (8 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 27/28] md/raid1: fix confusing 'redirect sector' message NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 26/28] md: don't unregister the thread in mddev_suspend NeilBrown
                   ` (18 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

When metadata is being managed by user-space, md doesn't know
what the maximum number of devices allowed in an array is
so ->max_disks is 0.  In this case we should allow any (+ve)
number of disks.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 30389bc..9385d1e 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2774,8 +2774,9 @@ static void analyze_sbs(mddev_t * mddev)
 
 	i = 0;
 	rdev_for_each(rdev, tmp, mddev) {
-		if (rdev->desc_nr >= mddev->max_disks ||
-		    i > mddev->max_disks) {
+		if (mddev->max_disks &&
+		    (rdev->desc_nr >= mddev->max_disks ||
+		     i > mddev->max_disks)) {
 			printk(KERN_WARNING
 			       "md: %s: %s: only %d devices permitted\n",
 			       mdname(mddev), bdevname(rdev->bdev, b),
@@ -5363,7 +5364,7 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks)
 	if (mddev->pers->check_reshape == NULL)
 		return -EINVAL;
 	if (raid_disks <= 0 ||
-	    raid_disks >= mddev->max_disks)
+	    (mddev->max_disks && raid_disks >= mddev->max_disks))
 		return -EINVAL;
 	if (mddev->sync_thread || mddev->reshape_position != MaxSector)
 		return -EBUSY;



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

* [md PATCH 11/28] md: remove unneeded sysfs files more promptly
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (16 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 19/28] md: factor do_md_run to separate accesses to ->gendisk NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 24/28] md: pass mddev to make_request functions rather than request_queue NeilBrown
                   ` (10 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

When an array is stopped we need to remove some
sysfs files which are dependent on the type of array.

We need to delay that deletion as deleting them while holding
reconfig_mutex can lead to deadlocks.

We currently delay them until the array is completely destroyed.
However it is possible to deactivate and then reactivate the array.
So we need to delete these files more promptly: as soon as
reconfig_mutex is dropped.

We need to ensure this happens before do_md_run can restart the array,
so we use open_mutex for some extra locking.  This is not deadlock
prone.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c |   41 +++++++++++++++++++++++++++++++----------
 1 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 9385d1e..3fcbe8a 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -507,9 +507,32 @@ static inline int mddev_trylock(mddev_t * mddev)
 	return mutex_trylock(&mddev->reconfig_mutex);
 }
 
+static struct attribute_group md_redundancy_group;
+
 static inline void mddev_unlock(mddev_t * mddev)
 {
-	mutex_unlock(&mddev->reconfig_mutex);
+	if (mddev->pers == NULL && mddev->private) {
+		/* These cannot be removed under reconfig_mutex as
+		 * an access to the files will try to take reconfig_mutex
+		 * while holding the file unremovable, which leads to
+		 * a deadlock.
+		 * So hold open_mutex instead - we are allowed to take
+		 * it while holding reconfig_mutex, and md_run can
+		 * use it to wait for the remove to complete.
+		 */
+		mutex_lock(&mddev->open_mutex);
+		mutex_unlock(&mddev->reconfig_mutex);
+
+		sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
+		if (mddev->private != (void*)1)
+			sysfs_remove_group(&mddev->kobj, mddev->private);
+		if (mddev->sysfs_action)
+			sysfs_put(mddev->sysfs_action);
+		mddev->sysfs_action = NULL;
+		mddev->private = NULL;
+		mutex_unlock(&mddev->open_mutex);
+	} else
+		mutex_unlock(&mddev->reconfig_mutex);
 
 	md_wakeup_thread(mddev->thread);
 }
@@ -4097,15 +4120,6 @@ static void mddev_delayed_delete(struct work_struct *ws)
 {
 	mddev_t *mddev = container_of(ws, mddev_t, del_work);
 
-	if (mddev->private) {
-		sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
-		if (mddev->private != (void*)1)
-			sysfs_remove_group(&mddev->kobj, mddev->private);
-		if (mddev->sysfs_action)
-			sysfs_put(mddev->sysfs_action);
-		mddev->sysfs_action = NULL;
-		mddev->private = NULL;
-	}
 	sysfs_remove_group(&mddev->kobj, &md_bitmap_group);
 	kobject_del(&mddev->kobj);
 	kobject_put(&mddev->kobj);
@@ -4263,6 +4277,13 @@ static int do_md_run(mddev_t * mddev)
 	if (mddev->pers)
 		return -EBUSY;
 
+	/* These two calls synchronise us with the
+	 * sysfs_remove_group calls in mddev_unlock,
+	 * so they must have completed.
+	 */
+	mutex_lock(&mddev->open_mutex);
+	mutex_unlock(&mddev->open_mutex);
+
 	/*
 	 * Analyze all RAID superblock(s)
 	 */



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

* [md PATCH 12/28] md: manage redundancy group in sysfs when changing level.
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (26 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 23/28] md: call md_stop_writes from md_stop NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-05-02 17:59 ` [md PATCH 00/28] md patches destined for -next and the next merge window Dan Williams
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

Some levels expect the 'redundancy group' to be present,
others don't.
So when we change level of an array we might need to
add or remove this group.

This requires fixing up the current practice of overloading ->private
to indicate (when ->pers == NULL) that something needs to be removed.
So create a new ->to_remove to fill that role.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c    |   43 ++++++++++++++++++++++++++++++++-----------
 drivers/md/md.h    |    1 +
 drivers/md/raid5.c |    7 +++++--
 3 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 3fcbe8a..03d6a52 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -509,9 +509,9 @@ static inline int mddev_trylock(mddev_t * mddev)
 
 static struct attribute_group md_redundancy_group;
 
-static inline void mddev_unlock(mddev_t * mddev)
+static void mddev_unlock(mddev_t * mddev)
 {
-	if (mddev->pers == NULL && mddev->private) {
+	if (mddev->to_remove) {
 		/* These cannot be removed under reconfig_mutex as
 		 * an access to the files will try to take reconfig_mutex
 		 * while holding the file unremovable, which leads to
@@ -520,16 +520,20 @@ static inline void mddev_unlock(mddev_t * mddev)
 		 * it while holding reconfig_mutex, and md_run can
 		 * use it to wait for the remove to complete.
 		 */
+		struct attribute_group *to_remove = mddev->to_remove;
+		mddev->to_remove = NULL;
 		mutex_lock(&mddev->open_mutex);
 		mutex_unlock(&mddev->reconfig_mutex);
 
-		sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
-		if (mddev->private != (void*)1)
-			sysfs_remove_group(&mddev->kobj, mddev->private);
-		if (mddev->sysfs_action)
-			sysfs_put(mddev->sysfs_action);
-		mddev->sysfs_action = NULL;
-		mddev->private = NULL;
+		if (to_remove != &md_redundancy_group)
+			sysfs_remove_group(&mddev->kobj, to_remove);
+		if (mddev->pers == NULL ||
+		    mddev->pers->sync_request == NULL) {
+			sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
+			if (mddev->sysfs_action)
+				sysfs_put(mddev->sysfs_action);
+			mddev->sysfs_action = NULL;
+		}
 		mutex_unlock(&mddev->open_mutex);
 	} else
 		mutex_unlock(&mddev->reconfig_mutex);
@@ -2998,6 +3002,23 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
 	/* Looks like we have a winner */
 	mddev_suspend(mddev);
 	mddev->pers->stop(mddev);
+	
+	if (mddev->pers->sync_request == NULL &&
+	    pers->sync_request != NULL) {
+		/* need to add the md_redundancy_group */
+		if (sysfs_create_group(&mddev->kobj, &md_redundancy_group))
+			printk(KERN_WARNING
+			       "md: cannot register extra attributes for %s\n",
+			       mdname(mddev));
+		mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, "sync_action");
+	}		
+	if (mddev->pers->sync_request != NULL &&
+	    pers->sync_request == NULL) {
+		/* need to remove the md_redundancy_group */
+		if (mddev->to_remove == NULL)
+			mddev->to_remove = &md_redundancy_group;
+	}
+
 	if (mddev->pers->sync_request == NULL &&
 	    mddev->external) {
 		/* We are converting from a no-redundancy array
@@ -4572,8 +4593,8 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
 			mddev->queue->unplug_fn = NULL;
 			mddev->queue->backing_dev_info.congested_fn = NULL;
 			module_put(mddev->pers->owner);
-			if (mddev->pers->sync_request && mddev->private == NULL)
-				mddev->private = (void*)1;
+			if (mddev->pers->sync_request && mddev->to_remove == NULL)
+				mddev->to_remove = &md_redundancy_group;
 			mddev->pers = NULL;
 			/* tell userspace to handle 'inactive' */
 			sysfs_notify_dirent(mddev->sysfs_state);
diff --git a/drivers/md/md.h b/drivers/md/md.h
index b9dc3ea..e4836c6 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -299,6 +299,7 @@ struct mddev_s
 	atomic_t 			max_corr_read_errors; /* max read retries */
 	struct list_head		all_mddevs;
 
+	struct attribute_group		*to_remove;
 	/* Generic barrier handling.
 	 * If there is a pending barrier request, all other
 	 * writes are blocked while the devices are flushed.
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index c54ddbc..bb28fd6 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -5091,7 +5091,9 @@ static int run(mddev_t *mddev)
 	}
 
 	/* Ok, everything is just fine now */
-	if (sysfs_create_group(&mddev->kobj, &raid5_attrs_group))
+	if (mddev->to_remove == &raid5_attrs_group)
+		mddev->to_remove = NULL;
+	else if (sysfs_create_group(&mddev->kobj, &raid5_attrs_group))
 		printk(KERN_WARNING
 		       "raid5: failed to create sysfs attributes for %s\n",
 		       mdname(mddev));
@@ -5138,7 +5140,8 @@ static int stop(mddev_t *mddev)
 	mddev->queue->backing_dev_info.congested_fn = NULL;
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
 	free_conf(conf);
-	mddev->private = &raid5_attrs_group;
+	mddev->private = NULL;
+	mddev->to_remove = &raid5_attrs_group;
 	return 0;
 }
 



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

* [md PATCH 13/28] md: notify level changes through sysfs.
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (19 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 28/28] md/raid1: delay reads that could overtake behind-writes NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 18/28] md: remove ->changed and related code NeilBrown
                   ` (7 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid; +Cc: Maciej Trela

From: Maciej Trela <Maciej.Trela@intel.com>

Level changes can be very significant, so make sure
to notify them via sysfs.

Signed-off-by: Maciej Trela <maciej.trela@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 03d6a52..afe1065 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -3058,6 +3058,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
 	set_bit(MD_CHANGE_DEVS, &mddev->flags);
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
+	sysfs_notify(&mddev->kobj, NULL, "level");
 	return rv;
 }
 



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

* [md PATCH 14/28] md: add support for raid5 to raid4 conversion
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (13 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 22/28] md: split md_set_readonly out of do_md_stop NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 17/28] md: don't reference gendisk in getgeo NeilBrown
                   ` (13 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

This is unlikely to be wanted, but we may as well provide it
for completeness.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/raid5.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index bb28fd6..020143d 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -5788,6 +5788,18 @@ static void *raid5_takeover(mddev_t *mddev)
 	return ERR_PTR(-EINVAL);
 }
 
+static void *raid4_takeover(mddev_t *mddev)
+{
+	/* raid4 can take over raid5 if layout is right.
+	 */
+	if (mddev->level == 5 &&
+	    mddev->layout == ALGORITHM_PARITY_N) {
+		mddev->new_layout = 0;
+		mddev->new_level = 4;
+		return setup_conf(mddev);
+	}
+	return ERR_PTR(-EINVAL);
+}
 
 static struct mdk_personality raid5_personality;
 
@@ -5903,6 +5915,7 @@ static struct mdk_personality raid4_personality =
 	.start_reshape  = raid5_start_reshape,
 	.finish_reshape = raid5_finish_reshape,
 	.quiesce	= raid5_quiesce,
+	.takeover	= raid4_takeover,
 };
 
 static int __init raid5_init(void)



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

* [md PATCH 15/28] md/raid5: small tidyup in raid5_align_endio
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (22 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 21/28] md: factor md_stop_writes out of do_md_stop NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 16/28] md: move io accounting out of personalities into md_make_request NeilBrown
                   ` (4 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

Diving through ->queue to find mddev is unnecessarily complex - there
is an easier path to finding mddev, so use that.

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 020143d..7bfeba3 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3713,10 +3713,10 @@ static void raid5_align_endio(struct bio *bi, int error)
 
 	bio_put(bi);
 
-	mddev = raid_bi->bi_bdev->bd_disk->queue->queuedata;
-	conf = mddev->private;
 	rdev = (void*)raid_bi->bi_next;
 	raid_bi->bi_next = NULL;
+	mddev = rdev->mddev;
+	conf = mddev->private;
 
 	rdev_dec_pending(rdev, conf->mddev);
 



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

* [md PATCH 16/28] md: move io accounting out of personalities into md_make_request
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (23 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 15/28] md/raid5: small tidyup in raid5_align_endio NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 25/28] md: factor out init code for an mddev NeilBrown
                   ` (3 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

While I generally prefer letting personalities do as much as possible,
given that we have a central md_make_request anyway we may as well use
it to simplify code.
Also this centralises knowledge of ->gendisk which will help later.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/linear.c    |    8 --------
 drivers/md/md.c        |   11 +++++++++++
 drivers/md/multipath.c |    8 --------
 drivers/md/raid0.c     |    8 --------
 drivers/md/raid1.c     |    7 -------
 drivers/md/raid10.c    |    7 -------
 drivers/md/raid5.c     |    8 +-------
 7 files changed, 12 insertions(+), 45 deletions(-)

diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index bb2a231..93acbb2 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -287,23 +287,15 @@ static int linear_stop (mddev_t *mddev)
 
 static int linear_make_request (struct request_queue *q, struct bio *bio)
 {
-	const int rw = bio_data_dir(bio);
 	mddev_t *mddev = q->queuedata;
 	dev_info_t *tmp_dev;
 	sector_t start_sector;
-	int cpu;
 
 	if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) {
 		md_barrier_request(mddev, bio);
 		return 0;
 	}
 
-	cpu = part_stat_lock();
-	part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
-	part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
-		      bio_sectors(bio));
-	part_stat_unlock();
-
 	rcu_read_lock();
 	tmp_dev = which_dev(mddev, bio->bi_sector);
 	start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index afe1065..16f032b 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -214,8 +214,11 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
  */
 static int md_make_request(struct request_queue *q, struct bio *bio)
 {
+	const int rw = bio_data_dir(bio);
 	mddev_t *mddev = q->queuedata;
 	int rv;
+	int cpu;
+
 	if (mddev == NULL || mddev->pers == NULL) {
 		bio_io_error(bio);
 		return 0;
@@ -236,7 +239,15 @@ static int md_make_request(struct request_queue *q, struct bio *bio)
 	}
 	atomic_inc(&mddev->active_io);
 	rcu_read_unlock();
+
 	rv = mddev->pers->make_request(q, bio);
+
+	cpu = part_stat_lock();
+	part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
+	part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
+		      bio_sectors(bio));
+	part_stat_unlock();
+
 	if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended)
 		wake_up(&mddev->sb_wait);
 
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 97befd5..5b4e291 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -141,8 +141,6 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio)
 	multipath_conf_t *conf = mddev->private;
 	struct multipath_bh * mp_bh;
 	struct multipath_info *multipath;
-	const int rw = bio_data_dir(bio);
-	int cpu;
 
 	if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) {
 		md_barrier_request(mddev, bio);
@@ -154,12 +152,6 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio)
 	mp_bh->master_bio = bio;
 	mp_bh->mddev = mddev;
 
-	cpu = part_stat_lock();
-	part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
-	part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
-		      bio_sectors(bio));
-	part_stat_unlock();
-
 	mp_bh->path = multipath_map(conf);
 	if (mp_bh->path < 0) {
 		bio_endio(bio, -EIO);
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index afddf62..d535f9b 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -472,20 +472,12 @@ static int raid0_make_request(struct request_queue *q, struct bio *bio)
 	sector_t sector_offset;
 	struct strip_zone *zone;
 	mdk_rdev_t *tmp_dev;
-	const int rw = bio_data_dir(bio);
-	int cpu;
 
 	if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) {
 		md_barrier_request(mddev, bio);
 		return 0;
 	}
 
-	cpu = part_stat_lock();
-	part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
-	part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
-		      bio_sectors(bio));
-	part_stat_unlock();
-
 	chunk_sects = mddev->chunk_sectors;
 	if (unlikely(!is_io_in_chunk_boundary(mddev, chunk_sects, bio))) {
 		sector_t sector = bio->bi_sector;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index ff6f97b..d63f3ee 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -787,7 +787,6 @@ static int make_request(struct request_queue *q, struct bio * bio)
 	struct page **behind_pages = NULL;
 	const int rw = bio_data_dir(bio);
 	const bool do_sync = bio_rw_flagged(bio, BIO_RW_SYNCIO);
-	int cpu;
 	bool do_barriers;
 	mdk_rdev_t *blocked_rdev;
 
@@ -833,12 +832,6 @@ static int make_request(struct request_queue *q, struct bio * bio)
 
 	bitmap = mddev->bitmap;
 
-	cpu = part_stat_lock();
-	part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
-	part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
-		      bio_sectors(bio));
-	part_stat_unlock();
-
 	/*
 	 * make_request() can abort the operation when READA is being
 	 * used and no empty request is available.
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index beab7f6..00d2af6 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -795,7 +795,6 @@ static int make_request(struct request_queue *q, struct bio * bio)
 	mirror_info_t *mirror;
 	r10bio_t *r10_bio;
 	struct bio *read_bio;
-	int cpu;
 	int i;
 	int chunk_sects = conf->chunk_mask + 1;
 	const int rw = bio_data_dir(bio);
@@ -850,12 +849,6 @@ static int make_request(struct request_queue *q, struct bio * bio)
 	 */
 	wait_barrier(conf);
 
-	cpu = part_stat_lock();
-	part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
-	part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
-		      bio_sectors(bio));
-	part_stat_unlock();
-
 	r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
 
 	r10_bio->master_bio = bio;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 7bfeba3..c6ae7c1 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3879,7 +3879,7 @@ static int make_request(struct request_queue *q, struct bio * bi)
 	sector_t logical_sector, last_sector;
 	struct stripe_head *sh;
 	const int rw = bio_data_dir(bi);
-	int cpu, remaining;
+	int remaining;
 
 	if (unlikely(bio_rw_flagged(bi, BIO_RW_BARRIER))) {
 		/* Drain all pending writes.  We only really need
@@ -3894,12 +3894,6 @@ static int make_request(struct request_queue *q, struct bio * bi)
 
 	md_write_start(mddev, bi);
 
-	cpu = part_stat_lock();
-	part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
-	part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
-		      bio_sectors(bi));
-	part_stat_unlock();
-
 	if (rw == READ &&
 	     mddev->reshape_position == MaxSector &&
 	     chunk_aligned_read(q,bi))



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

* [md PATCH 17/28] md: don't reference gendisk in getgeo
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (14 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 14/28] md: add support for raid5 to raid4 conversion NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 19/28] md: factor do_md_run to separate accesses to ->gendisk NeilBrown
                   ` (12 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

Using ->array_sectors rather than get_capacity() is more
direct and is a step towards relaxing the tight connection
between mddev and gendisk.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 16f032b..56a2c12 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -5555,7 +5555,7 @@ static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 
 	geo->heads = 2;
 	geo->sectors = 4;
-	geo->cylinders = get_capacity(mddev->gendisk) / 8;
+	geo->cylinders = mddev->array_sectors / 8;
 	return 0;
 }
 



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

* [md PATCH 18/28] md: remove ->changed and related code.
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (20 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 13/28] md: notify level changes through sysfs NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 21/28] md: factor md_stop_writes out of do_md_stop NeilBrown
                   ` (6 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

We set ->changed to 1 and call check_disk_change at the end
of md_open so that bd_invalidated would be set and thus
partition rescan would happen appropriately.

Now that we call revalidate_disk directly, which sets bd_invalidates,
that indirection is no longer needed and can be removed.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c    |   22 +---------------------
 drivers/md/md.h    |    1 -
 drivers/md/raid1.c |    1 -
 drivers/md/raid5.c |    2 --
 4 files changed, 1 insertions(+), 25 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 56a2c12..06100d9 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4500,7 +4500,6 @@ static int do_md_run(mddev_t * mddev)
 	md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */
 
 	revalidate_disk(mddev->gendisk);
-	mddev->changed = 1;
 	md_new_event(mddev);
 	sysfs_notify_dirent(mddev->sysfs_state);
 	if (mddev->sysfs_action)
@@ -4619,7 +4618,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
 				}
 
 			set_capacity(disk, 0);
-			mddev->changed = 1;
+			revalidate_disk(disk);
 
 			if (mddev->ro)
 				mddev->ro = 0;
@@ -4685,7 +4684,6 @@ out:
 		mddev->sync_speed_min = mddev->sync_speed_max = 0;
 		mddev->recovery = 0;
 		mddev->in_sync = 0;
-		mddev->changed = 0;
 		mddev->degraded = 0;
 		mddev->barriers_work = 0;
 		mddev->safemode = 0;
@@ -5820,7 +5818,6 @@ static int md_open(struct block_device *bdev, fmode_t mode)
 	atomic_inc(&mddev->openers);
 	mutex_unlock(&mddev->open_mutex);
 
-	check_disk_change(bdev);
  out:
 	return err;
 }
@@ -5835,21 +5832,6 @@ static int md_release(struct gendisk *disk, fmode_t mode)
 
 	return 0;
 }
-
-static int md_media_changed(struct gendisk *disk)
-{
-	mddev_t *mddev = disk->private_data;
-
-	return mddev->changed;
-}
-
-static int md_revalidate(struct gendisk *disk)
-{
-	mddev_t *mddev = disk->private_data;
-
-	mddev->changed = 0;
-	return 0;
-}
 static const struct block_device_operations md_fops =
 {
 	.owner		= THIS_MODULE,
@@ -5860,8 +5842,6 @@ static const struct block_device_operations md_fops =
 	.compat_ioctl	= md_compat_ioctl,
 #endif
 	.getgeo		= md_getgeo,
-	.media_changed	= md_media_changed,
-	.revalidate_disk= md_revalidate,
 };
 
 static int md_thread(void * arg)
diff --git a/drivers/md/md.h b/drivers/md/md.h
index e4836c6..3225e25 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -237,7 +237,6 @@ struct mddev_s
 	atomic_t			active;		/* general refcount */
 	atomic_t			openers;	/* number of active opens */
 
-	int				changed;	/* true if we might need to reread partition info */
 	int				degraded;	/* whether md should consider
 							 * adding a spare
 							 */
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index d63f3ee..d751a5a 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -2183,7 +2183,6 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors)
 	if (mddev->array_sectors > raid1_size(mddev, sectors, 0))
 		return -EINVAL;
 	set_capacity(mddev->gendisk, mddev->array_sectors);
-	mddev->changed = 1;
 	revalidate_disk(mddev->gendisk);
 	if (sectors > mddev->dev_sectors &&
 	    mddev->recovery_cp == MaxSector) {
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index c6ae7c1..231afda 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -5335,7 +5335,6 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
 	    raid5_size(mddev, sectors, mddev->raid_disks))
 		return -EINVAL;
 	set_capacity(mddev->gendisk, mddev->array_sectors);
-	mddev->changed = 1;
 	revalidate_disk(mddev->gendisk);
 	if (sectors > mddev->dev_sectors && mddev->recovery_cp == MaxSector) {
 		mddev->recovery_cp = mddev->dev_sectors;
@@ -5549,7 +5548,6 @@ static void raid5_finish_reshape(mddev_t *mddev)
 		if (mddev->delta_disks > 0) {
 			md_set_array_sectors(mddev, raid5_size(mddev, 0, 0));
 			set_capacity(mddev->gendisk, mddev->array_sectors);
-			mddev->changed = 1;
 			revalidate_disk(mddev->gendisk);
 		} else {
 			int d;



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

* [md PATCH 19/28] md: factor do_md_run to separate accesses to ->gendisk
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (15 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 17/28] md: don't reference gendisk in getgeo NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 11/28] md: remove unneeded sysfs files more promptly NeilBrown
                   ` (11 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

As part of relaxing the binding between an mddev and gendisk,
we separate do_md_run into two functions.
  md_run does all the work internal to md
  do_md_run calls md_run and makes and changes to gendisk
     that are required.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c |   24 ++++++++++++++++--------
 1 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 06100d9..91333fe 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4296,11 +4296,10 @@ static void md_safemode_timeout(unsigned long data)
 
 static int start_dirty_degraded;
 
-static int do_md_run(mddev_t * mddev)
+static int md_run(mddev_t *mddev)
 {
 	int err;
 	mdk_rdev_t *rdev;
-	struct gendisk *disk;
 	struct mdk_personality *pers;
 
 	if (list_empty(&mddev->disks))
@@ -4365,8 +4364,6 @@ static int do_md_run(mddev_t * mddev)
 		sysfs_notify_dirent(rdev->sysfs_state);
 	}
 
-	disk = mddev->gendisk;
-
 	spin_lock(&pers_lock);
 	pers = find_pers(mddev->level, mddev->clevel);
 	if (!pers || !try_module_get(pers->owner)) {
@@ -4494,21 +4491,32 @@ static int do_md_run(mddev_t * mddev)
 	if (mddev->flags)
 		md_update_sb(mddev, 0);
 
-	set_capacity(disk, mddev->array_sectors);
-
 	md_wakeup_thread(mddev->thread);
 	md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */
 
-	revalidate_disk(mddev->gendisk);
 	md_new_event(mddev);
 	sysfs_notify_dirent(mddev->sysfs_state);
 	if (mddev->sysfs_action)
 		sysfs_notify_dirent(mddev->sysfs_action);
 	sysfs_notify(&mddev->kobj, NULL, "degraded");
-	kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
 	return 0;
 }
 
+static int do_md_run(mddev_t *mddev)
+{
+	int err;
+
+	err = md_run(mddev);
+	if (err)
+		goto out;
+
+	set_capacity(mddev->gendisk, mddev->array_sectors);
+	revalidate_disk(mddev->gendisk);
+	kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
+out:
+	return err;
+}
+
 static int restart_array(mddev_t *mddev)
 {
 	struct gendisk *disk = mddev->gendisk;



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

* [md PATCH 20/28] md: start to refactor do_md_stop
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (11 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 09/28] md: Correctly handle device removal via sysfs NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 22/28] md: split md_set_readonly out of do_md_stop NeilBrown
                   ` (15 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

do_md_stop is large and clunky, so hard to understand.

This is a first step of refactoring, pulling two simple
sub-functions out.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c |   98 +++++++++++++++++++++++++++++++------------------------
 1 files changed, 55 insertions(+), 43 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 91333fe..3e9a96e 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4567,6 +4567,58 @@ void restore_bitmap_write_access(struct file *file)
 	spin_unlock(&inode->i_lock);
 }
 
+static void md_clean(mddev_t *mddev)
+{
+	mddev->array_sectors = 0;
+	mddev->external_size = 0;
+	mddev->dev_sectors = 0;
+	mddev->raid_disks = 0;
+	mddev->recovery_cp = 0;
+	mddev->resync_min = 0;
+	mddev->resync_max = MaxSector;
+	mddev->reshape_position = MaxSector;
+	mddev->external = 0;
+	mddev->persistent = 0;
+	mddev->level = LEVEL_NONE;
+	mddev->clevel[0] = 0;
+	mddev->flags = 0;
+	mddev->ro = 0;
+	mddev->metadata_type[0] = 0;
+	mddev->chunk_sectors = 0;
+	mddev->ctime = mddev->utime = 0;
+	mddev->layout = 0;
+	mddev->max_disks = 0;
+	mddev->events = 0;
+	mddev->delta_disks = 0;
+	mddev->new_level = LEVEL_NONE;
+	mddev->new_layout = 0;
+	mddev->new_chunk_sectors = 0;
+	mddev->curr_resync = 0;
+	mddev->resync_mismatches = 0;
+	mddev->suspend_lo = mddev->suspend_hi = 0;
+	mddev->sync_speed_min = mddev->sync_speed_max = 0;
+	mddev->recovery = 0;
+	mddev->in_sync = 0;
+	mddev->degraded = 0;
+	mddev->barriers_work = 0;
+	mddev->safemode = 0;
+	mddev->bitmap_info.offset = 0;
+	mddev->bitmap_info.default_offset = 0;
+	mddev->bitmap_info.chunksize = 0;
+	mddev->bitmap_info.daemon_sleep = 0;
+	mddev->bitmap_info.max_write_behind = 0;
+}
+
+static void md_stop(mddev_t *mddev)
+{
+	mddev->pers->stop(mddev);
+	if (mddev->pers->sync_request && mddev->to_remove == NULL)
+		mddev->to_remove = &md_redundancy_group;
+	module_put(mddev->pers->owner);
+	mddev->pers = NULL;
+
+}
+
 /* mode:
  *   0 - completely stop and dis-assemble array
  *   1 - switch to readonly
@@ -4607,14 +4659,11 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
 			if (mddev->ro)
 				set_disk_ro(disk, 0);
 
-			mddev->pers->stop(mddev);
+			md_stop(mddev);
 			mddev->queue->merge_bvec_fn = NULL;
 			mddev->queue->unplug_fn = NULL;
 			mddev->queue->backing_dev_info.congested_fn = NULL;
-			module_put(mddev->pers->owner);
-			if (mddev->pers->sync_request && mddev->to_remove == NULL)
-				mddev->to_remove = &md_redundancy_group;
-			mddev->pers = NULL;
+
 			/* tell userspace to handle 'inactive' */
 			sysfs_notify_dirent(mddev->sysfs_state);
 
@@ -4662,44 +4711,7 @@ out:
 
 		export_array(mddev);
 
-		mddev->array_sectors = 0;
-		mddev->external_size = 0;
-		mddev->dev_sectors = 0;
-		mddev->raid_disks = 0;
-		mddev->recovery_cp = 0;
-		mddev->resync_min = 0;
-		mddev->resync_max = MaxSector;
-		mddev->reshape_position = MaxSector;
-		mddev->external = 0;
-		mddev->persistent = 0;
-		mddev->level = LEVEL_NONE;
-		mddev->clevel[0] = 0;
-		mddev->flags = 0;
-		mddev->ro = 0;
-		mddev->metadata_type[0] = 0;
-		mddev->chunk_sectors = 0;
-		mddev->ctime = mddev->utime = 0;
-		mddev->layout = 0;
-		mddev->max_disks = 0;
-		mddev->events = 0;
-		mddev->delta_disks = 0;
-		mddev->new_level = LEVEL_NONE;
-		mddev->new_layout = 0;
-		mddev->new_chunk_sectors = 0;
-		mddev->curr_resync = 0;
-		mddev->resync_mismatches = 0;
-		mddev->suspend_lo = mddev->suspend_hi = 0;
-		mddev->sync_speed_min = mddev->sync_speed_max = 0;
-		mddev->recovery = 0;
-		mddev->in_sync = 0;
-		mddev->degraded = 0;
-		mddev->barriers_work = 0;
-		mddev->safemode = 0;
-		mddev->bitmap_info.offset = 0;
-		mddev->bitmap_info.default_offset = 0;
-		mddev->bitmap_info.chunksize = 0;
-		mddev->bitmap_info.daemon_sleep = 0;
-		mddev->bitmap_info.max_write_behind = 0;
+		md_clean(mddev);
 		kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
 		if (mddev->hold_active == UNTIL_STOP)
 			mddev->hold_active = 0;



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

* [md PATCH 21/28] md: factor md_stop_writes out of do_md_stop.
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (21 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 18/28] md: remove ->changed and related code NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 15/28] md/raid5: small tidyup in raid5_align_endio NeilBrown
                   ` (5 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

Further refactoring of do_md_stop.
This one requires some explanation as it takes code from different
places in do_md_stop, so some re-ordering happens.

We only get into this part of do_md_stop if there are no active opens
of the device, so no writes can be happening and the device must have
been flushed.  In md_stop_writes we want to stop any internal sources
of writes - i.e. resync - and flush out the metadata.

The only code that was previously before some of this code is
code to clean up the queue, the mddev, the gendisk, or sysfs, all
of which is probably better after code that makes active changes (i.e.
triggers writes).

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c |   37 ++++++++++++++++++++++---------------
 1 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 3e9a96e..15f533d 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4609,6 +4609,27 @@ static void md_clean(mddev_t *mddev)
 	mddev->bitmap_info.max_write_behind = 0;
 }
 
+static void md_stop_writes(mddev_t *mddev)
+{
+	if (mddev->sync_thread) {
+		set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+		set_bit(MD_RECOVERY_INTR, &mddev->recovery);
+		md_unregister_thread(mddev->sync_thread);
+		mddev->sync_thread = NULL;
+	}
+
+	del_timer_sync(&mddev->safemode_timer);
+
+	bitmap_flush(mddev);
+	md_super_wait(mddev);
+
+	if (!mddev->in_sync || mddev->flags) {
+		/* mark array as shutdown cleanly */
+		mddev->in_sync = 1;
+		md_update_sb(mddev, 1);
+	}
+}
+
 static void md_stop(mddev_t *mddev)
 {
 	mddev->pers->stop(mddev);
@@ -4636,14 +4657,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
 		err = -EBUSY;
 	} else if (mddev->pers) {
 
-		if (mddev->sync_thread) {
-			set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
-			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
-			md_unregister_thread(mddev->sync_thread);
-			mddev->sync_thread = NULL;
-		}
-
-		del_timer_sync(&mddev->safemode_timer);
+		md_stop_writes(mddev);
 
 		switch(mode) {
 		case 1: /* readonly */
@@ -4654,8 +4668,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
 			break;
 		case 0: /* disassemble */
 		case 2: /* stop */
-			bitmap_flush(mddev);
-			md_super_wait(mddev);
 			if (mddev->ro)
 				set_disk_ro(disk, 0);
 
@@ -4680,11 +4692,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
 			if (mddev->ro)
 				mddev->ro = 0;
 		}
-		if (!mddev->in_sync || mddev->flags) {
-			/* mark array as shutdown cleanly */
-			mddev->in_sync = 1;
-			md_update_sb(mddev, 1);
-		}
 		if (mode == 1)
 			set_disk_ro(disk, 1);
 		clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);



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

* [md PATCH 22/28] md: split md_set_readonly out of do_md_stop
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (12 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 20/28] md: start to refactor do_md_stop NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 14/28] md: add support for raid5 to raid4 conversion NeilBrown
                   ` (14 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

Using do_md_stop to set an array to read-only is a little confusing.
Now most of the common code has been factored out, split
md_set_readonly off in to a separate function.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c |   90 +++++++++++++++++++++++++++++++------------------------
 1 files changed, 51 insertions(+), 39 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 15f533d..51a109e 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -3308,6 +3308,7 @@ array_state_show(mddev_t *mddev, char *page)
 }
 
 static int do_md_stop(mddev_t * mddev, int ro, int is_open);
+static int md_set_readonly(mddev_t * mddev, int is_open);
 static int do_md_run(mddev_t * mddev);
 static int restart_array(mddev_t *mddev);
 
@@ -3338,7 +3339,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
 		break; /* not supported yet */
 	case readonly:
 		if (mddev->pers)
-			err = do_md_stop(mddev, 1, 0);
+			err = md_set_readonly(mddev, 0);
 		else {
 			mddev->ro = 1;
 			set_disk_ro(mddev->gendisk, 1);
@@ -3348,7 +3349,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
 	case read_auto:
 		if (mddev->pers) {
 			if (mddev->ro == 0)
-				err = do_md_stop(mddev, 1, 0);
+				err = md_set_readonly(mddev, 0);
 			else if (mddev->ro == 1)
 				err = restart_array(mddev);
 			if (err == 0) {
@@ -4640,9 +4641,34 @@ static void md_stop(mddev_t *mddev)
 
 }
 
+static int md_set_readonly(mddev_t *mddev, int is_open)
+{
+	int err = 0;
+	mutex_lock(&mddev->open_mutex);
+	if (atomic_read(&mddev->openers) > is_open) {
+		printk("md: %s still in use.\n",mdname(mddev));
+		err = -EBUSY;
+		goto out;
+	}
+	if (mddev->pers) {
+		md_stop_writes(mddev);
+
+		err  = -ENXIO;
+		if (mddev->ro==1)
+			goto out;
+		mddev->ro = 1;
+		set_disk_ro(mddev->gendisk, 1);
+		clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+		sysfs_notify_dirent(mddev->sysfs_state);
+		err = 0;	
+	}
+out:
+	mutex_unlock(&mddev->open_mutex);
+	return err;
+}
+
 /* mode:
  *   0 - completely stop and dis-assemble array
- *   1 - switch to readonly
  *   2 - stop but do not disassemble array
  */
 static int do_md_stop(mddev_t * mddev, int mode, int is_open)
@@ -4659,45 +4685,33 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
 
 		md_stop_writes(mddev);
 
-		switch(mode) {
-		case 1: /* readonly */
-			err  = -ENXIO;
-			if (mddev->ro==1)
-				goto out;
-			mddev->ro = 1;
-			break;
-		case 0: /* disassemble */
-		case 2: /* stop */
-			if (mddev->ro)
-				set_disk_ro(disk, 0);
+		if (mddev->ro)
+			set_disk_ro(disk, 0);
 
-			md_stop(mddev);
-			mddev->queue->merge_bvec_fn = NULL;
-			mddev->queue->unplug_fn = NULL;
-			mddev->queue->backing_dev_info.congested_fn = NULL;
+		md_stop(mddev);
+		mddev->queue->merge_bvec_fn = NULL;
+		mddev->queue->unplug_fn = NULL;
+		mddev->queue->backing_dev_info.congested_fn = NULL;
 
-			/* tell userspace to handle 'inactive' */
-			sysfs_notify_dirent(mddev->sysfs_state);
+		/* tell userspace to handle 'inactive' */
+		sysfs_notify_dirent(mddev->sysfs_state);
 
-			list_for_each_entry(rdev, &mddev->disks, same_set)
-				if (rdev->raid_disk >= 0) {
-					char nm[20];
-					sprintf(nm, "rd%d", rdev->raid_disk);
-					sysfs_remove_link(&mddev->kobj, nm);
-				}
+		list_for_each_entry(rdev, &mddev->disks, same_set)
+			if (rdev->raid_disk >= 0) {
+				char nm[20];
+				sprintf(nm, "rd%d", rdev->raid_disk);
+				sysfs_remove_link(&mddev->kobj, nm);
+			}
 
-			set_capacity(disk, 0);
-			revalidate_disk(disk);
+		set_capacity(disk, 0);
+		revalidate_disk(disk);
 
-			if (mddev->ro)
-				mddev->ro = 0;
-		}
-		if (mode == 1)
-			set_disk_ro(disk, 1);
+		if (mddev->ro)
+			mddev->ro = 0;
+		
 		clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
 		err = 0;
 	}
-out:
 	mutex_unlock(&mddev->open_mutex);
 	if (err)
 		return err;
@@ -4723,9 +4737,7 @@ out:
 		if (mddev->hold_active == UNTIL_STOP)
 			mddev->hold_active = 0;
 
-	} else if (mddev->pers)
-		printk(KERN_INFO "md: %s switched to read-only mode.\n",
-			mdname(mddev));
+	}
 	err = 0;
 	blk_integrity_unregister(disk);
 	md_new_event(mddev);
@@ -5722,7 +5734,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
 			goto done_unlock;
 
 		case STOP_ARRAY_RO:
-			err = do_md_stop(mddev, 1, 1);
+			err = md_set_readonly(mddev, 1);
 			goto done_unlock;
 
 	}
@@ -7110,7 +7122,7 @@ static int md_notify_reboot(struct notifier_block *this,
 				 * appears to still be in use.  Hence
 				 * the '100'.
 				 */
-				do_md_stop(mddev, 1, 100);
+				md_set_readonly(mddev, 100);
 				mddev_unlock(mddev);
 			}
 		/*



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

* [md PATCH 23/28] md: call md_stop_writes from md_stop
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (25 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 25/28] md: factor out init code for an mddev NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 12/28] md: manage redundancy group in sysfs when changing level NeilBrown
  2010-05-02 17:59 ` [md PATCH 00/28] md patches destined for -next and the next merge window Dan Williams
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

This moves the call to the other side of set_readonly, but that should
not be an issue.
This encapsulates in 'md_stop' all of the functionality for internally
stopping the array, leaving all the interactions with externalities
(sysfs, request_queue, gendisk) in do_md_stop.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 51a109e..ebc0fc9 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4633,12 +4633,14 @@ static void md_stop_writes(mddev_t *mddev)
 
 static void md_stop(mddev_t *mddev)
 {
+	md_stop_writes(mddev);
+
 	mddev->pers->stop(mddev);
 	if (mddev->pers->sync_request && mddev->to_remove == NULL)
 		mddev->to_remove = &md_redundancy_group;
 	module_put(mddev->pers->owner);
 	mddev->pers = NULL;
-
+	clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
 }
 
 static int md_set_readonly(mddev_t *mddev, int is_open)
@@ -4683,8 +4685,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
 		err = -EBUSY;
 	} else if (mddev->pers) {
 
-		md_stop_writes(mddev);
-
 		if (mddev->ro)
 			set_disk_ro(disk, 0);
 
@@ -4709,7 +4709,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
 		if (mddev->ro)
 			mddev->ro = 0;
 		
-		clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
 		err = 0;
 	}
 	mutex_unlock(&mddev->open_mutex);



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

* [md PATCH 24/28] md: pass mddev to make_request functions rather than request_queue
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (17 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 11/28] md: remove unneeded sysfs files more promptly NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 28/28] md/raid1: delay reads that could overtake behind-writes NeilBrown
                   ` (9 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

We used to pass the personality make_request function direct
to the block layer so the first argument had to be a queue.
But now we have the intermediary md_make_request so it makes
at lot more sense to pass a struct mddev_s.
It makes it possible to have an mddev without its own queue too.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/faulty.c    |    3 +--
 drivers/md/linear.c    |    7 +++----
 drivers/md/md.c        |    4 ++--
 drivers/md/md.h        |    2 +-
 drivers/md/multipath.c |    3 +--
 drivers/md/raid0.c     |    7 +++----
 drivers/md/raid1.c     |    3 +--
 drivers/md/raid10.c    |    7 +++----
 drivers/md/raid5.c     |    8 +++-----
 9 files changed, 18 insertions(+), 26 deletions(-)

diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index 608a8d3..bd4348f 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -168,9 +168,8 @@ static void add_sector(conf_t *conf, sector_t start, int mode)
 		conf->nfaults = n+1;
 }
 
-static int make_request(struct request_queue *q, struct bio *bio)
+static int make_request(mddev_t *mddev, struct bio *bio)
 {
-	mddev_t *mddev = q->queuedata;
 	conf_t *conf = mddev->private;
 	int failit = 0;
 
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 93acbb2..cb58c35 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -285,9 +285,8 @@ static int linear_stop (mddev_t *mddev)
 	return 0;
 }
 
-static int linear_make_request (struct request_queue *q, struct bio *bio)
+static int linear_make_request (mddev_t *mddev, struct bio *bio)
 {
-	mddev_t *mddev = q->queuedata;
 	dev_info_t *tmp_dev;
 	sector_t start_sector;
 
@@ -327,9 +326,9 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
 
 		bp = bio_split(bio, end_sector - bio->bi_sector);
 
-		if (linear_make_request(q, &bp->bio1))
+		if (linear_make_request(mddev, &bp->bio1))
 			generic_make_request(&bp->bio1);
-		if (linear_make_request(q, &bp->bio2))
+		if (linear_make_request(mddev, &bp->bio2))
 			generic_make_request(&bp->bio2);
 		bio_pair_release(bp);
 		return 0;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index ebc0fc9..967df62 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -240,7 +240,7 @@ static int md_make_request(struct request_queue *q, struct bio *bio)
 	atomic_inc(&mddev->active_io);
 	rcu_read_unlock();
 
-	rv = mddev->pers->make_request(q, bio);
+	rv = mddev->pers->make_request(mddev, bio);
 
 	cpu = part_stat_lock();
 	part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
@@ -354,7 +354,7 @@ static void md_submit_barrier(struct work_struct *ws)
 		bio_endio(bio, 0);
 	else {
 		bio->bi_rw &= ~(1<<BIO_RW_BARRIER);
-		if (mddev->pers->make_request(mddev->queue, bio))
+		if (mddev->pers->make_request(mddev, bio))
 			generic_make_request(bio);
 		mddev->barrier = POST_REQUEST_BARRIER;
 		submit_barriers(mddev);
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 3225e25..a536f54 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -330,7 +330,7 @@ struct mdk_personality
 	int level;
 	struct list_head list;
 	struct module *owner;
-	int (*make_request)(struct request_queue *q, struct bio *bio);
+	int (*make_request)(mddev_t *mddev, struct bio *bio);
 	int (*run)(mddev_t *mddev);
 	int (*stop)(mddev_t *mddev);
 	void (*status)(struct seq_file *seq, mddev_t *mddev);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 5b4e291..50bf8e6 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -135,9 +135,8 @@ static void multipath_unplug(struct request_queue *q)
 }
 
 
-static int multipath_make_request (struct request_queue *q, struct bio * bio)
+static int multipath_make_request(mddev_t *mddev, struct bio * bio)
 {
-	mddev_t *mddev = q->queuedata;
 	multipath_conf_t *conf = mddev->private;
 	struct multipath_bh * mp_bh;
 	struct multipath_info *multipath;
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index d535f9b..9f9c6b7 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -465,9 +465,8 @@ static inline int is_io_in_chunk_boundary(mddev_t *mddev,
 	}
 }
 
-static int raid0_make_request(struct request_queue *q, struct bio *bio)
+static int raid0_make_request(mddev_t *mddev, struct bio *bio)
 {
-	mddev_t *mddev = q->queuedata;
 	unsigned int chunk_sects;
 	sector_t sector_offset;
 	struct strip_zone *zone;
@@ -495,9 +494,9 @@ static int raid0_make_request(struct request_queue *q, struct bio *bio)
 		else
 			bp = bio_split(bio, chunk_sects -
 				       sector_div(sector, chunk_sects));
-		if (raid0_make_request(q, &bp->bio1))
+		if (raid0_make_request(mddev, &bp->bio1))
 			generic_make_request(&bp->bio1);
-		if (raid0_make_request(q, &bp->bio2))
+		if (raid0_make_request(mddev, &bp->bio2))
 			generic_make_request(&bp->bio2);
 
 		bio_pair_release(bp);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index d751a5a..dd0ef70 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -773,9 +773,8 @@ do_sync_io:
 	return NULL;
 }
 
-static int make_request(struct request_queue *q, struct bio * bio)
+static int make_request(mddev_t *mddev, struct bio * bio)
 {
-	mddev_t *mddev = q->queuedata;
 	conf_t *conf = mddev->private;
 	mirror_info_t *mirror;
 	r1bio_t *r1_bio;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 00d2af6..4800299 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -788,9 +788,8 @@ static void unfreeze_array(conf_t *conf)
 	spin_unlock_irq(&conf->resync_lock);
 }
 
-static int make_request(struct request_queue *q, struct bio * bio)
+static int make_request(mddev_t *mddev, struct bio * bio)
 {
-	mddev_t *mddev = q->queuedata;
 	conf_t *conf = mddev->private;
 	mirror_info_t *mirror;
 	r10bio_t *r10_bio;
@@ -824,9 +823,9 @@ static int make_request(struct request_queue *q, struct bio * bio)
 		 */
 		bp = bio_split(bio,
 			       chunk_sects - (bio->bi_sector & (chunk_sects - 1)) );
-		if (make_request(q, &bp->bio1))
+		if (make_request(mddev, &bp->bio1))
 			generic_make_request(&bp->bio1);
-		if (make_request(q, &bp->bio2))
+		if (make_request(mddev, &bp->bio2))
 			generic_make_request(&bp->bio2);
 
 		bio_pair_release(bp);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 231afda..2882a26 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3753,9 +3753,8 @@ static int bio_fits_rdev(struct bio *bi)
 }
 
 
-static int chunk_aligned_read(struct request_queue *q, struct bio * raid_bio)
+static int chunk_aligned_read(mddev_t *mddev, struct bio * raid_bio)
 {
-	mddev_t *mddev = q->queuedata;
 	raid5_conf_t *conf = mddev->private;
 	int dd_idx;
 	struct bio* align_bi;
@@ -3870,9 +3869,8 @@ static struct stripe_head *__get_priority_stripe(raid5_conf_t *conf)
 	return sh;
 }
 
-static int make_request(struct request_queue *q, struct bio * bi)
+static int make_request(mddev_t *mddev, struct bio * bi)
 {
-	mddev_t *mddev = q->queuedata;
 	raid5_conf_t *conf = mddev->private;
 	int dd_idx;
 	sector_t new_sector;
@@ -3896,7 +3894,7 @@ static int make_request(struct request_queue *q, struct bio * bi)
 
 	if (rw == READ &&
 	     mddev->reshape_position == MaxSector &&
-	     chunk_aligned_read(q,bi))
+	     chunk_aligned_read(mddev,bi))
 		return 0;
 
 	logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);



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

* [md PATCH 25/28] md: factor out init code for an mddev
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (24 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 16/28] md: move io accounting out of personalities into md_make_request NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 23/28] md: call md_stop_writes from md_stop NeilBrown
                   ` (2 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

This is a simple factorisation that makes mddev_find easier to read.


Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c |   39 ++++++++++++++++++++++-----------------
 1 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 967df62..59bf6aa 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -416,6 +416,27 @@ static void mddev_put(mddev_t *mddev)
 	spin_unlock(&all_mddevs_lock);
 }
 
+static void mddev_init(mddev_t *mddev)
+{
+	mutex_init(&mddev->open_mutex);
+	mutex_init(&mddev->reconfig_mutex);
+	mutex_init(&mddev->bitmap_info.mutex);
+	INIT_LIST_HEAD(&mddev->disks);
+	INIT_LIST_HEAD(&mddev->all_mddevs);
+	init_timer(&mddev->safemode_timer);
+	atomic_set(&mddev->active, 1);
+	atomic_set(&mddev->openers, 0);
+	atomic_set(&mddev->active_io, 0);
+	spin_lock_init(&mddev->write_lock);
+	atomic_set(&mddev->flush_pending, 0);
+	init_waitqueue_head(&mddev->sb_wait);
+	init_waitqueue_head(&mddev->recovery_wait);
+	mddev->reshape_position = MaxSector;
+	mddev->resync_min = 0;
+	mddev->resync_max = MaxSector;
+	mddev->level = LEVEL_NONE;
+}
+
 static mddev_t * mddev_find(dev_t unit)
 {
 	mddev_t *mddev, *new = NULL;
@@ -482,23 +503,7 @@ static mddev_t * mddev_find(dev_t unit)
 	else
 		new->md_minor = MINOR(unit) >> MdpMinorShift;
 
-	mutex_init(&new->open_mutex);
-	mutex_init(&new->reconfig_mutex);
-	mutex_init(&new->bitmap_info.mutex);
-	INIT_LIST_HEAD(&new->disks);
-	INIT_LIST_HEAD(&new->all_mddevs);
-	init_timer(&new->safemode_timer);
-	atomic_set(&new->active, 1);
-	atomic_set(&new->openers, 0);
-	atomic_set(&new->active_io, 0);
-	spin_lock_init(&new->write_lock);
-	atomic_set(&new->flush_pending, 0);
-	init_waitqueue_head(&new->sb_wait);
-	init_waitqueue_head(&new->recovery_wait);
-	new->reshape_position = MaxSector;
-	new->resync_min = 0;
-	new->resync_max = MaxSector;
-	new->level = LEVEL_NONE;
+	mddev_init(new);
 
 	goto retry;
 }



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

* [md PATCH 27/28] md/raid1: fix confusing 'redirect sector' message.
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (7 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 07/28] md: Add support for Raid5->Raid0 and Raid10->Raid0 takeover NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 10/28] md: Relax checks on ->max_disks when external metadata handling is used NeilBrown
                   ` (19 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid; +Cc: Tim Burgess

This message seems to suggest the named device is the one on which a
read failed, however it is actually the device that the read will be
redirected to.
So make the message a little clearer.

Reported-by: Tim Burgess <ozburgess@gmail.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/raid1.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index dd0ef70..d0d32f0 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1688,10 +1688,10 @@ static void raid1d(mddev_t *mddev)
 				r1_bio->bios[r1_bio->read_disk] = bio;
 				rdev = conf->mirrors[disk].rdev;
 				if (printk_ratelimit())
-					printk(KERN_ERR "raid1: %s: redirecting sector %llu to"
-					       " another mirror\n",
-					       bdevname(rdev->bdev,b),
-					       (unsigned long long)r1_bio->sector);
+					printk(KERN_ERR "raid1: redirecting sector %llu to"
+					       " other mirror: %s\n",
+					       (unsigned long long)r1_bio->sector,
+					       bdevname(rdev->bdev,b));
 				bio->bi_sector = r1_bio->sector + rdev->data_offset;
 				bio->bi_bdev = rdev->bdev;
 				bio->bi_end_io = raid1_end_read_request;



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

* [md PATCH 26/28] md: don't unregister the thread in mddev_suspend
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (9 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 10/28] md: Relax checks on ->max_disks when external metadata handling is used NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 09/28] md: Correctly handle device removal via sysfs NeilBrown
                   ` (17 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

This is
 - unnecessary because mddev_suspend is always followed by a call to
   ->stop, and each ->stop unregisters the thread, and
 - a problem as it makes it awkwards to suspend and then resume a
   device as we will want later.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/md.c |   13 ++++++-------
 1 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index 59bf6aa..ad7e2b8 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -254,6 +254,12 @@ static int md_make_request(struct request_queue *q, struct bio *bio)
 	return rv;
 }
 
+/* mddev_suspend makes sure no new requests are submitted
+ * to the device, and that any requests that have been submitted
+ * are completely handled.
+ * Once ->stop is called and completes, the module will be completely
+ * unused.
+ */
 static void mddev_suspend(mddev_t *mddev)
 {
 	BUG_ON(mddev->suspended);
@@ -261,13 +267,6 @@ static void mddev_suspend(mddev_t *mddev)
 	synchronize_rcu();
 	wait_event(mddev->sb_wait, atomic_read(&mddev->active_io) == 0);
 	mddev->pers->quiesce(mddev, 1);
-	md_unregister_thread(mddev->thread);
-	mddev->thread = NULL;
-	/* we now know that no code is executing in the personality module,
-	 * except possibly the tail end of a ->bi_end_io function, but that
-	 * is certain to complete before the module has a chance to get
-	 * unloaded
-	 */
 }
 
 static void mddev_resume(mddev_t *mddev)



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

* [md PATCH 28/28] md/raid1: delay reads that could overtake behind-writes.
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (18 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 24/28] md: pass mddev to make_request functions rather than request_queue NeilBrown
@ 2010-04-15  6:21 ` NeilBrown
  2010-04-15  6:21 ` [md PATCH 13/28] md: notify level changes through sysfs NeilBrown
                   ` (8 subsequent siblings)
  28 siblings, 0 replies; 33+ messages in thread
From: NeilBrown @ 2010-04-15  6:21 UTC (permalink / raw)
  To: linux-raid

When a raid1 array is configured to support write-behind
on some devices, it normally only reads from other devices.
If all devices are write-behind (because the rest have failed)
it is possible for a read request to be serviced before a
behind-write request, which would appear as data corruption.

So when forced to read from a WriteMostly device, wait for any
write-behind to complete, and don't start any more behind-writes.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 drivers/md/bitmap.c |    4 +++-
 drivers/md/bitmap.h |    1 +
 drivers/md/raid1.c  |   25 ++++++++++++++++++-------
 3 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 49d6080..c9c6a34 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -1356,7 +1356,8 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
 {
 	if (!bitmap) return;
 	if (behind) {
-		atomic_dec(&bitmap->behind_writes);
+		if (atomic_dec_and_test(&bitmap->behind_writes))
+			wake_up(&bitmap->behind_wait);
 		PRINTK(KERN_DEBUG "dec write-behind count %d/%d\n",
 		  atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
 	}
@@ -1680,6 +1681,7 @@ int bitmap_create(mddev_t *mddev)
 	atomic_set(&bitmap->pending_writes, 0);
 	init_waitqueue_head(&bitmap->write_wait);
 	init_waitqueue_head(&bitmap->overflow_wait);
+	init_waitqueue_head(&bitmap->behind_wait);
 
 	bitmap->mddev = mddev;
 
diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h
index aa82b7c..3797dea 100644
--- a/drivers/md/bitmap.h
+++ b/drivers/md/bitmap.h
@@ -240,6 +240,7 @@ struct bitmap {
 	atomic_t pending_writes; /* pending writes to the bitmap file */
 	wait_queue_head_t write_wait;
 	wait_queue_head_t overflow_wait;
+	wait_queue_head_t behind_wait;
 
 	struct sysfs_dirent *sysfs_can_clear;
 };
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index d0d32f0..3744fe2 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -857,6 +857,15 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 		}
 		mirror = conf->mirrors + rdisk;
 
+		if (test_bit(WriteMostly, &mirror->rdev->flags) &&
+		    bitmap) {
+			/* Reading from a write-mostly device must
+			 * take care not to over-take any writes
+			 * that are 'behind'
+			 */
+			wait_event(bitmap->behind_wait,
+				   atomic_read(&bitmap->behind_writes) == 0);
+		}
 		r1_bio->read_disk = rdisk;
 
 		read_bio = bio_clone(bio, GFP_NOIO);
@@ -933,10 +942,14 @@ static int make_request(mddev_t *mddev, struct bio * bio)
 		set_bit(R1BIO_Degraded, &r1_bio->state);
 	}
 
-	/* do behind I/O ? */
+	/* do behind I/O ?
+	 * Not if there are too many, or cannot allocate memory,
+	 * or a reader on WriteMostly is waiting for behind writes 
+	 * to flush */
 	if (bitmap &&
 	    (atomic_read(&bitmap->behind_writes)
 	     < mddev->bitmap_info.max_write_behind) &&
+	    !waitqueue_active(&bitmap->behind_wait) &&
 	    (behind_pages = alloc_behind_pages(bio)) != NULL)
 		set_bit(R1BIO_BehindIO, &r1_bio->state);
 
@@ -2143,15 +2156,13 @@ static int stop(mddev_t *mddev)
 {
 	conf_t *conf = mddev->private;
 	struct bitmap *bitmap = mddev->bitmap;
-	int behind_wait = 0;
 
 	/* wait for behind writes to complete */
-	while (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
-		behind_wait++;
-		printk(KERN_INFO "raid1: behind writes in progress on device %s, waiting to stop (%d)\n", mdname(mddev), behind_wait);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ); /* wait a second */
+	if (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
+		printk(KERN_INFO "raid1: behind writes in progress on device %s, waiting to stop.\n", mdname(mddev));
 		/* need to kick something here to make sure I/O goes? */
+		wait_event(bitmap->behind_wait,
+			   atomic_read(&bitmap->behind_writes) == 0);
 	}
 
 	raise_barrier(conf);



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

* Re: [md PATCH 00/28] md patches destined for -next and the next merge window
  2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
                   ` (27 preceding siblings ...)
  2010-04-15  6:21 ` [md PATCH 12/28] md: manage redundancy group in sysfs when changing level NeilBrown
@ 2010-05-02 17:59 ` Dan Williams
  2010-05-03  3:11   ` Neil Brown
  28 siblings, 1 reply; 33+ messages in thread
From: Dan Williams @ 2010-05-02 17:59 UTC (permalink / raw)
  To: NeilBrown; +Cc: linux-raid

On Wed, Apr 14, 2010 at 11:21 PM, NeilBrown <neilb@suse.de> wrote:
> Hi all,
>  I thought it was time I posted my patch queue for review to be sure
>  it would be ready for the next merge window.
>
>  Apart from sundry bug fixes and minor improvements there are two big
>  themes here
>  1/ enhancements to level conversion so e.g. we can now convert RAID0
>    to RAID5 or RAID10 (near-2 only) and back.
>  2/ general refactoring of bits of md code - some functions
>    (e.g. do_md_stop) had become really big and were just a mess of
>    stuff that all had to be done at much the same time.  It is now
>    broken into somewhat meaningful parts.  There is a deeper reason
>    for doing this refactoring .... you'll find out soon. :-)
>
>  This is all available at
>    git://neil.brown.name/md for-next
>  and should be in linux-next in a day or two.
>
>
>  All review, testing, and comments most welcome.
>

A few fixes/enhancements while playing with the takeover code are available at:

  git://git.kernel.org/pub/scm/linux/kernel/git/djbw/md.git for-neil

Dan Williams (3):
      md/raid4: permit raid0 takeover
      md: notify mdstat waiters of level change
      md: allow integers to be passed to md/level

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

I'd like to get "raid6: fix recovery performance regression" in for
2.6.34.  I pushed it out to the url below, let me know if you just
want me to send it directly.

  git://git.kernel.org/pub/scm/linux/kernel/git/djbw/md.git fixes

Dan Williams (1):
      raid6: fix recovery performance regression

 crypto/async_tx/async_raid6_recov.c |   21 +++++++++++++--------
 1 files changed, 13 insertions(+), 8 deletions(-)

Full diff of these 4 patches below (whitespace damaged):

diff --git a/crypto/async_tx/async_raid6_recov.c
b/crypto/async_tx/async_raid6_recov.c
index 943f2ab..3df6746 100644
--- a/crypto/async_tx/async_raid6_recov.c
+++ b/crypto/async_tx/async_raid6_recov.c
@@ -324,6 +324,7 @@ struct dma_async_tx_descriptor *
 async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
 			struct page **blocks, struct async_submit_ctl *submit)
 {
+	void *scribble = submit->scribble;
 	int non_zero_srcs, i;

 	BUG_ON(faila == failb);
@@ -332,11 +333,13 @@ async_raid6_2data_recov(int disks, size_t bytes,
int faila, int failb,

 	pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes);

-	/* we need to preserve the contents of 'blocks' for the async
-	 * case, so punt to synchronous if a scribble buffer is not available
+	/* if a dma resource is not available or a scribble buffer is not
+	 * available punt to the synchronous path.  In the 'dma not
+	 * available' case be sure to use the scribble buffer to
+	 * preserve the content of 'blocks' as the caller intended.
 	 */
-	if (!submit->scribble) {
-		void **ptrs = (void **) blocks;
+	if (async_dma_find_channel(DMA_PQ) == NULL || !scribble) {
+		void **ptrs = scribble ? scribble : (void **) blocks;

 		async_tx_quiesce(&submit->depend_tx);
 		for (i = 0; i < disks; i++)
@@ -406,11 +409,13 @@ async_raid6_datap_recov(int disks, size_t bytes,
int faila,

 	pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes);

-	/* we need to preserve the contents of 'blocks' for the async
-	 * case, so punt to synchronous if a scribble buffer is not available
+	/* if a dma resource is not available or a scribble buffer is not
+	 * available punt to the synchronous path.  In the 'dma not
+	 * available' case be sure to use the scribble buffer to
+	 * preserve the content of 'blocks' as the caller intended.
 	 */
-	if (!scribble) {
-		void **ptrs = (void **) blocks;
+	if (async_dma_find_channel(DMA_PQ) == NULL || !scribble) {
+		void **ptrs = scribble ? scribble : (void **) blocks;

 		async_tx_quiesce(&submit->depend_tx);
 		for (i = 0; i < disks; i++)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index f177de0..e3ec0fd 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2935,9 +2935,10 @@ level_show(mddev_t *mddev, char *page)
 static ssize_t
 level_store(mddev_t *mddev, const char *buf, size_t len)
 {
-	char level[16];
+	char clevel[16];
 	ssize_t rv = len;
 	struct mdk_personality *pers;
+	long level;
 	void *priv;
 	mdk_rdev_t *rdev;

@@ -2970,19 +2971,22 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
 	}

 	/* Now find the new personality */
-	if (len == 0 || len >= sizeof(level))
+	if (len == 0 || len >= sizeof(clevel))
 		return -EINVAL;
-	strncpy(level, buf, len);
-	if (level[len-1] == '\n')
+	strncpy(clevel, buf, len);
+	if (clevel[len-1] == '\n')
 		len--;
-	level[len] = 0;
+	clevel[len] = 0;
+	if (strict_strtol(clevel, 10, &level))
+		level = LEVEL_NONE;

-	request_module("md-%s", level);
+	if (request_module("md-%s", clevel) != 0)
+		request_module("md-level-%s", clevel);
 	spin_lock(&pers_lock);
-	pers = find_pers(LEVEL_NONE, level);
+	pers = find_pers(level, clevel);
 	if (!pers || !try_module_get(pers->owner)) {
 		spin_unlock(&pers_lock);
-		printk(KERN_WARNING "md: personality %s not loaded\n", level);
+		printk(KERN_WARNING "md: personality %s not loaded\n", clevel);
 		return -EINVAL;
 	}
 	spin_unlock(&pers_lock);
@@ -2995,7 +2999,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
 	if (!pers->takeover) {
 		module_put(pers->owner);
 		printk(KERN_WARNING "md: %s: %s does not support personality takeover\n",
-		       mdname(mddev), level);
+		       mdname(mddev), clevel);
 		return -EINVAL;
 	}

@@ -3011,7 +3015,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
 		mddev->delta_disks = 0;
 		module_put(pers->owner);
 		printk(KERN_WARNING "md: %s: %s would not accept array\n",
-		       mdname(mddev), level);
+		       mdname(mddev), clevel);
 		return PTR_ERR(priv);
 	}

@@ -3075,6 +3079,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
 	sysfs_notify(&mddev->kobj, NULL, "level");
+	md_new_event(mddev);
 	return rv;
 }

diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 042651b..d09c263 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -5607,10 +5607,17 @@ static void raid5_quiesce(mddev_t *mddev, int state)
 }


-static void *raid5_takeover_raid0(mddev_t *mddev)
+static void *raid45_takeover_raid0(mddev_t *mddev, int level)
 {
+	struct raid0_private_data *raid0_priv = mddev->private;

-	mddev->new_level = 5;
+	/* for raid0 takeover only one zone is supported */
+	if (raid0_priv->nr_strip_zones > 1) {
+		printk(KERN_ERR "md: cannot takeover raid0 with more than one zone.\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	mddev->new_level = level;
 	mddev->new_layout = ALGORITHM_PARITY_N;
 	mddev->new_chunk_sectors = mddev->chunk_sectors;
 	mddev->raid_disks += 1;
@@ -5746,22 +5753,13 @@ static int raid6_check_reshape(mddev_t *mddev)
 static void *raid5_takeover(mddev_t *mddev)
 {
 	/* raid5 can take over:
-	 *  raid0 - if all devices are the same - make it a raid4 layout
+	 *  raid0 - if there is only one strip zone - make it a raid4 layout
 	 *  raid1 - if there are two drives.  We need to know the chunk size
 	 *  raid4 - trivial - just use a raid4 layout.
 	 *  raid6 - Providing it is a *_6 layout
 	 */
-	if (mddev->level == 0) {
-		/* for raid0 takeover only one zone is supported */
-		struct raid0_private_data *raid0_priv
-			= mddev->private;
-		if (raid0_priv->nr_strip_zones > 1) {
-			printk(KERN_ERR "md: cannot takeover raid 0 with more than one zone.\n");
-			return ERR_PTR(-EINVAL);
-		}
-		return raid5_takeover_raid0(mddev);
-	}
-
+	if (mddev->level == 0)
+		return raid45_takeover_raid0(mddev, 5);
 	if (mddev->level == 1)
 		return raid5_takeover_raid1(mddev);
 	if (mddev->level == 4) {
@@ -5777,8 +5775,12 @@ static void *raid5_takeover(mddev_t *mddev)

 static void *raid4_takeover(mddev_t *mddev)
 {
-	/* raid4 can take over raid5 if layout is right.
+	/* raid4 can take over:
+	 *  raid0 - if there is only one strip zone
+	 *  raid5 - if layout is right
 	 */
+	if (mddev->level == 0)
+		return raid45_takeover_raid0(mddev, 4);
 	if (mddev->level == 5 &&
 	    mddev->layout == ALGORITHM_PARITY_N) {
 		mddev->new_layout = 0;
--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [md PATCH 00/28] md patches destined for -next and the next merge  window
  2010-05-02 17:59 ` [md PATCH 00/28] md patches destined for -next and the next merge window Dan Williams
@ 2010-05-03  3:11   ` Neil Brown
  2010-05-03 15:27     ` Dan Williams
  0 siblings, 1 reply; 33+ messages in thread
From: Neil Brown @ 2010-05-03  3:11 UTC (permalink / raw)
  To: Dan Williams; +Cc: linux-raid

On Sun, 2 May 2010 10:59:02 -0700
Dan Williams <dan.j.williams@intel.com> wrote:

> On Wed, Apr 14, 2010 at 11:21 PM, NeilBrown <neilb@suse.de> wrote:
> > Hi all,
> >  I thought it was time I posted my patch queue for review to be sure
> >  it would be ready for the next merge window.
> >
> >  Apart from sundry bug fixes and minor improvements there are two big
> >  themes here
> >  1/ enhancements to level conversion so e.g. we can now convert RAID0
> >    to RAID5 or RAID10 (near-2 only) and back.
> >  2/ general refactoring of bits of md code - some functions
> >    (e.g. do_md_stop) had become really big and were just a mess of
> >    stuff that all had to be done at much the same time.  It is now
> >    broken into somewhat meaningful parts.  There is a deeper reason
> >    for doing this refactoring .... you'll find out soon. :-)
> >
> >  This is all available at
> >    git://neil.brown.name/md for-next
> >  and should be in linux-next in a day or two.
> >
> >
> >  All review, testing, and comments most welcome.
> >
> 
> A few fixes/enhancements while playing with the takeover code are available at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/djbw/md.git for-neil

Thanks - they all make sense.
I've merged them with my queue and push them to my for-next branch.

NeilBrown


> 
> Dan Williams (3):
>       md/raid4: permit raid0 takeover
>       md: notify mdstat waiters of level change
>       md: allow integers to be passed to md/level
> 
>  drivers/md/md.c    |   25 +++++++++++++++----------
>  drivers/md/raid5.c |   32 +++++++++++++++++---------------
>  2 files changed, 32 insertions(+), 25 deletions(-)
> 
> I'd like to get "raid6: fix recovery performance regression" in for
> 2.6.34.  I pushed it out to the url below, let me know if you just
> want me to send it directly.
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/djbw/md.git fixes
> 
> Dan Williams (1):
>       raid6: fix recovery performance regression
> 
>  crypto/async_tx/async_raid6_recov.c |   21 +++++++++++++--------
>  1 files changed, 13 insertions(+), 8 deletions(-)
> 
> Full diff of these 4 patches below (whitespace damaged):
> 
> diff --git a/crypto/async_tx/async_raid6_recov.c
> b/crypto/async_tx/async_raid6_recov.c
> index 943f2ab..3df6746 100644
> --- a/crypto/async_tx/async_raid6_recov.c
> +++ b/crypto/async_tx/async_raid6_recov.c
> @@ -324,6 +324,7 @@ struct dma_async_tx_descriptor *
>  async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
>  			struct page **blocks, struct async_submit_ctl *submit)
>  {
> +	void *scribble = submit->scribble;
>  	int non_zero_srcs, i;
> 
>  	BUG_ON(faila == failb);
> @@ -332,11 +333,13 @@ async_raid6_2data_recov(int disks, size_t bytes,
> int faila, int failb,
> 
>  	pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes);
> 
> -	/* we need to preserve the contents of 'blocks' for the async
> -	 * case, so punt to synchronous if a scribble buffer is not available
> +	/* if a dma resource is not available or a scribble buffer is not
> +	 * available punt to the synchronous path.  In the 'dma not
> +	 * available' case be sure to use the scribble buffer to
> +	 * preserve the content of 'blocks' as the caller intended.
>  	 */
> -	if (!submit->scribble) {
> -		void **ptrs = (void **) blocks;
> +	if (async_dma_find_channel(DMA_PQ) == NULL || !scribble) {
> +		void **ptrs = scribble ? scribble : (void **) blocks;
> 
>  		async_tx_quiesce(&submit->depend_tx);
>  		for (i = 0; i < disks; i++)
> @@ -406,11 +409,13 @@ async_raid6_datap_recov(int disks, size_t bytes,
> int faila,
> 
>  	pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes);
> 
> -	/* we need to preserve the contents of 'blocks' for the async
> -	 * case, so punt to synchronous if a scribble buffer is not available
> +	/* if a dma resource is not available or a scribble buffer is not
> +	 * available punt to the synchronous path.  In the 'dma not
> +	 * available' case be sure to use the scribble buffer to
> +	 * preserve the content of 'blocks' as the caller intended.
>  	 */
> -	if (!scribble) {
> -		void **ptrs = (void **) blocks;
> +	if (async_dma_find_channel(DMA_PQ) == NULL || !scribble) {
> +		void **ptrs = scribble ? scribble : (void **) blocks;
> 
>  		async_tx_quiesce(&submit->depend_tx);
>  		for (i = 0; i < disks; i++)
> diff --git a/drivers/md/md.c b/drivers/md/md.c
> index f177de0..e3ec0fd 100644
> --- a/drivers/md/md.c
> +++ b/drivers/md/md.c
> @@ -2935,9 +2935,10 @@ level_show(mddev_t *mddev, char *page)
>  static ssize_t
>  level_store(mddev_t *mddev, const char *buf, size_t len)
>  {
> -	char level[16];
> +	char clevel[16];
>  	ssize_t rv = len;
>  	struct mdk_personality *pers;
> +	long level;
>  	void *priv;
>  	mdk_rdev_t *rdev;
> 
> @@ -2970,19 +2971,22 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
>  	}
> 
>  	/* Now find the new personality */
> -	if (len == 0 || len >= sizeof(level))
> +	if (len == 0 || len >= sizeof(clevel))
>  		return -EINVAL;
> -	strncpy(level, buf, len);
> -	if (level[len-1] == '\n')
> +	strncpy(clevel, buf, len);
> +	if (clevel[len-1] == '\n')
>  		len--;
> -	level[len] = 0;
> +	clevel[len] = 0;
> +	if (strict_strtol(clevel, 10, &level))
> +		level = LEVEL_NONE;
> 
> -	request_module("md-%s", level);
> +	if (request_module("md-%s", clevel) != 0)
> +		request_module("md-level-%s", clevel);
>  	spin_lock(&pers_lock);
> -	pers = find_pers(LEVEL_NONE, level);
> +	pers = find_pers(level, clevel);
>  	if (!pers || !try_module_get(pers->owner)) {
>  		spin_unlock(&pers_lock);
> -		printk(KERN_WARNING "md: personality %s not loaded\n", level);
> +		printk(KERN_WARNING "md: personality %s not loaded\n", clevel);
>  		return -EINVAL;
>  	}
>  	spin_unlock(&pers_lock);
> @@ -2995,7 +2999,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
>  	if (!pers->takeover) {
>  		module_put(pers->owner);
>  		printk(KERN_WARNING "md: %s: %s does not support personality takeover\n",
> -		       mdname(mddev), level);
> +		       mdname(mddev), clevel);
>  		return -EINVAL;
>  	}
> 
> @@ -3011,7 +3015,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
>  		mddev->delta_disks = 0;
>  		module_put(pers->owner);
>  		printk(KERN_WARNING "md: %s: %s would not accept array\n",
> -		       mdname(mddev), level);
> +		       mdname(mddev), clevel);
>  		return PTR_ERR(priv);
>  	}
> 
> @@ -3075,6 +3079,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
>  	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
>  	md_wakeup_thread(mddev->thread);
>  	sysfs_notify(&mddev->kobj, NULL, "level");
> +	md_new_event(mddev);
>  	return rv;
>  }
> 
> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
> index 042651b..d09c263 100644
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -5607,10 +5607,17 @@ static void raid5_quiesce(mddev_t *mddev, int state)
>  }
> 
> 
> -static void *raid5_takeover_raid0(mddev_t *mddev)
> +static void *raid45_takeover_raid0(mddev_t *mddev, int level)
>  {
> +	struct raid0_private_data *raid0_priv = mddev->private;
> 
> -	mddev->new_level = 5;
> +	/* for raid0 takeover only one zone is supported */
> +	if (raid0_priv->nr_strip_zones > 1) {
> +		printk(KERN_ERR "md: cannot takeover raid0 with more than one zone.\n");
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	mddev->new_level = level;
>  	mddev->new_layout = ALGORITHM_PARITY_N;
>  	mddev->new_chunk_sectors = mddev->chunk_sectors;
>  	mddev->raid_disks += 1;
> @@ -5746,22 +5753,13 @@ static int raid6_check_reshape(mddev_t *mddev)
>  static void *raid5_takeover(mddev_t *mddev)
>  {
>  	/* raid5 can take over:
> -	 *  raid0 - if all devices are the same - make it a raid4 layout
> +	 *  raid0 - if there is only one strip zone - make it a raid4 layout
>  	 *  raid1 - if there are two drives.  We need to know the chunk size
>  	 *  raid4 - trivial - just use a raid4 layout.
>  	 *  raid6 - Providing it is a *_6 layout
>  	 */
> -	if (mddev->level == 0) {
> -		/* for raid0 takeover only one zone is supported */
> -		struct raid0_private_data *raid0_priv
> -			= mddev->private;
> -		if (raid0_priv->nr_strip_zones > 1) {
> -			printk(KERN_ERR "md: cannot takeover raid 0 with more than one zone.\n");
> -			return ERR_PTR(-EINVAL);
> -		}
> -		return raid5_takeover_raid0(mddev);
> -	}
> -
> +	if (mddev->level == 0)
> +		return raid45_takeover_raid0(mddev, 5);
>  	if (mddev->level == 1)
>  		return raid5_takeover_raid1(mddev);
>  	if (mddev->level == 4) {
> @@ -5777,8 +5775,12 @@ static void *raid5_takeover(mddev_t *mddev)
> 
>  static void *raid4_takeover(mddev_t *mddev)
>  {
> -	/* raid4 can take over raid5 if layout is right.
> +	/* raid4 can take over:
> +	 *  raid0 - if there is only one strip zone
> +	 *  raid5 - if layout is right
>  	 */
> +	if (mddev->level == 0)
> +		return raid45_takeover_raid0(mddev, 4);
>  	if (mddev->level == 5 &&
>  	    mddev->layout == ALGORITHM_PARITY_N) {
>  		mddev->new_layout = 0;

--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [md PATCH 00/28] md patches destined for -next and the next merge window
  2010-05-03  3:11   ` Neil Brown
@ 2010-05-03 15:27     ` Dan Williams
  2010-05-04  3:01       ` Neil Brown
  0 siblings, 1 reply; 33+ messages in thread
From: Dan Williams @ 2010-05-03 15:27 UTC (permalink / raw)
  To: Neil Brown; +Cc: linux-raid

On Sun, May 2, 2010 at 8:11 PM, Neil Brown <neilb@suse.de> wrote:
> On Sun, 2 May 2010 10:59:02 -0700
> Dan Williams <dan.j.williams@intel.com> wrote:
>> A few fixes/enhancements while playing with the takeover code are available at:
>>
>>   git://git.kernel.org/pub/scm/linux/kernel/git/djbw/md.git for-neil
>
> Thanks - they all make sense.
> I've merged them with my queue and push them to my for-next branch.

Ok, thanks, and this one below on the 'fixes' branch...?

>> I'd like to get "raid6: fix recovery performance regression" in for
>> 2.6.34.  I pushed it out to the url below, let me know if you just
>> want me to send it directly.
>>
>>   git://git.kernel.org/pub/scm/linux/kernel/git/djbw/md.git fixes
>>
>> Dan Williams (1):
>>       raid6: fix recovery performance regression
>>
>>  crypto/async_tx/async_raid6_recov.c |   21 +++++++++++++--------
>>  1 files changed, 13 insertions(+), 8 deletions(-)
--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [md PATCH 00/28] md patches destined for -next and the next merge  window
  2010-05-03 15:27     ` Dan Williams
@ 2010-05-04  3:01       ` Neil Brown
  0 siblings, 0 replies; 33+ messages in thread
From: Neil Brown @ 2010-05-04  3:01 UTC (permalink / raw)
  To: Dan Williams; +Cc: linux-raid

On Mon, 3 May 2010 08:27:04 -0700
Dan Williams <dan.j.williams@intel.com> wrote:

> On Sun, May 2, 2010 at 8:11 PM, Neil Brown <neilb@suse.de> wrote:
> > On Sun, 2 May 2010 10:59:02 -0700
> > Dan Williams <dan.j.williams@intel.com> wrote:
> >> A few fixes/enhancements while playing with the takeover code are available at:
> >>
> >>   git://git.kernel.org/pub/scm/linux/kernel/git/djbw/md.git for-neil
> >
> > Thanks - they all make sense.
> > I've merged them with my queue and push them to my for-next branch.
> 
> Ok, thanks, and this one below on the 'fixes' branch...?
> 
> >> I'd like to get "raid6: fix recovery performance regression" in for
> >> 2.6.34.  I pushed it out to the url below, let me know if you just
> >> want me to send it directly.

Sorry, I didn't notice this line before.
Yes, just send it directly.
I consider crypto/async_tx to be your domain.  I'm happy to know whats going
on in there but don't think that I need to be on the path into the kernel.

Thanks,
NeilBrown


> >>
> >>   git://git.kernel.org/pub/scm/linux/kernel/git/djbw/md.git fixes
> >>
> >> Dan Williams (1):
> >>       raid6: fix recovery performance regression
> >>
> >>  crypto/async_tx/async_raid6_recov.c |   21 +++++++++++++--------
> >>  1 files changed, 13 insertions(+), 8 deletions(-)
> --
> To unsubscribe from this list: send the line "unsubscribe linux-raid" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2010-05-04  3:01 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-15  6:21 [md PATCH 00/28] md patches destined for -next and the next merge window NeilBrown
2010-04-15  6:21 ` [md PATCH 01/28] md: remove some dead fields from mddev_s NeilBrown
2010-04-15  6:21 ` [md PATCH 06/28] md:Add support for Raid0->Raid5 takeover NeilBrown
2010-04-15  6:21 ` [md PATCH 02/28] md: expose max value of behind writes counter NeilBrown
2010-04-15  6:21 ` [md PATCH 05/28] md: don't use mddev->raid_disks in raid0 or raid10 while array is active NeilBrown
2010-04-15  6:21 ` [md PATCH 08/28] md: Add support for Raid0->Raid10 takeover NeilBrown
2010-04-15  6:21 ` [md PATCH 04/28] md: discard StateChanged device flag NeilBrown
2010-04-15  6:21 ` [md PATCH 03/28] drivers/md: Remove unnecessary casts of void * NeilBrown
2010-04-15  6:21 ` [md PATCH 07/28] md: Add support for Raid5->Raid0 and Raid10->Raid0 takeover NeilBrown
2010-04-15  6:21 ` [md PATCH 27/28] md/raid1: fix confusing 'redirect sector' message NeilBrown
2010-04-15  6:21 ` [md PATCH 10/28] md: Relax checks on ->max_disks when external metadata handling is used NeilBrown
2010-04-15  6:21 ` [md PATCH 26/28] md: don't unregister the thread in mddev_suspend NeilBrown
2010-04-15  6:21 ` [md PATCH 09/28] md: Correctly handle device removal via sysfs NeilBrown
2010-04-15  6:21 ` [md PATCH 20/28] md: start to refactor do_md_stop NeilBrown
2010-04-15  6:21 ` [md PATCH 22/28] md: split md_set_readonly out of do_md_stop NeilBrown
2010-04-15  6:21 ` [md PATCH 14/28] md: add support for raid5 to raid4 conversion NeilBrown
2010-04-15  6:21 ` [md PATCH 17/28] md: don't reference gendisk in getgeo NeilBrown
2010-04-15  6:21 ` [md PATCH 19/28] md: factor do_md_run to separate accesses to ->gendisk NeilBrown
2010-04-15  6:21 ` [md PATCH 11/28] md: remove unneeded sysfs files more promptly NeilBrown
2010-04-15  6:21 ` [md PATCH 24/28] md: pass mddev to make_request functions rather than request_queue NeilBrown
2010-04-15  6:21 ` [md PATCH 28/28] md/raid1: delay reads that could overtake behind-writes NeilBrown
2010-04-15  6:21 ` [md PATCH 13/28] md: notify level changes through sysfs NeilBrown
2010-04-15  6:21 ` [md PATCH 18/28] md: remove ->changed and related code NeilBrown
2010-04-15  6:21 ` [md PATCH 21/28] md: factor md_stop_writes out of do_md_stop NeilBrown
2010-04-15  6:21 ` [md PATCH 15/28] md/raid5: small tidyup in raid5_align_endio NeilBrown
2010-04-15  6:21 ` [md PATCH 16/28] md: move io accounting out of personalities into md_make_request NeilBrown
2010-04-15  6:21 ` [md PATCH 25/28] md: factor out init code for an mddev NeilBrown
2010-04-15  6:21 ` [md PATCH 23/28] md: call md_stop_writes from md_stop NeilBrown
2010-04-15  6:21 ` [md PATCH 12/28] md: manage redundancy group in sysfs when changing level NeilBrown
2010-05-02 17:59 ` [md PATCH 00/28] md patches destined for -next and the next merge window Dan Williams
2010-05-03  3:11   ` Neil Brown
2010-05-03 15:27     ` Dan Williams
2010-05-04  3:01       ` Neil Brown

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