From owner-svn-src-projects@FreeBSD.ORG Tue Jan 25 15:34:07 2011 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B976C1065670; Tue, 25 Jan 2011 15:34:07 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id A7BEC8FC1A; Tue, 25 Jan 2011 15:34:07 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p0PFY7Yn039186; Tue, 25 Jan 2011 15:34:07 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p0PFY7cF039182; Tue, 25 Jan 2011 15:34:07 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201101251534.p0PFY7cF039182@svn.freebsd.org> From: Alexander Motin Date: Tue, 25 Jan 2011 15:34:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r217828 - projects/graid/head/sys/geom/raid X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Jan 2011 15:34:07 -0000 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 #include #include +#include #include #include #include @@ -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;