Status: devel Use ADD_NEW_DISK to hot-add to non-version-0 arrays Signed-off-by: Neil Brown ### Diffstat output ./Manage.c | 71 ++++++++++++++++++++++++++++++++++++++++++------------------- ./super1.c | 16 ++++++++++++- 2 files changed, 65 insertions(+), 22 deletions(-) diff ./Manage.c~current~ ./Manage.c --- ./Manage.c~current~ 2005-01-25 10:06:04.000000000 +1100 +++ ./Manage.c 2004-12-07 14:19:20.000000000 +1100 @@ -168,8 +168,8 @@ int Manage_subdevs(char *devname, int fd mddev_dev_t dv; struct stat stb; int j; - int save_errno; - static char buf[4096]; + struct supertype *st; + void *dsuper = NULL; if (ioctl(fd, GET_ARRAY_INFO, &array)) { fprintf(stderr, Name ": cannot get array info for %s\n", @@ -194,26 +194,54 @@ int Manage_subdevs(char *devname, int fd return 1; case 'a': /* add the device - hot or cold */ - if (ioctl(fd, HOT_ADD_DISK, (unsigned long)stb.st_rdev)==0) { - fprintf(stderr, Name ": hot added %s\n", - dv->devname); - continue; - } - save_errno = errno; - if (read(fd, buf, sizeof(buf)) > 0) { - /* array is active, so don't try to add. - * i.e. something is wrong - */ + if (array.major_version == 0) { + if (ioctl(fd, HOT_ADD_DISK, + (unsigned long)stb.st_rdev)==0) { + fprintf(stderr, Name ": hot added %s\n", + dv->devname); + continue; + } + fprintf(stderr, Name ": hot add failed for %s: %s\n", - dv->devname, strerror(save_errno)); + dv->devname, strerror(errno)); return 1; } - /* try ADD_NEW_DISK. - * we might be creating, we might be assembling, - * it is hard to tell. - * set up number/raid_disk/state just - * in case + + /* need to find a sample superblock to copy, and + * a spare slot to use */ + st = super_by_version(array.major_version, + array.minor_version); + if (!st) { + fprintf(stderr, Name ": unsupport array - version %d.%d\n", + array.major_version, array.minor_version); + return 1; + } + for (j=0; jss->load_super(st, dfd, &dsuper, NULL)) { + close(dfd); + continue; + } + close(dfd); + break; + } + if (!dsuper) { + fprintf(stderr, Name ": cannot find valid superblock in this array - HELP\n"); + return 1; + } for (j=0; jss->write_init_super(st, dsuper, &disc, dv->devname)) + return 1; if (ioctl(fd,ADD_NEW_DISK, &disc)) { fprintf(stderr, Name ": add new device failed for %s: %s\n", dv->devname, strerror(errno)); diff ./super1.c~current~ ./super1.c --- ./super1.c~current~ 2005-01-25 10:06:04.000000000 +1100 +++ ./super1.c 2004-12-07 14:20:21.000000000 +1100 @@ -459,10 +459,13 @@ static int store_super1(int fd, void *sb return 0; } +static int load_super1(struct supertype *st, int fd, void **sbp, char *devname); + static int write_init_super1(struct supertype *st, void *sbv, mdu_disk_info_t *dinfo, char *devname) { struct mdp_superblock_1 *sb = sbv; - int fd = open(devname, O_RDWR, O_EXCL); + struct mdp_superblock_1 *refsb = NULL; + int fd = open(devname, O_RDWR | O_EXCL); int rv; long size; @@ -476,11 +479,22 @@ static int write_init_super1(struct supe } sb->dev_number = __cpu_to_le32(dinfo->number); + *(__u32*)(sb->device_uuid) = random(); *(__u32*)(sb->device_uuid+4) = random(); *(__u32*)(sb->device_uuid+8) = random(); *(__u32*)(sb->device_uuid+12) = random(); + sb->events = 0; + if (load_super1(st, fd, (void**)&refsb, NULL)==0) { + memcpy(sb->device_uuid, refsb->device_uuid, 16); + if (memcmp(sb->set_uuid, refsb->set_uuid, 16)==0) { + /* same array, so preserve events and dev_number */ + sb->events = refsb->events; + sb->dev_number = refsb->dev_number; + } + free(refsb); + } if (ioctl(fd, BLKGETSIZE, &size)) return 1;