svn commit: r217972 - projects/graid/head/sys/geom/raid
Warner Losh
imp at FreeBSD.org
Thu Jan 27 19:56:16 UTC 2011
Author: imp
Date: Thu Jan 27 19:56:15 2011
New Revision: 217972
URL: http://svn.freebsd.org/changeset/base/217972
Log:
Improvements:
(1) Move bio into trso so we don't have to allocate/free it all the time.
Saves on error recovery hassles if we can't allocate a bio.
(2) Interlock while we're doing things, so we don't duplicate each slab of work.
(3) Update metadata after each bundle of slabs. (mav: please comment on
frequency)
(4) Transition state to active when we successfully
# this makes things a little more robust, but more work there is needed
Modified:
projects/graid/head/sys/geom/raid/tr_raid1.c
Modified: projects/graid/head/sys/geom/raid/tr_raid1.c
==============================================================================
--- projects/graid/head/sys/geom/raid/tr_raid1.c Thu Jan 27 19:38:03 2011 (r217971)
+++ projects/graid/head/sys/geom/raid/tr_raid1.c Thu Jan 27 19:56:15 2011 (r217972)
@@ -62,6 +62,8 @@ static MALLOC_DEFINE(M_TR_raid1, "tr_rai
#define TR_RAID1_REBUILD 1
#define TR_RAID1_RESYNC 2
+#define TR_RAID1_F_DOING_SOME 0x1
+
struct g_raid_tr_raid1_object {
struct g_raid_tr_object trso_base;
int trso_starting;
@@ -69,9 +71,11 @@ struct g_raid_tr_raid1_object {
int trso_type;
int trso_recover_slabs; /* might need to be more */
int trso_fair_io;
+ int trso_flags;
struct g_raid_subdisk *trso_good_sd; /* specific rather than per tr */
struct g_raid_subdisk *trso_failed_sd;/* like per volume */
void *trso_buffer; /* Buffer space */
+ struct bio trso_bio;
};
static g_raid_tr_taste_t g_raid_tr_taste_raid1;
@@ -106,6 +110,8 @@ static struct g_raid_tr_class g_raid_tr_
static void g_raid_tr_raid1_rebuild_abort(struct g_raid_tr_object *tr,
struct g_raid_volume *vol);
+static void g_raid_tr_raid1_maybe_rebuild(struct g_raid_tr_object *tr,
+ struct g_raid_volume *vol);
static int
g_raid_tr_taste_raid1(struct g_raid_tr_object *tr, struct g_raid_volume *volume)
@@ -120,6 +126,40 @@ g_raid_tr_taste_raid1(struct g_raid_tr_o
return (G_RAID_TR_TASTE_SUCCEED);
}
+static int
+g_raid_tr_update_state_raid1(struct g_raid_volume *vol)
+{
+ struct g_raid_tr_raid1_object *trs;
+ u_int s;
+ int n;
+
+ trs = (struct g_raid_tr_raid1_object *)vol->v_tr;
+ if (trs->trso_stopped)
+ s = G_RAID_VOLUME_S_STOPPED;
+ else {
+ n = g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_ACTIVE);
+ if (n == vol->v_disks_count) {
+ s = G_RAID_VOLUME_S_OPTIMAL;
+ trs->trso_starting = 0;
+ } else {
+ if (trs->trso_starting)
+ s = G_RAID_VOLUME_S_STARTING;
+ else if (n > 0)
+ s = G_RAID_VOLUME_S_DEGRADED;
+ else
+ s = G_RAID_VOLUME_S_BROKEN;
+ }
+ }
+ g_raid_tr_raid1_maybe_rebuild(vol->v_tr, vol);
+ if (s != vol->v_state) {
+ g_raid_event_send(vol, G_RAID_VOLUME_S_ALIVE(s) ?
+ G_RAID_VOLUME_E_UP : G_RAID_VOLUME_E_DOWN,
+ G_RAID_EVENT_VOLUME);
+ g_raid_change_volume_state(vol, s);
+ }
+ return (0);
+}
+
static void
g_raid_tr_raid1_rebuild_some(struct g_raid_tr_object *tr,
struct g_raid_subdisk *sd)
@@ -127,11 +167,13 @@ g_raid_tr_raid1_rebuild_some(struct g_ra
struct g_raid_tr_raid1_object *trs;
struct bio *bp, *bp2;
-/* XXX need interlock here? */
trs = (struct g_raid_tr_raid1_object *)tr;
+ if (trs->trso_flags & TR_RAID1_F_DOING_SOME)
+ return;
+ trs->trso_flags |= TR_RAID1_F_DOING_SOME;
trs->trso_recover_slabs = SD_REBUILD_CLUSTER_IDLE;
trs->trso_fair_io = SD_REBUILD_FAIR_IO;
- bp = g_new_bio();
+ bp = &trs->trso_bio;
bp->bio_offset = sd->sd_rebuild_pos;
bp->bio_length = MIN(SD_REBUILD_SLAB,
sd->sd_volume->v_mediasize - sd->sd_rebuild_pos);
@@ -167,26 +209,35 @@ static void
g_raid_tr_raid1_rebuild_finish(struct g_raid_tr_object *tr, struct g_raid_volume *vol)
{
struct g_raid_tr_raid1_object *trs;
+ struct g_raid_subdisk *sd;
trs = (struct g_raid_tr_raid1_object *)tr;
+ sd = trs->trso_failed_sd;
+ g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_ACTIVE);
+ g_raid_tr_update_state_raid1(vol);
+ g_raid_write_metadata(vol->v_softc, vol, sd, sd->sd_disk);
free(trs->trso_buffer, M_TR_raid1);
+ trs->trso_flags &= ~TR_RAID1_F_DOING_SOME;
trs->trso_recover_slabs = 0;
trs->trso_failed_sd = NULL;
trs->trso_good_sd = NULL;
trs->trso_buffer = NULL;
vol->v_timeout = 0;
- /* xxx transition array? */
}
static void
-g_raid_tr_raid1_rebuild_abort(struct g_raid_tr_object *tr, struct g_raid_volume *vol)
+g_raid_tr_raid1_rebuild_abort(struct g_raid_tr_object *tr,
+ struct g_raid_volume *vol)
{
struct g_raid_tr_raid1_object *trs;
+ struct g_raid_subdisk *sd;
trs = (struct g_raid_tr_raid1_object *)tr;
- g_raid_unlock_range(tr->tro_volume,
- trs->trso_failed_sd->sd_rebuild_pos, SD_REBUILD_SLAB);
+ sd = trs->trso_failed_sd;
+ g_raid_unlock_range(tr->tro_volume,sd->sd_rebuild_pos, SD_REBUILD_SLAB);
+ g_raid_write_metadata(vol->v_softc, vol, sd, sd->sd_disk);
free(trs->trso_buffer, M_TR_raid1);
+ trs->trso_flags &= ~TR_RAID1_F_DOING_SOME;
trs->trso_recover_slabs = 0;
trs->trso_failed_sd = NULL;
trs->trso_good_sd = NULL;
@@ -271,40 +322,6 @@ g_raid_tr_raid1_maybe_rebuild(struct g_r
}
static int
-g_raid_tr_update_state_raid1(struct g_raid_volume *vol)
-{
- struct g_raid_tr_raid1_object *trs;
- u_int s;
- int n;
-
- trs = (struct g_raid_tr_raid1_object *)vol->v_tr;
- if (trs->trso_stopped)
- s = G_RAID_VOLUME_S_STOPPED;
- else {
- n = g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_ACTIVE);
- if (n == vol->v_disks_count) {
- s = G_RAID_VOLUME_S_OPTIMAL;
- trs->trso_starting = 0;
- } else {
- if (trs->trso_starting)
- s = G_RAID_VOLUME_S_STARTING;
- else if (n > 0)
- s = G_RAID_VOLUME_S_DEGRADED;
- else
- s = G_RAID_VOLUME_S_BROKEN;
- }
- }
- g_raid_tr_raid1_maybe_rebuild(vol->v_tr, vol);
- if (s != vol->v_state) {
- g_raid_event_send(vol, G_RAID_VOLUME_S_ALIVE(s) ?
- G_RAID_VOLUME_E_UP : G_RAID_VOLUME_E_DOWN,
- G_RAID_EVENT_VOLUME);
- g_raid_change_volume_state(vol, s);
- }
- return (0);
-}
-
-static int
g_raid_tr_event_raid1(struct g_raid_tr_object *tr,
struct g_raid_subdisk *sd, u_int event)
{
@@ -558,7 +575,7 @@ g_raid_tr_iodone_raid1(struct g_raid_tr_
bp->bio_error);
if (bp->bio_error != 0) {
g_raid_tr_raid1_rebuild_abort(tr, vol);
- goto out;
+ return;
}
cbp = g_clone_bio(pbp);
cbp->bio_cmd = BIO_WRITE;
@@ -582,7 +599,6 @@ g_raid_tr_iodone_raid1(struct g_raid_tr_
"rebuild write done. Error %d", bp->bio_error);
if (bp->bio_error != 0) {
g_raid_tr_raid1_rebuild_abort(tr, vol);
- g_destroy_bio(pbp);
return;
}
/* XXX A lot of the following is needed when we kick of the work -- refactor */
@@ -592,11 +608,13 @@ g_raid_tr_iodone_raid1(struct g_raid_tr_
nsd->sd_rebuild_pos += pbp->bio_length;
if (nsd->sd_rebuild_pos >= vol->v_mediasize) {
g_raid_tr_raid1_rebuild_finish(tr, vol);
- g_destroy_bio(pbp);
return;
}
- if (--trs->trso_recover_slabs == 0) {
- g_destroy_bio(pbp);
+ if (--trs->trso_recover_slabs <= 0) {
+ /* Have we done a substantial enough amount of recovery? */
+ g_raid_write_metadata(vol->v_softc, vol, nsd,
+ nsd->sd_disk);
+ trs->trso_flags &= ~TR_RAID1_F_DOING_SOME;
return;
}
pbp->bio_offset = nsd->sd_rebuild_pos;
@@ -711,7 +729,6 @@ g_raid_tr_iodone_raid1(struct g_raid_tr_
bp->bio_error = 0;
}
}
-out:;
if (pbp->bio_children == pbp->bio_inbed) {
pbp->bio_completed = pbp->bio_length;
g_raid_iodone(pbp, bp->bio_error);
More information about the svn-src-projects
mailing list