summaryrefslogtreecommitdiffstats
path: root/super1.c
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2007-05-21 14:25:37 +1000
committerNeil Brown <neilb@suse.de>2007-05-21 14:25:37 +1000
commitf752781f81a68588d0225cf8e3d96eeb6867b245 (patch)
tree5ab20970f51fdc52017a6fcb95fe5f05d720fbb5 /super1.c
parent68754bd17c81377091e509367e8d0cf9c80369a5 (diff)
downloadmdadm-f752781f81a68588d0225cf8e3d96eeb6867b245.tar.gz
mdadm-f752781f81a68588d0225cf8e3d96eeb6867b245.tar.xz
mdadm-f752781f81a68588d0225cf8e3d96eeb6867b245.zip
Fix --grow --add for linear arrays.
The new superblock needs to have a new disk.number. This is a bit of a hack... Fix handling of negative bitmap offsets on 64bit hosts. The bitmap offset is a signed 32bit number, so casting to (long) isn't sufficient. We must cast to (int32_t). Fix various problems with --grow --add for linear. The code to add a drive to a live linear array had never been tested properly and so was buggy. This tidies it up and means that the new regression-test passes.
Diffstat (limited to 'super1.c')
-rw-r--r--super1.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/super1.c b/super1.c
index 5995bb6..0e70e1e 100644
--- a/super1.c
+++ b/super1.c
@@ -549,11 +549,34 @@ static int update_super1(struct mdinfo *info, void *sbv, char *update,
rv = 1;
}
}
- if (strcmp(update, "grow") == 0) {
+ if (strcmp(update, "linear-grow-new") == 0) {
+ int i;
+ int rfd;
+ int max = __le32_to_cpu(sb->max_dev);
+
+ for (i=0 ; i < max ; i++)
+ if (__le16_to_cpu(sb->dev_roles[i]) >= 0xfffe)
+ break;
+ sb->dev_number = __cpu_to_le32(i);
+ info->disk.number = i;
+ if (max >= __le32_to_cpu(sb->max_dev))
+ sb->max_dev = __cpu_to_le32(max+1);
+
+ if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
+ read(rfd, sb->device_uuid, 16) != 16) {
+ *(__u32*)(sb->device_uuid) = random();
+ *(__u32*)(sb->device_uuid+4) = random();
+ *(__u32*)(sb->device_uuid+8) = random();
+ *(__u32*)(sb->device_uuid+12) = random();
+ }
+
+ sb->dev_roles[i] =
+ __cpu_to_le16(info->disk.raid_disk);
+ }
+ if (strcmp(update, "linear-grow-update") == 0) {
sb->raid_disks = __cpu_to_le32(info->array.raid_disks);
- /* As we are just adding a spare, there is no need to
- * make any change to the dev_roles array
- */
+ sb->dev_roles[info->disk.number] =
+ __cpu_to_le16(info->disk.raid_disk);
}
if (strcmp(update, "resync") == 0) {
/* make sure resync happens */