svn commit: r216649 - projects/graid/head/sys/geom/raid
Alexander Motin
mav at FreeBSD.org
Wed Dec 22 09:02:22 UTC 2010
Author: mav
Date: Wed Dec 22 09:02:22 2010
New Revision: 216649
URL: http://svn.freebsd.org/changeset/base/216649
Log:
Implement basic metadata generation check. To be sure that used metadata is
up to date - delay volumes creation until we have all disks or timeout
expires. This probably obsolete same functionality done at volumes level.
Modified:
projects/graid/head/sys/geom/raid/g_raid.c
projects/graid/head/sys/geom/raid/g_raid.h
projects/graid/head/sys/geom/raid/g_raid_md_if.m
projects/graid/head/sys/geom/raid/md_intel.c
Modified: projects/graid/head/sys/geom/raid/g_raid.c
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid.c Wed Dec 22 05:53:46 2010 (r216648)
+++ projects/graid/head/sys/geom/raid/g_raid.c Wed Dec 22 09:02:22 2010 (r216649)
@@ -55,7 +55,7 @@ u_int g_raid_debug = 1000;
TUNABLE_INT("kern.geom.raid.debug", &g_raid_debug);
SYSCTL_UINT(_kern_geom_raid, OID_AUTO, debug, CTLFLAG_RW, &g_raid_debug, 0,
"Debug level");
-static u_int g_raid_start_timeout = 4;
+u_int g_raid_start_timeout = 4;
TUNABLE_INT("kern.geom.raid.start_timeout", &g_raid_start_timeout);
SYSCTL_UINT(_kern_geom_raid, OID_AUTO, timeout, CTLFLAG_RW, &g_raid_start_timeout,
0, "Time to wait on all mirror components");
@@ -122,6 +122,8 @@ g_raid_disk_state2str(int state)
return ("SPARE");
case G_RAID_DISK_S_OFFLINE:
return ("OFFLINE");
+ case G_RAID_DISK_S_STALE:
+ return ("STALE");
default:
return ("INVALID");
}
@@ -1297,12 +1299,13 @@ g_raid_destroy_volume(struct g_raid_volu
}
int
-g_raid_stop_disk(struct g_raid_disk *disk)
+g_raid_destroy_disk(struct g_raid_disk *disk)
{
struct g_raid_softc *sc;
struct g_raid_subdisk *sd, *tmp;
sc = disk->d_softc;
+ G_RAID_DEBUG(2, "Destroying disk.");
if (disk->d_consumer) {
g_topology_lock();
g_raid_kill_consumer(sc, disk->d_consumer);
@@ -1315,21 +1318,9 @@ g_raid_stop_disk(struct g_raid_disk *dis
LIST_REMOVE(sd, sd_next);
sd->sd_disk = NULL;
}
- return (0);
-}
-
-int
-g_raid_destroy_disk(struct g_raid_disk *disk)
-{
- struct g_raid_softc *sc;
- int error;
-
- sc = disk->d_softc;
- G_RAID_DEBUG(2, "Destroying disk.");
- error = g_raid_stop_disk(disk);
- if (error)
- return (error);
LIST_REMOVE(disk, d_next);
+ if (sc->sc_md)
+ G_RAID_MD_FREE_DISK(sc->sc_md, disk);
free(disk, M_RAID);
return (0);
}
Modified: projects/graid/head/sys/geom/raid/g_raid.h
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid.h Wed Dec 22 05:53:46 2010 (r216648)
+++ projects/graid/head/sys/geom/raid/g_raid.h Wed Dec 22 09:02:22 2010 (r216649)
@@ -58,6 +58,7 @@ struct g_raid_tr_object;
#ifdef _KERNEL
extern u_int g_raid_debug;
+extern u_int g_raid_start_timeout;
#define G_RAID_DEBUG(lvl, fmt, ...) do { \
if (g_raid_debug >= (lvl)) { \
@@ -101,6 +102,7 @@ struct g_raid_event {
#define G_RAID_DISK_S_ACTIVE 0x01
#define G_RAID_DISK_S_SPARE 0x02
#define G_RAID_DISK_S_OFFLINE 0x03
+#define G_RAID_DISK_S_STALE 0x04
#define G_RAID_DISK_E_DISCONNECTED 0x01
@@ -284,10 +286,6 @@ struct g_raid_disk * g_raid_create_disk(
int g_raid_start_volume(struct g_raid_volume *vol);
-int g_raid_stop_node(struct g_raid_softc *sc);
-int g_raid_stop_volume(struct g_raid_volume *vol);
-int g_raid_stop_disk(struct g_raid_disk *disk);
-
int g_raid_destroy_node(struct g_raid_softc *sc, int worker);
int g_raid_destroy_volume(struct g_raid_volume *vol);
int g_raid_destroy_disk(struct g_raid_disk *disk);
Modified: projects/graid/head/sys/geom/raid/g_raid_md_if.m
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid_md_if.m Wed Dec 22 05:53:46 2010 (r216648)
+++ projects/graid/head/sys/geom/raid/g_raid_md_if.m Wed Dec 22 09:02:22 2010 (r216649)
@@ -71,6 +71,12 @@ METHOD int write {
struct g_raid_disk *disk;
};
+# free_disk() - disk destructor.
+METHOD int free_disk {
+ struct g_raid_md_object *md;
+ struct g_raid_disk *disk;
+};
+
# free() - destructor.
METHOD int free {
struct g_raid_md_object *md;
Modified: projects/graid/head/sys/geom/raid/md_intel.c
==============================================================================
--- projects/graid/head/sys/geom/raid/md_intel.c Wed Dec 22 05:53:46 2010 (r216648)
+++ projects/graid/head/sys/geom/raid/md_intel.c Wed Dec 22 09:02:22 2010 (r216649)
@@ -135,21 +135,31 @@ struct intel_raid_vol {
struct intel_raid_map map[1];
} __packed;
+struct g_raid_md_intel_perdisk {
+ struct intel_raid_conf *pd_meta;
+ int pd_disk_pos;
+};
+
struct g_raid_md_intel_object {
- struct g_raid_md_object mdio_base;
- uint32_t mdio_config_id;
+ struct g_raid_md_object mdio_base;
+ uint32_t mdio_config_id;
struct intel_raid_conf *mdio_meta;
+ struct callout mdio_start_co; /* STARTING state timer. */
+ int mdio_disks_present;
+ int mdio_started;
};
static g_raid_md_taste_t g_raid_md_taste_intel;
static g_raid_md_event_t g_raid_md_event_intel;
static g_raid_md_write_t g_raid_md_write_intel;
+static g_raid_md_free_disk_t g_raid_md_free_disk_intel;
static g_raid_md_free_t g_raid_md_free_intel;
static kobj_method_t g_raid_md_intel_methods[] = {
KOBJMETHOD(g_raid_md_taste, g_raid_md_taste_intel),
KOBJMETHOD(g_raid_md_event, g_raid_md_event_intel),
KOBJMETHOD(g_raid_md_write, g_raid_md_write_intel),
+ KOBJMETHOD(g_raid_md_free_disk, g_raid_md_free_disk_intel),
KOBJMETHOD(g_raid_md_free, g_raid_md_free_intel),
{ 0, 0 }
};
@@ -251,6 +261,17 @@ g_raid_md_intel_print(struct intel_raid_
printf("=================================================\n");
}
+static struct intel_raid_conf *
+intel_meta_copy(struct intel_raid_conf *meta)
+{
+ struct intel_raid_conf *nmeta;
+
+ nmeta = malloc(meta->config_size, M_MD_INTEL, M_WAITOK | M_ZERO);
+ memcpy(nmeta, meta, meta->config_size);
+ return (nmeta);
+}
+
+#if 0
static struct g_raid_disk *
g_raid_md_intel_get_disk(struct g_raid_softc *sc, int id)
{
@@ -262,6 +283,7 @@ g_raid_md_intel_get_disk(struct g_raid_s
}
return (disk);
}
+#endif
static struct g_raid_volume *
g_raid_md_intel_get_volume(struct g_raid_softc *sc, int id)
@@ -275,6 +297,166 @@ g_raid_md_intel_get_volume(struct g_raid
return (vol);
}
+static void
+g_raid_md_intel_start_disk(struct g_raid_disk *disk)
+{
+ struct g_raid_softc *sc;
+ struct g_raid_volume *vol;
+ struct g_raid_subdisk *sd;
+ struct g_raid_md_object *md;
+ struct g_raid_md_intel_object *mdi;
+ struct g_raid_md_intel_perdisk *pd;
+ struct intel_raid_conf *meta, *pdmeta;
+ struct intel_raid_vol *mvol;
+ struct intel_raid_map *map;
+ int i, j;
+
+ sc = disk->d_softc;
+ md = sc->sc_md;
+ mdi = (struct g_raid_md_intel_object *)md;
+ meta = mdi->mdio_meta;
+ pd = (struct g_raid_md_intel_perdisk *)disk->d_md_data;
+ pdmeta = pd->pd_meta;
+
+ if (pdmeta->generation != meta->generation) {
+ g_raid_change_disk_state(disk, G_RAID_DISK_S_STALE);
+ return;
+ }
+
+ /* Update disk state. */
+ g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE);
+
+ /* Create subdisks. */
+ for (i = 0; i < meta->total_volumes; i++) {
+ mvol = intel_get_volume(meta, i);
+ map = intel_get_map(mvol, 0);
+ for (j = 0; j < map->total_disks; j++) {
+ if ((map->disk_idx[j] & INTEL_DI_IDX) == pd->pd_disk_pos)
+ break;
+ }
+ if (j == map->total_disks)
+ continue;
+ vol = g_raid_md_intel_get_volume(sc, i);
+ sd = &vol->v_subdisks[j];
+ sd->sd_disk = disk;
+ sd->sd_offset = map->offset * 512; //ZZZ
+ sd->sd_size = map->disk_sectors;
+ LIST_INSERT_HEAD(&disk->d_subdisks, sd, sd_next);
+ g_raid_event_send(sd, G_RAID_SUBDISK_E_NEW,
+ G_RAID_EVENT_SUBDISK);
+ }
+
+}
+
+static void
+g_raid_md_intel_start(struct g_raid_softc *sc)
+{
+ struct g_raid_md_object *md;
+ struct g_raid_md_intel_object *mdi;
+ struct intel_raid_conf *meta;
+ struct intel_raid_vol *mvol;
+ struct intel_raid_map *map;
+ struct g_raid_volume *vol;
+ struct g_raid_disk *disk;
+ int i;
+
+ md = sc->sc_md;
+ mdi = (struct g_raid_md_intel_object *)md;
+ meta = mdi->mdio_meta;
+ /* Create volumes */
+ for (i = 0; i < meta->total_volumes; i++) {
+ mvol = intel_get_volume(meta, i);
+ map = intel_get_map(mvol, 0);
+ vol = g_raid_create_volume(sc, mvol->name);
+ vol->v_md_data = (void *)(intptr_t)i;
+ if (map->type == INTEL_T_RAID0)
+ vol->v_raid_level = G_RAID_VOLUME_RL_RAID0;
+ else if (map->type == INTEL_T_RAID1 &&
+ map->total_disks < 4)
+ vol->v_raid_level = G_RAID_VOLUME_RL_RAID1;
+ else if (map->type == INTEL_T_RAID1)
+ vol->v_raid_level = G_RAID_VOLUME_RL_RAID10;
+ else if (map->type == INTEL_T_RAID5)
+ vol->v_raid_level = G_RAID_VOLUME_RL_RAID5;
+ else
+ vol->v_raid_level = G_RAID_VOLUME_RL_UNKNOWN;
+ vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_NONE;
+ vol->v_strip_size = map->stripe_sectors * 512; //ZZZ
+ vol->v_disks_count = map->total_disks;
+ vol->v_mediasize = mvol->total_sectors * 512; //ZZZ
+ vol->v_sectorsize = 512; //ZZZ
+ g_raid_start_volume(vol);
+ }
+ LIST_FOREACH(disk, &sc->sc_disks, d_next) {
+ g_raid_md_intel_start_disk(disk);
+ }
+}
+
+static void
+g_raid_md_intel_new_disk(struct g_raid_disk *disk)
+{
+ struct g_raid_softc *sc;
+ struct g_raid_md_object *md;
+ struct g_raid_md_intel_object *mdi;
+ struct intel_raid_conf *meta, *pdmeta;
+ struct g_raid_md_intel_perdisk *pd;
+
+ sc = disk->d_softc;
+ md = sc->sc_md;
+ mdi = (struct g_raid_md_intel_object *)md;
+ pd = (struct g_raid_md_intel_perdisk *)disk->d_md_data;
+ pdmeta = pd->pd_meta;
+
+ if (mdi->mdio_meta == NULL ||
+ pdmeta->generation > mdi->mdio_meta->generation) {
+ if (mdi->mdio_started) {
+ G_RAID_DEBUG(1, "Newer disk, but already started");
+ } else {
+ G_RAID_DEBUG(1, "Newer disk");
+ if (mdi->mdio_meta != NULL)
+ free(mdi->mdio_meta, M_MD_INTEL);
+ mdi->mdio_meta = intel_meta_copy(pdmeta);
+ mdi->mdio_disks_present = 1;
+ }
+ } else if (pdmeta->generation == mdi->mdio_meta->generation) {
+ mdi->mdio_disks_present++;
+ G_RAID_DEBUG(1, "Matching disk (%d up)",
+ mdi->mdio_disks_present);
+ } else {
+ G_RAID_DEBUG(1, "Stale disk");
+ }
+
+ meta = mdi->mdio_meta;
+ if (mdi->mdio_started) {
+ g_raid_md_intel_start_disk(disk);
+ } else {
+ if (mdi->mdio_disks_present == meta->total_disks) {
+ mdi->mdio_started = 1;
+ callout_stop(&mdi->mdio_start_co);
+ g_raid_md_intel_start(sc);
+ }
+ }
+}
+
+static void
+g_raid_intel_go(void *arg)
+{
+ struct g_raid_softc *sc;
+ struct g_raid_md_object *md;
+ struct g_raid_md_intel_object *mdi;
+
+ sc = arg;
+ md = sc->sc_md;
+ mdi = (struct g_raid_md_intel_object *)md;
+ sx_xlock(&sc->sc_lock);
+ if (!mdi->mdio_started) {
+ G_RAID_DEBUG(0, "Force node %s start due to timeout.", sc->sc_name);
+ mdi->mdio_started = 1;
+ g_raid_md_intel_start(sc);
+ }
+ sx_xunlock(&sc->sc_lock);
+}
+
static int
g_raid_md_taste_intel(struct g_raid_md_object *md, struct g_class *mp,
struct g_consumer *cp, struct g_geom **gp)
@@ -283,16 +465,13 @@ g_raid_md_taste_intel(struct g_raid_md_o
struct g_provider *pp;
struct g_raid_md_intel_object *mdi, *mdi1;
struct g_raid_softc *sc;
- struct g_raid_volume *vol;
- struct g_raid_subdisk *subdisk;
struct g_raid_disk *disk;
struct intel_raid_conf *meta;
- struct intel_raid_vol *mvol;
- struct intel_raid_map *map;
+ struct g_raid_md_intel_perdisk *pd;
struct g_geom *geom;
uint32_t checksum, *ptr;
char *buf, *tmp;
- int i, j, error, serial_len, disk_pos, result;
+ int i, error, serial_len, disk_pos, result;
char serial[INTEL_SERIAL_LEN];
char name[16];
@@ -364,6 +543,7 @@ g_raid_md_taste_intel(struct g_raid_md_o
g_raid_md_intel_print(meta);
G_RAID_DEBUG(1, "Intel disk position %d", disk_pos);
+ /* Search for matching node. */
sc = NULL;
mdi1 = NULL;
LIST_FOREACH(geom, &mp->geom, geom) {
@@ -388,41 +568,14 @@ g_raid_md_taste_intel(struct g_raid_md_o
} else { /* Not found matching node. */
result = G_RAID_MD_TASTE_NEW;
mdi->mdio_config_id = meta->config_id;
- mdi->mdio_meta = meta;
snprintf(name, sizeof(name), "Intel-%08x", meta->config_id);
sc = g_raid_create_node(mp, name, md);
md->mdo_softc = sc;
geom = sc->sc_geom;
G_RAID_DEBUG(1, "Created new node %s", sc->sc_name);
-
- /* Create volumes */
- for (i = 0; i < meta->total_volumes; i++) {
- mvol = intel_get_volume(meta, i);
- map = intel_get_map(mvol, 0);
- vol = g_raid_create_volume(sc, mvol->name);
- vol->v_md_data = (void *)(intptr_t)i;
- if (map->type == INTEL_T_RAID0)
- vol->v_raid_level = G_RAID_VOLUME_RL_RAID0;
- else if (map->type == INTEL_T_RAID1 &&
- map->total_disks < 4)
- vol->v_raid_level = G_RAID_VOLUME_RL_RAID1;
- else if (map->type == INTEL_T_RAID1)
- vol->v_raid_level = G_RAID_VOLUME_RL_RAID10;
- else if (map->type == INTEL_T_RAID5)
- vol->v_raid_level = G_RAID_VOLUME_RL_RAID5;
- else
- vol->v_raid_level = G_RAID_VOLUME_RL_UNKNOWN;
- vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_NONE;
- vol->v_strip_size = map->stripe_sectors * 512; //ZZZ
- vol->v_disks_count = map->total_disks;
- vol->v_mediasize = mvol->total_sectors * 512; //ZZZ
- vol->v_sectorsize = 512; //ZZZ
- g_topology_unlock();
- sx_xlock(&sc->sc_lock);
- g_raid_start_volume(vol);
- sx_xunlock(&sc->sc_lock);
- g_topology_lock();
- }
+ callout_init(&mdi->mdio_start_co, 1);
+ callout_reset(&mdi->mdio_start_co, g_raid_start_timeout * hz,
+ g_raid_intel_go, sc);
}
rcp = g_new_consumer(geom);
@@ -433,34 +586,15 @@ g_raid_md_taste_intel(struct g_raid_md_o
g_topology_unlock();
sx_xlock(&sc->sc_lock);
- disk = g_raid_md_intel_get_disk(sc, disk_pos);
- if (disk != 0)
- ; /* Error, duplicate disk! */
+ pd = malloc(sizeof(*pd), M_MD_INTEL, M_WAITOK | M_ZERO);
+ pd->pd_meta = meta;
+ pd->pd_disk_pos = disk_pos;
disk = g_raid_create_disk(sc);
- disk->d_md_data = (void *)(intptr_t)disk_pos;
+ disk->d_md_data = (void *)pd;
disk->d_consumer = rcp;
- g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE);
rcp->private = disk;
- /* Create subdisks */
- for (i = 0; i < meta->total_volumes; i++) {
- mvol = intel_get_volume(meta, i);
- map = intel_get_map(mvol, 0);
- for (j = 0; j < map->total_disks; j++) {
- if ((map->disk_idx[j] & INTEL_DI_IDX) == disk_pos)
- break;
- }
- if (j == map->total_disks)
- continue;
- vol = g_raid_md_intel_get_volume(sc, i);
- subdisk = &vol->v_subdisks[j];
- subdisk->sd_disk = disk;
- subdisk->sd_offset = map->offset * 512; //ZZZ
- subdisk->sd_size = map->disk_sectors;
- LIST_INSERT_HEAD(&disk->d_subdisks, subdisk, sd_next);
- g_raid_event_send(subdisk, G_RAID_SUBDISK_E_NEW,
- G_RAID_EVENT_SUBDISK);
- }
+ g_raid_md_intel_new_disk(disk);
sx_xunlock(&sc->sc_lock);
g_topology_lock();
@@ -501,13 +635,35 @@ g_raid_md_write_intel(struct g_raid_md_o
}
static int
+g_raid_md_free_disk_intel(struct g_raid_md_object *md,
+ struct g_raid_disk *disk)
+{
+ struct g_raid_md_intel_perdisk *pd;
+
+ pd = (struct g_raid_md_intel_perdisk *)disk->d_md_data;
+ if (pd->pd_meta != NULL) {
+ free(pd->pd_meta, M_MD_INTEL);
+ pd->pd_meta = NULL;
+ }
+ free(pd, M_MD_INTEL);
+ disk->d_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;
mdi = (struct g_raid_md_intel_object *)md;
- free(mdi->mdio_meta, M_MD_INTEL);
- mdi->mdio_meta = NULL;
+ if (!mdi->mdio_started) {
+ mdi->mdio_started = 0;
+ callout_stop(&mdi->mdio_start_co);
+ }
+ if (mdi->mdio_meta != NULL) {
+ free(mdi->mdio_meta, M_MD_INTEL);
+ mdi->mdio_meta = NULL;
+ }
return (0);
}
More information about the svn-src-projects
mailing list