svn commit: r219619 - projects/graid/head/sys/geom/raid
Alexander Motin
mav at FreeBSD.org
Sun Mar 13 19:07:59 UTC 2011
Author: mav
Date: Sun Mar 13 19:07:58 2011
New Revision: 219619
URL: http://svn.freebsd.org/changeset/base/219619
Log:
Add few more bricks to the Promise metadata module.
Add free_volume() method to metadata API to allow private data cleanup
on volume destruction. Unlike previous, Promise uses many per-volume data.
Modified:
projects/graid/head/sys/geom/raid/g_raid.c
projects/graid/head/sys/geom/raid/g_raid_md_if.m
projects/graid/head/sys/geom/raid/md_promise.c
Modified: projects/graid/head/sys/geom/raid/g_raid.c
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid.c Sun Mar 13 18:26:16 2011 (r219618)
+++ projects/graid/head/sys/geom/raid/g_raid.c Sun Mar 13 19:07:58 2011 (r219619)
@@ -1704,6 +1704,8 @@ g_raid_create_volume(struct g_raid_softc
vol->v_softc = sc;
strlcpy(vol->v_name, name, G_RAID_MAX_VOLUMENAME);
vol->v_state = G_RAID_VOLUME_S_STARTING;
+ vol->v_raid_level = G_RAID_VOLUME_RL_UNKNOWN;
+ vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_UNKNOWN;
bioq_init(&vol->v_inflight);
bioq_init(&vol->v_locked);
LIST_INIT(&vol->v_locks);
@@ -1878,6 +1880,8 @@ g_raid_destroy_volume(struct g_raid_volu
TAILQ_REMOVE(&disk->d_subdisks, &vol->v_subdisks[i], sd_next);
}
G_RAID_DEBUG1(2, sc, "Volume %s destroyed.", vol->v_name);
+ if (sc->sc_md)
+ G_RAID_MD_FREE_VOLUME(sc->sc_md, vol);
free(vol, M_RAID);
if (sc->sc_stopping == G_RAID_DESTROY_HARD) {
/* Wake up worker to let it selfdestruct. */
@@ -1905,8 +1909,6 @@ g_raid_destroy_disk(struct g_raid_disk *
sd->sd_disk = NULL;
}
TAILQ_REMOVE(&sc->sc_disks, 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_md_if.m
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid_md_if.m Sun Mar 13 18:26:16 2011 (r219618)
+++ projects/graid/head/sys/geom/raid/g_raid_md_if.m Sun Mar 13 19:07:58 2011 (r219619)
@@ -62,6 +62,22 @@ CODE {
return (-1);
}
+
+ static int
+ g_raid_md_free_disk_default(struct g_raid_md_object *md,
+ struct g_raid_volume *vol)
+ {
+
+ return (0);
+ }
+
+ static int
+ g_raid_md_free_volume_default(struct g_raid_md_object *md,
+ struct g_raid_volume *vol)
+ {
+
+ return (0);
+ }
};
# create() - create new node from scratch.
@@ -111,7 +127,13 @@ METHOD int fail_disk {
METHOD int free_disk {
struct g_raid_md_object *md;
struct g_raid_disk *disk;
-};
+} DEFAULT g_raid_md_free_disk_default;
+
+# free_volume() - volume destructor.
+METHOD int free_volume {
+ struct g_raid_md_object *md;
+ struct g_raid_volume *vol;
+} DEFAULT g_raid_md_free_volume_default;
# free() - destructor.
METHOD int free {
Modified: projects/graid/head/sys/geom/raid/md_promise.c
==============================================================================
--- projects/graid/head/sys/geom/raid/md_promise.c Sun Mar 13 18:26:16 2011 (r219618)
+++ projects/graid/head/sys/geom/raid/md_promise.c Sun Mar 13 19:07:58 2011 (r219619)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2010 Alexander Motin <mav at FreeBSD.org>
+ * Copyright (c) 2011 Alexander Motin <mav at FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,7 @@ static MALLOC_DEFINE(M_MD_PROMISE, "md_p
#define PROMISE_MAX_DISKS 8
#define PROMISE_MAX_SUBDISKS 4
+#define PROMISE_META_OFFSET 14
struct promise_raid_disk {
uint8_t flags; /* Subdisk status. */
@@ -121,17 +122,22 @@ struct promise_raid_conf {
struct g_raid_md_promise_perdisk {
int pd_subdisks;
- struct {
- struct promise_raid_conf *pd_meta;
- int pd_disk_pos;
- struct promise_raid_disk pd_disk_meta;
- } pd_subdisk[PROMISE_MAX_SUBDISKS];
+ struct promise_raid_conf *pd_meta[PROMISE_MAX_SUBDISKS];
+// struct {
+// int pd_disk_pos;
+// struct promise_raid_disk pd_disk_meta;
+// } pd_subdisk[PROMISE_MAX_SUBDISKS];
+};
+
+struct g_raid_md_promise_pervolume {
+ uint64_t pv_id;
+ uint16_t pv_generation;
+ int pv_disks_present;
+ struct promise_raid_conf *pv_meta;
};
struct g_raid_md_promise_object {
struct g_raid_md_object mdio_base;
- uint32_t mdio_generation;
- struct promise_raid_conf *mdio_meta;
struct callout mdio_start_co; /* STARTING state timer. */
int mdio_disks_present;
int mdio_started;
@@ -146,6 +152,7 @@ static g_raid_md_ctl_t g_raid_md_ctl_pro
static g_raid_md_write_t g_raid_md_write_promise;
static g_raid_md_fail_disk_t g_raid_md_fail_disk_promise;
static g_raid_md_free_disk_t g_raid_md_free_disk_promise;
+static g_raid_md_free_volume_t g_raid_md_free_volume_promise;
static g_raid_md_free_t g_raid_md_free_promise;
static kobj_method_t g_raid_md_promise_methods[] = {
@@ -156,6 +163,7 @@ static kobj_method_t g_raid_md_promise_m
KOBJMETHOD(g_raid_md_write, g_raid_md_write_promise),
KOBJMETHOD(g_raid_md_fail_disk, g_raid_md_fail_disk_promise),
KOBJMETHOD(g_raid_md_free_disk, g_raid_md_free_disk_promise),
+ KOBJMETHOD(g_raid_md_free_volume, g_raid_md_free_volume_promise),
KOBJMETHOD(g_raid_md_free, g_raid_md_free_promise),
{ 0, 0 }
};
@@ -207,7 +215,6 @@ g_raid_md_promise_print(struct promise_r
printf("=================================================\n");
}
-#if 0
static struct promise_raid_conf *
promise_meta_copy(struct promise_raid_conf *meta)
{
@@ -217,8 +224,8 @@ promise_meta_copy(struct promise_raid_co
memcpy(nmeta, meta, sizeof(*nmeta));
return (nmeta);
}
-#endif
+#if 0
static int
promise_meta_find_disk(struct promise_raid_conf *meta, uint64_t id)
{
@@ -230,26 +237,28 @@ promise_meta_find_disk(struct promise_ra
}
return (-1);
}
+#endif
-static struct promise_raid_conf *
-promise_meta_read(struct g_consumer *cp)
+static int
+promise_meta_read(struct g_consumer *cp, struct promise_raid_conf **metaarr)
{
struct g_provider *pp;
struct promise_raid_conf *meta;
char *buf;
- int error, i;
+ int error, i, subdisks;
uint32_t checksum, *ptr;
pp = cp->provider;
-
- /* Read the anchor sector. */
- buf = g_read_data(cp,
- pp->mediasize - pp->sectorsize * 63,
+ subdisks = 0;
+next:
+ /* Read metadata block. */
+ buf = g_read_data(cp, pp->mediasize - pp->sectorsize *
+ (63 - subdisks * PROMISE_META_OFFSET),
pp->sectorsize * 4, &error);
if (buf == NULL) {
G_RAID_DEBUG(1, "Cannot read metadata from %s (error=%d).",
pp->name, error);
- return (NULL);
+ return (subdisks);
}
meta = (struct promise_raid_conf *)buf;
@@ -258,7 +267,7 @@ promise_meta_read(struct g_consumer *cp)
strncmp(meta->promise_id, FREEBSD_MAGIC, strlen(FREEBSD_MAGIC))) {
G_RAID_DEBUG(1, "Promise signature check failed on %s", pp->name);
g_free(buf);
- return (NULL);
+ return (subdisks);
}
meta = malloc(sizeof(*meta), M_MD_PROMISE, M_WAITOK);
memcpy(meta, buf, min(sizeof(*meta), pp->sectorsize * 4));
@@ -270,16 +279,23 @@ promise_meta_read(struct g_consumer *cp)
if (checksum != meta->checksum) {
G_RAID_DEBUG(1, "Promise checksum check failed on %s", pp->name);
free(meta, M_MD_PROMISE);
- return (NULL);
+ return (subdisks);
}
if ((meta->integrity & PROMISE_I_VALID) == 0) {
G_RAID_DEBUG(1, "Promise metadata is invalid on %s", pp->name);
free(meta, M_MD_PROMISE);
- return (NULL);
+ return (subdisks);
}
- return (meta);
+ /* Save this part and look for next. */
+ *metaarr = meta;
+ metaarr++;
+ subdisks++;
+ if (subdisks < PROMISE_MAX_SUBDISKS)
+ goto next;
+
+ return (subdisks);
}
#if 0
@@ -376,19 +392,21 @@ g_raid_md_promise_get_disk(struct g_raid
}
return (disk);
}
+#endif
static struct g_raid_volume *
-g_raid_md_promise_get_volume(struct g_raid_softc *sc, int id)
+g_raid_md_promise_get_volume(struct g_raid_softc *sc, uint64_t id)
{
- struct g_raid_volume *mvol;
+ struct g_raid_volume *vol;
+ struct g_raid_md_promise_pervolume *pv;
- TAILQ_FOREACH(mvol, &sc->sc_volumes, v_next) {
- if ((intptr_t)(mvol->v_md_data) == id)
+ TAILQ_FOREACH(vol, &sc->sc_volumes, v_next) {
+ pv = vol->v_md_data;
+ if (pv->pv_id == id)
break;
}
- return (mvol);
+ return (vol);
}
-#endif
static int
g_raid_md_promise_supported(int level, int qual, int disks, int force)
@@ -656,6 +674,7 @@ nofit:
return (0);
}
+#if 0
static void
g_disk_md_promise_retaste(void *arg, int pending)
{
@@ -664,10 +683,12 @@ g_disk_md_promise_retaste(void *arg, int
g_retaste(&g_raid_class);
free(arg, M_MD_PROMISE);
}
+#endif
static void
g_raid_md_promise_refill(struct g_raid_softc *sc)
{
+#if 0
struct g_raid_md_object *md;
struct g_raid_md_promise_object *mdi;
struct promise_raid_conf *meta;
@@ -727,6 +748,7 @@ g_raid_md_promise_refill(struct g_raid_s
TASK_INIT(task, 0, g_disk_md_promise_retaste, task);
taskqueue_enqueue(taskqueue_swi, task);
}
+#endif
}
static void
@@ -845,40 +867,61 @@ g_raid_md_promise_start(struct g_raid_so
static void
g_raid_md_promise_new_disk(struct g_raid_disk *disk)
{
-#if 0
struct g_raid_softc *sc;
struct g_raid_md_object *md;
struct g_raid_md_promise_object *mdi;
struct promise_raid_conf *pdmeta;
struct g_raid_md_promise_perdisk *pd;
+ struct g_raid_md_promise_pervolume *pv;
+ struct g_raid_volume *vol;
+ int i;
sc = disk->d_softc;
md = sc->sc_md;
mdi = (struct g_raid_md_promise_object *)md;
pd = (struct g_raid_md_promise_perdisk *)disk->d_md_data;
- pdmeta = pd->pd_meta;
- if (mdi->mdio_started) {
- if (g_raid_md_promise_start_disk(disk))
- g_raid_md_write_promise(md, NULL, NULL, NULL);
- } else {
+ for (i = 0; i < pd->pd_subdisks; i++) {
+ pdmeta = pd->pd_meta[i];
+
+ /* Look for volume with matching ID. */
+ vol = g_raid_md_promise_get_volume(sc,
+ pdmeta->volume_id);
+ if (vol == NULL) {
+ vol = g_raid_create_volume(sc, pdmeta->name);
+ pv = malloc(sizeof(*pv), M_MD_PROMISE, M_WAITOK | M_ZERO);
+ pv->pv_id = pdmeta->volume_id;
+ vol->v_md_data = pv;
+ g_raid_start_volume(vol);
+ } else
+ pv = vol->v_md_data;
+
/* If we haven't started yet - check metadata freshness. */
- if (mdi->mdio_meta == NULL ||
- ((int32_t)(pdmeta->generation - mdi->mdio_generation)) > 0) {
+ if (pv->pv_meta != NULL && mdi->mdio_started)
+ continue;
+ if (pv->pv_meta == NULL ||
+ ((int16_t)(pdmeta->generation - pv->pv_generation)) > 0) {
G_RAID_DEBUG1(1, sc, "Newer disk");
- if (mdi->mdio_meta != NULL)
- free(mdi->mdio_meta, M_MD_PROMISE);
- mdi->mdio_meta = promise_meta_copy(pdmeta);
- mdi->mdio_generation = mdi->mdio_meta->generation;
- mdi->mdio_disks_present = 1;
- } else if (pdmeta->generation == mdi->mdio_generation) {
- mdi->mdio_disks_present++;
+ if (pv->pv_meta != NULL)
+ free(pv->pv_meta, M_MD_PROMISE);
+ pv->pv_meta = promise_meta_copy(pdmeta);
+ pv->pv_generation = pv->pv_meta->generation;
+ pv->pv_disks_present = 1;
+ } else if (pdmeta->generation == pv->pv_generation) {
+ pv->pv_disks_present++;
G_RAID_DEBUG1(1, sc, "Matching disk (%d of %d up)",
- mdi->mdio_disks_present,
- mdi->mdio_meta->total_disks);
+ pv->pv_disks_present,
+ pv->pv_meta->total_disks);
} else {
G_RAID_DEBUG1(1, sc, "Older disk");
}
+ }
+
+#if 0
+ if (mdi->mdio_started) {
+ if (g_raid_md_promise_start_disk(disk))
+ g_raid_md_write_promise(md, NULL, NULL, NULL);
+ } else {
/* If we collected all needed disks - start array. */
if (mdi->mdio_disks_present == mdi->mdio_meta->total_disks)
g_raid_md_promise_start(sc);
@@ -913,7 +956,6 @@ g_raid_md_create_promise(struct g_raid_m
char name[16];
mdi = (struct g_raid_md_promise_object *)md;
- mdi->mdio_generation = 0;
snprintf(name, sizeof(name), "Promise");
sc = g_raid_create_node(mp, name, md);
if (sc == NULL)
@@ -932,10 +974,10 @@ g_raid_md_taste_promise(struct g_raid_md
struct g_raid_md_promise_object *mdi, *mdi1;
struct g_raid_softc *sc;
struct g_raid_disk *disk;
- struct promise_raid_conf *meta;
+ struct promise_raid_conf *meta, *metaarr[4];
struct g_raid_md_promise_perdisk *pd;
struct g_geom *geom;
- int error, disk_pos, result, spare, len;
+ int error, i, result, spare, len, subdisks;
char name[16];
uint16_t vendor;
@@ -947,43 +989,36 @@ g_raid_md_taste_promise(struct g_raid_md
meta = NULL;
spare = 0;
vendor = 0xffff;
- disk_pos = 0;
if (g_access(cp, 1, 0, 0) != 0)
return (G_RAID_MD_TASTE_FAIL);
g_topology_unlock();
len = 2;
if (pp->geom->rank == 1)
g_io_getattr("GEOM::hba_vendor", cp, &len, &vendor);
- meta = promise_meta_read(cp);
+ subdisks = promise_meta_read(cp, metaarr);
g_topology_lock();
g_access(cp, -1, 0, 0);
- if (meta == NULL) {
+ if (subdisks == 0) {
if (g_raid_aggressive_spare) {
- if (vendor == 0x8086) {
+ if (vendor == 0x105a || vendor == 0x1002) {
G_RAID_DEBUG(1,
"No Promise metadata, forcing spare.");
spare = 2;
goto search;
} else {
G_RAID_DEBUG(1,
- "Promise vendor mismatch 0x%04x != 0x8086",
+ "Promise vendor mismatch "
+ "0x%04x != 0x105a/0x1002",
vendor);
}
}
return (G_RAID_MD_TASTE_FAIL);
}
- /* Check this disk position in obtained metadata. */
- disk_pos = promise_meta_find_disk(meta, meta->disk.id);
- if (disk_pos < 0) {
- G_RAID_DEBUG(1, "Promise id 0x%016jx not found", meta->disk.id);
- goto fail1;
- }
-
/* Metadata valid. Print it. */
- g_raid_md_promise_print(meta);
- G_RAID_DEBUG(1, "Promise disk position %d", disk_pos);
- spare = meta->disks[disk_pos].flags & PROMISE_F_SPARE;
+ for (i = 0; i < subdisks; i++)
+ g_raid_md_promise_print(metaarr[i]);
+ spare = 0;//meta->disks[disk_pos].flags & PROMISE_F_SPARE;
search:
/* Search for matching node. */
@@ -1028,8 +1063,10 @@ search:
sx_xlock(&sc->sc_lock);
pd = malloc(sizeof(*pd), M_MD_PROMISE, M_WAITOK | M_ZERO);
+ pd->pd_subdisks = subdisks;
+ for (i = 0; i < subdisks; i++)
+ pd->pd_meta[i] = metaarr[i];
#if 0
- pd->pd_meta = meta;
pd->pd_disk_pos = -1;
if (spare == 2) {
// pd->pd_disk_meta.sectors = pp->mediasize / pp->sectorsize;
@@ -1059,9 +1096,9 @@ search:
g_topology_lock();
*gp = geom;
return (result);
-fail1:
- free(meta, M_MD_PROMISE);
- return (G_RAID_MD_TASTE_FAIL);
+//fail1:
+// free(meta, M_MD_PROMISE);
+// return (G_RAID_MD_TASTE_FAIL);
}
static int
@@ -2033,9 +2070,9 @@ g_raid_md_free_disk_promise(struct g_rai
pd = (struct g_raid_md_promise_perdisk *)disk->d_md_data;
for (i = 0; i < pd->pd_subdisks; i++) {
- if (pd->pd_subdisk[i].pd_meta != NULL) {
- free(pd->pd_subdisk[i].pd_meta, M_MD_PROMISE);
- pd->pd_subdisk[i].pd_meta = NULL;
+ if (pd->pd_meta[i] != NULL) {
+ free(pd->pd_meta[i], M_MD_PROMISE);
+ pd->pd_meta[i] = NULL;
}
}
free(pd, M_MD_PROMISE);
@@ -2044,6 +2081,20 @@ g_raid_md_free_disk_promise(struct g_rai
}
static int
+g_raid_md_free_volume_promise(struct g_raid_md_object *md,
+ struct g_raid_volume *vol)
+{
+ struct g_raid_md_promise_pervolume *pv;
+
+ pv = (struct g_raid_md_promise_pervolume *)vol->v_md_data;
+ if (pv && pv->pv_meta != NULL) {
+ free(pv->pv_meta, M_MD_PROMISE);
+ pv->pv_meta = NULL;
+ }
+ return (0);
+}
+
+static int
g_raid_md_free_promise(struct g_raid_md_object *md)
{
struct g_raid_md_promise_object *mdi;
@@ -2057,10 +2108,6 @@ g_raid_md_free_promise(struct g_raid_md_
root_mount_rel(mdi->mdio_rootmount);
mdi->mdio_rootmount = NULL;
}
- if (mdi->mdio_meta != NULL) {
- free(mdi->mdio_meta, M_MD_PROMISE);
- mdi->mdio_meta = NULL;
- }
return (0);
}
More information about the svn-src-projects
mailing list