Clarify disks/volumes above 2TiB support in geom_raid:
- add support for volumes above 2TiB with Promise metadata format; - enforse and document other limitations: - Intel and Promise metadata formats do not support disks above 2TiB; - NVIDIA metadata format does not support volumes above 2TiB. Sponsored by: iXsystems, Inc. MFC after: 2 weeks
This commit is contained in:
parent
25afe423b6
commit
a4f906fd74
@ -24,7 +24,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd March 22, 2011
|
.Dd October 26, 2011
|
||||||
.Dt GRAID 8
|
.Dt GRAID 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -250,6 +250,9 @@ If you started migration using BIOS or in some other way, make sure to
|
|||||||
complete it there.
|
complete it there.
|
||||||
Do not run GEOM RAID class on migrating volumes under pain of possible data
|
Do not run GEOM RAID class on migrating volumes under pain of possible data
|
||||||
corruption!
|
corruption!
|
||||||
|
.Sh 2TiB BARRIERS
|
||||||
|
Intel and Promise metadata formats do not support disks above 2TiB.
|
||||||
|
NVIDIA metadata format does not support volumes above 2TiB.
|
||||||
.Sh EXIT STATUS
|
.Sh EXIT STATUS
|
||||||
Exit status is 0 on success, and non-zero if the command fails.
|
Exit status is 0 on success, and non-zero if the command fails.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
|
@ -1172,15 +1172,18 @@ g_raid_md_taste_intel(struct g_raid_md_object *md, struct g_class *mp,
|
|||||||
g_access(cp, -1, 0, 0);
|
g_access(cp, -1, 0, 0);
|
||||||
if (meta == NULL) {
|
if (meta == NULL) {
|
||||||
if (g_raid_aggressive_spare) {
|
if (g_raid_aggressive_spare) {
|
||||||
if (vendor == 0x8086) {
|
if (vendor != 0x8086) {
|
||||||
|
G_RAID_DEBUG(1,
|
||||||
|
"Intel vendor mismatch 0x%04x != 0x8086",
|
||||||
|
vendor);
|
||||||
|
} else if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
|
||||||
|
G_RAID_DEBUG(1,
|
||||||
|
"Intel disk '%s' is too big.", pp->name);
|
||||||
|
} else {
|
||||||
G_RAID_DEBUG(1,
|
G_RAID_DEBUG(1,
|
||||||
"No Intel metadata, forcing spare.");
|
"No Intel metadata, forcing spare.");
|
||||||
spare = 2;
|
spare = 2;
|
||||||
goto search;
|
goto search;
|
||||||
} else {
|
|
||||||
G_RAID_DEBUG(1,
|
|
||||||
"Intel vendor mismatch 0x%04x != 0x8086",
|
|
||||||
vendor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (G_RAID_MD_TASTE_FAIL);
|
return (G_RAID_MD_TASTE_FAIL);
|
||||||
@ -1194,9 +1197,9 @@ g_raid_md_taste_intel(struct g_raid_md_object *md, struct g_class *mp,
|
|||||||
}
|
}
|
||||||
if (meta->disk[disk_pos].sectors !=
|
if (meta->disk[disk_pos].sectors !=
|
||||||
(pp->mediasize / pp->sectorsize)) {
|
(pp->mediasize / pp->sectorsize)) {
|
||||||
G_RAID_DEBUG(1, "Intel size mismatch %u != %u",
|
G_RAID_DEBUG(1, "Intel size mismatch %ju != %ju",
|
||||||
meta->disk[disk_pos].sectors,
|
(off_t)meta->disk[disk_pos].sectors,
|
||||||
(u_int)(pp->mediasize / pp->sectorsize));
|
(off_t)(pp->mediasize / pp->sectorsize));
|
||||||
goto fail1;
|
goto fail1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1449,6 +1452,13 @@ g_raid_md_ctl_intel(struct g_raid_md_object *md,
|
|||||||
cp->private = disk;
|
cp->private = disk;
|
||||||
g_topology_unlock();
|
g_topology_unlock();
|
||||||
|
|
||||||
|
if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
|
||||||
|
gctl_error(req,
|
||||||
|
"Disk '%s' is too big.", diskname);
|
||||||
|
error = -8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
error = g_raid_md_get_label(cp,
|
error = g_raid_md_get_label(cp,
|
||||||
&pd->pd_disk_meta.serial[0], INTEL_SERIAL_LEN);
|
&pd->pd_disk_meta.serial[0], INTEL_SERIAL_LEN);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
@ -1940,6 +1950,14 @@ g_raid_md_ctl_intel(struct g_raid_md_object *md,
|
|||||||
pp = cp->provider;
|
pp = cp->provider;
|
||||||
g_topology_unlock();
|
g_topology_unlock();
|
||||||
|
|
||||||
|
if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
|
||||||
|
gctl_error(req,
|
||||||
|
"Disk '%s' is too big.", diskname);
|
||||||
|
g_raid_kill_consumer(sc, cp);
|
||||||
|
error = -8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read disk serial. */
|
/* Read disk serial. */
|
||||||
error = g_raid_md_get_label(cp,
|
error = g_raid_md_get_label(cp,
|
||||||
&serial[0], INTEL_SERIAL_LEN);
|
&serial[0], INTEL_SERIAL_LEN);
|
||||||
|
@ -1033,7 +1033,7 @@ g_raid_md_ctl_nvidia(struct g_raid_md_object *md,
|
|||||||
char arg[16];
|
char arg[16];
|
||||||
const char *verb, *volname, *levelname, *diskname;
|
const char *verb, *volname, *levelname, *diskname;
|
||||||
int *nargs, *force;
|
int *nargs, *force;
|
||||||
off_t size, sectorsize, strip;
|
off_t size, sectorsize, strip, volsize;
|
||||||
intmax_t *sizearg, *striparg;
|
intmax_t *sizearg, *striparg;
|
||||||
int numdisks, i, len, level, qual, update;
|
int numdisks, i, len, level, qual, update;
|
||||||
int error;
|
int error;
|
||||||
@ -1182,7 +1182,20 @@ g_raid_md_ctl_nvidia(struct g_raid_md_object *md,
|
|||||||
gctl_error(req, "Size too small.");
|
gctl_error(req, "Size too small.");
|
||||||
return (-13);
|
return (-13);
|
||||||
}
|
}
|
||||||
if (size > 0xffffffffffffllu * sectorsize) {
|
|
||||||
|
if (level == G_RAID_VOLUME_RL_RAID0 ||
|
||||||
|
level == G_RAID_VOLUME_RL_CONCAT ||
|
||||||
|
level == G_RAID_VOLUME_RL_SINGLE)
|
||||||
|
volsize = size * numdisks;
|
||||||
|
else if (level == G_RAID_VOLUME_RL_RAID1)
|
||||||
|
volsize = size;
|
||||||
|
else if (level == G_RAID_VOLUME_RL_RAID5)
|
||||||
|
volsize = size * (numdisks - 1);
|
||||||
|
else { /* RAID1E */
|
||||||
|
volsize = ((size * numdisks) / strip / 2) *
|
||||||
|
strip;
|
||||||
|
}
|
||||||
|
if (volsize > 0xffffffffllu * sectorsize) {
|
||||||
gctl_error(req, "Size too big.");
|
gctl_error(req, "Size too big.");
|
||||||
return (-14);
|
return (-14);
|
||||||
}
|
}
|
||||||
@ -1196,18 +1209,7 @@ g_raid_md_ctl_nvidia(struct g_raid_md_object *md,
|
|||||||
vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_NONE;
|
vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_NONE;
|
||||||
vol->v_strip_size = strip;
|
vol->v_strip_size = strip;
|
||||||
vol->v_disks_count = numdisks;
|
vol->v_disks_count = numdisks;
|
||||||
if (level == G_RAID_VOLUME_RL_RAID0 ||
|
vol->v_mediasize = volsize;
|
||||||
level == G_RAID_VOLUME_RL_CONCAT ||
|
|
||||||
level == G_RAID_VOLUME_RL_SINGLE)
|
|
||||||
vol->v_mediasize = size * numdisks;
|
|
||||||
else if (level == G_RAID_VOLUME_RL_RAID1)
|
|
||||||
vol->v_mediasize = size;
|
|
||||||
else if (level == G_RAID_VOLUME_RL_RAID5)
|
|
||||||
vol->v_mediasize = size * (numdisks - 1);
|
|
||||||
else { /* RAID1E */
|
|
||||||
vol->v_mediasize = ((size * numdisks) / strip / 2) *
|
|
||||||
strip;
|
|
||||||
}
|
|
||||||
vol->v_sectorsize = sectorsize;
|
vol->v_sectorsize = sectorsize;
|
||||||
g_raid_start_volume(vol);
|
g_raid_start_volume(vol);
|
||||||
|
|
||||||
|
@ -121,7 +121,8 @@ struct promise_raid_conf {
|
|||||||
uint64_t rebuild_lba64; /* Per-volume rebuild position. */
|
uint64_t rebuild_lba64; /* Per-volume rebuild position. */
|
||||||
uint32_t magic_4;
|
uint32_t magic_4;
|
||||||
uint32_t magic_5;
|
uint32_t magic_5;
|
||||||
uint32_t filler3[325];
|
uint32_t total_sectors_high;
|
||||||
|
uint32_t filler3[324];
|
||||||
uint32_t checksum;
|
uint32_t checksum;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
@ -213,6 +214,7 @@ g_raid_md_promise_print(struct promise_raid_conf *meta)
|
|||||||
printf("rebuild_lba64 %ju\n", meta->rebuild_lba64);
|
printf("rebuild_lba64 %ju\n", meta->rebuild_lba64);
|
||||||
printf("magic_4 0x%08x\n", meta->magic_4);
|
printf("magic_4 0x%08x\n", meta->magic_4);
|
||||||
printf("magic_5 0x%08x\n", meta->magic_5);
|
printf("magic_5 0x%08x\n", meta->magic_5);
|
||||||
|
printf("total_sectors_high 0x%08x\n", meta->total_sectors_high);
|
||||||
printf("=================================================\n");
|
printf("=================================================\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -867,6 +869,9 @@ g_raid_md_promise_start(struct g_raid_volume *vol)
|
|||||||
vol->v_strip_size = 512 << meta->stripe_shift; //ZZZ
|
vol->v_strip_size = 512 << meta->stripe_shift; //ZZZ
|
||||||
vol->v_disks_count = meta->total_disks;
|
vol->v_disks_count = meta->total_disks;
|
||||||
vol->v_mediasize = (off_t)meta->total_sectors * 512; //ZZZ
|
vol->v_mediasize = (off_t)meta->total_sectors * 512; //ZZZ
|
||||||
|
if (meta->total_sectors_high < 256) /* If value looks sane. */
|
||||||
|
vol->v_mediasize |=
|
||||||
|
((off_t)meta->total_sectors_high << 32) * 512; //ZZZ
|
||||||
vol->v_sectorsize = 512; //ZZZ
|
vol->v_sectorsize = 512; //ZZZ
|
||||||
for (i = 0; i < vol->v_disks_count; i++) {
|
for (i = 0; i < vol->v_disks_count; i++) {
|
||||||
sd = &vol->v_subdisks[i];
|
sd = &vol->v_subdisks[i];
|
||||||
@ -1318,6 +1323,13 @@ g_raid_md_ctl_promise(struct g_raid_md_object *md,
|
|||||||
cp->private = disk;
|
cp->private = disk;
|
||||||
g_topology_unlock();
|
g_topology_unlock();
|
||||||
|
|
||||||
|
if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
|
||||||
|
gctl_error(req,
|
||||||
|
"Disk '%s' is too big.", diskname);
|
||||||
|
error = -8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read kernel dumping information. */
|
/* Read kernel dumping information. */
|
||||||
disk->d_kd.offset = 0;
|
disk->d_kd.offset = 0;
|
||||||
disk->d_kd.length = OFF_MAX;
|
disk->d_kd.length = OFF_MAX;
|
||||||
@ -1609,8 +1621,17 @@ g_raid_md_ctl_promise(struct g_raid_md_object *md,
|
|||||||
error = -4;
|
error = -4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
pp = cp->provider;
|
||||||
g_topology_unlock();
|
g_topology_unlock();
|
||||||
|
|
||||||
|
if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
|
||||||
|
gctl_error(req,
|
||||||
|
"Disk '%s' is too big.", diskname);
|
||||||
|
g_raid_kill_consumer(sc, cp);
|
||||||
|
error = -8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
pd = malloc(sizeof(*pd), M_MD_PROMISE, M_WAITOK | M_ZERO);
|
pd = malloc(sizeof(*pd), M_MD_PROMISE, M_WAITOK | M_ZERO);
|
||||||
|
|
||||||
disk = g_raid_create_disk(sc);
|
disk = g_raid_create_disk(sc);
|
||||||
@ -1716,6 +1737,8 @@ g_raid_md_write_promise(struct g_raid_md_object *md, struct g_raid_volume *tvol,
|
|||||||
meta->array_width /= 2;
|
meta->array_width /= 2;
|
||||||
meta->array_number = vol->v_global_id;
|
meta->array_number = vol->v_global_id;
|
||||||
meta->total_sectors = vol->v_mediasize / vol->v_sectorsize;
|
meta->total_sectors = vol->v_mediasize / vol->v_sectorsize;
|
||||||
|
meta->total_sectors_high =
|
||||||
|
(vol->v_mediasize / vol->v_sectorsize) >> 32;
|
||||||
meta->cylinders = meta->total_sectors / (255 * 63) - 1;
|
meta->cylinders = meta->total_sectors / (255 * 63) - 1;
|
||||||
meta->heads = 254;
|
meta->heads = 254;
|
||||||
meta->sectors = 63;
|
meta->sectors = 63;
|
||||||
|
Loading…
Reference in New Issue
Block a user