svn commit: r217828 - projects/graid/head/sys/geom/raid
Alexander Motin
mav at FreeBSD.org
Tue Jan 25 15:34:07 UTC 2011
Author: mav
Date: Tue Jan 25 15:34:07 2011
New Revision: 217828
URL: http://svn.freebsd.org/changeset/base/217828
Log:
Implement kernel dumping to geom_raid volumes. Dumping mechanism supports
any RAID levels without any additional magic. Dumping to RAID0 and RAID1
verified to work right now.
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/md_intel.c
Modified: projects/graid/head/sys/geom/raid/g_raid.c
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid.c Tue Jan 25 15:18:10 2011 (r217827)
+++ projects/graid/head/sys/geom/raid/g_raid.c Tue Jan 25 15:34:07 2011 (r217828)
@@ -116,8 +116,10 @@ static int g_raid_update_subdisk(struct
static int g_raid_update_volume(struct g_raid_volume *vol, u_int state);
static void g_raid_dumpconf(struct sbuf *sb, const char *indent,
struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp);
+static void g_raid_start(struct bio *bp);
static void g_raid_start_request(struct bio *bp);
static void g_raid_disk_done(struct bio *bp);
+static void g_raid_poll(struct g_raid_softc *sc);
static const char *
g_raid_disk_state2str(int state)
@@ -714,6 +716,73 @@ g_raid_unidle(struct g_raid_volume *vol)
}
static void
+g_raid_dumpdone(struct bio *bp)
+{
+
+ bp->bio_flags |= BIO_DONE;
+}
+
+static int
+g_raid_dump(void *arg,
+ void *virtual, vm_offset_t physical, off_t offset, size_t length)
+{
+ struct g_raid_softc *sc;
+ struct g_raid_volume *vol;
+ struct bio *bp;
+
+ vol = (struct g_raid_volume *)arg;
+ sc = vol->v_softc;
+ G_RAID_DEBUG(3, "Dumping at off %llu len %llu.",
+ (long long unsigned)offset, (long long unsigned)length);
+
+ bp = g_alloc_bio();
+ bp->bio_cmd = BIO_WRITE;
+ bp->bio_done = g_raid_dumpdone;
+ bp->bio_attribute = NULL;
+ bp->bio_offset = offset;
+ bp->bio_length = length;
+ bp->bio_data = virtual;
+ bp->bio_to = vol->v_provider;
+
+ g_raid_start(bp);
+
+ while (!(bp->bio_flags & BIO_DONE)) {
+ G_RAID_DEBUG(4, "Poll...");
+ g_raid_poll(sc);
+ DELAY(10);
+ }
+
+ G_RAID_DEBUG(3, "Dumping at off %llu len %llu done.",
+ (long long unsigned)offset, (long long unsigned)length);
+
+ g_destroy_bio(bp);
+ return (0);
+}
+
+static void
+g_raid_kerneldump(struct g_raid_softc *sc, struct bio *bp)
+{
+ struct g_kerneldump *gkd;
+ struct g_provider *pp;
+ struct g_raid_volume *vol;
+
+ gkd = (struct g_kerneldump*)bp->bio_data;
+ pp = bp->bio_to;
+ vol = pp->private;
+ g_trace(G_T_TOPOLOGY, "g_raid_kerneldump(%s, %jd, %jd)",
+ pp->name, (intmax_t)gkd->offset, (intmax_t)gkd->length);
+ gkd->di.dumper = g_raid_dump;
+ gkd->di.priv = vol;
+ gkd->di.blocksize = vol->v_sectorsize;
+ gkd->di.maxiosize = DFLTPHYS;
+ gkd->di.mediaoffset = gkd->offset;
+ if ((gkd->offset + gkd->length) > vol->v_mediasize)
+ gkd->length = vol->v_mediasize - gkd->offset;
+ gkd->di.mediasize = gkd->length;
+ g_io_deliver(bp, 0);
+}
+
+static void
g_raid_start(struct bio *bp)
{
struct g_raid_softc *sc;
@@ -736,6 +805,12 @@ g_raid_start(struct bio *bp)
case BIO_FLUSH:
g_io_deliver(bp, EOPNOTSUPP);
return;
+ case BIO_GETATTR:
+ if (!strcmp(bp->bio_attribute, "GEOM::kerneldump"))
+ g_raid_kerneldump(sc, bp);
+ else
+ g_io_deliver(bp, EOPNOTSUPP);
+ return;
default:
g_io_deliver(bp, EOPNOTSUPP);
return;
@@ -743,8 +818,10 @@ g_raid_start(struct bio *bp)
mtx_lock(&sc->sc_queue_mtx);
bioq_disksort(&sc->sc_queue, bp);
mtx_unlock(&sc->sc_queue_mtx);
- G_RAID_DEBUG(4, "%s: Waking up %p.", __func__, sc);
- wakeup(sc);
+ if (!dumping) {
+ G_RAID_DEBUG(4, "%s: Waking up %p.", __func__, sc);
+ wakeup(sc);
+ }
}
static int
@@ -947,12 +1024,27 @@ g_raid_subdisk_iostart(struct g_raid_sub
cp = sd->sd_disk->d_consumer;
bp->bio_done = g_raid_disk_done;
+ bp->bio_from = sd->sd_disk->d_consumer;
bp->bio_to = sd->sd_disk->d_consumer->provider;
bp->bio_offset += sd->sd_offset;
bp->bio_caller1 = sd;
cp->index++;
- G_RAID_LOGREQ(3, bp, "Sending request.");
- g_io_request(bp, cp);
+ if (dumping) {
+ G_RAID_LOGREQ(3, bp, "Sending dumping request.");
+ if (sd->sd_disk->d_kd.di.dumper == NULL) {
+ bp->bio_error = EOPNOTSUPP;
+ g_raid_disk_done(bp);
+ return;
+ }
+ dump_write(&sd->sd_disk->d_kd.di,
+ bp->bio_data, 0,
+ sd->sd_disk->d_kd.di.mediaoffset + bp->bio_offset,
+ bp->bio_length);
+ g_raid_disk_done(bp);
+ } else {
+ G_RAID_LOGREQ(3, bp, "Sending request.");
+ g_io_request(bp, cp);
+ }
}
static void
@@ -964,7 +1056,8 @@ g_raid_disk_done(struct bio *bp)
mtx_lock(&sc->sc_queue_mtx);
bioq_disksort(&sc->sc_queue, bp);
mtx_unlock(&sc->sc_queue_mtx);
- wakeup(sc);
+ if (!dumping)
+ wakeup(sc);
}
static void
@@ -1068,7 +1161,8 @@ process:
if (ep != NULL)
g_raid_handle_event(sc, ep);
if (bp != NULL) {
- if (bp->bio_from->geom != sc->sc_geom)
+ if (bp->bio_from == NULL ||
+ bp->bio_from->geom != sc->sc_geom)
g_raid_start_request(bp);
else
g_raid_disk_done_request(bp);
@@ -1080,6 +1174,38 @@ process:
}
}
+static void
+g_raid_poll(struct g_raid_softc *sc)
+{
+ struct g_raid_event *ep;
+ struct bio *bp;
+
+ sx_xlock(&sc->sc_lock);
+ mtx_lock(&sc->sc_queue_mtx);
+ /*
+ * First take a look at events.
+ * This is important to handle events before any I/O requests.
+ */
+ ep = TAILQ_FIRST(&sc->sc_events);
+ if (ep != NULL) {
+ TAILQ_REMOVE(&sc->sc_events, ep, e_next);
+ mtx_unlock(&sc->sc_queue_mtx);
+ g_raid_handle_event(sc, ep);
+ goto out;
+ }
+ bp = bioq_takefirst(&sc->sc_queue);
+ if (bp != NULL) {
+ mtx_unlock(&sc->sc_queue_mtx);
+ if (bp->bio_from == NULL ||
+ bp->bio_from->geom != sc->sc_geom)
+ g_raid_start_request(bp);
+ else
+ g_raid_disk_done_request(bp);
+ }
+out:
+ sx_xunlock(&sc->sc_lock);
+}
+
#if 0
static void
g_raid_update_idle(struct g_raid_softc *sc, struct g_raid_disk *disk)
Modified: projects/graid/head/sys/geom/raid/g_raid.h
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid.h Tue Jan 25 15:18:10 2011 (r217827)
+++ projects/graid/head/sys/geom/raid/g_raid.h Tue Jan 25 15:34:07 2011 (r217828)
@@ -114,6 +114,7 @@ struct g_raid_disk {
struct g_raid_softc *d_softc; /* Back-pointer to softc. */
struct g_consumer *d_consumer; /* GEOM disk consumer. */
void *d_md_data; /* Disk's metadata storage. */
+ struct g_kerneldump d_kd; /* Kernel dumping method/args. */
u_int d_state; /* Disk state. */
uint64_t d_flags; /* Additional flags. */
u_int d_load; /* Disk average load. */
Modified: projects/graid/head/sys/geom/raid/md_intel.c
==============================================================================
--- projects/graid/head/sys/geom/raid/md_intel.c Tue Jan 25 15:18:10 2011 (r217827)
+++ projects/graid/head/sys/geom/raid/md_intel.c Tue Jan 25 15:34:07 2011 (r217828)
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/kernel.h>
#include <sys/kobj.h>
+#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
@@ -1092,6 +1093,14 @@ search:
disk->d_consumer = rcp;
rcp->private = disk;
+ /* Read kernel dumping information. */
+ disk->d_kd.offset = 0;
+ disk->d_kd.length = OFF_MAX;
+ len = sizeof(disk->d_kd);
+ error = g_io_getattr("GEOM::kerneldump", rcp, &len, &disk->d_kd);
+ if (disk->d_kd.di.dumper == NULL)
+ G_RAID_DEBUG(2, "Dumping not supported: %d.", error);
+
g_raid_md_intel_new_disk(disk);
sx_xunlock(&sc->sc_lock);
@@ -1267,6 +1276,15 @@ g_raid_md_ctl_intel(struct g_raid_md_obj
error = -8;
break;
}
+
+ /* Read kernel dumping information. */
+ disk->d_kd.offset = 0;
+ disk->d_kd.length = OFF_MAX;
+ len = sizeof(disk->d_kd);
+ g_io_getattr("GEOM::kerneldump", cp, &len, &disk->d_kd);
+ if (disk->d_kd.di.dumper == NULL)
+ G_RAID_DEBUG(2, "Dumping not supported.");
+
pd->pd_disk_meta.sectors = pp->mediasize / pp->sectorsize;
if (size > pp->mediasize)
size = pp->mediasize;
@@ -1494,6 +1512,14 @@ g_raid_md_ctl_intel(struct g_raid_md_obj
disk->d_md_data = (void *)pd;
cp->private = disk;
+ /* Read kernel dumping information. */
+ disk->d_kd.offset = 0;
+ disk->d_kd.length = OFF_MAX;
+ len = sizeof(disk->d_kd);
+ g_io_getattr("GEOM::kerneldump", cp, &len, &disk->d_kd);
+ if (disk->d_kd.di.dumper == NULL)
+ G_RAID_DEBUG(2, "Dumping not supported.");
+
memcpy(&pd->pd_disk_meta.serial[0], &serial[0],
INTEL_SERIAL_LEN);
pd->pd_disk_meta.sectors = pp->mediasize / pp->sectorsize;
More information about the svn-src-projects
mailing list