Deleted Added
full compact
geom_bsd.c (116196) geom_bsd.c (119660)
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

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

33 * SUCH DAMAGE.
34 *
35 * This is the method for dealing with BSD disklabels. It has been
36 * extensively (by my standards at least) commented, in the vain hope that
37 * it will serve as the source in future copy&paste operations.
38 */
39
40#include <sys/cdefs.h>
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

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

33 * SUCH DAMAGE.
34 *
35 * This is the method for dealing with BSD disklabels. It has been
36 * extensively (by my standards at least) commented, in the vain hope that
37 * it will serve as the source in future copy&paste operations.
38 */
39
40#include <sys/cdefs.h>
41__FBSDID("$FreeBSD: head/sys/geom/geom_bsd.c 116196 2003-06-11 06:49:16Z obrien $");
41__FBSDID("$FreeBSD: head/sys/geom/geom_bsd.c 119660 2003-09-01 20:45:32Z phk $");
42
43#include <sys/param.h>
44#include <sys/endian.h>
45#include <sys/systm.h>
46#include <sys/kernel.h>
47#include <sys/conf.h>
48#include <sys/bio.h>
49#include <sys/malloc.h>

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

262 error = g_write_data(cp, ms->labeloffset - secoff, buf, secsize);
263 g_free(buf);
264 } else {
265 error = g_write_data(cp, 0, bootcode, BBSIZE);
266 }
267 return(error);
268}
269
42
43#include <sys/param.h>
44#include <sys/endian.h>
45#include <sys/systm.h>
46#include <sys/kernel.h>
47#include <sys/conf.h>
48#include <sys/bio.h>
49#include <sys/malloc.h>

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

262 error = g_write_data(cp, ms->labeloffset - secoff, buf, secsize);
263 g_free(buf);
264 } else {
265 error = g_write_data(cp, 0, bootcode, BBSIZE);
266 }
267 return(error);
268}
269
270
271/*
270/*
272 * Implement certain ioctls to modify disklabels with. This function
273 * is called by the event handler thread with topology locked as result
274 * of the g_post_event() in g_bsd_start(). It is not necessary to keep
275 * topology locked all the time but make sure to return with topology
276 * locked as well.
277 */
278
279static void
280g_bsd_ioctl(void *arg, int flag)
281{
282 struct bio *bp;
283 struct g_geom *gp;
284 struct g_ioctl *gio;
285 u_char *label;
286 int error;
287
288 g_topology_assert();
289 bp = arg;
290 if (flag == EV_CANCEL) {
291 g_io_deliver(bp, ENXIO);
292 return;
293 }
294
295 gp = bp->bio_to->geom;
296 gio = (struct g_ioctl *)bp->bio_data;
297
298 label = g_malloc(LABELSIZE, M_WAITOK);
299
300 /* The disklabel to set is the ioctl argument. */
301 bsd_disklabel_le_enc(label, gio->data);
302
303 /* Validate and modify our slice instance to match. */
304 error = g_bsd_modify(gp, label); /* Picks up topology lock on success. */
305 g_free(label);
306 if (error || gio->cmd == DIOCSDINFO) {
307 g_io_deliver(bp, error);
308 return;
309 }
310
311 KASSERT(gio->cmd == DIOCWDINFO, ("Unknown ioctl in g_bsd_ioctl"));
312 g_io_deliver(bp, g_bsd_writelabel(gp, NULL));
313}
314
315/*
316 * Rewrite the bootblock, which is BBSIZE bytes from the start of the disk.
317 * We punch down the disklabel where we expect it to be before writing.
318 */
319static int
320g_bsd_diocbsdbb(dev_t dev, u_long cmd __unused, caddr_t data, int fflag __unused, struct thread *td __unused)
321{
322 struct g_geom *gp;
323 struct g_slicer *gsp;
324 struct g_bsd_softc *ms;
325 struct g_consumer *cp;
326 u_char *buf;
327 void *p;
328 int error, i;
329 uint64_t sum;
330
331 /* Get hold of the interesting bits from the bio. */
332 gp = (void *)dev;
333 gsp = gp->softc;
334 ms = gsp->softc;
335
336 /* The disklabel to set is the ioctl argument. */
337 buf = g_malloc(BBSIZE, M_WAITOK);
338 p = *(void **)data;
339 error = copyin(p, buf, BBSIZE);
340 if (!error) {
341 DROP_GIANT();
342 g_topology_lock();
343 /* Validate and modify our slice instance to match. */
344 error = g_bsd_modify(gp, buf + ms->labeloffset);
345 if (!error) {
346 cp = LIST_FIRST(&gp->consumer);
347 if (ms->labeloffset == ALPHA_LABEL_OFFSET) {
348 sum = 0;
349 for (i = 0; i < 63; i++)
350 sum += le64dec(buf + i * 8);
351 le64enc(buf + 504, sum);
352 }
353 error = g_write_data(cp, 0, buf, BBSIZE);
354 }
355 g_topology_unlock();
356 PICKUP_GIANT();
357 }
358 g_free(buf);
359 return (error);
360}
361
362/*
363 * If the user tries to overwrite our disklabel through an open partition
364 * or via a magicwrite config call, we end up here and try to prevent
365 * footshooting as best we can.
366 */
367static void
368g_bsd_hotwrite(void *arg, int flag)
369{
370 struct bio *bp;

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

401 * trivial ones are handled autonomously by the slice code.
402 * For requests we handle here, we must call the g_io_deliver() on the
403 * bio, and return non-zero to indicate to the slice code that we did so.
404 * This code executes in the "DOWN" I/O path, this means:
405 * * No sleeping.
406 * * Don't grab the topology lock.
407 * * Don't call biowait, g_getattr(), g_setattr() or g_read_data()
408 */
271 * If the user tries to overwrite our disklabel through an open partition
272 * or via a magicwrite config call, we end up here and try to prevent
273 * footshooting as best we can.
274 */
275static void
276g_bsd_hotwrite(void *arg, int flag)
277{
278 struct bio *bp;

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

309 * trivial ones are handled autonomously by the slice code.
310 * For requests we handle here, we must call the g_io_deliver() on the
311 * bio, and return non-zero to indicate to the slice code that we did so.
312 * This code executes in the "DOWN" I/O path, this means:
313 * * No sleeping.
314 * * Don't grab the topology lock.
315 * * Don't call biowait, g_getattr(), g_setattr() or g_read_data()
316 */
409
410static int
317static int
411g_bsd_start(struct bio *bp)
318g_bsd_ioctl(struct g_provider *pp, u_long cmd, void * data, struct thread *td)
412{
413 struct g_geom *gp;
414 struct g_bsd_softc *ms;
415 struct g_slicer *gsp;
319{
320 struct g_geom *gp;
321 struct g_bsd_softc *ms;
322 struct g_slicer *gsp;
416 struct g_ioctl *gio;
323 u_char *label;
417 int error;
418
324 int error;
325
419 gp = bp->bio_to->geom;
326 gp = pp->geom;
420 gsp = gp->softc;
421 ms = gsp->softc;
327 gsp = gp->softc;
328 ms = gsp->softc;
422 switch(bp->bio_cmd) {
423 case BIO_GETATTR:
424 if (g_handleattr(bp, "BSD::labelsum", ms->labelsum,
425 sizeof(ms->labelsum)))
426 return (1);
427 break;
428 default:
429 KASSERT(0 == 1, ("Unknown bio_cmd in g_bsd_start (%d)",
430 bp->bio_cmd));
431 }
432
329
433 /* We only handle ioctl(2) requests of the right format. */
434 if (strcmp(bp->bio_attribute, "GEOM::ioctl"))
435 return (0);
436 else if (bp->bio_length != sizeof(*gio))
437 return (0);
438
439 /* Get hold of the ioctl parameters. */
440 gio = (struct g_ioctl *)bp->bio_data;
441
442 switch (gio->cmd) {
330 switch(cmd) {
443 case DIOCGDINFO:
444 /* Return a copy of the disklabel to userland. */
331 case DIOCGDINFO:
332 /* Return a copy of the disklabel to userland. */
445 bsd_disklabel_le_dec(ms->label, gio->data, MAXPARTITIONS);
446 g_io_deliver(bp, 0);
447 return (1);
448 case DIOCBSDBB:
449 gio->func = g_bsd_diocbsdbb;
450 gio->dev = (void *)gp;
451 g_io_deliver(bp, EDIRIOCTL);
452 return (1);
333 bsd_disklabel_le_dec(ms->label, data, MAXPARTITIONS);
334 return(0);
335 case DIOCBSDBB: {
336 struct g_consumer *cp;
337 u_char *buf;
338 void *p;
339 int error, i;
340 uint64_t sum;
341
342 /* The disklabel to set is the ioctl argument. */
343 buf = g_malloc(BBSIZE, M_WAITOK);
344 p = *(void **)data;
345 error = copyin(p, buf, BBSIZE);
346 if (!error) {
347 /* XXX: Rude, but supposedly safe */
348 DROP_GIANT();
349 g_topology_lock();
350 /* Validate and modify our slice instance to match. */
351 error = g_bsd_modify(gp, buf + ms->labeloffset);
352 if (!error) {
353 cp = LIST_FIRST(&gp->consumer);
354 if (ms->labeloffset == ALPHA_LABEL_OFFSET) {
355 sum = 0;
356 for (i = 0; i < 63; i++)
357 sum += le64dec(buf + i * 8);
358 le64enc(buf + 504, sum);
359 }
360 error = g_write_data(cp, 0, buf, BBSIZE);
361 }
362 g_topology_unlock();
363 PICKUP_GIANT();
364 }
365 g_free(buf);
366 return (error);
367 }
453 case DIOCSDINFO:
368 case DIOCSDINFO:
454 case DIOCWDINFO:
455 /*
456 * These we cannot do without the topology lock and some
457 * some I/O requests. Ask the event-handler to schedule
458 * us in a less restricted environment.
459 */
460 error = g_post_event(g_bsd_ioctl, bp, M_NOWAIT, gp, NULL);
461 if (error)
462 g_io_deliver(bp, error);
463 /*
464 * We must return non-zero to indicate that we will deal
465 * with this bio, even though we have not done so yet.
466 */
467 return (1);
369 case DIOCWDINFO: {
370 label = g_malloc(LABELSIZE, M_WAITOK);
371
372 /* The disklabel to set is the ioctl argument. */
373 bsd_disklabel_le_enc(label, data);
374
375 DROP_GIANT();
376 g_topology_lock();
377 /* Validate and modify our slice instance to match. */
378 error = g_bsd_modify(gp, label);
379 if (error == 0 && cmd == DIOCWDINFO)
380 error = g_bsd_writelabel(gp, NULL);
381 g_topology_unlock();
382 PICKUP_GIANT();
383 g_free(label);
384 return(error);
385 }
468 default:
386 default:
469 return (0);
387 return (ENOIOCTL);
470 }
471}
472
388 }
389}
390
391static int
392g_bsd_start(struct bio *bp)
393{
394 struct g_geom *gp;
395 struct g_bsd_softc *ms;
396 struct g_slicer *gsp;
397
398 gp = bp->bio_to->geom;
399 gsp = gp->softc;
400 ms = gsp->softc;
401 if (bp->bio_cmd == BIO_GETATTR) {
402 if (g_handleattr(bp, "BSD::labelsum", ms->labelsum,
403 sizeof(ms->labelsum)))
404 return (1);
405 }
406 return (0);
407}
408
473/*
474 * Dump configuration information in XML format.
475 * Notice that the function is called once for the geom and once for each
476 * consumer and provider. We let g_slice_dumpconf() do most of the work.
477 */
478static void
479g_bsd_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp)
480{

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

554 if (gp == NULL)
555 return (NULL);
556
557 /*
558 * Fill in the optional details, in our case we have a dumpconf
559 * routine which the "slice" code should call at the right time
560 */
561 gp->dumpconf = g_bsd_dumpconf;
409/*
410 * Dump configuration information in XML format.
411 * Notice that the function is called once for the geom and once for each
412 * consumer and provider. We let g_slice_dumpconf() do most of the work.
413 */
414static void
415g_bsd_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp)
416{

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

490 if (gp == NULL)
491 return (NULL);
492
493 /*
494 * Fill in the optional details, in our case we have a dumpconf
495 * routine which the "slice" code should call at the right time
496 */
497 gp->dumpconf = g_bsd_dumpconf;
498 gp->ioctl = g_bsd_ioctl;
562
563 /* Get the geom_slicer softc from the geom. */
564 gsp = gp->softc;
565
566 /*
567 * The do...while loop here allows us to have multiple escapes
568 * using a simple "break". This improves code clarity without
569 * ending up in deep nesting and without using goto or come from.

--- 170 unchanged lines hidden ---
499
500 /* Get the geom_slicer softc from the geom. */
501 gsp = gp->softc;
502
503 /*
504 * The do...while loop here allows us to have multiple escapes
505 * using a simple "break". This improves code clarity without
506 * ending up in deep nesting and without using goto or come from.

--- 170 unchanged lines hidden ---