Run a revision on the OAM api.

Use prefix gctl_ systematically.
Add flag with access perms for each argument.
Add ro/rw versions of argument building functions.
General cleanup.
This commit is contained in:
Poul-Henning Kamp 2003-03-27 14:35:00 +00:00
parent 5e52756d9d
commit 63728c47e8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=112709
6 changed files with 441 additions and 181 deletions

View File

@ -35,29 +35,30 @@
#include <stdint.h>
#include <sys/types.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <paths.h>
#include <sys/queue.h>
#define GEOM_CTL_TABLE 1
#define GCTL_TABLE 1
#include <libgeom.h>
#include <geom/geom_ext.h>
void
geom_ctl_dump(struct geom_ctl_req *req, FILE *f)
gctl_dump(struct gctl_req *req, FILE *f)
{
u_int i;
int j;
struct geom_ctl_req_arg *ap;
struct gctl_req_arg *ap;
if (req == NULL) {
fprintf(f, "Dump of geom_ctl request at NULL\n");
fprintf(f, "Dump of gctl request at NULL\n");
return;
}
fprintf(f, "Dump of geom_ctl %s request at %p:\n", req->reqt->name, req);
fprintf(f, "Dump of gctl %s request at %p:\n", req->reqt->name, req);
if (req->error != NULL)
fprintf(f, " error:\t\"%s\"\n", req->error);
else
@ -68,24 +69,30 @@ geom_ctl_dump(struct geom_ctl_req *req, FILE *f)
fprintf(f, " param:\t\"%s\"", ap->name);
else
fprintf(f, " meta:\t@%jd", (intmax_t)ap->offset);
fprintf(f, " [%s%s",
ap->flag & GCTL_PARAM_RD ? "R" : "",
ap->flag & GCTL_PARAM_WR ? "W" : "");
fflush(f);
if (ap->len < 0)
fprintf(f, " = [%d] \"%s\"", -ap->len, (char *)ap->value);
if (ap->flag & GCTL_PARAM_ASCII)
fprintf(f, "%d] = \"%s\"", ap->len, (char *)ap->value);
else if (ap->len > 0) {
fprintf(f, " = [%d]", ap->len);
fprintf(f, "%d] = ", ap->len);
fflush(f);
for (j = 0; j < ap->len; j++) {
fprintf(f, " %02x", ((u_char *)ap->value)[j]);
}
} else {
fprintf(f, " = [0] %p", ap->value);
fprintf(f, "0] = %p", ap->value);
}
fprintf(f, "\n");
}
}
/*
* Set an error message, if one does not already exist.
*/
static void
geom_ctl_set_error(struct geom_ctl_req *req, const char *error, ...)
gctl_set_error(struct gctl_req *req, const char *error, ...)
{
va_list ap;
@ -93,107 +100,145 @@ geom_ctl_set_error(struct geom_ctl_req *req, const char *error, ...)
return;
va_start(ap, error);
vasprintf(&req->error, error, ap);
va_end(ap);
}
/*
* Check that a malloc operation succeeded, and set a consistent error
* message if not.
*/
static void
geom_ctl_check_alloc(struct geom_ctl_req *req, void *ptr)
gctl_check_alloc(struct gctl_req *req, void *ptr)
{
if (ptr != NULL)
return;
geom_ctl_set_error(req, "Could not allocate memory");
gctl_set_error(req, "Could not allocate memory");
if (req->error == NULL)
req->error = "Could not allocate memory";
}
struct geom_ctl_req *
geom_ctl_get_handle(enum geom_ctl_request req)
/*
* Allocate a new request handle of the specified type.
* XXX: Why bother checking the type ?
*/
struct gctl_req *
gctl_get_handle(enum gctl_request req)
{
struct geom_ctl_req_table *gtp;
struct geom_ctl_req *rp;
struct gctl_req_table *gtp;
struct gctl_req *rp;
rp = calloc(1, sizeof *rp);
if (rp == NULL)
return (NULL);
for (gtp = gcrt; gtp->request != req; gtp++)
if (gtp->request == GEOM_INVALID_REQUEST)
if (gtp->request == GCTL_INVALID_REQUEST)
break;
rp->request = req;
rp->reqt = gtp;
if (rp->reqt->request == GEOM_INVALID_REQUEST)
geom_ctl_set_error(rp, "Invalid request");
if (rp->reqt->request == GCTL_INVALID_REQUEST)
gctl_set_error(rp, "Invalid request");
return (rp);
}
void
geom_ctl_set_param(struct geom_ctl_req *req, const char *name, int len, void* value)
/*
* Allocate space for another argument.
*/
static struct gctl_req_arg *
gctl_new_arg(struct gctl_req *req)
{
struct geom_ctl_req_arg *ap;
struct gctl_req_arg *ap;
req->narg++;
req->arg = realloc(req->arg, sizeof *ap * req->narg);
gctl_check_alloc(req, req->arg);
if (req->arg == NULL) {
req->narg = 0;
return (NULL);
}
ap = req->arg + (req->narg - 1);
memset(ap, 0, sizeof *ap);
return (ap);
}
void
gctl_ro_param(struct gctl_req *req, const char *name, int len, const void* value)
{
struct gctl_req_arg *ap;
if (req == NULL || req->error != NULL)
return;
if (req->reqt->params == 0)
geom_ctl_set_error(req, "Request takes no parameters");
req->narg++;
req->arg = realloc(req->arg, sizeof *ap * req->narg);
geom_ctl_check_alloc(req, req->arg);
if (req->arg != NULL) {
ap = req->arg + (req->narg - 1);
memset(ap, 0, sizeof *ap);
ap->name = strdup(name);
geom_ctl_check_alloc(req, ap->name);
ap->nlen = strlen(ap->name);
ap = gctl_new_arg(req);
if (ap == NULL)
return;
ap->name = strdup(name);
gctl_check_alloc(req, ap->name);
ap->nlen = strlen(ap->name) + 1;
ap->value = __DECONST(void *, value);
ap->flag = GCTL_PARAM_RD;
if (len >= 0)
ap->len = len;
if (len > 0) {
ap->value = value;
} else if (len < 0) {
ap->len = -strlen(value);
ap->value = strdup(value);
} else {
ap->value = value;
}
if (len != 0)
geom_ctl_check_alloc(req, ap->value);
} else {
req->narg = 0;
else if (len < 0) {
ap->flag |= GCTL_PARAM_ASCII;
ap->len = strlen(value) + 1;
}
}
void
geom_ctl_set_meta(struct geom_ctl_req *req, off_t offset, u_int len, void* value)
gctl_rw_param(struct gctl_req *req, const char *name, int len, void* value)
{
struct geom_ctl_req_arg *ap;
u_int i;
struct gctl_req_arg *ap;
if (req == NULL || req->error != NULL)
return;
if (req->reqt->meta == 0)
geom_ctl_set_error(req, "Request takes no meta data");
for (i = 0; i < req->narg; i++) {
ap = &req->arg[i];
if (ap->name != NULL)
continue;
if (ap->offset >= offset + len)
continue;
if (ap->offset + ap->len <= offset)
continue;
geom_ctl_set_error(req, "Overlapping meta data");
ap = gctl_new_arg(req);
if (ap == NULL)
return;
}
req->narg++;
req->arg = realloc(req->arg, sizeof *ap * req->narg);
geom_ctl_check_alloc(req, req->arg);
if (req->arg != NULL) {
ap = req->arg + (req->narg - 1);
memset(ap, 0, sizeof *ap);
ap->value = value;
ap->offset = offset;
ap->name = strdup(name);
gctl_check_alloc(req, ap->name);
ap->nlen = strlen(ap->name) + 1;
ap->value = value;
ap->flag = GCTL_PARAM_RW;
if (len >= 0)
ap->len = len;
} else {
req->narg = 0;
}
else if (len < 0)
ap->len = strlen(value) + 1;
}
void
gctl_ro_meta(struct gctl_req *req, off_t offset, u_int len, const void* value)
{
struct gctl_req_arg *ap;
if (req == NULL || req->error != NULL)
return;
ap = gctl_new_arg(req);
if (ap == NULL)
return;
ap->value = __DECONST(void *, value);
ap->flag = GCTL_PARAM_RD;
ap->offset = offset;
ap->len = len;
}
void
gctl_rw_meta(struct gctl_req *req, off_t offset, u_int len, void* value)
{
struct gctl_req_arg *ap;
if (req == NULL || req->error != NULL)
return;
ap = gctl_new_arg(req);
if (ap == NULL)
return;
ap->value = value;
ap->flag = GCTL_PARAM_RW;
ap->offset = offset;
ap->len = len;
}
const char *
geom_ctl_issue(struct geom_ctl_req *req)
gctl_issue(struct gctl_req *req)
{
int fd, error;
@ -202,16 +247,21 @@ geom_ctl_issue(struct geom_ctl_req *req)
if (req->error != NULL)
return (req->error);
req->version = GEOM_CTL_VERSION;
req->version = GCTL_VERSION;
req->lerror = BUFSIZ; /* XXX: arbitrary number */
req->error = malloc(req->lerror);
if (req->error == NULL) {
gctl_check_alloc(req, req->error);
return (req->error);
}
memset(req->error, 0, req->lerror);
req->lerror--;
fd = open(_PATH_DEV PATH_GEOM_CTL, O_RDONLY);
if (fd < 0)
return(strerror(errno));
error = ioctl(fd, GEOM_CTL, req);
if (error && errno == EINVAL && req->error[0] != '\0')
close(fd);
if (req->error[0] != '\0')
return (req->error);
if (error != 0)
return(strerror(errno));
@ -219,19 +269,18 @@ geom_ctl_issue(struct geom_ctl_req *req)
}
void
geom_ctl_free(struct geom_ctl_req *req)
gctl_free(struct gctl_req *req)
{
u_int i;
if (req == NULL)
return;
for (i = 0; i < req->narg; i++) {
if (req->arg[i].name != NULL)
free(req->arg[i].name);
if (req->arg[i].len < 0)
free(req->arg[i].value);
}
free(req->arg);
if (req->error != NULL)
free(req->error);
free(req->arg);
free(req);
}

View File

@ -129,23 +129,17 @@ void geom_deletetree(struct gmesh *gmp);
/* geom_ctl.c */
struct geom_ctl_req;
struct gctl_req;
#ifdef _STDIO_H_ /* limit #include pollution */
void geom_ctl_dump(struct geom_ctl_req *req, FILE *f);
void gctl_dump(struct gctl_req *req, FILE *f);
#endif
void geom_ctl_free(struct geom_ctl_req *req);
struct geom_ctl_req *geom_ctl_get_handle(enum geom_ctl_request req);
const char *geom_ctl_issue(struct geom_ctl_req *req);
void geom_ctl_set_class_by_id(struct geom_ctl_req *req, void *id);
void geom_ctl_set_class_by_name(struct geom_ctl_req *req, const char *name);
void geom_ctl_set_consumer_by_id(struct geom_ctl_req *req, void *id);
void geom_ctl_set_consumer_by_name(struct geom_ctl_req *req, const char *name);
void geom_ctl_set_geom_by_id(struct geom_ctl_req *req, void *id);
void geom_ctl_set_geom_by_name(struct geom_ctl_req *req, const char *name);
void geom_ctl_set_meta(struct geom_ctl_req *req, off_t offset, u_int len, void* val);
void geom_ctl_set_param(struct geom_ctl_req *req, const char *name, int len, void* val);
void geom_ctl_set_provider_by_id(struct geom_ctl_req *req, void *id);
void geom_ctl_set_provider_by_name(struct geom_ctl_req *req, const char *name);
void gctl_free(struct gctl_req *req);
struct gctl_req *gctl_get_handle(enum gctl_request req);
const char *gctl_issue(struct gctl_req *req);
void gctl_ro_meta(struct gctl_req *req, off_t offset, u_int len, const void* val);
void gctl_rw_meta(struct gctl_req *req, off_t offset, u_int len, void* val);
void gctl_ro_param(struct gctl_req *req, const char *name, int len, const void* val);
void gctl_rw_param(struct gctl_req *req, const char *name, int len, void* val);
#endif /* _LIBGEOM_H_ */

View File

@ -62,9 +62,12 @@ struct g_stat;
struct thread;
struct bio;
struct sbuf;
struct gctl_req;
struct g_configargs;
typedef int g_config_t (struct g_configargs *ca);
typedef int g_ctl_create_geom_t (struct gctl_req *, struct g_class *cp, struct g_provider *pp);
typedef int g_ctl_destroy_geom_t (struct gctl_req *, struct g_class *cp, struct g_geom *gp);
typedef struct g_geom * g_taste_t (struct g_class *, struct g_provider *,
int flags);
#define G_TF_NORMAL 0
@ -90,6 +93,8 @@ struct g_class {
const char *name;
g_taste_t *taste;
g_config_t *config;
g_ctl_create_geom_t *create_geom;
g_ctl_destroy_geom_t *destroy_geom;
/*
* The remaning elements are private and classes should use
* the G_CLASS_INITIALIZER macro to initialize them.
@ -426,6 +431,10 @@ struct gcfg_magicrw {
*/
/* geom_ctl.c */
void *gctl_get_param(struct gctl_req *req, const char *param, int *len);
int gctl_error(struct gctl_req *req, const char *errtxt);
/* geom_enc.c */
uint16_t g_dec_be2(const u_char *p);
uint32_t g_dec_be4(const u_char *p);

View File

@ -55,7 +55,7 @@
#include <geom/geom.h>
#include <geom/geom_int.h>
#define GEOM_CTL_TABLE 1
#define GCTL_TABLE 1
#include <geom/geom_ctl.h>
#include <geom/geom_ext.h>
@ -74,6 +74,10 @@ g_ctl_init(void)
make_dev(&g_ctl_cdevsw, 0,
UID_ROOT, GID_OPERATOR, 0640, PATH_GEOM_CTL);
KASSERT(GCTL_PARAM_RD == VM_PROT_READ,
("GCTL_PARAM_RD != VM_PROT_READ"));
KASSERT(GCTL_PARAM_WR == VM_PROT_WRITE,
("GCTL_PARAM_WR != VM_PROT_WRITE"));
}
static int
@ -125,8 +129,8 @@ g_ctl_ioctl_configgeom(dev_t dev, u_long cmd, caddr_t data, int fflag, struct th
* XXX: should not be static.
* XXX: should take printf like args.
*/
static int
g_ctl_seterror(struct geom_ctl_req *req, const char *errtxt)
int
gctl_error(struct gctl_req *req, const char *errtxt)
{
int error;
@ -142,7 +146,7 @@ g_ctl_seterror(struct geom_ctl_req *req, const char *errtxt)
* XXX: this should really be a standard function in the kernel.
*/
static void *
geom_alloc_copyin(void *uaddr, size_t len, int *errp)
geom_alloc_copyin(struct gctl_req *req, void *uaddr, size_t len, int *errp)
{
int error;
void *ptr;
@ -154,6 +158,7 @@ geom_alloc_copyin(void *uaddr, size_t len, int *errp)
error = copyin(uaddr, ptr, len);
if (!error)
return (ptr);
gctl_error(req, "no access to argument");
*errp = error;
if (ptr != NULL)
g_free(ptr);
@ -169,45 +174,46 @@ geom_alloc_copyin(void *uaddr, size_t len, int *errp)
*/
static int
geom_ctl_copyin(struct geom_ctl_req *req)
gctl_copyin(struct gctl_req *req)
{
int error, i, j;
struct geom_ctl_req_arg *ap;
struct gctl_req_arg *ap;
char *p;
error = 0;
if (!useracc(req->error, req->lerror, VM_PROT_WRITE))
return (g_ctl_seterror(req, "No access to error field"));
ap = geom_alloc_copyin(req->arg, req->narg * sizeof(*ap), &error);
if (ap == NULL)
ap = geom_alloc_copyin(req, req->arg, req->narg * sizeof(*ap), &error);
if (ap == NULL) {
gctl_error(req, "copyin() of arguments failed");
return (error);
}
for (i = 0; !error && i < req->narg; i++) {
if (ap[i].len < 0 &&
!useracc(ap[i].value, 1 + -ap[i].len, VM_PROT_READ))
error = g_ctl_seterror(req, "No access to param data");
else if (ap[i].len > 0 &&
!useracc(ap[i].value, ap[i].len,
VM_PROT_READ | VM_PROT_WRITE))
error = g_ctl_seterror(req, "No access to param data");
if (ap[i].name == NULL)
continue;
if (ap[i].len > 0 &&
!useracc(ap[i].value, ap[i].len,
ap[i].flag & GCTL_PARAM_RW))
error = gctl_error(req, "no access to param data");
if (ap[i].name == NULL) {
if (req->reqt->meta)
continue;
error = gctl_error(req,
"request does not take metadata arguments");
break;
}
p = NULL;
if (ap[i].nlen < 1 || ap[i].nlen > SPECNAMELEN)
error = EINVAL;
if (error)
if (ap[i].nlen < 1 || ap[i].nlen > SPECNAMELEN) {
error = gctl_error(req, "wrong param name length");
break;
p = geom_alloc_copyin(ap[i].name, ap[i].nlen + 1, &error);
if (error)
}
p = geom_alloc_copyin(req, ap[i].name, ap[i].nlen, &error);
if (p == NULL)
break;
if (p[ap[i].nlen] != '\0')
error = EINVAL;
if (!error) {
ap[i].name = p;
ap[i].nlen = 0;
} else {
if (p[ap[i].nlen - 1] != '\0') {
error = gctl_error(req, "unterminated param name");
g_free(p);
break;
}
ap[i].name = p;
ap[i].nlen = 0;
}
if (!error) {
req->arg = ap;
@ -221,17 +227,17 @@ geom_ctl_copyin(struct geom_ctl_req *req)
}
static void
geom_ctl_dump(struct geom_ctl_req *req)
gctl_dump(struct gctl_req *req)
{
u_int i;
int j, error;
struct geom_ctl_req_arg *ap;
struct gctl_req_arg *ap;
void *p;
printf("Dump of geom_ctl %s request at %p:\n", req->reqt->name, req);
printf("Dump of gctl %s request at %p:\n", req->reqt->name, req);
if (req->lerror > 0) {
p = geom_alloc_copyin(req->error, req->lerror, &error);
p = geom_alloc_copyin(req, req->error, req->lerror, &error);
if (p != NULL) {
((char *)p)[req->lerror - 1] = '\0';
printf(" error:\t\"%s\"\n", (char *)p);
@ -244,15 +250,19 @@ geom_ctl_dump(struct geom_ctl_req *req)
printf(" param:\t\"%s\"", ap->name);
else
printf(" meta:\t@%jd", (intmax_t)ap->offset);
printf(" [%d] = ", ap->len);
if (ap->len < 0) {
p = geom_alloc_copyin(ap->value, 1 + -ap->len, &error);
((char *)p)[-ap->len] = '\0';
if (p != NULL)
printf(" [%s%s%d] = ",
ap->flag & GCTL_PARAM_RD ? "R" : "",
ap->flag & GCTL_PARAM_WR ? "W" : "",
ap->len);
if (ap->flag & GCTL_PARAM_ASCII) {
p = geom_alloc_copyin(req, ap->value, ap->len, &error);
if (p != NULL) {
((char *)p)[ap->len - 1] = '\0';
printf("\"%s\"", (char *)p);
}
g_free(p);
} else if (ap->len > 0) {
p = geom_alloc_copyin(ap->value, ap->len, &error);
p = geom_alloc_copyin(req, ap->value, ap->len, &error);
for (j = 0; j < ap->len; j++)
printf(" %02x", ((u_char *)p)[j]);
g_free(p);
@ -263,6 +273,171 @@ geom_ctl_dump(struct geom_ctl_req *req)
}
}
void *
gctl_get_param(struct gctl_req *req, const char *param, int *len)
{
int i, error, j;
void *p;
struct gctl_req_arg *ap;
for (i = 0; i < req->narg; i++) {
ap = &req->arg[i];
if (strcmp(param, ap->name))
continue;
if (!(ap->flag & GCTL_PARAM_RD))
continue;
if (ap->len > 0)
j = ap->len;
else
j = 0;
if (j != 0)
p = geom_alloc_copyin(req, ap->value, j, &error);
/* XXX: should not fail, tested prviously */
else
p = ap->value;
if (len != NULL)
*len = j;
return (p);
}
return (NULL);
}
static struct g_class*
gctl_get_class(struct gctl_req *req)
{
char *p;
int len;
struct g_class *cp;
p = gctl_get_param(req, "class", &len);
if (p == NULL)
return (NULL);
if (p[len - 1] != '\0') {
gctl_error(req, "Unterminated class name");
g_free(p);
return (NULL);
}
LIST_FOREACH(cp, &g_classes, class) {
if (!strcmp(p, cp->name)) {
g_free(p);
return (cp);
}
}
gctl_error(req, "Class not found");
return (NULL);
}
static struct g_geom*
gctl_get_geom(struct gctl_req *req, struct g_class *mpr)
{
char *p;
int len;
struct g_class *mp;
struct g_geom *gp;
p = gctl_get_param(req, "geom", &len);
if (p == NULL)
return (NULL);
if (p[len - 1] != '\0') {
gctl_error(req, "Unterminated provider name");
g_free(p);
return (NULL);
}
LIST_FOREACH(mp, &g_classes, class) {
if (mpr != NULL && mpr != mp)
continue;
LIST_FOREACH(gp, &mp->geom, geom) {
if (!strcmp(p, gp->name)) {
g_free(p);
return (gp);
}
}
}
gctl_error(req, "Geom not found");
return (NULL);
}
static struct g_provider*
gctl_get_provider(struct gctl_req *req)
{
char *p;
int len;
struct g_class *cp;
struct g_geom *gp;
struct g_provider *pp;
p = gctl_get_param(req, "provider", &len);
if (p == NULL)
return (NULL);
if (p[len - 1] != '\0') {
gctl_error(req, "Unterminated provider name");
g_free(p);
return (NULL);
}
LIST_FOREACH(cp, &g_classes, class) {
LIST_FOREACH(gp, &cp->geom, geom) {
LIST_FOREACH(pp, &gp->provider, provider) {
if (!strcmp(p, pp->name)) {
g_free(p);
return (pp);
}
}
}
}
gctl_error(req, "Provider not found");
return (NULL);
}
static void
gctl_create_geom(struct gctl_req *req)
{
struct g_class *mp;
struct g_provider *pp;
g_topology_assert();
mp = gctl_get_class(req);
if (mp == NULL)
return;
printf("Found class: %p\n", mp);
if (mp->create_geom == NULL) {
gctl_error(req, "Class has no create_geom method");
return;
}
pp = gctl_get_provider(req);
printf("Found provider: %p\n", pp);
mp->create_geom(req, mp, pp);
g_topology_assert();
}
static void
gctl_destroy_geom(struct gctl_req *req)
{
struct g_class *mp;
struct g_geom *gp;
g_topology_assert();
mp = gctl_get_class(req);
if (mp == NULL)
return;
printf("Found class: %p\n", mp);
if (mp->destroy_geom == NULL) {
gctl_error(req, "Class has no destroy_geom method");
return;
}
gp = gctl_get_geom(req, mp);
if (gp == NULL) {
gctl_error(req, "Geom not specified");
return;
}
if (gp->class != mp) {
gctl_error(req, "Geom not of specificed class");
return;
}
printf("Found geom: %p\n", gp);
mp->destroy_geom(req, mp, gp);
g_topology_assert();
}
/*
* Handle ioctl from libgeom::geom_ctl.c
*/
@ -271,28 +446,53 @@ g_ctl_ioctl_ctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *t
{
int error;
int i;
struct geom_ctl_req *req;
struct gctl_req *req;
req = (void *)data;
/* It is an error if we cannot return an error text */
if (req->lerror < 1)
return (EINVAL);
if (req->version != GEOM_CTL_VERSION)
return (g_ctl_seterror(req,
"Kernel and libgeom version skew."));
for (i = 0; gcrt[i].request != GEOM_INVALID_REQUEST; i++)
if (gcrt[i].request == req->request) {
req->reqt = &gcrt[i];
if (!useracc(req->error, req->lerror, VM_PROT_WRITE))
return (EINVAL);
/* Check the version */
if (req->version != GCTL_VERSION)
return (gctl_error(req,
"kernel and libgeom version mismatch."));
/* Check the request type */
for (i = 0; gcrt[i].request != GCTL_INVALID_REQUEST; i++)
if (gcrt[i].request == req->request)
break;
}
if (gcrt[i].request == GEOM_INVALID_REQUEST)
return (g_ctl_seterror(req, "Invalid request"));
error = geom_ctl_copyin(req);
if (gcrt[i].request == GCTL_INVALID_REQUEST)
return (gctl_error(req, "invalid request"));
req->reqt = &gcrt[i];
/* Get things on board */
error = gctl_copyin(req);
if (error)
return (error);
req->reqt = &gcrt[i];
gctl_dump(req);
#if 0
g_stall_events();
geom_ctl_dump(req);
#endif
g_topology_lock();
switch (req->request) {
case GCTL_CREATE_GEOM:
gctl_create_geom(req);
break;
case GCTL_DESTROY_GEOM:
gctl_destroy_geom(req);
break;
default:
gctl_error(req, "XXX: TBD");
break;
}
g_topology_unlock();
#if 0
g_release_events();
#endif
return (0);
}
@ -310,7 +510,9 @@ g_ctl_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
PICKUP_GIANT();
break;
case GEOM_CTL:
DROP_GIANT();
error = g_ctl_ioctl_ctl(dev, cmd, data, fflag, td);
PICKUP_GIANT();
break;
default:
error = ENOTTY;

View File

@ -35,27 +35,27 @@
/*
* Version number. Used to check consistency between kernel and libgeom.
*/
#define GEOM_CTL_VERSION 1
#define GCTL_VERSION 1
/*
* Primitives.
*/
enum geom_ctl_request {
GEOM_INVALID_REQUEST = 0,
GEOM_CREATE_GEOM,
GEOM_NEW_GEOM,
GEOM_ATTACH,
GEOM_DETACH,
GEOM_CREATE_PROVIDER,
GEOM_DESTROY_PROVIDER,
GEOM_INSERT_GEOM,
GEOM_ELIMINATE_GEOM,
GEOM_WRITE_META,
GEOM_READ_META
enum gctl_request {
GCTL_INVALID_REQUEST = 0,
GCTL_CREATE_GEOM,
GCTL_DESTROY_GEOM,
GCTL_ATTACH,
GCTL_DETACH,
GCTL_CREATE_PROVIDER,
GCTL_DESTROY_PROVIDER,
GCTL_INSERT_GEOM,
GCTL_ELIMINATE_GEOM,
GCTL_WRITE_META,
GCTL_READ_META
};
#ifdef GEOM_CTL_TABLE
struct geom_ctl_req_table {
#ifdef GCTL_TABLE
struct gctl_req_table {
int class;
int geom;
int provider;
@ -63,24 +63,24 @@ struct geom_ctl_req_table {
int params;
int meta;
char *name;
enum geom_ctl_request request;
enum gctl_request request;
} gcrt[] = {
/* Cl Ge Pr Co Pa Me Name Request */
{ 1, 1, 1, 0, 1, 0, "create geom", GEOM_CREATE_GEOM },
{ 1, 1, 0, 0, 1, 0, "new geom", GEOM_NEW_GEOM },
{ 0, 1, 1, 0, 1, 0, "attach", GEOM_ATTACH },
{ 0, 1, 1, 0, 1, 0, "detach", GEOM_DETACH },
{ 0, 1, 0, 0, 1, 0, "create provider", GEOM_CREATE_PROVIDER },
{ 0, 1, 1, 0, 1, 0, "destroy provider", GEOM_DESTROY_PROVIDER },
{ 1, 1, 1, 0, 1, 0, "insert geom", GEOM_INSERT_GEOM },
{ 0, 1, 0, 0, 1, 0, "eliminate geom", GEOM_ELIMINATE_GEOM },
{ 0, 1, 0, 0, 1, 1, "write meta", GEOM_WRITE_META },
{ 0, 1, 0, 0, 1, 1, "read meta", GEOM_READ_META },
{ 1, 0, 1, 0, 1, 0, "create geom", GCTL_CREATE_GEOM },
{ 0, 1, 0, 0, 1, 0, "destroy geom", GCTL_DESTROY_GEOM },
{ 0, 1, 1, 0, 1, 0, "attach", GCTL_ATTACH },
{ 0, 1, 1, 0, 1, 0, "detach", GCTL_DETACH },
{ 0, 1, 0, 0, 1, 0, "create provider", GCTL_CREATE_PROVIDER },
{ 0, 1, 1, 0, 1, 0, "destroy provider", GCTL_DESTROY_PROVIDER },
{ 1, 1, 1, 0, 1, 0, "insert geom", GCTL_INSERT_GEOM },
{ 0, 1, 0, 0, 1, 0, "eliminate geom", GCTL_ELIMINATE_GEOM },
{ 0, 1, 0, 0, 1, 1, "write meta", GCTL_WRITE_META },
{ 0, 1, 0, 0, 1, 1, "read meta", GCTL_READ_META },
/* Terminator entry */
{ 1, 1, 1, 1, 1, 1, "*INVALID*", GEOM_INVALID_REQUEST }
{ 1, 1, 1, 1, 1, 1, "*INVALID*", GCTL_INVALID_REQUEST }
};
#endif /* GEOM_CTL_TABLE */
#endif /* GCTL_TABLE */
#endif /* _GEOM_GEOM_CTL_H_ */

View File

@ -40,26 +40,32 @@
#include <sys/ioccom.h>
#include <geom/geom_ctl.h>
struct geom_ctl_req_arg {
struct gctl_req_arg {
u_int nlen;
char *name;
off_t offset;
int flag;
int len;
void *value;
};
struct geom_ctl_req {
#define GCTL_PARAM_RD 1 /* Must match VM_PROT_READ */
#define GCTL_PARAM_WR 2 /* Must match VM_PROT_WRITE */
#define GCTL_PARAM_RW (GCTL_PARAM_RD | GCTL_PARAM_WR)
#define GCTL_PARAM_ASCII 4
struct gctl_req {
u_int version;
u_int serial;
enum geom_ctl_request request;
enum gctl_request request;
u_int narg;
struct geom_ctl_req_arg *arg;
struct gctl_req_arg *arg;
u_int lerror;
char *error;
struct geom_ctl_req_table *reqt;
struct gctl_req_table *reqt;
};
#define GEOM_CTL _IOW('G', GEOM_CTL_VERSION, struct geom_ctl_req)
#define GEOM_CTL _IOW('G', GCTL_VERSION, struct gctl_req)
#define PATH_GEOM_CTL "geom.ctl"