* [PATCH md 0 of 5] Introduction
@ 2004-10-20 3:26 NeilBrown
2004-10-20 3:26 ` [PATCH md 4 of 5] Fix typos in md and raid10 NeilBrown
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: NeilBrown @ 2004-10-20 3:26 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-raid
Five patches for md in 2.6.latest
The first fixes a very unfortuante bug which causes raid1 to not
survive a a drive failure (the data survives, the the host will need a
reboot :-( )
The remaining 4 fix issues of smaller significance which may affect
some poeple, but not most.
NeilBrown
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH md 5 of 5] Fixes to make version-1 superblocks work in md driver
2004-10-20 3:26 [PATCH md 0 of 5] Introduction NeilBrown
` (3 preceding siblings ...)
2004-10-20 3:26 ` [PATCH md 2 of 5] Discard calc_sb_csum_common in favour of csum_fold NeilBrown
@ 2004-10-20 3:26 ` NeilBrown
4 siblings, 0 replies; 6+ messages in thread
From: NeilBrown @ 2004-10-20 3:26 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-raid
Add some missing data_offset additions and some le_to_cpu
convertions and fix a few other little mistakes.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
### Diffstat output
./drivers/md/md.c | 31 +++++++++++--------------------
./drivers/md/multipath.c | 2 ++
./drivers/md/raid10.c | 1 +
./include/linux/raid/md.h | 2 +-
./include/linux/raid/md_p.h | 4 ++--
5 files changed, 17 insertions(+), 23 deletions(-)
diff ./drivers/md/md.c~current~ ./drivers/md/md.c
--- ./drivers/md/md.c~current~ 2004-10-20 13:21:27.000000000 +1000
+++ ./drivers/md/md.c 2004-10-20 13:21:27.000000000 +1000
@@ -791,7 +791,7 @@ static unsigned int calc_sb_1_csum(struc
{
unsigned int disk_csum, csum;
unsigned long long newcsum;
- int size = 256 + sb->max_dev*2;
+ int size = 256 + le32_to_cpu(sb->max_dev)*2;
unsigned int *isuper = (unsigned int*)sb;
int i;
@@ -806,7 +806,7 @@ static unsigned int calc_sb_1_csum(struc
csum = (newcsum & 0xffffffff) + (newcsum >> 32);
sb->sb_csum = disk_csum;
- return csum;
+ return cpu_to_le32(csum);
}
static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
@@ -828,7 +828,7 @@ static int super_1_load(mdk_rdev_t *rdev
case 0:
sb_offset = rdev->bdev->bd_inode->i_size >> 9;
sb_offset -= 8*2;
- sb_offset &= ~(4*2);
+ sb_offset &= ~(4*2-1);
/* convert from sectors to K */
sb_offset /= 2;
break;
@@ -861,6 +861,11 @@ static int super_1_load(mdk_rdev_t *rdev
bdevname(rdev->bdev,b));
return -EINVAL;
}
+ if (le64_to_cpu(sb->data_size) < 10) {
+ printk("md: data_size too small on %s\n",
+ bdevname(rdev->bdev,b));
+ return -EINVAL;
+ }
rdev->preferred_minor = 0xffff;
rdev->data_offset = le64_to_cpu(sb->data_offset);
@@ -905,7 +910,6 @@ static int super_1_validate(mddev_t *mdd
if (mddev->raid_disks == 0) {
mddev->major_version = 1;
- mddev->minor_version = 0;
mddev->patch_version = 0;
mddev->persistent = 1;
mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9;
@@ -914,7 +918,7 @@ static int super_1_validate(mddev_t *mdd
mddev->level = le32_to_cpu(sb->level);
mddev->layout = le32_to_cpu(sb->layout);
mddev->raid_disks = le32_to_cpu(sb->raid_disks);
- mddev->size = (u32)le64_to_cpu(sb->size);
+ mddev->size = le64_to_cpu(sb->size)/2;
mddev->events = le64_to_cpu(sb->events);
mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
@@ -982,7 +986,7 @@ static void super_1_sync(mddev_t *mddev,
if (rdev2->desc_nr > max_dev)
max_dev = rdev2->desc_nr;
- sb->max_dev = max_dev;
+ sb->max_dev = cpu_to_le32(max_dev);
for (i=0; i<max_dev;i++)
sb->dev_roles[max_dev] = cpu_to_le16(0xfffe);
@@ -1477,17 +1481,6 @@ static int analyze_sbs(mddev_t * mddev)
}
- /*
- * Check if we can support this RAID array
- */
- if (mddev->major_version != MD_MAJOR_VERSION ||
- mddev->minor_version > MD_MINOR_VERSION) {
- printk(KERN_ALERT
- "md: %s: unsupported raid array version %d.%d.%d\n",
- mdname(mddev), mddev->major_version,
- mddev->minor_version, mddev->patch_version);
- goto abort;
- }
if ((mddev->recovery_cp != MaxSector) &&
((mddev->level == 1) ||
@@ -1497,8 +1490,6 @@ static int analyze_sbs(mddev_t * mddev)
mdname(mddev));
return 0;
-abort:
- return 1;
}
int mdp_major = 0;
@@ -2023,7 +2014,7 @@ static int get_array_info(mddev_t * mdde
info.major_version = mddev->major_version;
info.minor_version = mddev->minor_version;
- info.patch_version = 1;
+ info.patch_version = MD_PATCHLEVEL_VERSION;
info.ctime = mddev->ctime;
info.level = mddev->level;
info.size = mddev->size;
diff ./drivers/md/multipath.c~current~ ./drivers/md/multipath.c
--- ./drivers/md/multipath.c~current~ 2004-10-20 13:21:27.000000000 +1000
+++ ./drivers/md/multipath.c 2004-10-20 13:21:27.000000000 +1000
@@ -209,6 +209,7 @@ static int multipath_make_request (reque
multipath = conf->multipaths + mp_bh->path;
mp_bh->bio = *bio;
+ mp_bh->bio.bi_sector += multipath->rdev->data_offset;
mp_bh->bio.bi_bdev = multipath->rdev->bdev;
mp_bh->bio.bi_rw |= (1 << BIO_RW_FAILFAST);
mp_bh->bio.bi_end_io = multipath_end_request;
@@ -428,6 +429,7 @@ static void multipathd (mddev_t *mddev)
bdevname(bio->bi_bdev,b),
(unsigned long long)bio->bi_sector);
*bio = *(mp_bh->master_bio);
+ bio->bi_sector += conf->multipaths[mp_bh->path].rdev->data_offset;
bio->bi_bdev = conf->multipaths[mp_bh->path].rdev->bdev;
bio->bi_rw |= (1 << BIO_RW_FAILFAST);
bio->bi_end_io = multipath_end_request;
diff ./drivers/md/raid10.c~current~ ./drivers/md/raid10.c
--- ./drivers/md/raid10.c~current~ 2004-10-20 13:21:27.000000000 +1000
+++ ./drivers/md/raid10.c 2004-10-20 13:21:27.000000000 +1000
@@ -1149,6 +1149,7 @@ static void sync_request_write(mddev_t *
atomic_inc(&r10_bio->remaining);
md_sync_acct(conf->mirrors[d].rdev->bdev, tbio->bi_size >> 9);
+ tbio->bi_sector += conf->mirrors[d].rdev->data_offset;
generic_make_request(tbio);
}
diff ./include/linux/raid/md.h~current~ ./include/linux/raid/md.h
--- ./include/linux/raid/md.h~current~ 2004-10-20 13:21:27.000000000 +1000
+++ ./include/linux/raid/md.h 2004-10-20 13:21:27.000000000 +1000
@@ -60,7 +60,7 @@
*/
#define MD_MAJOR_VERSION 0
#define MD_MINOR_VERSION 90
-#define MD_PATCHLEVEL_VERSION 0
+#define MD_PATCHLEVEL_VERSION 1
extern int register_md_personality (int p_num, mdk_personality_t *p);
extern int unregister_md_personality (int p_num);
diff ./include/linux/raid/md_p.h~current~ ./include/linux/raid/md_p.h
--- ./include/linux/raid/md_p.h~current~ 2004-10-20 13:21:27.000000000 +1000
+++ ./include/linux/raid/md_p.h 2004-10-20 13:21:27.000000000 +1000
@@ -197,7 +197,7 @@ struct mdp_superblock_1 {
__u32 chunksize; /* in 512byte sectors */
__u32 raid_disks;
- __u8 pad1[128-92]; /* set to 0 when written */
+ __u8 pad1[128-96]; /* set to 0 when written */
/* constant this-device information - 64 bytes */
__u64 data_offset; /* sector start of data, often 0 */
@@ -215,7 +215,7 @@ struct mdp_superblock_1 {
__u64 resync_offset; /* data before this offset (from data_offset) known to be in sync */
__u32 sb_csum; /* checksum upto devs[max_dev] */
__u32 max_dev; /* size of devs[] array to consider */
- __u8 pad3[64-40]; /* set to 0 when writing */
+ __u8 pad3[64-32]; /* set to 0 when writing */
/* device state information. Indexed by dev_number.
* 2 bytes per device
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH md 3 of 5] Don't hold lock on md devices while waiting for them to finish resync.
2004-10-20 3:26 [PATCH md 0 of 5] Introduction NeilBrown
2004-10-20 3:26 ` [PATCH md 4 of 5] Fix typos in md and raid10 NeilBrown
2004-10-20 3:26 ` [PATCH md 1 of 5] Make read retry use a new bio in raid1 " NeilBrown
@ 2004-10-20 3:26 ` NeilBrown
2004-10-20 3:26 ` [PATCH md 2 of 5] Discard calc_sb_csum_common in favour of csum_fold NeilBrown
2004-10-20 3:26 ` [PATCH md 5 of 5] Fixes to make version-1 superblocks work in md driver NeilBrown
4 siblings, 0 replies; 6+ messages in thread
From: NeilBrown @ 2004-10-20 3:26 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-raid
If one md array is waiting for another to finish resyncing, then it holds
a reference to the array, so the array cannot be stopped.
With this patch, we drop the reference before waiting.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
### Diffstat output
./drivers/md/md.c | 53 ++++++++++++++++++++++++++++++++++++-----------------
1 files changed, 36 insertions(+), 17 deletions(-)
diff ./drivers/md/md.c~current~ ./drivers/md/md.c
--- ./drivers/md/md.c~current~ 2004-10-20 13:21:25.000000000 +1000
+++ ./drivers/md/md.c 2004-10-20 13:21:26.000000000 +1000
@@ -3378,33 +3378,54 @@ static void md_do_sync(mddev_t *mddev)
* 1 == like 2, but have yielded to allow conflicting resync to
* commense
* other == active in resync - this many blocks
+ *
+ * Before starting a resync we must have set curr_resync to
+ * 2, and then checked that every "conflicting" array has curr_resync
+ * less than ours. When we find one that is the same or higher
+ * we wait on resync_wait. To avoid deadlock, we reduce curr_resync
+ * to 1 if we choose to yield (based arbitrarily on address of mddev structure).
+ * This will mean we have to start checking from the beginning again.
+ *
*/
+
do {
mddev->curr_resync = 2;
+ try_again:
+ if (signal_pending(current)) {
+ flush_signals(current);
+ goto skip;
+ }
ITERATE_MDDEV(mddev2,tmp) {
+ printk(".");
if (mddev2 == mddev)
continue;
if (mddev2->curr_resync &&
match_mddev_units(mddev,mddev2)) {
- printk(KERN_INFO "md: delaying resync of %s"
- " until %s has finished resync (they"
- " share one or more physical units)\n",
- mdname(mddev), mdname(mddev2));
- if (mddev < mddev2) {/* arbitrarily yield */
+ DEFINE_WAIT(wq);
+ if (mddev < mddev2 && mddev->curr_resync == 2) {
+ /* arbitrarily yield */
mddev->curr_resync = 1;
wake_up(&resync_wait);
}
- if (wait_event_interruptible(resync_wait,
- mddev2->curr_resync < mddev->curr_resync)) {
- flush_signals(current);
+ if (mddev > mddev2 && mddev->curr_resync == 1)
+ /* no need to wait here, we can wait the next
+ * time 'round when curr_resync == 2
+ */
+ continue;
+ prepare_to_wait(&resync_wait, &wq, TASK_INTERRUPTIBLE);
+ if (!signal_pending(current)
+ && mddev2->curr_resync >= mddev->curr_resync) {
+ printk(KERN_INFO "md: delaying resync of %s"
+ " until %s has finished resync (they"
+ " share one or more physical units)\n",
+ mdname(mddev), mdname(mddev2));
mddev_put(mddev2);
- goto skip;
+ schedule();
+ finish_wait(&resync_wait, &wq);
+ goto try_again;
}
- }
- if (mddev->curr_resync == 1) {
- mddev_put(mddev2);
- break;
+ finish_wait(&resync_wait, &wq);
}
}
} while (mddev->curr_resync < 2);
@@ -3552,6 +3573,7 @@ static void md_do_sync(mddev_t *mddev)
md_enter_safemode(mddev);
skip:
mddev->curr_resync = 0;
+ wake_up(&resync_wait);
set_bit(MD_RECOVERY_DONE, &mddev->recovery);
md_wakeup_thread(mddev->thread);
}
@@ -3619,15 +3641,12 @@ void md_check_recovery(mddev_t *mddev)
mddev->recovery = 0;
/* flag recovery needed just to double check */
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
- wake_up(&resync_wait);
md_new_event();
goto unlock;
}
- if (mddev->recovery) {
+ if (mddev->recovery)
/* probably just the RECOVERY_NEEDED flag */
mddev->recovery = 0;
- wake_up(&resync_wait);
- }
/* no recovery is running.
* remove any failed drives, then
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH md 2 of 5] Discard calc_sb_csum_common in favour of csum_fold
2004-10-20 3:26 [PATCH md 0 of 5] Introduction NeilBrown
` (2 preceding siblings ...)
2004-10-20 3:26 ` [PATCH md 3 of 5] Don't hold lock on md devices while waiting for them to finish resync NeilBrown
@ 2004-10-20 3:26 ` NeilBrown
2004-10-20 3:26 ` [PATCH md 5 of 5] Fixes to make version-1 superblocks work in md driver NeilBrown
4 siblings, 0 replies; 6+ messages in thread
From: NeilBrown @ 2004-10-20 3:26 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-raid
csum_fold should always have been used on the result
of csum_partial. calc_sb_csum_common therefore isn't needed.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
### Diffstat output
./drivers/md/md.c | 27 +--------------------------
1 files changed, 1 insertion(+), 26 deletions(-)
diff ./drivers/md/md.c~current~ ./drivers/md/md.c
--- ./drivers/md/md.c~current~ 2004-10-20 13:21:25.000000000 +1000
+++ ./drivers/md/md.c 2004-10-20 13:21:25.000000000 +1000
@@ -483,30 +483,6 @@ static unsigned int calc_sb_csum(mdp_sup
return csum;
}
-/* csum_partial is not consistent between different architectures.
- * Some (i386) do a 32bit csum. Some (alpha) do 16 bit.
- * This makes it hard for user-space to know what to do.
- * So we use calc_sb_csum to set the checksum to allow working
- * with older kernels, but allow calc_sb_csum_common to
- * be used when checking if a checksum is correct, to
- * make life easier for user-space tools that might write
- * a superblock.
- */
-static unsigned int calc_sb_csum_common(mdp_super_t *super)
-{
- unsigned int disk_csum = super->sb_csum;
- unsigned long long newcsum = 0;
- unsigned int csum;
- int i;
- unsigned int *superc = (int*) super;
- super->sb_csum = 0;
-
- for (i=0; i<MD_SB_BYTES/4; i++)
- newcsum+= superc[i];
- csum = (newcsum& 0xffffffff) + (newcsum>>32);
- super->sb_csum = disk_csum;
- return csum;
-}
/*
* Handle superblock details.
@@ -590,8 +566,7 @@ static int super_90_load(mdk_rdev_t *rde
if (sb->raid_disks <= 0)
goto abort;
- if (calc_sb_csum(sb) != sb->sb_csum &&
- calc_sb_csum_common(sb) != sb->sb_csum) {
+ if (csum_fold(calc_sb_csum(sb)) != csum_fold(sb->sb_csum)) {
printk(KERN_WARNING "md: invalid superblock checksum on %s\n",
b);
goto abort;
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH md 1 of 5] Make read retry use a new bio in raid1 and raid10
2004-10-20 3:26 [PATCH md 0 of 5] Introduction NeilBrown
2004-10-20 3:26 ` [PATCH md 4 of 5] Fix typos in md and raid10 NeilBrown
@ 2004-10-20 3:26 ` NeilBrown
2004-10-20 3:26 ` [PATCH md 3 of 5] Don't hold lock on md devices while waiting for them to finish resync NeilBrown
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: NeilBrown @ 2004-10-20 3:26 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-raid
When retrying a read request, we need to "Reset" the bio.
It is easiest to get this right if we discard the bio we have
and re-clone it.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
### Diffstat output
./drivers/md/raid1.c | 6 +++++-
./drivers/md/raid10.c | 13 ++++++-------
2 files changed, 11 insertions(+), 8 deletions(-)
diff ./drivers/md/raid1.c~current~ ./drivers/md/raid1.c
--- ./drivers/md/raid1.c~current~ 2004-10-20 13:21:25.000000000 +1000
+++ ./drivers/md/raid1.c 2004-10-20 13:21:25.000000000 +1000
@@ -943,6 +943,8 @@ static void raid1d(mddev_t *mddev)
} else {
r1_bio->bios[r1_bio->read_disk] = NULL;
r1_bio->read_disk = disk;
+ bio_put(bio);
+ bio = bio_clone(r1_bio->master_bio, GFP_NOIO);
r1_bio->bios[r1_bio->read_disk] = bio;
rdev = conf->mirrors[disk].rdev;
if (printk_ratelimit())
@@ -950,9 +952,11 @@ static void raid1d(mddev_t *mddev)
" another mirror\n",
bdevname(rdev->bdev,b),
(unsigned long long)r1_bio->sector);
- bio->bi_bdev = rdev->bdev;
bio->bi_sector = r1_bio->sector + rdev->data_offset;
+ bio->bi_bdev = rdev->bdev;
+ bio->bi_end_io = raid1_end_read_request;
bio->bi_rw = READ;
+ bio->bi_private = r1_bio;
unplug = 1;
generic_make_request(bio);
}
diff ./drivers/md/raid10.c~current~ ./drivers/md/raid10.c
--- ./drivers/md/raid10.c~current~ 2004-10-20 13:21:25.000000000 +1000
+++ ./drivers/md/raid10.c 2004-10-20 13:21:25.000000000 +1000
@@ -1237,8 +1237,8 @@ static void raid10d(mddev_t *mddev)
int mirror;
bio = r10_bio->devs[r10_bio->read_slot].bio;
r10_bio->devs[r10_bio->read_slot].bio = NULL;
+ bio_put(bio);
mirror = read_balance(conf, r10_bio);
- r10_bio->devs[r10_bio->read_slot].bio = bio;
if (mirror == -1) {
printk(KERN_ALERT "raid10: %s: unrecoverable I/O"
" read error for block %llu\n",
@@ -1252,15 +1252,14 @@ static void raid10d(mddev_t *mddev)
" another mirror\n",
bdevname(rdev->bdev,b),
(unsigned long long)r10_bio->sector);
- bio->bi_bdev = rdev->bdev;
+ bio = bio_clone(r10_bio->master_bio, GFP_NOIO);
+ r10_bio->devs[r10_bio->read_slot].bio = bio;
bio->bi_sector = r10_bio->devs[r10_bio->read_slot].addr
+ rdev->data_offset;
- bio->bi_next = NULL;
- bio->bi_flags &= (1<<BIO_CLONED);
- bio->bi_flags |= 1 << BIO_UPTODATE;
- bio->bi_idx = 0;
- bio->bi_size = r10_bio->sectors << 9;
+ bio->bi_bdev = rdev->bdev;
bio->bi_rw = READ;
+ bio->bi_private = r10_bio;
+ bio->bi_end_io = raid10_end_read_request;
unplug = 1;
generic_make_request(bio);
}
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH md 4 of 5] Fix typos in md and raid10
2004-10-20 3:26 [PATCH md 0 of 5] Introduction NeilBrown
@ 2004-10-20 3:26 ` NeilBrown
2004-10-20 3:26 ` [PATCH md 1 of 5] Make read retry use a new bio in raid1 " NeilBrown
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: NeilBrown @ 2004-10-20 3:26 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-raid
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
### Diffstat output
./drivers/md/md.c | 4 ++--
./drivers/md/raid10.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff ./drivers/md/md.c~current~ ./drivers/md/md.c
--- ./drivers/md/md.c~current~ 2004-10-20 13:21:26.000000000 +1000
+++ ./drivers/md/md.c 2004-10-20 13:21:27.000000000 +1000
@@ -1833,7 +1833,7 @@ static void autorun_array(mddev_t *mddev
err = do_md_run (mddev);
if (err) {
- printk(KERN_WARNING "md :do_md_run() returned %d\n", err);
+ printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
do_md_stop (mddev, 0);
}
}
@@ -2424,7 +2424,7 @@ static int update_array_info(mddev_t *md
/* The "size" is the amount of each device that is used.
* This can only make sense for arrays with redundancy.
* linear and raid0 always use whatever space is available
- * We can only consider changing the size of no resync
+ * We can only consider changing the size if no resync
* or reconstruction is happening, and if the new size
* is acceptable. It must fit before the sb_offset or,
* if that is <data_offset, it must fit before the
diff ./drivers/md/raid10.c~current~ ./drivers/md/raid10.c
--- ./drivers/md/raid10.c~current~ 2004-10-20 13:21:25.000000000 +1000
+++ ./drivers/md/raid10.c 2004-10-20 13:21:27.000000000 +1000
@@ -36,7 +36,7 @@
* device of the previous section.
* Thus there are (near_copies*far_copies) of each chunk, and each is on a different
* drive.
- * near_copies and far_copies must be at least one, and there product is at most
+ * near_copies and far_copies must be at least one, and their product is at most
* raid_disks.
*/
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2004-10-20 3:26 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-10-20 3:26 [PATCH md 0 of 5] Introduction NeilBrown
2004-10-20 3:26 ` [PATCH md 4 of 5] Fix typos in md and raid10 NeilBrown
2004-10-20 3:26 ` [PATCH md 1 of 5] Make read retry use a new bio in raid1 " NeilBrown
2004-10-20 3:26 ` [PATCH md 3 of 5] Don't hold lock on md devices while waiting for them to finish resync NeilBrown
2004-10-20 3:26 ` [PATCH md 2 of 5] Discard calc_sb_csum_common in favour of csum_fold NeilBrown
2004-10-20 3:26 ` [PATCH md 5 of 5] Fixes to make version-1 superblocks work in md driver NeilBrown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox