diff options
author | Neil Brown <neilb@suse.de> | 2007-05-21 14:25:37 +1000 |
---|---|---|
committer | Neil Brown <neilb@suse.de> | 2007-05-21 14:25:37 +1000 |
commit | f752781f81a68588d0225cf8e3d96eeb6867b245 (patch) | |
tree | 5ab20970f51fdc52017a6fcb95fe5f05d720fbb5 /super1.c | |
parent | 68754bd17c81377091e509367e8d0cf9c80369a5 (diff) | |
download | mdadm-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.c | 31 |
1 files changed, 27 insertions, 4 deletions
@@ -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 */ |