1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-17 10:26:15 +00:00

Add an ability to set dumpdev via loader(8) tunable.

MFC after:	3 weeks
This commit is contained in:
Andrey V. Elsukov 2014-10-08 12:18:16 +00:00
parent 8e72737119
commit 0478dc0c16
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=272746

View File

@ -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);