summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Brown <neilb@cse.unsw.edu.au>2004-10-25 04:13:38 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-10-25 04:13:38 -0700
commit512c3373155cec986eb381e0c078f0e61d103eba (patch)
tree5b2e97d75c1195bedce9ed1a32316d1868175849
parent2353acb9e6df9cd00de4cf157c4ded00102ff7ab (diff)
[PATCH] md: fixes to make version-1 superblocks work in md driver
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> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/md/md.c31
-rw-r--r--drivers/md/multipath.c2
-rw-r--r--drivers/md/raid10.c1
-rw-r--r--include/linux/raid/md.h2
-rw-r--r--include/linux/raid/md_p.h4
5 files changed, 17 insertions, 23 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index c8e7a5cb3b32..d3950b9edd48 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -748,7 +748,7 @@ static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
{
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;
@@ -763,7 +763,7 @@ static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
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)
@@ -785,7 +785,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
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;
@@ -818,6 +818,11 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
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);
@@ -862,7 +867,6 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
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;
@@ -871,7 +875,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
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);
@@ -939,7 +943,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
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);
@@ -1434,17 +1438,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) ||
@@ -1454,8 +1447,6 @@ static int analyze_sbs(mddev_t * mddev)
mdname(mddev));
return 0;
-abort:
- return 1;
}
int mdp_major = 0;
@@ -1978,7 +1969,7 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
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 --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 2877e8bdfc31..cbce9d22093e 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -190,6 +190,7 @@ static int multipath_make_request (request_queue_t *q, struct bio * bio)
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;
@@ -410,6 +411,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 --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 10f850affa27..9596358572e3 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1149,6 +1149,7 @@ static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio)
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 --git a/include/linux/raid/md.h b/include/linux/raid/md.h
index fad5699f5b7c..a6a67d102bfa 100644
--- a/include/linux/raid/md.h
+++ b/include/linux/raid/md.h
@@ -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 --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index 022b607bf9d8..8ba95d67329f 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -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