summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog1
-rw-r--r--Grow.c15
-rw-r--r--super0.c13
-rw-r--r--super1.c31
4 files changed, 45 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index caa2539..a25463e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,7 @@ Changes Prior to this release
- fix internal bitmap allocation problems with v1.1, v1.2 metadata.
- --help now goes to stdout so you can direct it to a pager.
- Various manpage updates.
+ - Make "--grow --add" for linear arrays really work.
Changes Prior to 2.6.1 release
- --monitor was producing some meaningless warnings due to a bug.
diff --git a/Grow.c b/Grow.c
index c160f2c..c28c1ac 100644
--- a/Grow.c
+++ b/Grow.c
@@ -121,10 +121,12 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
info.disk.minor = minor(stb.st_rdev);
info.disk.raid_disk = d;
info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
- st->ss->update_super(&info, super, "grow", newdev, 0, 0, NULL);
+ st->ss->update_super(&info, super, "linear-grow-new", newdev,
+ 0, 0, NULL);
if (st->ss->store_super(st, nfd, super)) {
- fprintf(stderr, Name ": Cannot store new superblock on %s\n", newdev);
+ fprintf(stderr, Name ": Cannot store new superblock on %s\n",
+ newdev);
close(nfd);
return 1;
}
@@ -174,12 +176,9 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
info.array.nr_disks = nd+1;
info.array.active_disks = nd+1;
info.array.working_disks = nd+1;
- info.disk.number = nd;
- info.disk.major = major(stb.st_rdev);
- info.disk.minor = minor(stb.st_rdev);
- info.disk.raid_disk = nd;
- info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
- st->ss->update_super(&info, super, "grow", dv, 0, 0, NULL);
+
+ st->ss->update_super(&info, super, "linear-grow-update", dv,
+ 0, 0, NULL);
if (st->ss->store_super(st, fd2, super)) {
fprintf(stderr, Name ": Cannot store new superblock on %s\n", dv);
diff --git a/super0.c b/super0.c
index 5828e15..30da8aa 100644
--- a/super0.c
+++ b/super0.c
@@ -459,7 +459,16 @@ static int update_super0(struct mdinfo *info, void *sbv, char *update,
rv = 1;
}
}
- if (strcmp(update, "grow") == 0) {
+ if (strcmp(update, "linear-grow-new") == 0) {
+ memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0]));
+ sb->disks[info->disk.number].number = info->disk.number;
+ sb->disks[info->disk.number].major = info->disk.major;
+ sb->disks[info->disk.number].minor = info->disk.minor;
+ sb->disks[info->disk.number].raid_disk = info->disk.raid_disk;
+ sb->disks[info->disk.number].state = info->disk.state;
+ sb->this_disk = sb->disks[info->disk.number];
+ }
+ if (strcmp(update, "linear-grow-update") == 0) {
sb->raid_disks = info->array.raid_disks;
sb->nr_disks = info->array.nr_disks;
sb->active_disks = info->array.active_disks;
@@ -470,8 +479,6 @@ static int update_super0(struct mdinfo *info, void *sbv, char *update,
sb->disks[info->disk.number].minor = info->disk.minor;
sb->disks[info->disk.number].raid_disk = info->disk.raid_disk;
sb->disks[info->disk.number].state = info->disk.state;
- if (sb->this_disk.number == info->disk.number)
- sb->this_disk = sb->disks[info->disk.number];
}
if (strcmp(update, "resync") == 0) {
/* make sure resync happens */
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 */