Changeset View
Changeset View
Standalone View
Standalone View
head/sys/geom/geom_dev.c
Show All 30 Lines | |||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include "opt_compat.h" | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/conf.h> | #include <sys/conf.h> | ||||
#include <sys/ctype.h> | #include <sys/ctype.h> | ||||
#include <sys/bio.h> | #include <sys/bio.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
▲ Show 20 Lines • Show All 76 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 thread *td) | 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) | if (dev == NULL || kda == NULL) | ||||
return (set_dumper(NULL, NULL, td)); | return (set_dumper(NULL, NULL, td, 0, NULL, 0, NULL)); | ||||
cp = dev->si_drv2; | cp = dev->si_drv2; | ||||
len = sizeof(kd); | len = sizeof(kd); | ||||
kd.offset = 0; | kd.offset = 0; | ||||
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) | ||||
error = set_dumper(&kd.di, devtoname(dev), td); | return (error); | ||||
error = set_dumper(&kd.di, devtoname(dev), td, 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 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)); | |||||
kda.kda_enable = 1; | |||||
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, curthread); | error = g_dev_setdumpdev(dev, &kda, curthread); | ||||
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 303 Lines • ▼ Show 20 Lines | g_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td) | ||||
case DIOCGFWHEADS: | case DIOCGFWHEADS: | ||||
error = g_io_getattr("GEOM::fwheads", cp, &i, data); | error = g_io_getattr("GEOM::fwheads", cp, &i, data); | ||||
if (error == 0 && *(u_int *)data == 0) | if (error == 0 && *(u_int *)data == 0) | ||||
error = ENOENT; | error = ENOENT; | ||||
break; | break; | ||||
case DIOCGFRONTSTUFF: | case DIOCGFRONTSTUFF: | ||||
error = g_io_getattr("GEOM::frontstuff", cp, &i, data); | error = g_io_getattr("GEOM::frontstuff", cp, &i, data); | ||||
break; | break; | ||||
case DIOCSKERNELDUMP: | #ifdef COMPAT_FREEBSD11 | ||||
if (*(u_int *)data == 0) | case DIOCSKERNELDUMP_FREEBSD11: | ||||
error = g_dev_setdumpdev(NULL, td); | { | ||||
struct diocskerneldump_arg kda; | |||||
bzero(&kda, sizeof(kda)); | |||||
kda.kda_encryption = KERNELDUMP_ENC_NONE; | |||||
kda.kda_enable = (uint8_t)*(u_int *)data; | |||||
if (kda.kda_enable == 0) | |||||
error = g_dev_setdumpdev(NULL, NULL, td); | |||||
else | else | ||||
error = g_dev_setdumpdev(dev, td); | error = g_dev_setdumpdev(dev, &kda, td); | ||||
break; | break; | ||||
} | |||||
#endif | |||||
case DIOCSKERNELDUMP: | |||||
{ | |||||
struct diocskerneldump_arg *kda; | |||||
uint8_t *encryptedkey; | |||||
kda = (struct diocskerneldump_arg *)data; | |||||
if (kda->kda_enable == 0) { | |||||
error = g_dev_setdumpdev(NULL, NULL, td); | |||||
break; | |||||
} | |||||
if (kda->kda_encryption != KERNELDUMP_ENC_NONE) { | |||||
if (kda->kda_encryptedkeysize <= 0 || | |||||
kda->kda_encryptedkeysize > | |||||
KERNELDUMP_ENCKEY_MAX_SIZE) { | |||||
return (EINVAL); | |||||
} | |||||
encryptedkey = malloc(kda->kda_encryptedkeysize, M_TEMP, | |||||
M_WAITOK); | |||||
error = copyin(kda->kda_encryptedkey, encryptedkey, | |||||
kda->kda_encryptedkeysize); | |||||
} else { | |||||
encryptedkey = NULL; | |||||
} | |||||
if (error == 0) { | |||||
kda->kda_encryptedkey = encryptedkey; | |||||
error = g_dev_setdumpdev(dev, kda, td); | |||||
} | |||||
if (encryptedkey != NULL) { | |||||
explicit_bzero(encryptedkey, kda->kda_encryptedkeysize); | |||||
free(encryptedkey, M_TEMP); | |||||
} | |||||
explicit_bzero(kda, sizeof(*kda)); | |||||
break; | |||||
} | |||||
case DIOCGFLUSH: | case DIOCGFLUSH: | ||||
error = g_io_flush(cp); | error = g_io_flush(cp); | ||||
break; | break; | ||||
case DIOCGDELETE: | case DIOCGDELETE: | ||||
offset = ((off_t *)data)[0]; | offset = ((off_t *)data)[0]; | ||||
length = ((off_t *)data)[1]; | length = ((off_t *)data)[1]; | ||||
if ((offset % cp->provider->sectorsize) != 0 || | if ((offset % cp->provider->sectorsize) != 0 || | ||||
(length % cp->provider->sectorsize) != 0 || length <= 0) { | (length % cp->provider->sectorsize) != 0 || length <= 0) { | ||||
▲ Show 20 Lines • Show All 241 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)set_dumper(NULL, NULL, curthread); | (void)set_dumper(NULL, NULL, curthread, 0, NULL, 0, NULL); | ||||
/* Destroy the struct cdev *so we get no more requests */ | /* Destroy the struct cdev *so we get no more requests */ | ||||
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); |