diff -r d8ec6a195b58 src/sys/dev/ata/ata_raid.c --- a/src/sys/dev/ata/ata_raid.c Tue Jun 01 00:42:40 2010 +0900 +++ b/src/sys/dev/ata/ata_raid.c Wed Jun 02 23:02:46 2010 +0900 @@ -270,14 +270,10 @@ aai = malloc(sizeof(*aai), M_DEVBUF, M_WAITOK | M_ZERO); aai->aai_type = type; aai->aai_arrayno = arrayno; + aai->aai_curdisk = 0; ataraid_array_info_count++; - if (TAILQ_EMPTY(&ataraid_array_info_list)) { - TAILQ_INSERT_TAIL(&ataraid_array_info_list, aai, aai_list); - goto out; - } - /* Sort it into the list: type first, then array number. */ TAILQ_FOREACH(laai, &ataraid_array_info_list, aai_list) { if (aai->aai_type < laai->aai_type) { diff -r d8ec6a195b58 src/sys/dev/ata/ata_raid_intel.c --- a/src/sys/dev/ata/ata_raid_intel.c Tue Jun 01 00:42:40 2010 +0900 +++ b/src/sys/dev/ata/ata_raid_intel.c Wed Jun 02 23:02:46 2010 +0900 @@ -62,6 +62,9 @@ #define DPRINTF(x) /* nothing */ #endif +static int find_volume_id(struct intel_raid_conf *); + + #ifdef ATA_RAID_DEBUG static const char * ata_raid_intel_type(int type) @@ -139,10 +142,10 @@ struct ataraid_disk_info *adi; struct vnode *vp; uint32_t checksum, *ptr; - static int curdrive; int bmajor, count, curvol = 0, error = 0; char *tmp; dev_t dev; + int volumeid, diskidx; info = malloc(1536, M_DEVBUF, M_WAITOK|M_ZERO); @@ -203,11 +206,19 @@ /* This one points to the first volume */ map = (struct intel_raid_mapping *)&info->disk[info->total_disks]; + volumeid = find_volume_id(info); + if (volumeid < 0) { + aprint_error_dev(sc->sc_dev, + "too many RAID arrays\n"); + error = ENOMEM; + goto out; + } + findvol: /* * Lookup or allocate a new array info structure for this array. */ - aai = ata_raid_get_array_info(ATA_RAID_TYPE_INTEL, curvol); + aai = ata_raid_get_array_info(ATA_RAID_TYPE_INTEL, volumeid + curvol); /* Fill in array info */ aai->aai_generation = info->generation; @@ -241,7 +252,7 @@ aai->aai_type = ATA_RAID_TYPE_INTEL; aai->aai_capacity = map->total_sectors; - aai->aai_interleave = map->stripe_sectors / 2; + aai->aai_interleave = map->stripe_sectors; aai->aai_ndisks = map->total_disks; aai->aai_heads = 255; aai->aai_sectors = 63; @@ -253,24 +264,26 @@ strlcpy(aai->aai_name, map->name, sizeof(aai->aai_name)); /* Fill in disk info */ - adi = &aai->aai_disks[curdrive]; + diskidx = aai->aai_curdisk++; + adi = &aai->aai_disks[diskidx]; adi->adi_status = 0; - if (info->disk[curdrive].flags & INTEL_F_ONLINE) + if (info->disk[diskidx].flags & INTEL_F_ONLINE) adi->adi_status |= ADI_S_ONLINE; - if (info->disk[curdrive].flags & INTEL_F_ASSIGNED) + if (info->disk[diskidx].flags & INTEL_F_ASSIGNED) adi->adi_status |= ADI_S_ASSIGNED; - if (info->disk[curdrive].flags & INTEL_F_SPARE) { + if (info->disk[diskidx].flags & INTEL_F_SPARE) { adi->adi_status &= ~ADI_S_ONLINE; adi->adi_status |= ADI_S_SPARE; } - if (info->disk[curdrive].flags & INTEL_F_DOWN) + if (info->disk[diskidx].flags & INTEL_F_DOWN) adi->adi_status &= ~ADI_S_ONLINE; if (adi->adi_status) { adi->adi_dev = sc->sc_dev; - adi->adi_sectors = info->disk[curdrive].sectors; + adi->adi_sectors = info->disk[diskidx].sectors; adi->adi_compsize = adi->adi_sectors - aai->aai_reserved; + /* * Check if that is the only volume, otherwise repeat * the process to find more. @@ -281,10 +294,57 @@ &map->disk_idx[map->total_disks]; goto findvol; } - curdrive++; } out: free(info, M_DEVBUF); return error; } + + +/* + * Assign `volume id' to RAID volumes. + */ +static struct { + /* We assume disks are on the same array if these three values + are same. */ + uint32_t config_id; + uint32_t generation; + uint32_t checksum; + + int id; +} array_note[10]; /* XXX: this array is not used after ld_ataraid is + * configured. */ + +static int n_array = 0; +static int volume_id = 0; + +static int +find_volume_id(struct intel_raid_conf *info) +{ + int i, ret; + + for (i=0; i < n_array; ++i) { + if (info->checksum == array_note[i].checksum && + info->config_id == array_note[i].config_id && + info->generation == array_note[i].generation) { + /* we have already seen this array */ + return array_note[i].id; + } + } + + if (n_array >= __arraycount(array_note)) { + /* Too many arrays */ + return -1; + } + + array_note[n_array].checksum = info->checksum; + array_note[n_array].config_id = info->config_id; + array_note[n_array].generation = info->generation; + array_note[n_array].id = ret = volume_id; + + /* Allocate volume ids for all volumes in this array */ + volume_id += info->total_volumes; + ++n_array; + return ret; +} diff -r d8ec6a195b58 src/sys/dev/ata/ata_raidvar.h --- a/src/sys/dev/ata/ata_raidvar.h Tue Jun 01 00:42:40 2010 +0900 +++ b/src/sys/dev/ata/ata_raidvar.h Wed Jun 02 23:02:46 2010 +0900 @@ -67,8 +67,8 @@ struct ataraid_disk_info { device_t adi_dev; /* disk's device */ int adi_status; /* disk's status */ - u_int adi_sectors; - u_int adi_compsize; /* in sectors */ + uint64_t adi_sectors; + uint64_t adi_compsize; /* in sectors */ }; /* adi_status */ @@ -94,12 +94,13 @@ u_int aai_heads; /* tracks/cyl */ u_int aai_sectors; /* secs/track */ u_int aai_cylinders; /* cyl/unit */ - u_int aai_capacity; /* in sectors */ - u_int aai_offset; /* component start offset */ - u_int aai_reserved; /* component reserved sectors */ + uint64_t aai_capacity; /* in sectors */ + daddr_t aai_offset; /* component start offset */ + uint64_t aai_reserved; /* component reserved sectors */ char aai_name[32]; /* array volume name */ + uint aai_curdisk; /* to enumerate component disks */ struct ataraid_disk_info aai_disks[ATA_RAID_MAX_DISKS]; }; diff -r d8ec6a195b58 src/sys/dev/ata/ld_ataraid.c --- a/src/sys/dev/ata/ld_ataraid.c Tue Jun 01 00:42:40 2010 +0900 +++ b/src/sys/dev/ata/ld_ataraid.c Wed Jun 02 23:02:46 2010 +0900 @@ -621,6 +621,7 @@ { struct ataraid_array_info *aai = sc->sc_aai; struct ld_softc *ld = &sc->sc_ld; +#define to_kibytes(ld,s) (ld->sc_secsize*(s)/1024) /* Fill in data for _this_ volume */ bv->bv_percent = -1; @@ -640,7 +641,7 @@ switch (aai->aai_level) { case AAI_L_SPAN: case AAI_L_RAID0: - bv->bv_stripe_size = aai->aai_interleave; + bv->bv_stripe_size = to_kibytes(ld, aai->aai_interleave); bv->bv_level = 0; break; case AAI_L_RAID1: @@ -648,7 +649,7 @@ bv->bv_level = 1; break; case AAI_L_RAID5: - bv->bv_stripe_size = aai->aai_interleave; + bv->bv_stripe_size = to_kibytes(ld, aai->aai_interleave); bv->bv_level = 5; break; }