Deleted Added
full compact
geom_ctl.c (112534) geom_ctl.c (112709)
1/*-
2 * Copyright (c) 2002 Poul-Henning Kamp
3 * Copyright (c) 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7 * and NAI Labs, the Security Research Division of Network Associates, Inc.
8 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the

--- 18 unchanged lines hidden (view full) ---

27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
1/*-
2 * Copyright (c) 2002 Poul-Henning Kamp
3 * Copyright (c) 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7 * and NAI Labs, the Security Research Division of Network Associates, Inc.
8 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the

--- 18 unchanged lines hidden (view full) ---

27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * $FreeBSD: head/sys/geom/geom_ctl.c 112534 2003-03-24 13:37:15Z phk $
35 * $FreeBSD: head/sys/geom/geom_ctl.c 112709 2003-03-27 14:35:00Z phk $
36 */
37
38#include "opt_geom.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>
43#include <sys/sysctl.h>

--- 6 unchanged lines hidden (view full) ---

50#include <sys/lock.h>
51#include <sys/mutex.h>
52
53#include <vm/vm.h>
54#include <vm/vm_extern.h>
55
56#include <geom/geom.h>
57#include <geom/geom_int.h>
36 */
37
38#include "opt_geom.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>
43#include <sys/sysctl.h>

--- 6 unchanged lines hidden (view full) ---

50#include <sys/lock.h>
51#include <sys/mutex.h>
52
53#include <vm/vm.h>
54#include <vm/vm_extern.h>
55
56#include <geom/geom.h>
57#include <geom/geom_int.h>
58#define GEOM_CTL_TABLE 1
58#define GCTL_TABLE 1
59#include <geom/geom_ctl.h>
60#include <geom/geom_ext.h>
61
62static d_ioctl_t g_ctl_ioctl;
63
64static struct cdevsw g_ctl_cdevsw = {
65 .d_open = nullopen,
66 .d_close = nullclose,
67 .d_ioctl = g_ctl_ioctl,
68 .d_name = "g_ctl",
69};
70
71void
72g_ctl_init(void)
73{
74
75 make_dev(&g_ctl_cdevsw, 0,
76 UID_ROOT, GID_OPERATOR, 0640, PATH_GEOM_CTL);
59#include <geom/geom_ctl.h>
60#include <geom/geom_ext.h>
61
62static d_ioctl_t g_ctl_ioctl;
63
64static struct cdevsw g_ctl_cdevsw = {
65 .d_open = nullopen,
66 .d_close = nullclose,
67 .d_ioctl = g_ctl_ioctl,
68 .d_name = "g_ctl",
69};
70
71void
72g_ctl_init(void)
73{
74
75 make_dev(&g_ctl_cdevsw, 0,
76 UID_ROOT, GID_OPERATOR, 0640, PATH_GEOM_CTL);
77 KASSERT(GCTL_PARAM_RD == VM_PROT_READ,
78 ("GCTL_PARAM_RD != VM_PROT_READ"));
79 KASSERT(GCTL_PARAM_WR == VM_PROT_WRITE,
80 ("GCTL_PARAM_WR != VM_PROT_WRITE"));
77}
78
79static int
80g_ctl_ioctl_configgeom(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
81{
82 struct geomconfiggeom *gcp;
83 struct g_configargs ga;
84 int error;

--- 35 unchanged lines hidden (view full) ---

120}
121
122/*
123 * Report an error back to the user in ascii format. Return whatever copyout
124 * returned, or EINVAL if it succeeded.
125 * XXX: should not be static.
126 * XXX: should take printf like args.
127 */
81}
82
83static int
84g_ctl_ioctl_configgeom(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
85{
86 struct geomconfiggeom *gcp;
87 struct g_configargs ga;
88 int error;

--- 35 unchanged lines hidden (view full) ---

124}
125
126/*
127 * Report an error back to the user in ascii format. Return whatever copyout
128 * returned, or EINVAL if it succeeded.
129 * XXX: should not be static.
130 * XXX: should take printf like args.
131 */
128static int
129g_ctl_seterror(struct geom_ctl_req *req, const char *errtxt)
132int
133gctl_error(struct gctl_req *req, const char *errtxt)
130{
131 int error;
132
133 error = copyout(errtxt, req->error,
134 imin(req->lerror, strlen(errtxt) + 1));
135 if (!error)
136 error = EINVAL;
137 return (error);
138}
139
140/*
141 * Allocate space and copyin() something.
142 * XXX: this should really be a standard function in the kernel.
143 */
144static void *
134{
135 int error;
136
137 error = copyout(errtxt, req->error,
138 imin(req->lerror, strlen(errtxt) + 1));
139 if (!error)
140 error = EINVAL;
141 return (error);
142}
143
144/*
145 * Allocate space and copyin() something.
146 * XXX: this should really be a standard function in the kernel.
147 */
148static void *
145geom_alloc_copyin(void *uaddr, size_t len, int *errp)
149geom_alloc_copyin(struct gctl_req *req, void *uaddr, size_t len, int *errp)
146{
147 int error;
148 void *ptr;
149
150 ptr = g_malloc(len, M_WAITOK);
151 if (ptr == NULL)
152 error = ENOMEM;
153 else
154 error = copyin(uaddr, ptr, len);
155 if (!error)
156 return (ptr);
150{
151 int error;
152 void *ptr;
153
154 ptr = g_malloc(len, M_WAITOK);
155 if (ptr == NULL)
156 error = ENOMEM;
157 else
158 error = copyin(uaddr, ptr, len);
159 if (!error)
160 return (ptr);
161 gctl_error(req, "no access to argument");
157 *errp = error;
158 if (ptr != NULL)
159 g_free(ptr);
160 return (NULL);
161}
162
163
164/*
165 * XXX: This function is a nightmare. It walks through the request and
166 * XXX: makes sure that the various bits and pieces are there and copies
167 * XXX: some of them into kernel memory to make things easier.
168 * XXX: I really wish we had a standard marshalling layer somewhere.
169 */
170
171static int
162 *errp = error;
163 if (ptr != NULL)
164 g_free(ptr);
165 return (NULL);
166}
167
168
169/*
170 * XXX: This function is a nightmare. It walks through the request and
171 * XXX: makes sure that the various bits and pieces are there and copies
172 * XXX: some of them into kernel memory to make things easier.
173 * XXX: I really wish we had a standard marshalling layer somewhere.
174 */
175
176static int
172geom_ctl_copyin(struct geom_ctl_req *req)
177gctl_copyin(struct gctl_req *req)
173{
174 int error, i, j;
178{
179 int error, i, j;
175 struct geom_ctl_req_arg *ap;
180 struct gctl_req_arg *ap;
176 char *p;
177
178 error = 0;
181 char *p;
182
183 error = 0;
179 if (!useracc(req->error, req->lerror, VM_PROT_WRITE))
180 return (g_ctl_seterror(req, "No access to error field"));
181 ap = geom_alloc_copyin(req->arg, req->narg * sizeof(*ap), &error);
182 if (ap == NULL)
184 ap = geom_alloc_copyin(req, req->arg, req->narg * sizeof(*ap), &error);
185 if (ap == NULL) {
186 gctl_error(req, "copyin() of arguments failed");
183 return (error);
187 return (error);
188 }
189
184 for (i = 0; !error && i < req->narg; i++) {
190 for (i = 0; !error && i < req->narg; i++) {
185 if (ap[i].len < 0 &&
186 !useracc(ap[i].value, 1 + -ap[i].len, VM_PROT_READ))
187 error = g_ctl_seterror(req, "No access to param data");
188 else if (ap[i].len > 0 &&
189 !useracc(ap[i].value, ap[i].len,
190 VM_PROT_READ | VM_PROT_WRITE))
191 error = g_ctl_seterror(req, "No access to param data");
192 if (ap[i].name == NULL)
193 continue;
191 if (ap[i].len > 0 &&
192 !useracc(ap[i].value, ap[i].len,
193 ap[i].flag & GCTL_PARAM_RW))
194 error = gctl_error(req, "no access to param data");
195 if (ap[i].name == NULL) {
196 if (req->reqt->meta)
197 continue;
198 error = gctl_error(req,
199 "request does not take metadata arguments");
200 break;
201 }
194 p = NULL;
202 p = NULL;
195 if (ap[i].nlen < 1 || ap[i].nlen > SPECNAMELEN)
196 error = EINVAL;
197 if (error)
203 if (ap[i].nlen < 1 || ap[i].nlen > SPECNAMELEN) {
204 error = gctl_error(req, "wrong param name length");
198 break;
205 break;
199 p = geom_alloc_copyin(ap[i].name, ap[i].nlen + 1, &error);
200 if (error)
206 }
207 p = geom_alloc_copyin(req, ap[i].name, ap[i].nlen, &error);
208 if (p == NULL)
201 break;
209 break;
202 if (p[ap[i].nlen] != '\0')
203 error = EINVAL;
204 if (!error) {
205 ap[i].name = p;
206 ap[i].nlen = 0;
207 } else {
210 if (p[ap[i].nlen - 1] != '\0') {
211 error = gctl_error(req, "unterminated param name");
208 g_free(p);
209 break;
210 }
212 g_free(p);
213 break;
214 }
215 ap[i].name = p;
216 ap[i].nlen = 0;
211 }
212 if (!error) {
213 req->arg = ap;
214 return (0);
215 }
216 for (j = 0; j < i; j++)
217 if (ap[j].nlen == 0 && ap[j].name != NULL)
218 g_free(ap[j].name);
219 g_free(ap);
220 return (error);
221}
222
223static void
217 }
218 if (!error) {
219 req->arg = ap;
220 return (0);
221 }
222 for (j = 0; j < i; j++)
223 if (ap[j].nlen == 0 && ap[j].name != NULL)
224 g_free(ap[j].name);
225 g_free(ap);
226 return (error);
227}
228
229static void
224geom_ctl_dump(struct geom_ctl_req *req)
230gctl_dump(struct gctl_req *req)
225{
226 u_int i;
227 int j, error;
231{
232 u_int i;
233 int j, error;
228 struct geom_ctl_req_arg *ap;
234 struct gctl_req_arg *ap;
229 void *p;
230
231
235 void *p;
236
237
232 printf("Dump of geom_ctl %s request at %p:\n", req->reqt->name, req);
238 printf("Dump of gctl %s request at %p:\n", req->reqt->name, req);
233 if (req->lerror > 0) {
239 if (req->lerror > 0) {
234 p = geom_alloc_copyin(req->error, req->lerror, &error);
240 p = geom_alloc_copyin(req, req->error, req->lerror, &error);
235 if (p != NULL) {
236 ((char *)p)[req->lerror - 1] = '\0';
237 printf(" error:\t\"%s\"\n", (char *)p);
238 g_free(p);
239 }
240 }
241 for (i = 0; i < req->narg; i++) {
242 ap = &req->arg[i];
243 if (ap->name != NULL)
244 printf(" param:\t\"%s\"", ap->name);
245 else
246 printf(" meta:\t@%jd", (intmax_t)ap->offset);
241 if (p != NULL) {
242 ((char *)p)[req->lerror - 1] = '\0';
243 printf(" error:\t\"%s\"\n", (char *)p);
244 g_free(p);
245 }
246 }
247 for (i = 0; i < req->narg; i++) {
248 ap = &req->arg[i];
249 if (ap->name != NULL)
250 printf(" param:\t\"%s\"", ap->name);
251 else
252 printf(" meta:\t@%jd", (intmax_t)ap->offset);
247 printf(" [%d] = ", ap->len);
248 if (ap->len < 0) {
249 p = geom_alloc_copyin(ap->value, 1 + -ap->len, &error);
250 ((char *)p)[-ap->len] = '\0';
251 if (p != NULL)
253 printf(" [%s%s%d] = ",
254 ap->flag & GCTL_PARAM_RD ? "R" : "",
255 ap->flag & GCTL_PARAM_WR ? "W" : "",
256 ap->len);
257 if (ap->flag & GCTL_PARAM_ASCII) {
258 p = geom_alloc_copyin(req, ap->value, ap->len, &error);
259 if (p != NULL) {
260 ((char *)p)[ap->len - 1] = '\0';
252 printf("\"%s\"", (char *)p);
261 printf("\"%s\"", (char *)p);
262 }
253 g_free(p);
254 } else if (ap->len > 0) {
263 g_free(p);
264 } else if (ap->len > 0) {
255 p = geom_alloc_copyin(ap->value, ap->len, &error);
265 p = geom_alloc_copyin(req, ap->value, ap->len, &error);
256 for (j = 0; j < ap->len; j++)
257 printf(" %02x", ((u_char *)p)[j]);
258 g_free(p);
259 } else {
260 printf(" = %p", ap->value);
261 }
262 printf("\n");
263 }
264}
265
266 for (j = 0; j < ap->len; j++)
267 printf(" %02x", ((u_char *)p)[j]);
268 g_free(p);
269 } else {
270 printf(" = %p", ap->value);
271 }
272 printf("\n");
273 }
274}
275
276void *
277gctl_get_param(struct gctl_req *req, const char *param, int *len)
278{
279 int i, error, j;
280 void *p;
281 struct gctl_req_arg *ap;
282
283 for (i = 0; i < req->narg; i++) {
284 ap = &req->arg[i];
285 if (strcmp(param, ap->name))
286 continue;
287 if (!(ap->flag & GCTL_PARAM_RD))
288 continue;
289 if (ap->len > 0)
290 j = ap->len;
291 else
292 j = 0;
293 if (j != 0)
294 p = geom_alloc_copyin(req, ap->value, j, &error);
295 /* XXX: should not fail, tested prviously */
296 else
297 p = ap->value;
298 if (len != NULL)
299 *len = j;
300 return (p);
301 }
302 return (NULL);
303}
304
305static struct g_class*
306gctl_get_class(struct gctl_req *req)
307{
308 char *p;
309 int len;
310 struct g_class *cp;
311
312 p = gctl_get_param(req, "class", &len);
313 if (p == NULL)
314 return (NULL);
315 if (p[len - 1] != '\0') {
316 gctl_error(req, "Unterminated class name");
317 g_free(p);
318 return (NULL);
319 }
320 LIST_FOREACH(cp, &g_classes, class) {
321 if (!strcmp(p, cp->name)) {
322 g_free(p);
323 return (cp);
324 }
325 }
326 gctl_error(req, "Class not found");
327 return (NULL);
328}
329
330static struct g_geom*
331gctl_get_geom(struct gctl_req *req, struct g_class *mpr)
332{
333 char *p;
334 int len;
335 struct g_class *mp;
336 struct g_geom *gp;
337
338 p = gctl_get_param(req, "geom", &len);
339 if (p == NULL)
340 return (NULL);
341 if (p[len - 1] != '\0') {
342 gctl_error(req, "Unterminated provider name");
343 g_free(p);
344 return (NULL);
345 }
346 LIST_FOREACH(mp, &g_classes, class) {
347 if (mpr != NULL && mpr != mp)
348 continue;
349 LIST_FOREACH(gp, &mp->geom, geom) {
350 if (!strcmp(p, gp->name)) {
351 g_free(p);
352 return (gp);
353 }
354 }
355 }
356 gctl_error(req, "Geom not found");
357 return (NULL);
358}
359
360static struct g_provider*
361gctl_get_provider(struct gctl_req *req)
362{
363 char *p;
364 int len;
365 struct g_class *cp;
366 struct g_geom *gp;
367 struct g_provider *pp;
368
369 p = gctl_get_param(req, "provider", &len);
370 if (p == NULL)
371 return (NULL);
372 if (p[len - 1] != '\0') {
373 gctl_error(req, "Unterminated provider name");
374 g_free(p);
375 return (NULL);
376 }
377 LIST_FOREACH(cp, &g_classes, class) {
378 LIST_FOREACH(gp, &cp->geom, geom) {
379 LIST_FOREACH(pp, &gp->provider, provider) {
380 if (!strcmp(p, pp->name)) {
381 g_free(p);
382 return (pp);
383 }
384 }
385 }
386 }
387 gctl_error(req, "Provider not found");
388 return (NULL);
389}
390
391static void
392gctl_create_geom(struct gctl_req *req)
393{
394 struct g_class *mp;
395 struct g_provider *pp;
396
397 g_topology_assert();
398 mp = gctl_get_class(req);
399 if (mp == NULL)
400 return;
401 printf("Found class: %p\n", mp);
402 if (mp->create_geom == NULL) {
403 gctl_error(req, "Class has no create_geom method");
404 return;
405 }
406 pp = gctl_get_provider(req);
407 printf("Found provider: %p\n", pp);
408 mp->create_geom(req, mp, pp);
409 g_topology_assert();
410}
411
412static void
413gctl_destroy_geom(struct gctl_req *req)
414{
415 struct g_class *mp;
416 struct g_geom *gp;
417
418 g_topology_assert();
419 mp = gctl_get_class(req);
420 if (mp == NULL)
421 return;
422 printf("Found class: %p\n", mp);
423 if (mp->destroy_geom == NULL) {
424 gctl_error(req, "Class has no destroy_geom method");
425 return;
426 }
427 gp = gctl_get_geom(req, mp);
428 if (gp == NULL) {
429 gctl_error(req, "Geom not specified");
430 return;
431 }
432 if (gp->class != mp) {
433 gctl_error(req, "Geom not of specificed class");
434 return;
435 }
436 printf("Found geom: %p\n", gp);
437 mp->destroy_geom(req, mp, gp);
438 g_topology_assert();
439}
440
266/*
267 * Handle ioctl from libgeom::geom_ctl.c
268 */
269static int
270g_ctl_ioctl_ctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
271{
272 int error;
273 int i;
441/*
442 * Handle ioctl from libgeom::geom_ctl.c
443 */
444static int
445g_ctl_ioctl_ctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
446{
447 int error;
448 int i;
274 struct geom_ctl_req *req;
449 struct gctl_req *req;
275
276 req = (void *)data;
450
451 req = (void *)data;
452 /* It is an error if we cannot return an error text */
277 if (req->lerror < 1)
278 return (EINVAL);
453 if (req->lerror < 1)
454 return (EINVAL);
279 if (req->version != GEOM_CTL_VERSION)
280 return (g_ctl_seterror(req,
281 "Kernel and libgeom version skew."));
282 for (i = 0; gcrt[i].request != GEOM_INVALID_REQUEST; i++)
283 if (gcrt[i].request == req->request) {
284 req->reqt = &gcrt[i];
455 if (!useracc(req->error, req->lerror, VM_PROT_WRITE))
456 return (EINVAL);
457
458 /* Check the version */
459 if (req->version != GCTL_VERSION)
460 return (gctl_error(req,
461 "kernel and libgeom version mismatch."));
462
463 /* Check the request type */
464 for (i = 0; gcrt[i].request != GCTL_INVALID_REQUEST; i++)
465 if (gcrt[i].request == req->request)
285 break;
466 break;
286 }
287 if (gcrt[i].request == GEOM_INVALID_REQUEST)
288 return (g_ctl_seterror(req, "Invalid request"));
289 error = geom_ctl_copyin(req);
467 if (gcrt[i].request == GCTL_INVALID_REQUEST)
468 return (gctl_error(req, "invalid request"));
469 req->reqt = &gcrt[i];
470
471 /* Get things on board */
472 error = gctl_copyin(req);
290 if (error)
291 return (error);
473 if (error)
474 return (error);
292 req->reqt = &gcrt[i];
475
476 gctl_dump(req);
477#if 0
293 g_stall_events();
478 g_stall_events();
294 geom_ctl_dump(req);
479#endif
480 g_topology_lock();
481 switch (req->request) {
482 case GCTL_CREATE_GEOM:
483 gctl_create_geom(req);
484 break;
485 case GCTL_DESTROY_GEOM:
486 gctl_destroy_geom(req);
487 break;
488 default:
489 gctl_error(req, "XXX: TBD");
490 break;
491 }
492 g_topology_unlock();
493#if 0
295 g_release_events();
494 g_release_events();
495#endif
296 return (0);
297}
298
299static int
300g_ctl_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
301{
302 int error;
303
304 switch(cmd) {
305 case GEOMCONFIGGEOM:
306 DROP_GIANT();
307 g_topology_lock();
308 error = g_ctl_ioctl_configgeom(dev, cmd, data, fflag, td);
309 g_topology_unlock();
310 PICKUP_GIANT();
311 break;
312 case GEOM_CTL:
496 return (0);
497}
498
499static int
500g_ctl_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
501{
502 int error;
503
504 switch(cmd) {
505 case GEOMCONFIGGEOM:
506 DROP_GIANT();
507 g_topology_lock();
508 error = g_ctl_ioctl_configgeom(dev, cmd, data, fflag, td);
509 g_topology_unlock();
510 PICKUP_GIANT();
511 break;
512 case GEOM_CTL:
513 DROP_GIANT();
313 error = g_ctl_ioctl_ctl(dev, cmd, data, fflag, td);
514 error = g_ctl_ioctl_ctl(dev, cmd, data, fflag, td);
515 PICKUP_GIANT();
314 break;
315 default:
316 error = ENOTTY;
317 break;
318 }
319 return (error);
320
321}
516 break;
517 default:
518 error = ENOTTY;
519 break;
520 }
521 return (error);
522
523}