Changeset View
Standalone View
sys/geom/geom_dev.c
Show First 20 Lines • Show All 129 Lines • ▼ Show 20 Lines | |||||
g_dev_fini(struct g_class *mp) | g_dev_fini(struct g_class *mp) | ||||
{ | { | ||||
freeenv(dumpdev); | freeenv(dumpdev); | ||||
dumpdev = NULL; | dumpdev = NULL; | ||||
} | } | ||||
static int | static int | ||||
g_dev_setdumpdev(struct cdev *dev, struct diocskerneldump_arg *kda, | g_dev_setdumpdev(struct cdev *dev, struct diocskerneldump_arg *kda) | ||||
struct thread *td) | |||||
{ | { | ||||
struct g_kerneldump kd; | struct g_kerneldump kd; | ||||
struct g_consumer *cp; | struct g_consumer *cp; | ||||
int error, len; | int error, len; | ||||
if (dev == NULL || kda == NULL) | MPASS(dev != NULL && kda != NULL); | ||||
return (clear_dumper(td)); | MPASS(kda->kda_index != KDA_REMOVE); | ||||
cp = dev->si_drv2; | cp = dev->si_drv2; | ||||
len = sizeof(kd); | len = sizeof(kd); | ||||
memset(&kd, 0, len); | memset(&kd, 0, len); | ||||
kd.offset = 0; | kd.offset = 0; | ||||
markj: This snippet is duplicated across `insert_dumper()` callers. Can the logic just move into… | |||||
Done Inline ActionsIt could. I mostly (out of habit) wanted to normalize the index to 0-based as soon as possible and pass around a 0-based index, even if there is a little duplication. Mixing up 0- and 1-based indices happens and the easiest way to avoid that is to normalize as soon as possible. In this case, I think it would be ok to push the 1-based index down into insert_dumper. (The motivation for 1-based indexing at all is to retain (some) ioctl ABI compatibility with 12.0, in that kda_enable/kda_index of 0 still means "disable," and kda_enable/kda_index of 1 still means "configure this dump device on.") cem: It could. I mostly (out of habit) wanted to normalize the index to 0-based as soon as possible… | |||||
kd.length = OFF_MAX; | kd.length = OFF_MAX; | ||||
error = g_io_getattr("GEOM::kerneldump", cp, &len, &kd); | error = g_io_getattr("GEOM::kerneldump", cp, &len, &kd); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
error = set_dumper(&kd.di, devtoname(dev), td, kda->kda_compression, | error = dumper_insert(&kd.di, devtoname(dev), kda); | ||||
kda->kda_encryption, kda->kda_key, kda->kda_encryptedkeysize, | |||||
kda->kda_encryptedkey); | |||||
if (error == 0) | if (error == 0) | ||||
dev->si_flags |= SI_DUMPDEV; | dev->si_flags |= SI_DUMPDEV; | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
init_dumpdev(struct cdev *dev) | init_dumpdev(struct cdev *dev) | ||||
{ | { | ||||
struct diocskerneldump_arg kda; | struct diocskerneldump_arg kda; | ||||
struct g_consumer *cp; | struct g_consumer *cp; | ||||
const char *devprefix = "/dev/", *devname; | const char *devprefix = "/dev/", *devname; | ||||
int error; | int error; | ||||
size_t len; | size_t len; | ||||
bzero(&kda, sizeof(kda)); | bzero(&kda, sizeof(kda)); | ||||
kda.kda_enable = 1; | kda.kda_index = KDA_APPEND; | ||||
if (dumpdev == NULL) | if (dumpdev == NULL) | ||||
return (0); | return (0); | ||||
len = strlen(devprefix); | len = strlen(devprefix); | ||||
devname = devtoname(dev); | devname = devtoname(dev); | ||||
if (strcmp(devname, dumpdev) != 0 && | if (strcmp(devname, dumpdev) != 0 && | ||||
(strncmp(dumpdev, devprefix, len) != 0 || | (strncmp(dumpdev, devprefix, len) != 0 || | ||||
strcmp(devname, dumpdev + len) != 0)) | strcmp(devname, dumpdev + len) != 0)) | ||||
return (0); | return (0); | ||||
cp = (struct g_consumer *)dev->si_drv2; | cp = (struct g_consumer *)dev->si_drv2; | ||||
error = g_access(cp, 1, 0, 0); | error = g_access(cp, 1, 0, 0); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
error = g_dev_setdumpdev(dev, &kda, curthread); | error = g_dev_setdumpdev(dev, &kda); | ||||
if (error == 0) { | if (error == 0) { | ||||
freeenv(dumpdev); | freeenv(dumpdev); | ||||
dumpdev = NULL; | dumpdev = NULL; | ||||
} | } | ||||
(void)g_access(cp, -1, 0, 0); | (void)g_access(cp, -1, 0, 0); | ||||
return (error); | return (error); | ||||
▲ Show 20 Lines • Show All 302 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static int | static int | ||||
g_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td) | g_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td) | ||||
{ | { | ||||
struct g_consumer *cp; | struct g_consumer *cp; | ||||
struct g_provider *pp; | struct g_provider *pp; | ||||
off_t offset, length, chunk, odd; | off_t offset, length, chunk, odd; | ||||
int i, error; | int i, error; | ||||
#ifdef COMPAT_FREEBSD12 | |||||
struct diocskerneldump_arg kda_copy; | |||||
Not Done Inline ActionsMight as well move this definition into the case statement below? markj: Might as well move this definition into the case statement below? | |||||
Done Inline ActionsCan't — it must be in-scope after leaving that case statement's embedded block due to the fallthrough. cem: Can't — it must be in-scope after leaving that case statement's embedded block due to the… | |||||
Not Done Inline ActionsAh, I thought it was permitted to refer to variables outside of their lexical scope so long as you're still in the same function. markj: Ah, I thought it was permitted to refer to variables outside of their lexical scope so long as… | |||||
Done Inline ActionsYou might be right, but I wasn't confident of that and don't want to dig up the C standard to figure it out. :-) cem: You might be right, but I wasn't confident of that and don't want to dig up the C standard to… | |||||
#endif | |||||
cp = dev->si_drv2; | cp = dev->si_drv2; | ||||
pp = cp->provider; | pp = cp->provider; | ||||
error = 0; | error = 0; | ||||
KASSERT(cp->acr || cp->acw, | KASSERT(cp->acr || cp->acw, | ||||
("Consumer with zero access count in g_dev_ioctl")); | ("Consumer with zero access count in g_dev_ioctl")); | ||||
Show All 22 Lines | #endif | ||||
case DIOCGFRONTSTUFF: | case DIOCGFRONTSTUFF: | ||||
error = g_io_getattr("GEOM::frontstuff", cp, &i, data); | error = g_io_getattr("GEOM::frontstuff", cp, &i, data); | ||||
break; | break; | ||||
#ifdef COMPAT_FREEBSD11 | #ifdef COMPAT_FREEBSD11 | ||||
case DIOCSKERNELDUMP_FREEBSD11: | case DIOCSKERNELDUMP_FREEBSD11: | ||||
{ | { | ||||
struct diocskerneldump_arg kda; | struct diocskerneldump_arg kda; | ||||
gone_in(13, "FreeBSD 11.x ABI compat"); | |||||
bzero(&kda, sizeof(kda)); | bzero(&kda, sizeof(kda)); | ||||
kda.kda_encryption = KERNELDUMP_ENC_NONE; | kda.kda_encryption = KERNELDUMP_ENC_NONE; | ||||
kda.kda_enable = (uint8_t)*(u_int *)data; | kda.kda_index = (*(u_int *)data ? 0 : KDA_REMOVE_ALL); | ||||
if (kda.kda_enable == 0) | if (kda.kda_index == KDA_REMOVE_ALL) | ||||
error = g_dev_setdumpdev(NULL, NULL, td); | error = dumper_remove(devtoname(dev), &kda); | ||||
else | else | ||||
error = g_dev_setdumpdev(dev, &kda, td); | error = g_dev_setdumpdev(dev, &kda); | ||||
break; | break; | ||||
} | } | ||||
#endif | #endif | ||||
#ifdef COMPAT_FREEBSD12 | |||||
case DIOCSKERNELDUMP_FREEBSD12: | |||||
{ | |||||
struct diocskerneldump_arg_freebsd12 *kda12; | |||||
gone_in(14, "FreeBSD 12.x ABI compat"); | |||||
kda12 = (void *)data; | |||||
memcpy(&kda_copy, kda12, sizeof(kda_copy)); | |||||
kda_copy.kda_index = (kda12->kda12_enable ? | |||||
0 : KDA_REMOVE_ALL); | |||||
explicit_bzero(kda12, sizeof(*kda12)); | |||||
/* Kludge to pass kda_copy to kda in fallthrough. */ | |||||
data = (void *)&kda_copy; | |||||
} | |||||
/* FALLTHROUGH */ | |||||
#endif | |||||
case DIOCSKERNELDUMP: | case DIOCSKERNELDUMP: | ||||
{ | { | ||||
struct diocskerneldump_arg *kda; | struct diocskerneldump_arg *kda; | ||||
uint8_t *encryptedkey; | uint8_t *encryptedkey; | ||||
kda = (struct diocskerneldump_arg *)data; | kda = (struct diocskerneldump_arg *)data; | ||||
if (kda->kda_enable == 0) { | if (kda->kda_index == KDA_REMOVE_ALL || | ||||
error = g_dev_setdumpdev(NULL, NULL, td); | kda->kda_index == KDA_REMOVE_DEV || | ||||
kda->kda_index == KDA_REMOVE) { | |||||
error = dumper_remove(devtoname(dev), kda); | |||||
explicit_bzero(kda, sizeof(*kda)); | |||||
break; | break; | ||||
} | } | ||||
if (kda->kda_encryption != KERNELDUMP_ENC_NONE) { | if (kda->kda_encryption != KERNELDUMP_ENC_NONE) { | ||||
if (kda->kda_encryptedkeysize <= 0 || | if (kda->kda_encryptedkeysize == 0 || | ||||
kda->kda_encryptedkeysize > | kda->kda_encryptedkeysize > | ||||
KERNELDUMP_ENCKEY_MAX_SIZE) { | KERNELDUMP_ENCKEY_MAX_SIZE) { | ||||
explicit_bzero(kda, sizeof(*kda)); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
encryptedkey = malloc(kda->kda_encryptedkeysize, M_TEMP, | encryptedkey = malloc(kda->kda_encryptedkeysize, M_TEMP, | ||||
M_WAITOK); | M_WAITOK); | ||||
error = copyin(kda->kda_encryptedkey, encryptedkey, | error = copyin(kda->kda_encryptedkey, encryptedkey, | ||||
kda->kda_encryptedkeysize); | kda->kda_encryptedkeysize); | ||||
} else { | } else { | ||||
encryptedkey = NULL; | encryptedkey = NULL; | ||||
} | } | ||||
if (error == 0) { | if (error == 0) { | ||||
kda->kda_encryptedkey = encryptedkey; | kda->kda_encryptedkey = encryptedkey; | ||||
error = g_dev_setdumpdev(dev, kda, td); | error = g_dev_setdumpdev(dev, kda); | ||||
} | } | ||||
if (encryptedkey != NULL) { | if (encryptedkey != NULL) { | ||||
explicit_bzero(encryptedkey, kda->kda_encryptedkeysize); | explicit_bzero(encryptedkey, kda->kda_encryptedkeysize); | ||||
free(encryptedkey, M_TEMP); | free(encryptedkey, M_TEMP); | ||||
} | } | ||||
explicit_bzero(kda, sizeof(*kda)); | explicit_bzero(kda, sizeof(*kda)); | ||||
break; | break; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 260 Lines • ▼ Show 20 Lines | g_dev_orphan(struct g_consumer *cp) | ||||
g_topology_assert(); | g_topology_assert(); | ||||
sc = cp->private; | sc = cp->private; | ||||
dev = sc->sc_dev; | dev = sc->sc_dev; | ||||
g_trace(G_T_TOPOLOGY, "g_dev_orphan(%p(%s))", cp, cp->geom->name); | g_trace(G_T_TOPOLOGY, "g_dev_orphan(%p(%s))", cp, cp->geom->name); | ||||
/* Reset any dump-area set on this device */ | /* Reset any dump-area set on this device */ | ||||
if (dev->si_flags & SI_DUMPDEV) | if (dev->si_flags & SI_DUMPDEV) | ||||
(void)clear_dumper(curthread); | (void)dumper_remove(devtoname(dev), NULL); | ||||
/* Destroy the struct cdev *so we get no more requests */ | /* Destroy the struct cdev *so we get no more requests */ | ||||
delist_dev(dev); | delist_dev(dev); | ||||
destroy_dev_sched_cb(dev, g_dev_callback, cp); | destroy_dev_sched_cb(dev, g_dev_callback, cp); | ||||
} | } | ||||
DECLARE_GEOM_CLASS(g_dev_class, g_dev); | DECLARE_GEOM_CLASS(g_dev_class, g_dev); |
This snippet is duplicated across insert_dumper() callers. Can the logic just move into insert_dumper()?