Implement read-only support for volumes in optimal state (without using
redundancy) for the following RAID levels: RAID4/5E/5EE/6/MDF.
This commit is contained in:
parent
6632cb429f
commit
4b97ff6137
@ -24,7 +24,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd April 30, 2012
|
.Dd May 3, 2012
|
||||||
.Dt GRAID 8
|
.Dt GRAID 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -261,9 +261,11 @@ own risk: RAID1 (3+ disks), RAID10 (6+ disks).
|
|||||||
.Sh SUPPORTED RAID LEVELS
|
.Sh SUPPORTED RAID LEVELS
|
||||||
The GEOM RAID class follows a modular design, allowing different RAID levels
|
The GEOM RAID class follows a modular design, allowing different RAID levels
|
||||||
to be used.
|
to be used.
|
||||||
Support for the following RAID levels is currently implemented: RAID0, RAID1,
|
Full support for the following RAID levels is currently implemented:
|
||||||
RAID1E, RAID5, RAID10, SINGLE, CONCAT.
|
RAID0, RAID1, RAID1E, RAID10, SINGLE, CONCAT.
|
||||||
RAID5 support is read-only and only for volumes in optimal state.
|
The following RAID levels supported as read-only for volumes in optimal
|
||||||
|
state (without using redundancy): RAID4, RAID5, RAID5E, RAID5EE, RAID6,
|
||||||
|
RAIDMDF.
|
||||||
.Sh RAID LEVEL MIGRATION
|
.Sh RAID LEVEL MIGRATION
|
||||||
The GEOM RAID class has no support for RAID level migration, allowed by some
|
The GEOM RAID class has no support for RAID level migration, allowed by some
|
||||||
metadata formats.
|
metadata formats.
|
||||||
|
@ -376,17 +376,17 @@ g_raid_volume_str2level(const char *str, int *level, int *qual)
|
|||||||
else if (strcasecmp(str, "RAID3-P0") == 0) {
|
else if (strcasecmp(str, "RAID3-P0") == 0) {
|
||||||
*level = G_RAID_VOLUME_RL_RAID3;
|
*level = G_RAID_VOLUME_RL_RAID3;
|
||||||
*qual = G_RAID_VOLUME_RLQ_R3P0;
|
*qual = G_RAID_VOLUME_RLQ_R3P0;
|
||||||
} else if (strcasecmp(str, "RAID3-PN") == 0 &&
|
} else if (strcasecmp(str, "RAID3-PN") == 0 ||
|
||||||
strcasecmp(str, "RAID3") == 0) {
|
strcasecmp(str, "RAID3") == 0) {
|
||||||
*level = G_RAID_VOLUME_RL_RAID3;
|
*level = G_RAID_VOLUME_RL_RAID3;
|
||||||
*qual = G_RAID_VOLUME_RLQ_R3P0;
|
*qual = G_RAID_VOLUME_RLQ_R3PN;
|
||||||
} else if (strcasecmp(str, "RAID4-P0") == 0) {
|
} else if (strcasecmp(str, "RAID4-P0") == 0) {
|
||||||
*level = G_RAID_VOLUME_RL_RAID4;
|
*level = G_RAID_VOLUME_RL_RAID4;
|
||||||
*qual = G_RAID_VOLUME_RLQ_R4P0;
|
*qual = G_RAID_VOLUME_RLQ_R4P0;
|
||||||
} else if (strcasecmp(str, "RAID4-PN") == 0 &&
|
} else if (strcasecmp(str, "RAID4-PN") == 0 ||
|
||||||
strcasecmp(str, "RAID4") == 0) {
|
strcasecmp(str, "RAID4") == 0) {
|
||||||
*level = G_RAID_VOLUME_RL_RAID4;
|
*level = G_RAID_VOLUME_RL_RAID4;
|
||||||
*qual = G_RAID_VOLUME_RLQ_R4P0;
|
*qual = G_RAID_VOLUME_RLQ_R4PN;
|
||||||
} else if (strcasecmp(str, "RAID5-RA") == 0) {
|
} else if (strcasecmp(str, "RAID5-RA") == 0) {
|
||||||
*level = G_RAID_VOLUME_RL_RAID5;
|
*level = G_RAID_VOLUME_RL_RAID5;
|
||||||
*qual = G_RAID_VOLUME_RLQ_R5RA;
|
*qual = G_RAID_VOLUME_RLQ_R5RA;
|
||||||
|
@ -106,9 +106,16 @@ g_raid_tr_taste_raid5(struct g_raid_tr_object *tr, struct g_raid_volume *vol)
|
|||||||
|
|
||||||
trs = (struct g_raid_tr_raid5_object *)tr;
|
trs = (struct g_raid_tr_raid5_object *)tr;
|
||||||
qual = tr->tro_volume->v_raid_level_qualifier;
|
qual = tr->tro_volume->v_raid_level_qualifier;
|
||||||
if (tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID5 &&
|
if (tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID4 &&
|
||||||
|
qual >= 0 && qual <= 1) {
|
||||||
|
/* RAID4 */
|
||||||
|
} else if ((tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID5 ||
|
||||||
|
tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID5E ||
|
||||||
|
tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID5EE ||
|
||||||
|
tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID6 ||
|
||||||
|
tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAIDMDF) &&
|
||||||
qual >= 0 && qual <= 3) {
|
qual >= 0 && qual <= 3) {
|
||||||
/* RAID5 */
|
/* RAID5/5E/5EE/6/MDF */
|
||||||
} else
|
} else
|
||||||
return (G_RAID_TR_TASTE_FAIL);
|
return (G_RAID_TR_TASTE_FAIL);
|
||||||
trs->trso_starting = 1;
|
trs->trso_starting = 1;
|
||||||
@ -203,30 +210,55 @@ g_raid_tr_iostart_raid5_read(struct g_raid_tr_object *tr, struct bio *bp)
|
|||||||
struct bio *cbp;
|
struct bio *cbp;
|
||||||
char *addr;
|
char *addr;
|
||||||
off_t offset, start, length, nstripe, remain;
|
off_t offset, start, length, nstripe, remain;
|
||||||
int no, pno;
|
int no, pno, ddisks, pdisks;
|
||||||
u_int strip_size, qual;
|
u_int strip_size, lvl, qual;
|
||||||
|
|
||||||
vol = tr->tro_volume;
|
vol = tr->tro_volume;
|
||||||
addr = bp->bio_data;
|
addr = bp->bio_data;
|
||||||
strip_size = vol->v_strip_size;
|
strip_size = vol->v_strip_size;
|
||||||
|
lvl = tr->tro_volume->v_raid_level;
|
||||||
qual = tr->tro_volume->v_raid_level_qualifier;
|
qual = tr->tro_volume->v_raid_level_qualifier;
|
||||||
|
|
||||||
/* Stripe number. */
|
/* Stripe number. */
|
||||||
nstripe = bp->bio_offset / strip_size;
|
nstripe = bp->bio_offset / strip_size;
|
||||||
/* Start position in stripe. */
|
/* Start position in stripe. */
|
||||||
start = bp->bio_offset % strip_size;
|
start = bp->bio_offset % strip_size;
|
||||||
|
/* Number of data and parity disks. */
|
||||||
|
if (lvl == G_RAID_VOLUME_RL_RAIDMDF)
|
||||||
|
pdisks = 3;
|
||||||
|
else if (lvl == G_RAID_VOLUME_RL_RAID5EE ||
|
||||||
|
lvl == G_RAID_VOLUME_RL_RAID6)
|
||||||
|
pdisks = 2;
|
||||||
|
else
|
||||||
|
pdisks = 1;
|
||||||
|
ddisks = vol->v_disks_count - pdisks;
|
||||||
/* Parity disk number. */
|
/* Parity disk number. */
|
||||||
pno = nstripe / (vol->v_disks_count - 1) % vol->v_disks_count;
|
if (lvl == G_RAID_VOLUME_RL_RAID4) {
|
||||||
if (qual >= 2)
|
if (qual == 0) /* P0 */
|
||||||
pno = (vol->v_disks_count - 1) - pno;
|
pno = 0;
|
||||||
/* Disk number. */
|
else /* PN */
|
||||||
no = nstripe % (vol->v_disks_count - 1);
|
pno = ddisks;
|
||||||
if (qual & 1) {
|
} else {
|
||||||
no = (pno + no + 1) % vol->v_disks_count;
|
pno = (nstripe / ddisks) % vol->v_disks_count;
|
||||||
} else if (no >= pno)
|
if (qual >= 2) { /* PN/Left */
|
||||||
no++;
|
pno = ddisks - pno;
|
||||||
|
if (pno < 0)
|
||||||
|
pno += vol->v_disks_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Data disk number. */
|
||||||
|
no = nstripe % ddisks;
|
||||||
|
if (lvl == G_RAID_VOLUME_RL_RAID4) {
|
||||||
|
if (qual == 0)
|
||||||
|
no += pdisks;
|
||||||
|
} else if (qual & 1) { /* Continuation/Symmetric */
|
||||||
|
no = (pno + pdisks + no) % vol->v_disks_count;
|
||||||
|
} else if (no >= pno) /* Restart/Asymmetric */
|
||||||
|
no += pdisks;
|
||||||
|
else
|
||||||
|
no += imax(0, pno + pdisks - vol->v_disks_count);
|
||||||
/* Stripe start position in disk. */
|
/* Stripe start position in disk. */
|
||||||
offset = (nstripe / (vol->v_disks_count - 1)) * strip_size;
|
offset = (nstripe / ddisks) * strip_size;
|
||||||
/* Length of data to operate. */
|
/* Length of data to operate. */
|
||||||
remain = bp->bio_length;
|
remain = bp->bio_length;
|
||||||
|
|
||||||
@ -242,33 +274,37 @@ g_raid_tr_iostart_raid5_read(struct g_raid_tr_object *tr, struct bio *bp)
|
|||||||
cbp->bio_caller1 = &vol->v_subdisks[no];
|
cbp->bio_caller1 = &vol->v_subdisks[no];
|
||||||
bioq_insert_tail(&queue, cbp);
|
bioq_insert_tail(&queue, cbp);
|
||||||
no++;
|
no++;
|
||||||
if (qual & 1) {
|
if (lvl == G_RAID_VOLUME_RL_RAID4) {
|
||||||
|
no %= vol->v_disks_count;
|
||||||
|
if (no == pno)
|
||||||
|
no = (no + pdisks) % vol->v_disks_count;
|
||||||
|
} else if (qual & 1) { /* Continuation/Symmetric */
|
||||||
no %= vol->v_disks_count;
|
no %= vol->v_disks_count;
|
||||||
if (no == pno) {
|
if (no == pno) {
|
||||||
if (qual < 2) {
|
if (qual < 2) /* P0/Right */
|
||||||
pno = (pno + 1) % vol->v_disks_count;
|
pno++;
|
||||||
no = (no + 2) % vol->v_disks_count;
|
else /* PN/Left */
|
||||||
} else if (pno == 0)
|
pno += vol->v_disks_count - 1;
|
||||||
pno = vol->v_disks_count - 1;
|
pno %= vol->v_disks_count;
|
||||||
else
|
no = (pno + pdisks) % vol->v_disks_count;
|
||||||
pno--;
|
|
||||||
offset += strip_size;
|
offset += strip_size;
|
||||||
}
|
}
|
||||||
} else {
|
} else { /* Restart/Asymmetric */
|
||||||
if (no == pno)
|
if (no == pno)
|
||||||
no++;
|
no += pdisks;
|
||||||
if (no >= vol->v_disks_count) {
|
if (no >= vol->v_disks_count) {
|
||||||
no %= vol->v_disks_count;
|
no -= vol->v_disks_count;
|
||||||
if (qual < 2)
|
if (qual < 2) /* P0/Right */
|
||||||
pno = (pno + 1) % vol->v_disks_count;
|
pno++;
|
||||||
else if (pno == 0)
|
else /* PN/Left */
|
||||||
pno = vol->v_disks_count - 1;
|
pno += vol->v_disks_count - 1;
|
||||||
|
pno %= vol->v_disks_count;
|
||||||
|
if (no == pno)
|
||||||
|
no += pdisks;
|
||||||
else
|
else
|
||||||
pno--;
|
no += imax(0, pno + pdisks - vol->v_disks_count);
|
||||||
offset += strip_size;
|
offset += strip_size;
|
||||||
}
|
}
|
||||||
if (no == pno)
|
|
||||||
no++;
|
|
||||||
}
|
}
|
||||||
remain -= length;
|
remain -= length;
|
||||||
addr += length;
|
addr += length;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user