Jason, thanks. Will integrate and test. Can you send me some metadata samples (in personal email) created with "dmraid -rD" for referenece, please ? Heinz On Thu, Jun 28, 2007 at 04:53:39PM -0700, Jason Gaston wrote: > This patch adds raid10(0+1) nested raid level support to the Intel isw > metadata format handler in dmraid 1.0.0.rc14. > > Signed-off-by: Jason Gaston <jason.d.gaston@xxxxxxxxx> > > --- 1.0.0.rc14/lib/format/ataraid/isw.c.orig 2006-09-22 11:11:37.000000000 > -0700 > +++ 1.0.0.rc14/lib/format/ataraid/isw.c 2007-06-28 14:06:31.000000000 -0700 > @@ -25,30 +25,59 @@ > #endif > > static const char *handler = HANDLER; > +static struct isw_disk *_get_disk(struct isw *isw, struct dev_info *di); > +int is_raid10(struct isw *isw); > > -/* > - * Make up RAID set name from family_num and volume name. > - */ > -static size_t _name(struct isw *isw, struct isw_dev *dev, > - char *str, size_t len) > +static size_t _name(struct isw *isw, char *str, size_t len, int subset, > + int num, struct isw_dev *dev) > { > - return snprintf(str, len, dev ? "isw_%u_%s" : "isw_%u", > + switch(subset) { > + case 2: > + return snprintf(str, len, "isw_%u", isw->family_num); > + case 1: > + if(!is_raid10(isw)) > + return snprintf(str, len, "isw_%u_%s", > isw->family_num, (char*) dev->volume); > -} > + else > + return snprintf(str, len, "isw_%u_%s-%u", > + isw->family_num, (char*) dev->volume, num); > + case 0: > + return snprintf(str, len, "isw_%u_%s", isw->family_num, > + (char*) dev->volume); > + } > + return 0; > +} > + > +static char *name(struct lib_context *lc, struct raid_dev *rd, > + unsigned int subset) > +{ > + size_t len; > + char *ret = NULL; > + int id = 0; > + struct isw *isw = META(rd, isw); > + struct isw_disk *disk = isw->disk; > + struct isw_dev *dev = (struct isw_dev*) (isw->disk + isw->num_disks); > > -static char *name(struct lib_context *lc, struct isw *isw, struct isw_dev > *dev) > -{ > - size_t len; > - char *ret; > + if((subset == 1) && (is_raid10(isw))) { > + if ((disk = _get_disk(isw, rd->di))) { > + if(disk == isw->disk) id = 0; > + else if(disk == isw->disk + 1) id = 1; > + else if(disk == isw->disk + 2) id = 2; > + else if(disk == isw->disk + 3) id = 3; > + else return ret; > + } > + id = id % 2; > + } > > - if ((ret = dbg_malloc((len = _name(isw, dev, NULL, 0) + 1)))) { > - _name(isw, dev, ret, len); > - mk_alpha(lc, ret + HANDLER_LEN, len - HANDLER_LEN - > - (dev ? strlen((char*) dev->volume) - 2 : 1)); > - } else > + if ((ret = dbg_malloc((len = _name(isw, ret, 0, subset, id, > + dev) + 1)))) { > + _name(isw, ret, len, subset, id, dev); > + mk_alpha(lc, ret + HANDLER_LEN, snprintf(ret, 0, "%u", > + isw->family_num)); > + } else > log_alloc_err(lc, handler); > > - return ret; > + return ret; > } > > /* Find a disk table slot by serial number. */ > @@ -59,7 +88,7 @@ > > do { > if (!strncmp(di->serial, (const char*) disk->serial, > - MAX_RAID_SERIAL_LEN)) > + MAX_RAID_SERIAL_LEN)) > return disk; > } while (++disk < isw->disk + isw->num_disks); > } > @@ -102,21 +131,38 @@ > } > > /* Neutralize disk type. */ > -static enum type type(struct raid_dev *rd) > +static enum type type(struct isw *isw) > { > /* Mapping of Intel types to generic types. */ > static struct types types[] = { > { ISW_T_RAID0, t_raid0}, > { ISW_T_RAID1, t_raid1}, > { ISW_T_RAID5, t_raid5_la}, > + { ISW_T_RAID10, t_raid0}, > { 0, t_undef}, > }; > - struct isw_dev *dev = rd->private.ptr; > + > + struct isw_dev *dev = (struct isw_dev*) (isw->disk + isw->num_disks); > + > + if(is_raid10(isw)) > + dev->vol.map.raid_level = ISW_T_RAID10; > > return dev ? rd_type(types, (unsigned int) dev->vol.map.raid_level) : > t_group; > } > > +int is_raid10(struct isw *isw) > +{ > + int ret; > + struct isw_dev *dev = (struct isw_dev*) (isw->disk + isw->num_disks); > + > + ret = ((dev->vol.map.raid_level == ISW_T_RAID10) || > + (dev->vol.map.raid_level == ISW_T_RAID1 && > + isw->num_disks > 3)); > + > + return ret; > +} > + > /* > * Generate checksum of Raid metadata for mpb_size/sizeof(u32) words > * (checksum field itself ignored for this calculation). > @@ -298,7 +344,8 @@ > } > > /* Check for RAID disk ok. */ > -static int disk_ok(struct lib_context *lc, struct dev_info *di, struct isw > *isw) > +static int disk_ok(struct lib_context *lc, struct dev_info *di, > + struct isw *isw) > { > struct isw_disk *disk = get_disk(lc, di, isw); > > @@ -306,15 +353,15 @@ > } > > static void *isw_read_metadata(struct lib_context *lc, struct dev_info *di, > - size_t *sz, uint64_t *offset, > - union read_info *info) > + size_t *sz, uint64_t *offset, > + union read_info *info) > { > size_t size = ISW_DISK_BLOCK_SIZE; > uint64_t isw_sboffset = ISW_CONFIGOFFSET; > struct isw *isw; > > if (!(isw = alloc_private_and_read(lc, handler, size, > - di->path, isw_sboffset))) > + di->path, isw_sboffset))) > goto out; > > /* > @@ -391,7 +438,7 @@ > */ > /* Check state if isw device map. */ > static int _check_map_state(struct lib_context *lc, struct raid_dev *rd, > - struct isw_dev *dev) > + struct isw_dev *dev) > { > /* FIXME: FAILED_MAP etc. */ > switch (dev->vol.map.map_state) { > @@ -415,20 +462,27 @@ > struct raid_dev *r; > > if (!_check_map_state(lc, rd, dev) || > - !(r = alloc_raid_dev(lc, handler))) > + !(r = alloc_raid_dev(lc, handler))) > return NULL; > > if (!(r->private.ptr = alloc_private(lc, handler, sizeof(*dev)))) > goto free; > - > memcpy(r->private.ptr, dev, sizeof(*dev)); > - if ((r->type = type(r)) == t_undef) { > + > + if (!(r->meta_areas = alloc_meta_areas(lc, rd, handler, 1))) > + return 0; > + > + r->meta_areas->offset = rd->meta_areas->offset; > + r->meta_areas->size = rd->meta_areas->size; > + r->meta_areas->area = rd->meta_areas->area; > + > + if ((r->type = type(isw)) == t_undef) { > log_err(lc, "%s: RAID type %u not supported", > handler, (unsigned int) dev->vol.map.raid_level); > goto free; > } > > - if (!(r->name = name(lc, isw, dev))) > + if (!(r->name = name(lc, rd, 1))) > goto free; > > r->di = rd->di; > @@ -460,43 +514,73 @@ > return _get_disk(isw, RD(new)->di) < _get_disk(isw, RD(pos)->di); > } > > +static void super_created(struct raid_set *super, void *private) > +{ > + super->type = t_raid1; > + super->stride = ((struct isw_dev*) private)->vol.map.blocks_per_strip; > +} > + > +static int set_sort(struct list_head *pos, struct list_head *new) > +{ > + return 0; > +} > + > /* > * rs_group contains the top-level group RAID set (type: t_group) on entry > * and shall be returned on success (or NULL on error). > */ > static struct raid_set *group_rd(struct lib_context *lc, > - struct raid_set *rs_group, > - struct raid_dev *rd_meta) > + struct raid_set *rs_group, > + struct raid_dev *rd_meta) > { > unsigned int d; > void *private; > struct isw *isw = META(rd_meta, isw); > struct isw_dev *dev; > struct raid_dev *rd; > - struct raid_set *rs; > - > + struct raid_set *rs, *ss; > + char *nm = NULL; > + > /* Loop the device/volume table. */ > for (d = 0; d < isw->num_raid_devs; d++) { > dev = raiddev(isw, d); > - > + > if (!(rd = _create_rd(lc, rd_meta, isw, dev))) > return NULL; > > - if (!(rs = find_or_alloc_raid_set(lc, rd->name, FIND_ALL, > - rd, &rs_group->sets, > - create_rs, dev))) { > - free_raid_dev(lc, &rd); > - return NULL; > + if(is_raid10(isw)) { > + nm = name(lc, rd, 0); > + ss = find_or_alloc_raid_set(lc, nm, FIND_TOP, rd, > + LC_RS(lc), super_created, dev); > + if (!(rs = find_or_alloc_raid_set(lc, rd->name, > + FIND_ALL, rd, &ss->sets, create_rs, > + dev))) { > + free_raid_dev(lc, &rd); > + return NULL; > + } > + } else { > + if (!(rs = find_or_alloc_raid_set(lc, rd->name, > + FIND_ALL, rd, &rs_group->sets, > + create_rs, dev))) { > + free_raid_dev(lc, &rd); > + return NULL; > + } > } > > + rs->status = s_ok; > + > /* Save and set to enable dev_sort(). */ > private = rd->private.ptr; > rd->private.ptr = isw; > - > list_add_sorted(lc, &rs->devs, &rd->devs, dev_sort); > - > /* Restore. */ > rd->private.ptr = private; > + > + if(is_raid10(isw)) { > + ss = join_superset(lc, name, super_created, set_sort, > + rs, rd); > + return ss; > + } > } > > return rs_group; > @@ -504,31 +588,35 @@ > > /* Add an Intel SW RAID device to a set */ > static struct raid_set *isw_group(struct lib_context *lc, > - struct raid_dev *rd_meta) > + struct raid_dev *rd_meta) > { > - struct raid_set *rs_group; > + struct raid_set *rs_group = NULL; > + struct isw *isw = META(rd_meta, isw); > > if (T_SPARE(rd_meta)) > return NULL; > > - /* > - * Once we get here, an Intel SW RAID disk containing a metadata area > - * with a volume table has been discovered by isw_read. > - */ > - /* Check if a top level group RAID set already exists. */ > - if (!(rs_group = find_or_alloc_raid_set(lc, rd_meta->name, FIND_TOP, > - rd_meta, LC_RS(lc), > - NO_CREATE, NO_CREATE_ARG))) > - return NULL; > + if(!is_raid10(isw)) { > + /* > + * Once we get here, an Intel SW RAID disk containing a metadata > + * area with a volume table has been discovered by isw_read. > + */ > + /* Check if a top level group RAID set already exists. */ > + if (!(rs_group = find_or_alloc_raid_set(lc, rd_meta->name, > + FIND_TOP, rd_meta, LC_RS(lc), > + NO_CREATE, NO_CREATE_ARG))) > + return NULL; > > - /* > - * Add the whole underlying (meta) RAID device to the group set. > - * Sorting is no problem here, because RAID sets and devices will > - * be created for all the Volumes of an ISW set and those need sorting. > - */ > - rd_meta->private.ptr = rd_meta->meta_areas->area; > - list_add_sorted(lc, &rs_group->devs, &rd_meta->devs, dev_sort); > - rd_meta->private.ptr = NULL; > + /* > + * Add the whole underlying (meta) RAID device to the group set. > + * Sorting is no problem here, because RAID sets and devices > + * will be created for all the Volumes of an ISW set and those > + * need sorting. > + */ > + rd_meta->private.ptr = rd_meta->meta_areas->area; > + list_add_sorted(lc, &rs_group->devs, &rd_meta->devs, dev_sort); > + rd_meta->private.ptr = NULL; > + } > > /* > * We need to run through the volume table and create a RAID set and > @@ -552,17 +640,16 @@ > } > > static int check_rd(struct lib_context *lc, struct raid_set *rs, > - struct raid_dev *rd, void *context) > + struct raid_dev *rd, void *context) > { > struct isw_dev *dev = rd->private.ptr; > > /* FIXME: more status checks ? */ > if (dev->status) > LOG_ERR(lc, 0, "%s device for volume \"%s\" broken on %s " > - "in RAID set \"%s\"", > - handler, dev->volume, rd->di->path, rs->name); > - > - return 1; > + "in RAID set \"%s\"", handler, dev->volume, > + rd->di->path, rs->name); > + return 1; > } > > static int _isw_check(struct lib_context *lc, struct raid_set *rs) > @@ -572,9 +659,14 @@ > > static int isw_check(struct lib_context *lc, struct raid_set *rs) > { > - return T_GROUP(rs) ? _isw_check(lc, rs) : 0; > + /* If it is a stacked set like RAID10 */ > + if((!T_GROUP(rs)) && SETS(rs)) { > + return check_raid_set(lc, rs, devices, NULL, > + NO_CHECK_RD, NULL, handler); > + } else { > + return T_GROUP(rs) ? _isw_check(lc, rs) : 0; > + } > } > - > /* > * IO error event handler. > */ > @@ -585,7 +677,7 @@ > struct isw_disk *disk; > > if (!(disk = get_disk(lc, rd->di, isw))) > - LOG_ERR(lc, 0, "%s: disk", handler); > + LOG_ERR(lc, 0, "%s: disk", handler); > > /* Avoid write trashing. */ > if (S_BROKEN(status(lc, rd))) > @@ -629,7 +721,7 @@ > for (i = 0; i < ISW_FILLERS; i++) { > if (isw->filler[i]) > P("filler[%i]: %u", isw, > - isw->filler[i], i, isw->filler[i]); > + isw->filler[i], i, isw->filler[i]); > } > > /* Disk table. */ > @@ -744,7 +836,7 @@ > static struct dmraid_format isw_format = { > .name = HANDLER, > .descr = "Intel Software RAID", > - .caps = "0,1", > + .caps = "0,1,10", > .format = FMT_RAID, > .read = isw_read, > .write = isw_write, > @@ -797,5 +889,7 @@ > rd->status = status(lc, rd); > rd->type = t_group; > > - return (rd->name = name(lc, isw, NULL)) ? 1 : 0; > + return (rd->name = name(lc, rd, 2)) ? 1 : 0; > } > + > + > --- 1.0.0.rc14/lib/format/ataraid/isw.h.orig 2006-01-24 07:02:54.000000000 > -0800 > +++ 1.0.0.rc14/lib/format/ataraid/isw.h 2007-06-27 15:24:19.000000000 -0700 > @@ -68,6 +68,7 @@ > uint8_t raid_level; > #define ISW_T_RAID0 0 > #define ISW_T_RAID1 1 > +#define ISW_T_RAID10 2 > #define ISW_T_RAID5 5 // since metadata version 1.2.02 ? > uint8_t num_members; // number of member disks > uint8_t reserved[3]; -- Regards, Heinz -- The LVM Guy -- *** Software bugs are stupid. Nevertheless it needs not so stupid people to solve them *** =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Heinz Mauelshagen Red Hat GmbH Consulting Development Engineer Am Sonnenhang 11 Storage Development 56242 Marienrachdorf Germany Mauelshagen@xxxxxxxxxx PHONE +49 171 7803392 FAX +49 2626 924446 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- _______________________________________________ Ataraid-list mailing list Ataraid-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/ataraid-list