Simplify the ioctl handling in GEOM.
This replaces the current ioctl processing with a direct call path from geom_dev() where the ioctl arrives (from SPECFS) to any directly connected GEOM class. The inverse of the above is no longer supported. This is the situation were you have one or more intervening GEOM classes, for instance a BSDlabel on top of a MBR or PC98. If you want to issue MBR or PC98 specific ioctls, you will need to issue them on a MBR or PC98 providers. This paves the way for inviting CD's, FD's and other special cases inside GEOM.
This commit is contained in:
parent
8778f63db2
commit
497c334767
@ -64,8 +64,8 @@ typedef int g_ctl_destroy_geom_t (struct gctl_req *, struct g_class *cp, struct
|
||||
typedef int g_ctl_config_geom_t (struct gctl_req *, struct g_geom *gp, const char *verb);
|
||||
typedef void g_init_t (struct g_class *mp);
|
||||
typedef void g_fini_t (struct g_class *mp);
|
||||
typedef struct g_geom * g_taste_t (struct g_class *, struct g_provider *,
|
||||
int flags);
|
||||
typedef struct g_geom * g_taste_t (struct g_class *, struct g_provider *, int flags);
|
||||
typedef int g_ioctl_t(struct g_provider *pp, u_long cmd, void *data, struct thread *td);
|
||||
#define G_TF_NORMAL 0
|
||||
#define G_TF_INSIST 1
|
||||
#define G_TF_TRANSPARENT 2
|
||||
@ -116,6 +116,7 @@ struct g_geom {
|
||||
g_dumpconf_t *dumpconf;
|
||||
g_access_t *access;
|
||||
g_orphan_t *orphan;
|
||||
g_ioctl_t *ioctl;
|
||||
void *softc;
|
||||
unsigned flags;
|
||||
#define G_GEOM_WITHER 1
|
||||
@ -231,20 +232,6 @@ int g_write_data(struct g_consumer *cp, off_t offset, void *ptr, off_t length);
|
||||
|
||||
/* geom_kern.c / geom_kernsim.c */
|
||||
|
||||
#ifndef _SYS_CONF_H_
|
||||
typedef int d_ioctl_t(dev_t dev, u_long cmd, caddr_t data,
|
||||
int fflag, struct thread *td);
|
||||
#endif
|
||||
|
||||
struct g_ioctl {
|
||||
u_long cmd;
|
||||
void *data;
|
||||
int fflag;
|
||||
struct thread *td;
|
||||
d_ioctl_t *func;
|
||||
void *dev;
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
struct g_kerneldump {
|
||||
|
@ -267,98 +267,6 @@ g_bsd_writelabel(struct g_geom *gp, u_char *bootcode)
|
||||
return(error);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Implement certain ioctls to modify disklabels with. This function
|
||||
* is called by the event handler thread with topology locked as result
|
||||
* of the g_post_event() in g_bsd_start(). It is not necessary to keep
|
||||
* topology locked all the time but make sure to return with topology
|
||||
* locked as well.
|
||||
*/
|
||||
|
||||
static void
|
||||
g_bsd_ioctl(void *arg, int flag)
|
||||
{
|
||||
struct bio *bp;
|
||||
struct g_geom *gp;
|
||||
struct g_ioctl *gio;
|
||||
u_char *label;
|
||||
int error;
|
||||
|
||||
g_topology_assert();
|
||||
bp = arg;
|
||||
if (flag == EV_CANCEL) {
|
||||
g_io_deliver(bp, ENXIO);
|
||||
return;
|
||||
}
|
||||
|
||||
gp = bp->bio_to->geom;
|
||||
gio = (struct g_ioctl *)bp->bio_data;
|
||||
|
||||
label = g_malloc(LABELSIZE, M_WAITOK);
|
||||
|
||||
/* The disklabel to set is the ioctl argument. */
|
||||
bsd_disklabel_le_enc(label, gio->data);
|
||||
|
||||
/* Validate and modify our slice instance to match. */
|
||||
error = g_bsd_modify(gp, label); /* Picks up topology lock on success. */
|
||||
g_free(label);
|
||||
if (error || gio->cmd == DIOCSDINFO) {
|
||||
g_io_deliver(bp, error);
|
||||
return;
|
||||
}
|
||||
|
||||
KASSERT(gio->cmd == DIOCWDINFO, ("Unknown ioctl in g_bsd_ioctl"));
|
||||
g_io_deliver(bp, g_bsd_writelabel(gp, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
* Rewrite the bootblock, which is BBSIZE bytes from the start of the disk.
|
||||
* We punch down the disklabel where we expect it to be before writing.
|
||||
*/
|
||||
static int
|
||||
g_bsd_diocbsdbb(dev_t dev, u_long cmd __unused, caddr_t data, int fflag __unused, struct thread *td __unused)
|
||||
{
|
||||
struct g_geom *gp;
|
||||
struct g_slicer *gsp;
|
||||
struct g_bsd_softc *ms;
|
||||
struct g_consumer *cp;
|
||||
u_char *buf;
|
||||
void *p;
|
||||
int error, i;
|
||||
uint64_t sum;
|
||||
|
||||
/* Get hold of the interesting bits from the bio. */
|
||||
gp = (void *)dev;
|
||||
gsp = gp->softc;
|
||||
ms = gsp->softc;
|
||||
|
||||
/* The disklabel to set is the ioctl argument. */
|
||||
buf = g_malloc(BBSIZE, M_WAITOK);
|
||||
p = *(void **)data;
|
||||
error = copyin(p, buf, BBSIZE);
|
||||
if (!error) {
|
||||
DROP_GIANT();
|
||||
g_topology_lock();
|
||||
/* Validate and modify our slice instance to match. */
|
||||
error = g_bsd_modify(gp, buf + ms->labeloffset);
|
||||
if (!error) {
|
||||
cp = LIST_FIRST(&gp->consumer);
|
||||
if (ms->labeloffset == ALPHA_LABEL_OFFSET) {
|
||||
sum = 0;
|
||||
for (i = 0; i < 63; i++)
|
||||
sum += le64dec(buf + i * 8);
|
||||
le64enc(buf + 504, sum);
|
||||
}
|
||||
error = g_write_data(cp, 0, buf, BBSIZE);
|
||||
}
|
||||
g_topology_unlock();
|
||||
PICKUP_GIANT();
|
||||
}
|
||||
g_free(buf);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the user tries to overwrite our disklabel through an open partition
|
||||
* or via a magicwrite config call, we end up here and try to prevent
|
||||
@ -406,6 +314,79 @@ g_bsd_hotwrite(void *arg, int flag)
|
||||
* * Don't grab the topology lock.
|
||||
* * Don't call biowait, g_getattr(), g_setattr() or g_read_data()
|
||||
*/
|
||||
static int
|
||||
g_bsd_ioctl(struct g_provider *pp, u_long cmd, void * data, struct thread *td)
|
||||
{
|
||||
struct g_geom *gp;
|
||||
struct g_bsd_softc *ms;
|
||||
struct g_slicer *gsp;
|
||||
u_char *label;
|
||||
int error;
|
||||
|
||||
gp = pp->geom;
|
||||
gsp = gp->softc;
|
||||
ms = gsp->softc;
|
||||
|
||||
switch(cmd) {
|
||||
case DIOCGDINFO:
|
||||
/* Return a copy of the disklabel to userland. */
|
||||
bsd_disklabel_le_dec(ms->label, data, MAXPARTITIONS);
|
||||
return(0);
|
||||
case DIOCBSDBB: {
|
||||
struct g_consumer *cp;
|
||||
u_char *buf;
|
||||
void *p;
|
||||
int error, i;
|
||||
uint64_t sum;
|
||||
|
||||
/* The disklabel to set is the ioctl argument. */
|
||||
buf = g_malloc(BBSIZE, M_WAITOK);
|
||||
p = *(void **)data;
|
||||
error = copyin(p, buf, BBSIZE);
|
||||
if (!error) {
|
||||
/* XXX: Rude, but supposedly safe */
|
||||
DROP_GIANT();
|
||||
g_topology_lock();
|
||||
/* Validate and modify our slice instance to match. */
|
||||
error = g_bsd_modify(gp, buf + ms->labeloffset);
|
||||
if (!error) {
|
||||
cp = LIST_FIRST(&gp->consumer);
|
||||
if (ms->labeloffset == ALPHA_LABEL_OFFSET) {
|
||||
sum = 0;
|
||||
for (i = 0; i < 63; i++)
|
||||
sum += le64dec(buf + i * 8);
|
||||
le64enc(buf + 504, sum);
|
||||
}
|
||||
error = g_write_data(cp, 0, buf, BBSIZE);
|
||||
}
|
||||
g_topology_unlock();
|
||||
PICKUP_GIANT();
|
||||
}
|
||||
g_free(buf);
|
||||
return (error);
|
||||
}
|
||||
case DIOCSDINFO:
|
||||
case DIOCWDINFO: {
|
||||
label = g_malloc(LABELSIZE, M_WAITOK);
|
||||
|
||||
/* The disklabel to set is the ioctl argument. */
|
||||
bsd_disklabel_le_enc(label, data);
|
||||
|
||||
DROP_GIANT();
|
||||
g_topology_lock();
|
||||
/* Validate and modify our slice instance to match. */
|
||||
error = g_bsd_modify(gp, label);
|
||||
if (error == 0 && cmd == DIOCWDINFO)
|
||||
error = g_bsd_writelabel(gp, NULL);
|
||||
g_topology_unlock();
|
||||
PICKUP_GIANT();
|
||||
g_free(label);
|
||||
return(error);
|
||||
}
|
||||
default:
|
||||
return (ENOIOCTL);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
g_bsd_start(struct bio *bp)
|
||||
@ -413,61 +394,16 @@ g_bsd_start(struct bio *bp)
|
||||
struct g_geom *gp;
|
||||
struct g_bsd_softc *ms;
|
||||
struct g_slicer *gsp;
|
||||
struct g_ioctl *gio;
|
||||
int error;
|
||||
|
||||
gp = bp->bio_to->geom;
|
||||
gsp = gp->softc;
|
||||
ms = gsp->softc;
|
||||
switch(bp->bio_cmd) {
|
||||
case BIO_GETATTR:
|
||||
if (bp->bio_cmd == BIO_GETATTR) {
|
||||
if (g_handleattr(bp, "BSD::labelsum", ms->labelsum,
|
||||
sizeof(ms->labelsum)))
|
||||
return (1);
|
||||
break;
|
||||
default:
|
||||
KASSERT(0 == 1, ("Unknown bio_cmd in g_bsd_start (%d)",
|
||||
bp->bio_cmd));
|
||||
}
|
||||
|
||||
/* We only handle ioctl(2) requests of the right format. */
|
||||
if (strcmp(bp->bio_attribute, "GEOM::ioctl"))
|
||||
return (0);
|
||||
else if (bp->bio_length != sizeof(*gio))
|
||||
return (0);
|
||||
|
||||
/* Get hold of the ioctl parameters. */
|
||||
gio = (struct g_ioctl *)bp->bio_data;
|
||||
|
||||
switch (gio->cmd) {
|
||||
case DIOCGDINFO:
|
||||
/* Return a copy of the disklabel to userland. */
|
||||
bsd_disklabel_le_dec(ms->label, gio->data, MAXPARTITIONS);
|
||||
g_io_deliver(bp, 0);
|
||||
return (1);
|
||||
case DIOCBSDBB:
|
||||
gio->func = g_bsd_diocbsdbb;
|
||||
gio->dev = (void *)gp;
|
||||
g_io_deliver(bp, EDIRIOCTL);
|
||||
return (1);
|
||||
case DIOCSDINFO:
|
||||
case DIOCWDINFO:
|
||||
/*
|
||||
* These we cannot do without the topology lock and some
|
||||
* some I/O requests. Ask the event-handler to schedule
|
||||
* us in a less restricted environment.
|
||||
*/
|
||||
error = g_post_event(g_bsd_ioctl, bp, M_NOWAIT, gp, NULL);
|
||||
if (error)
|
||||
g_io_deliver(bp, error);
|
||||
/*
|
||||
* We must return non-zero to indicate that we will deal
|
||||
* with this bio, even though we have not done so yet.
|
||||
*/
|
||||
return (1);
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -559,6 +495,7 @@ g_bsd_taste(struct g_class *mp, struct g_provider *pp, int flags)
|
||||
* routine which the "slice" code should call at the right time
|
||||
*/
|
||||
gp->dumpconf = g_bsd_dumpconf;
|
||||
gp->ioctl = g_bsd_ioctl;
|
||||
|
||||
/* Get the geom_slicer softc from the geom. */
|
||||
gsp = gp->softc;
|
||||
|
@ -279,17 +279,14 @@ g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
|
||||
struct g_kerneldump kd;
|
||||
int i, error;
|
||||
u_int u;
|
||||
struct g_ioctl *gio;
|
||||
|
||||
gp = dev->si_drv1;
|
||||
cp = dev->si_drv2;
|
||||
gio = NULL;
|
||||
|
||||
error = 0;
|
||||
KASSERT(cp->acr || cp->acw,
|
||||
("Consumer with zero access count in g_dev_ioctl"));
|
||||
|
||||
gio = NULL;
|
||||
i = IOCPARM_LEN(cmd);
|
||||
switch (cmd) {
|
||||
case DIOCGSECTORSIZE:
|
||||
@ -331,46 +328,14 @@ g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
|
||||
break;
|
||||
|
||||
default:
|
||||
gio = g_malloc(sizeof *gio, M_WAITOK | M_ZERO);
|
||||
gio->cmd = cmd;
|
||||
gio->data = data;
|
||||
gio->fflag = fflag;
|
||||
gio->td = td;
|
||||
i = sizeof *gio;
|
||||
/*
|
||||
* We always issue ioctls as getattr since the direction of data
|
||||
* movement in ioctl is no indication of the ioctl being a "set"
|
||||
* or "get" type ioctl or if such simplistic terms even apply
|
||||
*/
|
||||
error = g_io_getattr("GEOM::ioctl", cp, &i, gio);
|
||||
break;
|
||||
if (cp->provider->geom->ioctl != NULL) {
|
||||
error = cp->provider->geom->ioctl(cp->provider, cmd, data, td);
|
||||
if (error != ENOIOCTL)
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
if (error == EDIRIOCTL) {
|
||||
KASSERT(gio != NULL, ("NULL gio but EDIRIOCTL"));
|
||||
KASSERT(gio->func != NULL, ("NULL function but EDIRIOCTL"));
|
||||
error = (gio->func)(gio->dev, cmd, data, fflag, td);
|
||||
}
|
||||
g_waitidle();
|
||||
if (gio != NULL && (error == EOPNOTSUPP || error == ENOIOCTL)) {
|
||||
if (g_debugflags & G_T_TOPOLOGY) {
|
||||
i = IOCGROUP(cmd);
|
||||
printf("IOCTL(0x%lx) \"%s\"", cmd, gp->name);
|
||||
if (i > ' ' && i <= '~')
|
||||
printf(" '%c'", (int)IOCGROUP(cmd));
|
||||
else
|
||||
printf(" 0x%lx", IOCGROUP(cmd));
|
||||
printf("/%ld ", cmd & 0xff);
|
||||
if (cmd & IOC_IN)
|
||||
printf("I");
|
||||
if (cmd & IOC_OUT)
|
||||
printf("O");
|
||||
printf("(%ld) = ENOIOCTL\n", IOCPARM_LEN(cmd));
|
||||
}
|
||||
error = ENOTTY;
|
||||
}
|
||||
if (gio != NULL)
|
||||
g_free(gio);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -194,12 +194,29 @@ g_disk_done(struct bio *bp)
|
||||
mtx_unlock(&g_disk_done_mtx);
|
||||
}
|
||||
|
||||
static int
|
||||
g_disk_ioctl(struct g_provider *pp, u_long cmd, void * data, struct thread *td)
|
||||
{
|
||||
struct g_geom *gp;
|
||||
struct disk *dp;
|
||||
int error;
|
||||
|
||||
gp = pp->geom;
|
||||
dp = gp->softc;
|
||||
|
||||
if (dp->d_ioctl == NULL)
|
||||
return (ENOIOCTL);
|
||||
g_disk_lock_giant(dp);
|
||||
error = dp->d_ioctl(dp, cmd, data, 0, td);
|
||||
g_disk_unlock_giant(dp);
|
||||
return(error);
|
||||
}
|
||||
|
||||
static void
|
||||
g_disk_start(struct bio *bp)
|
||||
{
|
||||
struct bio *bp2, *bp3;
|
||||
struct disk *dp;
|
||||
struct g_ioctl *gio;
|
||||
int error;
|
||||
off_t off;
|
||||
|
||||
@ -264,15 +281,7 @@ g_disk_start(struct bio *bp)
|
||||
break;
|
||||
else if (!strcmp(bp->bio_attribute, "GEOM::kerneldump"))
|
||||
g_disk_kerneldump(bp, dp);
|
||||
else if ((g_debugflags & G_F_DISKIOCTL) &&
|
||||
(dp->d_ioctl != NULL) &&
|
||||
!strcmp(bp->bio_attribute, "GEOM::ioctl") &&
|
||||
bp->bio_length == sizeof *gio) {
|
||||
gio = (struct g_ioctl *)bp->bio_data;
|
||||
gio->dev = dp;
|
||||
gio->func = (d_ioctl_t *)(dp->d_ioctl);
|
||||
error = EDIRIOCTL;
|
||||
} else
|
||||
else
|
||||
error = ENOIOCTL;
|
||||
break;
|
||||
default:
|
||||
@ -317,6 +326,7 @@ g_disk_create(void *arg, int flag)
|
||||
gp = g_new_geomf(&g_disk_class, "%s%d", dp->d_name, dp->d_unit);
|
||||
gp->start = g_disk_start;
|
||||
gp->access = g_disk_access;
|
||||
gp->ioctl = g_disk_ioctl;
|
||||
gp->softc = dp;
|
||||
gp->dumpconf = g_disk_dumpconf;
|
||||
pp = g_new_providerf(gp, "%s", gp->name);
|
||||
|
@ -152,42 +152,36 @@ g_mbr_modify(struct g_geom *gp, struct g_mbr_softc *ms, u_char *sec0)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
g_mbr_ioctl(void *arg, int flag)
|
||||
static int
|
||||
g_mbr_ioctl(struct g_provider *pp, u_long cmd, void *data, struct thread *td)
|
||||
{
|
||||
struct bio *bp;
|
||||
struct g_geom *gp;
|
||||
struct g_slicer *gsp;
|
||||
struct g_mbr_softc *ms;
|
||||
struct g_ioctl *gio;
|
||||
struct g_slicer *gsp;
|
||||
struct g_consumer *cp;
|
||||
u_char *sec0;
|
||||
int error;
|
||||
|
||||
bp = arg;
|
||||
if (flag == EV_CANCEL) {
|
||||
g_io_deliver(bp, ENXIO);
|
||||
return;
|
||||
}
|
||||
gp = bp->bio_to->geom;
|
||||
gp = pp->geom;
|
||||
gsp = gp->softc;
|
||||
ms = gsp->softc;
|
||||
gio = (struct g_ioctl *)bp->bio_data;
|
||||
|
||||
/* The disklabel to set is the ioctl argument. */
|
||||
sec0 = gio->data;
|
||||
|
||||
error = g_mbr_modify(gp, ms, sec0);
|
||||
if (error) {
|
||||
g_io_deliver(bp, error);
|
||||
return;
|
||||
switch(cmd) {
|
||||
case DIOCSMBR: {
|
||||
DROP_GIANT();
|
||||
g_topology_lock();
|
||||
/* Validate and modify our slicer instance to match. */
|
||||
error = g_mbr_modify(gp, ms, data);
|
||||
cp = LIST_FIRST(&gp->consumer);
|
||||
error = g_write_data(cp, 0, data, 512);
|
||||
g_topology_unlock();
|
||||
PICKUP_GIANT();
|
||||
return(error);
|
||||
}
|
||||
default:
|
||||
return (ENOIOCTL);
|
||||
}
|
||||
cp = LIST_FIRST(&gp->consumer);
|
||||
error = g_write_data(cp, 0, sec0, 512);
|
||||
g_io_deliver(bp, error);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
g_mbr_start(struct bio *bp)
|
||||
{
|
||||
@ -195,8 +189,7 @@ g_mbr_start(struct bio *bp)
|
||||
struct g_geom *gp;
|
||||
struct g_mbr_softc *mp;
|
||||
struct g_slicer *gsp;
|
||||
struct g_ioctl *gio;
|
||||
int idx, error;
|
||||
int idx;
|
||||
|
||||
pp = bp->bio_to;
|
||||
idx = pp->index;
|
||||
@ -211,33 +204,7 @@ g_mbr_start(struct bio *bp)
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* We only handle ioctl(2) requests of the right format. */
|
||||
if (strcmp(bp->bio_attribute, "GEOM::ioctl"))
|
||||
return (0);
|
||||
else if (bp->bio_length != sizeof(*gio))
|
||||
return (0);
|
||||
|
||||
/* Get hold of the ioctl parameters. */
|
||||
gio = (struct g_ioctl *)bp->bio_data;
|
||||
|
||||
switch (gio->cmd) {
|
||||
case DIOCSMBR:
|
||||
/*
|
||||
* These we cannot do without the topology lock and some
|
||||
* some I/O requests. Ask the event-handler to schedule
|
||||
* us in a less restricted environment.
|
||||
*/
|
||||
error = g_post_event(g_mbr_ioctl, bp, M_NOWAIT, gp, NULL);
|
||||
if (error)
|
||||
g_io_deliver(bp, error);
|
||||
/*
|
||||
* We must return non-zero to indicate that we will deal
|
||||
* with this bio, even though we have not done so yet.
|
||||
*/
|
||||
return (1);
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -275,6 +242,7 @@ g_mbr_taste(struct g_class *mp, struct g_provider *pp, int insist)
|
||||
return (NULL);
|
||||
g_topology_unlock();
|
||||
gp->dumpconf = g_mbr_dumpconf;
|
||||
gp->ioctl = g_mbr_ioctl;
|
||||
do {
|
||||
if (gp->rank != 2 && insist == 0)
|
||||
break;
|
||||
|
@ -134,39 +134,34 @@ g_pc98_modify(struct g_geom *gp, struct g_pc98_softc *ms, u_char *sec)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
g_pc98_ioctl(void *arg, int flag)
|
||||
static int
|
||||
g_pc98_ioctl(struct g_provider *pp, u_long cmd, void *data, struct thread *td)
|
||||
{
|
||||
struct bio *bp;
|
||||
struct g_geom *gp;
|
||||
struct g_slicer *gsp;
|
||||
struct g_pc98_softc *ms;
|
||||
struct g_ioctl *gio;
|
||||
struct g_slicer *gsp;
|
||||
struct g_consumer *cp;
|
||||
u_char *sec;
|
||||
int error;
|
||||
|
||||
bp = arg;
|
||||
if (flag == EV_CANCEL) {
|
||||
g_io_deliver(bp, ENXIO);
|
||||
return;
|
||||
}
|
||||
gp = bp->bio_to->geom;
|
||||
gp = pp->geom;
|
||||
gsp = gp->softc;
|
||||
ms = gsp->softc;
|
||||
gio = (struct g_ioctl *)bp->bio_data;
|
||||
|
||||
/* The disklabel to set is the ioctl argument. */
|
||||
sec = gio->data;
|
||||
|
||||
error = g_pc98_modify(gp, ms, sec);
|
||||
if (error) {
|
||||
g_io_deliver(bp, error);
|
||||
return;
|
||||
switch(cmd) {
|
||||
case DIOCSPC98: {
|
||||
DROP_GIANT();
|
||||
g_topology_lock();
|
||||
/* Validate and modify our slicer instance to match. */
|
||||
error = g_pc98_modify(gp, ms, data);
|
||||
cp = LIST_FIRST(&gp->consumer);
|
||||
error = g_write_data(cp, 0, data, 8192);
|
||||
g_topology_unlock();
|
||||
PICKUP_GIANT();
|
||||
return(error);
|
||||
}
|
||||
default:
|
||||
return (ENOIOCTL);
|
||||
}
|
||||
cp = LIST_FIRST(&gp->consumer);
|
||||
error = g_write_data(cp, 0, sec, 8192);
|
||||
g_io_deliver(bp, error);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -176,8 +171,7 @@ g_pc98_start(struct bio *bp)
|
||||
struct g_geom *gp;
|
||||
struct g_pc98_softc *mp;
|
||||
struct g_slicer *gsp;
|
||||
struct g_ioctl *gio;
|
||||
int idx, error;
|
||||
int idx;
|
||||
|
||||
pp = bp->bio_to;
|
||||
idx = pp->index;
|
||||
@ -192,32 +186,7 @@ g_pc98_start(struct bio *bp)
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* We only handle ioctl(2) requests of the right format. */
|
||||
if (strcmp(bp->bio_attribute, "GEOM::ioctl"))
|
||||
return (0);
|
||||
else if (bp->bio_length != sizeof(*gio))
|
||||
return (0);
|
||||
/* Get hold of the ioctl parameters. */
|
||||
gio = (struct g_ioctl *)bp->bio_data;
|
||||
|
||||
switch (gio->cmd) {
|
||||
case DIOCSPC98:
|
||||
/*
|
||||
* These we cannot do without the topology lock and some
|
||||
* some I/O requests. Ask the event-handler to schedule
|
||||
* us in a less restricted environment.
|
||||
*/
|
||||
error = g_post_event(g_pc98_ioctl, bp, M_NOWAIT, gp, NULL);
|
||||
if (error)
|
||||
g_io_deliver(bp, error);
|
||||
/*
|
||||
* We must return non-zero to indicate that we will deal
|
||||
* with this bio, even though we have not done so yet.
|
||||
*/
|
||||
return (1);
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -270,6 +239,7 @@ g_pc98_taste(struct g_class *mp, struct g_provider *pp, int flags)
|
||||
return (NULL);
|
||||
g_topology_unlock();
|
||||
gp->dumpconf = g_pc98_dumpconf;
|
||||
gp->ioctl = g_pc98_ioctl;
|
||||
do {
|
||||
if (gp->rank != 2 && flags == G_TF_NORMAL)
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user