summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2014-10-08 12:18:16 +0000
committerae <ae@FreeBSD.org>2014-10-08 12:18:16 +0000
commite58acb98ef76ee1fd548f4268ff5754b32887174 (patch)
tree708db956e98a30209c441ff164651ad6a970b271
parentf5996ba41605d0e9cd59bb9482ab3e2e037d8d32 (diff)
downloadFreeBSD-src-e58acb98ef76ee1fd548f4268ff5754b32887174.zip
FreeBSD-src-e58acb98ef76ee1fd548f4268ff5754b32887174.tar.gz
Add an ability to set dumpdev via loader(8) tunable.
MFC after: 3 weeks
-rw-r--r--sys/geom/geom_dev.c76
1 files changed, 62 insertions, 14 deletions
diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c
index c7104d8..e6213ee 100644
--- a/sys/geom/geom_dev.c
+++ b/sys/geom/geom_dev.c
@@ -82,6 +82,8 @@ static struct cdevsw g_dev_cdevsw = {
.d_flags = D_DISK | D_TRACKCLOSE,
};
+static g_init_t g_dev_init;
+static g_fini_t g_dev_fini;
static g_taste_t g_dev_taste;
static g_orphan_t g_dev_orphan;
static g_attrchanged_t g_dev_attrchanged;
@@ -89,6 +91,8 @@ static g_attrchanged_t g_dev_attrchanged;
static struct g_class g_dev_class = {
.name = "DEV",
.version = G_VERSION,
+ .init = g_dev_init,
+ .fini = g_dev_fini,
.taste = g_dev_taste,
.orphan = g_dev_orphan,
.attrchanged = g_dev_attrchanged
@@ -107,6 +111,58 @@ SYSCTL_QUAD(_kern_geom_dev, OID_AUTO, delete_max_sectors, CTLFLAG_RW,
"delete request sent to the provider. Larger requests are chunked "
"so they can be interrupted. (0 = disable chunking)");
+static char *dumpdev = NULL;
+static void
+g_dev_init(struct g_class *mp)
+{
+
+ dumpdev = getenv("dumpdev");
+}
+
+static void
+g_dev_fini(struct g_class *mp)
+{
+
+ freeenv(dumpdev);
+}
+
+static int
+g_dev_setdumpdev(struct cdev *dev)
+{
+ struct g_kerneldump kd;
+ struct g_consumer *cp;
+ int error, len;
+
+ if (dev == NULL)
+ return (set_dumper(NULL, NULL));
+
+ cp = dev->si_drv2;
+ len = sizeof(kd);
+ kd.offset = 0;
+ kd.length = OFF_MAX;
+ error = g_io_getattr("GEOM::kerneldump", cp, &len, &kd);
+ if (error == 0) {
+ error = set_dumper(&kd.di, devtoname(dev));
+ if (error == 0)
+ dev->si_flags |= SI_DUMPDEV;
+ }
+ return (error);
+}
+
+static void
+init_dumpdev(struct cdev *dev)
+{
+
+ if (dumpdev == NULL)
+ return;
+ if (strcmp(devtoname(dev), dumpdev) != 0)
+ return;
+ if (g_dev_setdumpdev(dev) == 0) {
+ freeenv(dumpdev);
+ dumpdev = NULL;
+ }
+}
+
static void
g_dev_destroy(void *arg, int flags __unused)
{
@@ -261,10 +317,12 @@ g_dev_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
dev->si_iosize_max = MAXPHYS;
dev->si_drv2 = cp;
+ init_dumpdev(dev);
if (adev != NULL) {
adev->si_iosize_max = MAXPHYS;
adev->si_drv2 = cp;
adev->si_flags |= SI_UNMAPPED;
+ init_dumpdev(adev);
}
g_dev_attrchanged(cp, "GEOM::physpath");
@@ -358,7 +416,6 @@ g_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread
{
struct g_consumer *cp;
struct g_provider *pp;
- struct g_kerneldump kd;
off_t offset, length, chunk;
int i, error;
@@ -395,19 +452,10 @@ g_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread
error = g_io_getattr("GEOM::frontstuff", cp, &i, data);
break;
case DIOCSKERNELDUMP:
- if (*(u_int *)data == 0) {
- error = set_dumper(NULL, NULL);
- break;
- }
- kd.offset = 0;
- kd.length = OFF_MAX;
- i = sizeof kd;
- error = g_io_getattr("GEOM::kerneldump", cp, &i, &kd);
- if (error == 0) {
- error = set_dumper(&kd.di, devtoname(dev));
- if (error == 0)
- dev->si_flags |= SI_DUMPDEV;
- }
+ if (*(u_int *)data == 0)
+ error = g_dev_setdumpdev(NULL);
+ else
+ error = g_dev_setdumpdev(dev);
break;
case DIOCGFLUSH:
error = g_io_flush(cp);
OpenPOWER on IntegriCloud