diff --git a/lib/libgeom/geom_ctl.c b/lib/libgeom/geom_ctl.c index 382d75ad80b6..e28c91f789ba 100644 --- a/lib/libgeom/geom_ctl.c +++ b/lib/libgeom/geom_ctl.c @@ -35,29 +35,30 @@ #include #include #include +#include #include #include #include #include -#define GEOM_CTL_TABLE 1 +#define GCTL_TABLE 1 #include #include 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); } - diff --git a/lib/libgeom/libgeom.h b/lib/libgeom/libgeom.h index 9f00253de895..8b1c2e83139e 100644 --- a/lib/libgeom/libgeom.h +++ b/lib/libgeom/libgeom.h @@ -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_ */ diff --git a/sys/geom/geom.h b/sys/geom/geom.h index f07485a96cda..811fb8cea12f 100644 --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -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); diff --git a/sys/geom/geom_ctl.c b/sys/geom/geom_ctl.c index eda91d5ddb68..e098c186dd36 100644 --- a/sys/geom/geom_ctl.c +++ b/sys/geom/geom_ctl.c @@ -55,7 +55,7 @@ #include #include -#define GEOM_CTL_TABLE 1 +#define GCTL_TABLE 1 #include #include @@ -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; diff --git a/sys/geom/geom_ctl.h b/sys/geom/geom_ctl.h index 240a48aed860..15bcef1004df 100644 --- a/sys/geom/geom_ctl.h +++ b/sys/geom/geom_ctl.h @@ -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_ */ diff --git a/sys/geom/geom_ext.h b/sys/geom/geom_ext.h index 8cc795c0135d..a48fc0b83a43 100644 --- a/sys/geom/geom_ext.h +++ b/sys/geom/geom_ext.h @@ -40,26 +40,32 @@ #include #include -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"