On Thu, 10 Feb 2011 09:14:40 +0000 "Czarnowska, Anna" <anna.czarnowska@xxxxxxxxx> wrote: > >From 082f13fb974059de27804e0f28d05f11e3c3eb3b Mon Sep 17 00:00:00 2001 > From: Anna Czarnowska <anna.czarnowska@xxxxxxxxx> > Date: Thu, 10 Feb 2011 09:52:42 +0100 > Subject: [PATCH] fix: detect container early in Create > Cc: linux-raid@xxxxxxxxxxxxxxx, Williams, Dan J <dan.j.williams@xxxxxxxxx>, Ciechanowski, Ed <ed.ciechanowski@xxxxxxxxx> > > When creating raid0 subarray in a container giving list of > devices on the command line Create always sets chunk=512 > default_geometry will only return chunk!=0 for imsm > when we have superblock loaded. > When a list of disks is given instead of a container > we load superblock later, after wrong chunk size has been set. > This causes Create to fail for imsm. > > New function check_container is added to check if first > non "missing" device on given list is a container member. > If it is, we load container so we can get correct chunk. > At this stage we can abort creation if > - all given devices are "missing" or > - device can't be open for reading or > - metadata given on command line does not match container we found. > > As the container check was a part of validate geometry for ddf and imsm > metadata this part of code has been replaced by check_container. I don't like this patch. Choosing the correct default chunk size does not require loading the metadata. It only requires finding the option rom which you can easily do in default_geometry_imsm just like it is done in validate_geometry_imsm_container. There may be a case for factoring code out of both ddf and intel and putting it in util.c - I'm not sure. But it should be a separate patch with a separate justification. so: not applied. Thanks, NeilBrown > > Signed-off-by: Anna Czarnowska <anna.czarnowska@xxxxxxxxx> > --- > Create.c | 21 +++++++++++++++ > mdadm.h | 1 + > super-ddf.c | 78 ++++++-------------------------------------------------- > super-intel.c | 58 +---------------------------------------- > util.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 5 files changed, 111 insertions(+), 126 deletions(-) > > diff --git a/Create.c b/Create.c > index a0669fe..8208b19 100644 > --- a/Create.c > +++ b/Create.c > @@ -64,6 +64,21 @@ static int default_layout(struct supertype *st, int level, int verbose) > return layout; > } > > +static int devices_in_container(struct mddev_dev *devlist, struct supertype **stp, int verbose) > +{ > + struct mddev_dev *dv; > + > + for(dv = devlist; dv; dv = dv->next) > + if (strcasecmp(dv->devname, "missing") == 0) > + continue; > + else > + break; > + if (!dv) { > + fprintf(stderr, Name ": Cannot create this array on missing devices\n"); > + return -1; > + } > + return check_container(dv->devname, stp, verbose); > +} > > int Create(struct supertype *st, char *mddev, > int chunk, int level, int layout, unsigned long long size, > @@ -230,6 +245,12 @@ int Create(struct supertype *st, char *mddev, > case 6: > case 0: > if (chunk == 0) { > + /* check if listed devices are in a container > + * if so, load the container */ > + if ((!st || !st->sb) && > + devices_in_container(devlist, &st, verbose) < 0) > + /* error already printed */ > + return 1; > if (st && st->ss->default_geometry) > st->ss->default_geometry(st, NULL, NULL, &chunk); > chunk = chunk ? : 512; > diff --git a/mdadm.h b/mdadm.h > index 608095f..9be236f 100644 > --- a/mdadm.h > +++ b/mdadm.h > @@ -1133,6 +1133,7 @@ extern struct mdinfo *container_choose_spares(struct supertype *st, > struct domainlist *domlist, > char *spare_group, > const char *metadata, int get_one); > +extern int check_container(char *devname, struct supertype **stp, int verbose); > extern int move_spare(char *from_devname, char *to_devname, dev_t devid); > extern int add_disk(int mdfd, struct supertype *st, > struct mdinfo *sra, struct mdinfo *info); > diff --git a/super-ddf.c b/super-ddf.c > index 287fa7f..611626f 100644 > --- a/super-ddf.c > +++ b/super-ddf.c > @@ -2555,10 +2555,6 @@ static int validate_geometry_ddf(struct supertype *st, > char *dev, unsigned long long *freesize, > int verbose) > { > - int fd; > - struct mdinfo *sra; > - int cfd; > - > /* ddf potentially supports lots of things, but it depends on > * what devices are offered (and maybe kernel version?) > * If given unused devices, we will make a container. > @@ -2601,79 +2597,21 @@ static int validate_geometry_ddf(struct supertype *st, > return 1; > } > > - if (st->sb) { > - /* A container has already been opened, so we are > - * creating in there. Maybe a BVD, maybe an SVD. > + if (st->sb || check_container(dev, &st, verbose) == 1) { > + /* A container has already been opened > + * or dev is a ddf container member, so we are > + * creating in there. > + * Maybe a BVD, maybe an SVD. > * Should make a distinction one day. > */ > return validate_geometry_ddf_bvd(st, level, layout, raiddisks, > chunk, size, dev, freesize, > verbose); > } > - /* This is the first device for the array. > - * If it is a container, we read it in and do automagic allocations, > - * no other devices should be given. > - * Otherwise it must be a member device of a container, and we > - * do manual allocation. > - * Later we should check for a BVD and make an SVD. > - */ > - fd = open(dev, O_RDONLY|O_EXCL, 0); > - if (fd >= 0) { > - sra = sysfs_read(fd, 0, GET_VERSION); > - close(fd); > - if (sra && sra->array.major_version == -1 && > - strcmp(sra->text_version, "ddf") == 0) { > - > - /* load super */ > - /* find space for 'n' devices. */ > - /* remember the devices */ > - /* Somehow return the fact that we have enough */ > - } > - > - if (verbose) > - fprintf(stderr, > - Name ": ddf: Cannot create this array " > - "on device %s - a container is required.\n", > - dev); > - return 0; > - } > - if (errno != EBUSY || (fd = open(dev, O_RDONLY, 0)) < 0) { > - if (verbose) > - fprintf(stderr, Name ": ddf: Cannot open %s: %s\n", > - dev, strerror(errno)); > - return 0; > - } > - /* Well, it is in use by someone, maybe a 'ddf' container. */ > - cfd = open_container(fd); > - if (cfd < 0) { > - close(fd); > - if (verbose) > - fprintf(stderr, Name ": ddf: Cannot use %s: %s\n", > - dev, strerror(EBUSY)); > - return 0; > - } > - sra = sysfs_read(cfd, 0, GET_VERSION); > - close(fd); > - if (sra && sra->array.major_version == -1 && > - strcmp(sra->text_version, "ddf") == 0) { > - /* This is a member of a ddf container. Load the container > - * and try to create a bvd > - */ > - struct ddf_super *ddf; > - if (load_super_ddf_all(st, cfd, (void **)&ddf, NULL) == 0) { > - st->sb = ddf; > - st->container_dev = fd2devnum(cfd); > - close(cfd); > - return validate_geometry_ddf_bvd(st, level, layout, > - raiddisks, chunk, size, > - dev, freesize, > - verbose); > - } > - close(cfd); > - } else /* device may belong to a different container */ > - return 0; > + if (verbose) > + fprintf(stderr, Name ": ddf: failed container membership check\n"); > + return 0; > > - return 1; > } > > static int > diff --git a/super-intel.c b/super-intel.c > index 29f8fc4..4d4ff89 100644 > --- a/super-intel.c > +++ b/super-intel.c > @@ -4413,10 +4413,6 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, > char *dev, unsigned long long *freesize, > int verbose) > { > - int fd, cfd; > - struct mdinfo *sra; > - int is_member = 0; > - > /* if given unused devices create a container > * if given given devices in a container create a member volume > */ > @@ -4446,64 +4442,14 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, > } > return 1; > } > - if (st->sb) { > + if (st->sb || check_container(dev, &st, verbose) == 1) { > /* creating in a given container */ > return validate_geometry_imsm_volume(st, level, layout, > raiddisks, chunk, size, > dev, freesize, verbose); > } > - > - /* This device needs to be a device in an 'imsm' container */ > - fd = open(dev, O_RDONLY|O_EXCL, 0); > - if (fd >= 0) { > - if (verbose) > - fprintf(stderr, > - Name ": Cannot create this array on device %s\n", > - dev); > - close(fd); > - return 0; > - } > - if (errno != EBUSY || (fd = open(dev, O_RDONLY, 0)) < 0) { > - if (verbose) > - fprintf(stderr, Name ": Cannot open %s: %s\n", > - dev, strerror(errno)); > - return 0; > - } > - /* Well, it is in use by someone, maybe an 'imsm' container. */ > - cfd = open_container(fd); > - close(fd); > - if (cfd < 0) { > - if (verbose) > - fprintf(stderr, Name ": Cannot use %s: It is busy\n", > - dev); > - return 0; > - } > - sra = sysfs_read(cfd, 0, GET_VERSION); > - if (sra && sra->array.major_version == -1 && > - strcmp(sra->text_version, "imsm") == 0) > - is_member = 1; > - sysfs_free(sra); > - if (is_member) { > - /* This is a member of a imsm container. Load the container > - * and try to create a volume > - */ > - struct intel_super *super; > - > - if (load_super_imsm_all(st, cfd, (void **) &super, NULL) == 0) { > - st->sb = super; > - st->container_dev = fd2devnum(cfd); > - close(cfd); > - return validate_geometry_imsm_volume(st, level, layout, > - raiddisks, chunk, > - size, dev, > - freesize, verbose); > - } > - } > - > if (verbose) > - fprintf(stderr, Name ": failed container membership check\n"); > - > - close(cfd); > + fprintf(stderr, Name ": imsm: failed container membership check\n"); > return 0; > } > > diff --git a/util.c b/util.c > index 87c23dc..6aeb789 100644 > --- a/util.c > +++ b/util.c > @@ -1976,3 +1976,82 @@ struct mdinfo *container_choose_spares(struct supertype *st, > } > return disks; > } > + > +/* Returns > + * 1: if devname is a member of container with metadata type matching stp > + * -1: if device not suitable for creating array > + * 0: if not in container but device may be suitable for native array > + */ > +int check_container(char *devname, struct supertype **stp, int verbose) > +{ > + int fd, cfd, is_member = 0; > + struct mdinfo *sra; > + struct supertype *st = NULL; > + int container_expected = (*stp && (*stp)->ss->external); > + > + fd = open(devname, O_RDONLY|O_EXCL, 0); > + if (fd >= 0) { > + /* not in container but don't stop create > + * when creating native array */ > + close(fd); > + if (container_expected) { > + fprintf(stderr, Name > + ": Cannot create this array on device %s " > + "- a container is required.\n", > + devname); > + return -1; > + } > + return 0; > + } > + if (errno != EBUSY || (fd = open(devname, O_RDONLY, 0)) < 0) { > + if (verbose) > + fprintf(stderr, Name ": Cannot open %s: %s\n", > + devname, strerror(errno)); > + /* we can't create anything on this disk */ > + return -1; > + } > + /* Well, it is in use by someone, maybe a container. */ > + cfd = open_container(fd); > + close(fd); > + if (cfd < 0) { > + if (container_expected) { > + fprintf(stderr, Name ": Cannot use %s: It is busy\n", > + devname); > + return -1; > + } > + return 0; > + } > + sra = sysfs_read(cfd, 0, GET_VERSION); > + if (sra && sra->array.major_version == -1) { > + int i; > + for (i = 0; st == NULL && superlist[i] ; i++) > + st = superlist[i]->match_metadata_desc(sra->text_version); > + if (st) > + is_member = 1; > + } > + sysfs_free(sra); > + if (is_member) { > + /* This is a member of a container. > + * if *stp we expect some type of metadata > + * check if it matches with what we have found > + * then load the container */ > + if (*stp && st->ss != (*stp)->ss) { > + fprintf(stderr, Name ": Cannot use %s: " > + "member of %s container\n", > + devname, st->ss->name); > + close(cfd); > + free(st); > + return -1; > + } > + if (st->ss->load_container(st, cfd, NULL) == 0) { > + free(*stp); > + *stp = st; > + } else /* still return ok status > + * validate_geometry will fail anyway because !st->sb */ > + if (verbose) > + fprintf(stderr, Name ": Failed to load container" > + "information for %s\n", devname); > + } > + close(cfd); > + return is_member; > +} -- To unsubscribe from this list: send the line "unsubscribe linux-raid" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html