summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2002-04-19 09:24:12 +0000
committerphk <phk@FreeBSD.org>2002-04-19 09:24:12 +0000
commit4509f96cc589342df08f0237df6f9add315b10dc (patch)
tree78bdb30d9090fbc82c33e35fbf8e451f4f7f28f1
parenta274092cf658e3818cf7022f777b07ae66e89fe5 (diff)
downloadFreeBSD-src-4509f96cc589342df08f0237df6f9add315b10dc.zip
FreeBSD-src-4509f96cc589342df08f0237df6f9add315b10dc.tar.gz
Make kernel dumps work with GEOM.
Notice that if the device on which the dump is set is destroyed for any reason, the dump setting is lost. This in particular will happen in the case of spoilage. For instance if you set dump on ad0s1b and open ad0 for writing, ad0s* will be spoilt and the dump setting lost. See geom(4) for more about spoiling. Sponsored by: DARPA & NAI Labs.
-rw-r--r--sys/geom/geom.h5
-rw-r--r--sys/geom/geom_dev.c19
-rw-r--r--sys/geom/geom_disk.c20
-rw-r--r--sys/geom/geom_slice.c9
4 files changed, 53 insertions, 0 deletions
diff --git a/sys/geom/geom.h b/sys/geom/geom.h
index 6dfe745..e4c37b7 100644
--- a/sys/geom/geom.h
+++ b/sys/geom/geom.h
@@ -229,6 +229,11 @@ struct g_ioctl {
#ifdef _KERNEL
+struct g_kerneldump {
+ off_t offset;
+ off_t length;
+};
+
MALLOC_DECLARE(M_GEOM);
static __inline void *
diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c
index 3711fb0..b845b06 100644
--- a/sys/geom/geom_dev.c
+++ b/sys/geom/geom_dev.c
@@ -48,6 +48,7 @@
#include <sys/disk.h>
#include <sys/fcntl.h>
#include <geom/geom.h>
+#include <machine/limits.h>
#define CDEV_MAJOR 4
@@ -239,7 +240,9 @@ g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
{
struct g_geom *gp;
struct g_consumer *cp;
+ struct g_kerneldump kd;
int i, error;
+ u_int u;
struct g_ioctl *gio;
gp = dev->si_drv1;
@@ -265,6 +268,20 @@ g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
case DIOCGFRONTSTUFF:
error = g_io_getattr("GEOM::frontstuff", cp, &i, data);
break;
+ case DIOCSKERNELDUMP:
+ u = *((u_int *)data);
+ if (!u) {
+ set_dumper(NULL);
+ error = 0;
+ break;
+ }
+ kd.offset = 0;
+ kd.length = OFF_MAX;
+ i = sizeof kd;
+ error = g_io_getattr("GEOM::kerneldump", cp, &i, &kd);
+ if (!error)
+ dev->si_flags |= SI_DUMPDEV;
+ break;
default:
gio = g_malloc(sizeof *gio, M_WAITOK);
gio->cmd = cmd;
@@ -378,6 +395,8 @@ g_dev_orphan(struct g_consumer *cp)
if (cp->biocount > 0)
return;
dev = gp->softc;
+ if (dev->si_flags & SI_DUMPDEV)
+ set_dumper(NULL);
destroy_dev(dev);
if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
g_access_rel(cp, -cp->acr, -cp->acw, -cp->ace);
diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c
index e6a2bcd..6abb492 100644
--- a/sys/geom/geom_disk.c
+++ b/sys/geom/geom_disk.c
@@ -99,6 +99,24 @@ g_disk_access(struct g_provider *pp, int r, int w, int e)
}
static void
+g_disk_kerneldump(struct bio *bp, struct disk *dp)
+{
+ int error;
+ struct g_kerneldump *gkd;
+ struct dumperinfo di;
+
+ gkd = (struct g_kerneldump*)bp->bio_data;
+ printf("Kerneldump off=%lld len=%lld\n", gkd->offset, gkd->length);
+ di.dumper = (dumper_t *)dp->d_devsw->d_dump;
+ di.priv = dp->d_dev;
+ di.blocksize = dp->d_label.d_secsize;
+ di.mediaoffset = gkd->offset;
+ di.mediasize = gkd->length;
+ error = set_dumper(&di);
+ g_io_fail(bp, error);
+}
+
+static void
g_disk_done(struct bio *bp)
{
@@ -148,6 +166,8 @@ g_disk_start(struct bio *bp)
break;
else if (g_haveattr_off_t(bp, "GEOM::frontstuff", 0))
break;
+ else if (!strcmp(bp->bio_attribute, "GEOM::kerneldump"))
+ g_disk_kerneldump(bp, dp);
else if (!strcmp(bp->bio_attribute, "GEOM::ioctl") &&
bp->bio_length == sizeof *gio) {
gio = (struct g_ioctl *)bp->bio_data;
diff --git a/sys/geom/geom_slice.c b/sys/geom/geom_slice.c
index 21b514c..513ed26 100644
--- a/sys/geom/geom_slice.c
+++ b/sys/geom/geom_slice.c
@@ -173,6 +173,15 @@ g_slice_start(struct bio *bp)
g_haveattr_off_t(bp, "GEOM::frontstuff", t);
return;
}
+ if (!strcmp("GEOM::kerneldump", bp->bio_attribute)) {
+ struct g_kerneldump *gkd;
+
+ gkd = (struct g_kerneldump *)bp->bio_data;
+ gkd->offset += gsp->slices[index].offset;
+ if (gkd->length > gsp->slices[index].length)
+ gkd->length = gsp->slices[index].length;
+ /* now, pass it on downwards... */
+ }
bp2 = g_clone_bio(bp);
bp2->bio_done = g_std_done;
g_io_request(bp2, cp);
OpenPOWER on IntegriCloud