svn commit: r246168 - stable/9/sys/geom/raid
Alexander Motin
mav at FreeBSD.org
Thu Jan 31 22:12:26 UTC 2013
Author: mav
Date: Thu Jan 31 22:12:25 2013
New Revision: 246168
URL: http://svnweb.freebsd.org/changeset/base/246168
Log:
MFC r245326:
Add basic support for Intel Rapid Recover Technology (Intel RRT).
It is alike to RAID1, but with dedicating master and recovery disks and
providing manual control over synchronization. It allows to use recovery
disk as snapshot of the master disk from the time of the last sync.
This implementation is not functionaly complete comparing to Windows,
but it is better then silent conversion to RAID1 on first boot.
Modified:
stable/9/sys/geom/raid/g_raid.c
stable/9/sys/geom/raid/g_raid.h
stable/9/sys/geom/raid/md_intel.c
Directory Properties:
stable/9/sys/ (props changed)
Modified: stable/9/sys/geom/raid/g_raid.c
==============================================================================
--- stable/9/sys/geom/raid/g_raid.c Thu Jan 31 22:10:57 2013 (r246167)
+++ stable/9/sys/geom/raid/g_raid.c Thu Jan 31 22:12:25 2013 (r246168)
@@ -163,6 +163,8 @@ g_raid_disk_state2str(int state)
return ("NONE");
case G_RAID_DISK_S_OFFLINE:
return ("OFFLINE");
+ case G_RAID_DISK_S_DISABLED:
+ return ("DISABLED");
case G_RAID_DISK_S_FAILED:
return ("FAILED");
case G_RAID_DISK_S_STALE_FAILED:
@@ -535,7 +537,9 @@ g_raid_report_disk_state(struct g_raid_d
if (disk->d_consumer == NULL)
return;
- if (disk->d_state == G_RAID_DISK_S_FAILED ||
+ if (disk->d_state == G_RAID_DISK_S_DISABLED) {
+ ;
+ } else if (disk->d_state == G_RAID_DISK_S_FAILED ||
disk->d_state == G_RAID_DISK_S_STALE_FAILED) {
s = G_STATE_FAILED;
} else {
Modified: stable/9/sys/geom/raid/g_raid.h
==============================================================================
--- stable/9/sys/geom/raid/g_raid.h Thu Jan 31 22:10:57 2013 (r246167)
+++ stable/9/sys/geom/raid/g_raid.h Thu Jan 31 22:12:25 2013 (r246168)
@@ -140,11 +140,12 @@ struct g_raid_event {
};
#define G_RAID_DISK_S_NONE 0x00 /* State is unknown. */
#define G_RAID_DISK_S_OFFLINE 0x01 /* Missing disk placeholder. */
-#define G_RAID_DISK_S_FAILED 0x02 /* Failed. */
-#define G_RAID_DISK_S_STALE_FAILED 0x03 /* Old failed. */
-#define G_RAID_DISK_S_SPARE 0x04 /* Hot-spare. */
-#define G_RAID_DISK_S_STALE 0x05 /* Old disk, unused now. */
-#define G_RAID_DISK_S_ACTIVE 0x06 /* Operational. */
+#define G_RAID_DISK_S_DISABLED 0x02 /* Disabled. */
+#define G_RAID_DISK_S_FAILED 0x03 /* Failed. */
+#define G_RAID_DISK_S_STALE_FAILED 0x04 /* Old failed. */
+#define G_RAID_DISK_S_SPARE 0x05 /* Hot-spare. */
+#define G_RAID_DISK_S_STALE 0x06 /* Old disk, unused now. */
+#define G_RAID_DISK_S_ACTIVE 0x07 /* Operational. */
#define G_RAID_DISK_E_DISCONNECTED 0x01
Modified: stable/9/sys/geom/raid/md_intel.c
==============================================================================
--- stable/9/sys/geom/raid/md_intel.c Thu Jan 31 22:10:57 2013 (r246167)
+++ stable/9/sys/geom/raid/md_intel.c Thu Jan 31 22:12:25 2013 (r246168)
@@ -98,6 +98,8 @@ struct intel_raid_vol {
uint8_t cng_master_disk;
uint16_t cache_policy;
uint8_t cng_state;
+#define INTEL_SNGST_NEEDS_UPDATE 1
+#define INTEL_SNGST_MASTER_MISSING 2
uint8_t cng_sub_state;
uint32_t filler_0[10];
@@ -130,6 +132,7 @@ struct intel_raid_disk {
#define INTEL_F_ASSIGNED 0x02
#define INTEL_F_FAILED 0x04
#define INTEL_F_ONLINE 0x08
+#define INTEL_F_DISABLED 0x80
uint32_t owner_cfg_num;
uint32_t sectors_hi;
uint32_t filler[3];
@@ -187,6 +190,13 @@ struct g_raid_md_intel_perdisk {
struct intel_raid_disk pd_disk_meta;
};
+struct g_raid_md_intel_pervolume {
+ int pv_volume_pos;
+ int pv_cng;
+ int pv_cng_man_sync;
+ int pv_cng_master_disk;
+};
+
struct g_raid_md_intel_object {
struct g_raid_md_object mdio_base;
uint32_t mdio_config_id;
@@ -206,6 +216,7 @@ static g_raid_md_ctl_t g_raid_md_ctl_int
static g_raid_md_write_t g_raid_md_write_intel;
static g_raid_md_fail_disk_t g_raid_md_fail_disk_intel;
static g_raid_md_free_disk_t g_raid_md_free_disk_intel;
+static g_raid_md_free_volume_t g_raid_md_free_volume_intel;
static g_raid_md_free_t g_raid_md_free_intel;
static kobj_method_t g_raid_md_intel_methods[] = {
@@ -216,6 +227,7 @@ static kobj_method_t g_raid_md_intel_met
KOBJMETHOD(g_raid_md_write, g_raid_md_write_intel),
KOBJMETHOD(g_raid_md_fail_disk, g_raid_md_fail_disk_intel),
KOBJMETHOD(g_raid_md_free_disk, g_raid_md_free_disk_intel),
+ KOBJMETHOD(g_raid_md_free_volume, g_raid_md_free_volume_intel),
KOBJMETHOD(g_raid_md_free, g_raid_md_free_intel),
{ 0, 0 }
};
@@ -369,8 +381,15 @@ g_raid_md_intel_print(struct intel_raid_
printf(" ****** Volume %d ******\n", i);
printf(" name %.16s\n", mvol->name);
printf(" total_sectors %ju\n", mvol->total_sectors);
- printf(" state %u\n", mvol->state);
+ printf(" state 0x%08x\n", mvol->state);
printf(" reserved %u\n", mvol->reserved);
+ printf(" migr_priority %u\n", mvol->migr_priority);
+ printf(" num_sub_vols %u\n", mvol->num_sub_vols);
+ printf(" tid %u\n", mvol->tid);
+ printf(" cng_master_disk %u\n", mvol->cng_master_disk);
+ printf(" cache_policy %u\n", mvol->cache_policy);
+ printf(" cng_state %u\n", mvol->cng_state);
+ printf(" cng_sub_state %u\n", mvol->cng_sub_state);
printf(" curr_migr_unit %u\n", mvol->curr_migr_unit);
printf(" curr_migr_unit_hi %u\n", mvol->curr_migr_unit_hi);
printf(" checkpoint_id %u\n", mvol->checkpoint_id);
@@ -699,9 +718,11 @@ static struct g_raid_volume *
g_raid_md_intel_get_volume(struct g_raid_softc *sc, int id)
{
struct g_raid_volume *mvol;
+ struct g_raid_md_intel_pervolume *pv;
TAILQ_FOREACH(mvol, &sc->sc_volumes, v_next) {
- if ((intptr_t)(mvol->v_md_data) == id)
+ pv = mvol->v_md_data;
+ if (pv->pv_volume_pos == id)
break;
}
return (mvol);
@@ -715,6 +736,7 @@ g_raid_md_intel_start_disk(struct g_raid
struct g_raid_disk *olddisk, *tmpdisk;
struct g_raid_md_object *md;
struct g_raid_md_intel_object *mdi;
+ struct g_raid_md_intel_pervolume *pv;
struct g_raid_md_intel_perdisk *pd, *oldpd;
struct intel_raid_conf *meta;
struct intel_raid_vol *mvol;
@@ -732,6 +754,11 @@ g_raid_md_intel_start_disk(struct g_raid
disk_pos = intel_meta_find_disk(meta, pd->pd_disk_meta.serial);
if (disk_pos < 0) {
G_RAID_DEBUG1(1, sc, "Unknown, probably new or stale disk");
+ /* Disabled disk is useless for us. */
+ if (pd->pd_disk_meta.flags & INTEL_F_DISABLED) {
+ g_raid_change_disk_state(disk, G_RAID_DISK_S_DISABLED);
+ return (0);
+ }
/* Failed stale disk is useless for us. */
if (pd->pd_disk_meta.flags & INTEL_F_FAILED) {
g_raid_change_disk_state(disk, G_RAID_DISK_S_STALE_FAILED);
@@ -826,6 +853,8 @@ nofit:
/* Welcome the new disk. */
if (resurrection)
g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE);
+ else if (meta->disk[disk_pos].flags & INTEL_F_DISABLED)
+ g_raid_change_disk_state(disk, G_RAID_DISK_S_DISABLED);
else if (meta->disk[disk_pos].flags & INTEL_F_FAILED)
g_raid_change_disk_state(disk, G_RAID_DISK_S_FAILED);
else if (meta->disk[disk_pos].flags & INTEL_F_SPARE)
@@ -833,8 +862,8 @@ nofit:
else
g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE);
TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) {
- mvol = intel_get_volume(meta,
- (uintptr_t)(sd->sd_volume->v_md_data));
+ pv = sd->sd_volume->v_md_data;
+ mvol = intel_get_volume(meta, pv->pv_volume_pos);
mmap0 = intel_get_map(mvol, 0);
if (mvol->migr_state)
mmap1 = intel_get_map(mvol, 1);
@@ -845,12 +874,17 @@ nofit:
/* Stale disk, almost same as new. */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_NEW);
+ } else if (meta->disk[disk_pos].flags & INTEL_F_DISABLED) {
+ /* Disabled disk, useless. */
+ g_raid_change_subdisk_state(sd,
+ G_RAID_SUBDISK_S_NONE);
} else if (meta->disk[disk_pos].flags & INTEL_F_FAILED) {
/* Failed disk, almost useless. */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_FAILED);
} else if (mvol->migr_state == 0) {
- if (mmap0->status == INTEL_S_UNINITIALIZED) {
+ if (mmap0->status == INTEL_S_UNINITIALIZED &&
+ (!pv->pv_cng || pv->pv_cng_master_disk != disk_pos)) {
/* Freshly created uninitialized volume. */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_UNINITIALIZED);
@@ -858,7 +892,8 @@ nofit:
/* Freshly inserted disk. */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_NEW);
- } else if (mvol->dirty) {
+ } else if (mvol->dirty && (!pv->pv_cng ||
+ pv->pv_cng_master_disk != disk_pos)) {
/* Dirty volume (unclean shutdown). */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_STALE);
@@ -885,7 +920,8 @@ nofit:
sd->sd_volume->v_strip_size *
mmap0->total_domains;
}
- } else if (mvol->dirty) {
+ } else if (mvol->dirty && (!pv->pv_cng ||
+ pv->pv_cng_master_disk != disk_pos)) {
/* Dirty volume (unclean shutdown). */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_STALE);
@@ -1014,6 +1050,7 @@ g_raid_md_intel_start(struct g_raid_soft
{
struct g_raid_md_object *md;
struct g_raid_md_intel_object *mdi;
+ struct g_raid_md_intel_pervolume *pv;
struct g_raid_md_intel_perdisk *pd;
struct intel_raid_conf *meta;
struct intel_raid_vol *mvol;
@@ -1032,7 +1069,13 @@ g_raid_md_intel_start(struct g_raid_soft
mvol = intel_get_volume(meta, i);
mmap = intel_get_map(mvol, 0);
vol = g_raid_create_volume(sc, mvol->name, -1);
- vol->v_md_data = (void *)(intptr_t)i;
+ pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO);
+ pv->pv_volume_pos = i;
+ pv->pv_cng = (mvol->state & INTEL_ST_CLONE_N_GO) != 0;
+ pv->pv_cng_man_sync = (mvol->state & INTEL_ST_CLONE_MAN_SYNC) != 0;
+ if (mvol->cng_master_disk < mmap->total_disks)
+ pv->pv_cng_master_disk = mvol->cng_master_disk;
+ vol->v_md_data = pv;
vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_NONE;
if (mmap->type == INTEL_T_RAID0)
vol->v_raid_level = G_RAID_VOLUME_RL_RAID0;
@@ -1450,6 +1493,7 @@ g_raid_md_ctl_intel(struct g_raid_md_obj
struct g_raid_subdisk *sd;
struct g_raid_disk *disk;
struct g_raid_md_intel_object *mdi;
+ struct g_raid_md_intel_pervolume *pv;
struct g_raid_md_intel_perdisk *pd;
struct g_consumer *cp;
struct g_provider *pp;
@@ -1621,7 +1665,9 @@ g_raid_md_ctl_intel(struct g_raid_md_obj
/* We have all we need, create things: volume, ... */
mdi->mdio_started = 1;
vol = g_raid_create_volume(sc, volname, -1);
- vol->v_md_data = (void *)(intptr_t)0;
+ pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO);
+ pv->pv_volume_pos = 0;
+ vol->v_md_data = pv;
vol->v_raid_level = level;
vol->v_raid_level_qualifier = qual;
vol->v_strip_size = strip;
@@ -1814,7 +1860,9 @@ g_raid_md_ctl_intel(struct g_raid_md_obj
/* We have all we need, create things: volume, ... */
vol = g_raid_create_volume(sc, volname, -1);
- vol->v_md_data = (void *)(intptr_t)i;
+ pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO);
+ pv->pv_volume_pos = i;
+ vol->v_md_data = pv;
vol->v_raid_level = level;
vol->v_raid_level_qualifier = qual;
vol->v_strip_size = strip;
@@ -2105,6 +2153,7 @@ g_raid_md_write_intel(struct g_raid_md_o
struct g_raid_subdisk *sd;
struct g_raid_disk *disk;
struct g_raid_md_intel_object *mdi;
+ struct g_raid_md_intel_pervolume *pv;
struct g_raid_md_intel_perdisk *pd;
struct intel_raid_conf *meta;
struct intel_raid_vol *mvol;
@@ -2133,7 +2182,11 @@ g_raid_md_write_intel(struct g_raid_md_o
pd->pd_disk_meta.flags =
INTEL_F_ONLINE | INTEL_F_ASSIGNED;
} else if (disk->d_state == G_RAID_DISK_S_FAILED) {
- pd->pd_disk_meta.flags = INTEL_F_FAILED | INTEL_F_ASSIGNED;
+ pd->pd_disk_meta.flags = INTEL_F_FAILED |
+ INTEL_F_ASSIGNED;
+ } else if (disk->d_state == G_RAID_DISK_S_DISABLED) {
+ pd->pd_disk_meta.flags = INTEL_F_FAILED |
+ INTEL_F_ASSIGNED | INTEL_F_DISABLED;
} else {
pd->pd_disk_meta.flags = INTEL_F_ASSIGNED;
if (pd->pd_disk_meta.id != 0xffffffff) {
@@ -2165,12 +2218,13 @@ g_raid_md_write_intel(struct g_raid_md_o
vi = 0;
version = INTEL_VERSION_1000;
TAILQ_FOREACH(vol, &sc->sc_volumes, v_next) {
+ pv = vol->v_md_data;
if (vol->v_stopping)
continue;
mvol = intel_get_volume(meta, vi);
/* New metadata may have different volumes order. */
- vol->v_md_data = (void *)(intptr_t)vi;
+ pv->pv_volume_pos = vi;
for (sdi = 0; sdi < vol->v_disks_count; sdi++) {
sd = &vol->v_subdisks[sdi];
@@ -2192,8 +2246,8 @@ g_raid_md_write_intel(struct g_raid_md_o
if (meta->attributes & INTEL_ATTR_2TB)
cv = INTEL_VERSION_1300;
-// else if (dev->status == DEV_CLONE_N_GO)
-// cv = INTEL_VERSION_1206;
+ else if (pv->pv_cng)
+ cv = INTEL_VERSION_1206;
else if (vol->v_disks_count > 4)
cv = INTEL_VERSION_1204;
else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID5)
@@ -2211,6 +2265,17 @@ g_raid_md_write_intel(struct g_raid_md_o
strlcpy(&mvol->name[0], vol->v_name, sizeof(mvol->name));
mvol->total_sectors = vol->v_mediasize / sectorsize;
+ if (pv->pv_cng) {
+ mvol->state |= INTEL_ST_CLONE_N_GO;
+ if (pv->pv_cng_man_sync)
+ mvol->state |= INTEL_ST_CLONE_MAN_SYNC;
+ mvol->cng_master_disk = pv->pv_cng_master_disk;
+ if (vol->v_subdisks[pv->pv_cng_master_disk].sd_state ==
+ G_RAID_SUBDISK_S_NONE)
+ mvol->cng_state = INTEL_SNGST_MASTER_MISSING;
+ else if (vol->v_state != G_RAID_VOLUME_S_OPTIMAL)
+ mvol->cng_state = INTEL_SNGST_NEEDS_UPDATE;
+ }
/* Check for any recovery in progress. */
state = G_RAID_SUBDISK_S_ACTIVE;
@@ -2403,6 +2468,18 @@ g_raid_md_free_disk_intel(struct g_raid_
}
static int
+g_raid_md_free_volume_intel(struct g_raid_md_object *md,
+ struct g_raid_volume *vol)
+{
+ struct g_raid_md_intel_pervolume *pv;
+
+ pv = (struct g_raid_md_intel_pervolume *)vol->v_md_data;
+ free(pv, M_MD_INTEL);
+ vol->v_md_data = NULL;
+ return (0);
+}
+
+static int
g_raid_md_free_intel(struct g_raid_md_object *md)
{
struct g_raid_md_intel_object *mdi;
More information about the svn-src-stable-9
mailing list