For Promise/AMD metadata add support for disks with capacity above 2TiB
and for volumes with sector size above 512 bytes.
This commit is contained in:
parent
bfc486325b
commit
821a0f639e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=245522
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 13, 2012
|
||||
.Dd January 16, 2013
|
||||
.Dt GRAID 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -274,7 +274,6 @@ complete it there.
|
||||
Do not run GEOM RAID class on migrating volumes under pain of possible data
|
||||
corruption!
|
||||
.Sh 2TiB BARRIERS
|
||||
Promise metadata format does not support disks above 2TiB.
|
||||
NVIDIA metadata format does not support volumes above 2TiB.
|
||||
.Sh SYSCTL VARIABLES
|
||||
The following
|
||||
|
@ -84,7 +84,7 @@ struct promise_raid_conf {
|
||||
struct promise_raid_disk disk; /* This subdisk info. */
|
||||
uint32_t disk_offset; /* Subdisk offset. */
|
||||
uint32_t disk_sectors; /* Subdisk size */
|
||||
uint32_t rebuild_lba; /* Rebuild position. */
|
||||
uint32_t disk_rebuild; /* Rebuild position. */
|
||||
uint16_t generation; /* Generation number. */
|
||||
uint8_t status; /* Volume status. */
|
||||
#define PROMISE_S_VALID 0x01
|
||||
@ -123,7 +123,17 @@ struct promise_raid_conf {
|
||||
uint32_t magic_4;
|
||||
uint32_t magic_5;
|
||||
uint32_t total_sectors_high;
|
||||
uint32_t filler3[324];
|
||||
uint8_t magic_6;
|
||||
uint8_t sector_size;
|
||||
uint16_t magic_7;
|
||||
uint32_t magic_8[32];
|
||||
uint16_t magic_9;
|
||||
uint32_t disk_offset_high;
|
||||
uint32_t disk_sectors_high;
|
||||
uint32_t disk_rebuild_high;
|
||||
uint16_t magic_10;
|
||||
uint32_t magic_11[3];
|
||||
uint32_t filler3[284];
|
||||
uint32_t checksum;
|
||||
} __packed;
|
||||
|
||||
@ -191,7 +201,7 @@ g_raid_md_promise_print(struct promise_raid_conf *meta)
|
||||
meta->disk.device, meta->disk.id);
|
||||
printf("disk_offset %u\n", meta->disk_offset);
|
||||
printf("disk_sectors %u\n", meta->disk_sectors);
|
||||
printf("rebuild_lba %u\n", meta->rebuild_lba);
|
||||
printf("disk_rebuild %u\n", meta->disk_rebuild);
|
||||
printf("generation %u\n", meta->generation);
|
||||
printf("status 0x%02x\n", meta->status);
|
||||
printf("type %u\n", meta->type);
|
||||
@ -217,6 +227,10 @@ g_raid_md_promise_print(struct promise_raid_conf *meta)
|
||||
printf("magic_4 0x%08x\n", meta->magic_4);
|
||||
printf("magic_5 0x%08x\n", meta->magic_5);
|
||||
printf("total_sectors_high 0x%08x\n", meta->total_sectors_high);
|
||||
printf("sector_size %u\n", meta->sector_size);
|
||||
printf("disk_offset_high 0x%08x\n", meta->disk_offset_high);
|
||||
printf("disk_sectors_high 0x%08x\n", meta->disk_sectors_high);
|
||||
printf("disk_rebuild_high 0x%08x\n", meta->disk_rebuild_high);
|
||||
printf("=================================================\n");
|
||||
}
|
||||
|
||||
@ -244,9 +258,9 @@ promise_meta_find_disk(struct promise_raid_conf *meta, uint64_t id)
|
||||
|
||||
static int
|
||||
promise_meta_unused_range(struct promise_raid_conf **metaarr, int nsd,
|
||||
uint32_t sectors, uint32_t *off, uint32_t *size)
|
||||
off_t sectors, off_t *off, off_t *size)
|
||||
{
|
||||
uint32_t coff, csize;
|
||||
off_t coff, csize, tmp;
|
||||
int i, j;
|
||||
|
||||
sectors -= 131072;
|
||||
@ -257,10 +271,10 @@ promise_meta_unused_range(struct promise_raid_conf **metaarr, int nsd,
|
||||
i = 0;
|
||||
while (1) {
|
||||
for (j = 0; j < nsd; j++) {
|
||||
if (metaarr[j]->disk_offset >= coff) {
|
||||
csize = MIN(csize,
|
||||
metaarr[j]->disk_offset - coff);
|
||||
}
|
||||
tmp = ((off_t)metaarr[j]->disk_offset_high << 32) +
|
||||
metaarr[j]->disk_offset;
|
||||
if (tmp >= coff)
|
||||
csize = MIN(csize, tmp - coff);
|
||||
}
|
||||
if (csize > *size) {
|
||||
*off = coff;
|
||||
@ -268,7 +282,10 @@ promise_meta_unused_range(struct promise_raid_conf **metaarr, int nsd,
|
||||
}
|
||||
if (i >= nsd)
|
||||
break;
|
||||
coff = metaarr[i]->disk_offset + metaarr[i]->disk_sectors;
|
||||
coff = ((off_t)metaarr[i]->disk_offset_high << 32) +
|
||||
metaarr[i]->disk_offset +
|
||||
((off_t)metaarr[i]->disk_sectors_high << 32) +
|
||||
metaarr[i]->disk_sectors;
|
||||
csize = sectors - coff;
|
||||
i++;
|
||||
};
|
||||
@ -369,6 +386,25 @@ promise_meta_read(struct g_consumer *cp, struct promise_raid_conf **metaarr)
|
||||
return (subdisks);
|
||||
}
|
||||
|
||||
/* Remove filler garbage from fields used in newer metadata. */
|
||||
if (meta->disk_offset_high == 0x8b8c8d8e &&
|
||||
meta->disk_sectors_high == 0x8788898a &&
|
||||
meta->disk_rebuild_high == 0x83848586) {
|
||||
meta->disk_offset_high = 0;
|
||||
meta->disk_sectors_high = 0;
|
||||
if (meta->disk_rebuild == UINT32_MAX)
|
||||
meta->disk_rebuild_high = UINT32_MAX;
|
||||
else
|
||||
meta->disk_rebuild_high = 0;
|
||||
if (meta->total_sectors_high == 0x15161718) {
|
||||
meta->total_sectors_high = 0;
|
||||
if (meta->rebuild_lba64 == 0x2122232425262728)
|
||||
meta->rebuild_lba64 = UINT64_MAX;
|
||||
}
|
||||
}
|
||||
if (meta->sector_size < 1 || meta->sector_size > 8)
|
||||
meta->sector_size = 1;
|
||||
|
||||
/* Save this part and look for next. */
|
||||
*metaarr = meta;
|
||||
metaarr++;
|
||||
@ -386,8 +422,9 @@ promise_meta_write(struct g_consumer *cp,
|
||||
struct g_provider *pp;
|
||||
struct promise_raid_conf *meta;
|
||||
char *buf;
|
||||
off_t off, size;
|
||||
int error, i, subdisk, fake;
|
||||
uint32_t checksum, *ptr, off, size;
|
||||
uint32_t checksum, *ptr;
|
||||
|
||||
pp = cp->provider;
|
||||
subdisk = 0;
|
||||
@ -409,9 +446,12 @@ promise_meta_write(struct g_consumer *cp,
|
||||
meta->disk.flags = PROMISE_F_ONLINE | PROMISE_F_VALID;
|
||||
meta->disk.number = 0xff;
|
||||
arc4rand(&meta->disk.id, sizeof(meta->disk.id), 0);
|
||||
meta->disk_offset = off;
|
||||
meta->disk_sectors = size;
|
||||
meta->rebuild_lba = UINT32_MAX;
|
||||
meta->disk_offset_high = off >> 32;
|
||||
meta->disk_offset = (uint32_t)off;
|
||||
meta->disk_sectors_high = size >> 32;
|
||||
meta->disk_sectors = (uint32_t)size;
|
||||
meta->disk_rebuild_high = UINT32_MAX;
|
||||
meta->disk_rebuild = UINT32_MAX;
|
||||
fake = 1;
|
||||
}
|
||||
if (meta != NULL) {
|
||||
@ -464,6 +504,7 @@ static int
|
||||
promise_meta_write_spare(struct g_consumer *cp)
|
||||
{
|
||||
struct promise_raid_conf *meta;
|
||||
off_t tmp;
|
||||
int error;
|
||||
|
||||
meta = malloc(sizeof(*meta), M_MD_PROMISE, M_WAITOK | M_ZERO);
|
||||
@ -473,9 +514,11 @@ promise_meta_write_spare(struct g_consumer *cp)
|
||||
meta->disk.flags = PROMISE_F_SPARE | PROMISE_F_ONLINE | PROMISE_F_VALID;
|
||||
meta->disk.number = 0xff;
|
||||
arc4rand(&meta->disk.id, sizeof(meta->disk.id), 0);
|
||||
meta->disk_sectors = cp->provider->mediasize / cp->provider->sectorsize;
|
||||
meta->disk_sectors -= 131072;
|
||||
meta->rebuild_lba = UINT32_MAX;
|
||||
tmp = cp->provider->mediasize / cp->provider->sectorsize - 131072;
|
||||
meta->disk_sectors_high = tmp >> 32;
|
||||
meta->disk_sectors = (uint32_t)tmp;
|
||||
meta->disk_rebuild_high = UINT32_MAX;
|
||||
meta->disk_rebuild = UINT32_MAX;
|
||||
error = promise_meta_write(cp, &meta, 1);
|
||||
free(meta, M_MD_PROMISE);
|
||||
return (error);
|
||||
@ -617,9 +660,8 @@ g_raid_md_promise_start_disk(struct g_raid_disk *disk, int sdn,
|
||||
struct g_raid_md_promise_perdisk *pd;
|
||||
struct g_raid_md_promise_pervolume *pv;
|
||||
struct promise_raid_conf *meta;
|
||||
off_t size;
|
||||
off_t eoff, esize, size;
|
||||
int disk_pos, md_disk_pos, i, resurrection = 0;
|
||||
uint32_t eoff, esize;
|
||||
|
||||
sc = disk->d_softc;
|
||||
pd = (struct g_raid_md_promise_perdisk *)disk->d_md_data;
|
||||
@ -729,8 +771,10 @@ g_raid_md_promise_start_disk(struct g_raid_disk *disk, int sdn,
|
||||
sd->sd_offset = (off_t)eoff * 512;
|
||||
sd->sd_size = (off_t)esize * 512;
|
||||
} else {
|
||||
sd->sd_offset = (off_t)pd->pd_meta[sdn]->disk_offset * 512;
|
||||
sd->sd_size = (off_t)pd->pd_meta[sdn]->disk_sectors * 512;
|
||||
sd->sd_offset = (((off_t)pd->pd_meta[sdn]->disk_offset_high
|
||||
<< 32) + pd->pd_meta[sdn]->disk_offset) * 512;
|
||||
sd->sd_size = (((off_t)pd->pd_meta[sdn]->disk_sectors_high
|
||||
<< 32) + pd->pd_meta[sdn]->disk_sectors) * 512;
|
||||
}
|
||||
|
||||
if (resurrection) {
|
||||
@ -749,7 +793,8 @@ g_raid_md_promise_start_disk(struct g_raid_disk *disk, int sdn,
|
||||
sd->sd_rebuild_pos = 0;
|
||||
else {
|
||||
sd->sd_rebuild_pos =
|
||||
(off_t)pd->pd_meta[sdn]->rebuild_lba * 512;
|
||||
(((off_t)pd->pd_meta[sdn]->disk_rebuild << 32) +
|
||||
pd->pd_meta[sdn]->disk_rebuild) * 512;
|
||||
}
|
||||
} else if (!(meta->disks[md_disk_pos].flags & PROMISE_F_ONLINE)) {
|
||||
/* Rebuilding disk. */
|
||||
@ -875,13 +920,15 @@ g_raid_md_promise_start(struct g_raid_volume *vol)
|
||||
vol->v_disks_count = meta->total_disks;
|
||||
vol->v_mediasize = (off_t)meta->total_sectors * 512; //ZZZ
|
||||
if (meta->total_sectors_high < 256) /* If value looks sane. */
|
||||
vol->v_mediasize |=
|
||||
vol->v_mediasize +=
|
||||
((off_t)meta->total_sectors_high << 32) * 512; //ZZZ
|
||||
vol->v_sectorsize = 512; //ZZZ
|
||||
vol->v_sectorsize = 512 * meta->sector_size;
|
||||
for (i = 0; i < vol->v_disks_count; i++) {
|
||||
sd = &vol->v_subdisks[i];
|
||||
sd->sd_offset = (off_t)meta->disk_offset * 512; //ZZZ
|
||||
sd->sd_size = (off_t)meta->disk_sectors * 512; //ZZZ
|
||||
sd->sd_offset = (((off_t)meta->disk_offset_high << 32) +
|
||||
meta->disk_offset) * 512;
|
||||
sd->sd_size = (((off_t)meta->disk_sectors_high << 32) +
|
||||
meta->disk_sectors) * 512;
|
||||
}
|
||||
g_raid_start_volume(vol);
|
||||
|
||||
@ -1213,9 +1260,8 @@ g_raid_md_ctl_promise(struct g_raid_md_object *md,
|
||||
const char *nodename, *verb, *volname, *levelname, *diskname;
|
||||
char *tmp;
|
||||
int *nargs, *force;
|
||||
off_t size, sectorsize, strip;
|
||||
off_t esize, offs[PROMISE_MAX_DISKS], size, sectorsize, strip;
|
||||
intmax_t *sizearg, *striparg;
|
||||
uint32_t offs[PROMISE_MAX_DISKS], esize;
|
||||
int numdisks, i, len, level, qual;
|
||||
int error;
|
||||
|
||||
@ -1323,13 +1369,6 @@ g_raid_md_ctl_promise(struct g_raid_md_object *md,
|
||||
cp->private = disk;
|
||||
g_topology_unlock();
|
||||
|
||||
if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
|
||||
gctl_error(req,
|
||||
"Disk '%s' is too big.", diskname);
|
||||
error = -8;
|
||||
break;
|
||||
}
|
||||
|
||||
g_raid_get_disk_info(disk);
|
||||
|
||||
/* Reserve some space for metadata. */
|
||||
@ -1394,10 +1433,6 @@ g_raid_md_ctl_promise(struct g_raid_md_object *md,
|
||||
gctl_error(req, "Size too small.");
|
||||
return (-13);
|
||||
}
|
||||
if (size > 0xffffffffllu * sectorsize) {
|
||||
gctl_error(req, "Size too big.");
|
||||
return (-14);
|
||||
}
|
||||
|
||||
/* We have all we need, create things: volume, ... */
|
||||
pv = malloc(sizeof(*pv), M_MD_PROMISE, M_WAITOK | M_ZERO);
|
||||
@ -1629,14 +1664,6 @@ g_raid_md_ctl_promise(struct g_raid_md_object *md,
|
||||
pp = cp->provider;
|
||||
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);
|
||||
|
||||
disk = g_raid_create_disk(sc);
|
||||
@ -1733,9 +1760,9 @@ g_raid_md_write_promise(struct g_raid_md_object *md, struct g_raid_volume *tvol,
|
||||
vol->v_raid_level == G_RAID_VOLUME_RL_RAID1E)
|
||||
meta->array_width /= 2;
|
||||
meta->array_number = vol->v_global_id;
|
||||
meta->total_sectors = vol->v_mediasize / vol->v_sectorsize;
|
||||
meta->total_sectors_high =
|
||||
(vol->v_mediasize / vol->v_sectorsize) >> 32;
|
||||
meta->total_sectors = vol->v_mediasize / 512;
|
||||
meta->total_sectors_high = (vol->v_mediasize / 512) >> 32;
|
||||
meta->sector_size = vol->v_sectorsize / 512;
|
||||
meta->cylinders = meta->total_sectors / (255 * 63) - 1;
|
||||
meta->heads = 254;
|
||||
meta->sectors = 63;
|
||||
@ -1828,15 +1855,24 @@ g_raid_md_write_promise(struct g_raid_md_object *md, struct g_raid_volume *tvol,
|
||||
pd->pd_meta[j] = promise_meta_copy(meta);
|
||||
pd->pd_meta[j]->disk = meta->disks[pos];
|
||||
pd->pd_meta[j]->disk.number = pos;
|
||||
pd->pd_meta[j]->disk_offset_high =
|
||||
(sd->sd_offset / 512) >> 32;
|
||||
pd->pd_meta[j]->disk_offset = sd->sd_offset / 512;
|
||||
pd->pd_meta[j]->disk_sectors_high =
|
||||
(sd->sd_size / 512) >> 32;
|
||||
pd->pd_meta[j]->disk_sectors = sd->sd_size / 512;
|
||||
if (sd->sd_state == G_RAID_SUBDISK_S_REBUILD) {
|
||||
pd->pd_meta[j]->rebuild_lba =
|
||||
pd->pd_meta[j]->disk_rebuild_high =
|
||||
(sd->sd_rebuild_pos / 512) >> 32;
|
||||
pd->pd_meta[j]->disk_rebuild =
|
||||
sd->sd_rebuild_pos / 512;
|
||||
} else if (sd->sd_state < G_RAID_SUBDISK_S_REBUILD)
|
||||
pd->pd_meta[j]->rebuild_lba = 0;
|
||||
else
|
||||
pd->pd_meta[j]->rebuild_lba = UINT32_MAX;
|
||||
} else if (sd->sd_state < G_RAID_SUBDISK_S_REBUILD) {
|
||||
pd->pd_meta[j]->disk_rebuild_high = 0;
|
||||
pd->pd_meta[j]->disk_rebuild = 0;
|
||||
} else {
|
||||
pd->pd_meta[j]->disk_rebuild_high = UINT32_MAX;
|
||||
pd->pd_meta[j]->disk_rebuild = UINT32_MAX;
|
||||
}
|
||||
pd->pd_updated = 1;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user