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 --- |