Revision 4dca4b63 block.c
b/block.c | ||
---|---|---|
363 | 363 |
bs->is_temporary = 0; |
364 | 364 |
bs->encrypted = 0; |
365 | 365 |
bs->valid_key = 0; |
366 |
bs->open_flags = flags; |
|
366 | 367 |
/* buffer_alignment defaulted to 512, drivers can change this value */ |
367 | 368 |
bs->buffer_alignment = 512; |
368 | 369 |
|
... | ... | |
450 | 451 |
if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE)) |
451 | 452 |
bs->enable_write_cache = 1; |
452 | 453 |
|
453 |
bs->read_only = (flags & BDRV_O_RDWR) == 0; |
|
454 |
|
|
455 | 454 |
/* |
456 | 455 |
* Clear flags that are internal to the block layer before opening the |
457 | 456 |
* image. |
... | ... | |
472 | 471 |
goto free_and_fail; |
473 | 472 |
} |
474 | 473 |
|
474 |
bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR); |
|
475 | 475 |
if (drv->bdrv_getlength) { |
476 | 476 |
bs->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS; |
477 | 477 |
} |
... | ... | |
488 | 488 |
filename, bs->backing_file); |
489 | 489 |
if (bs->backing_format[0] != '\0') |
490 | 490 |
back_drv = bdrv_find_format(bs->backing_format); |
491 |
|
|
492 |
/* backing files always opened read-only */ |
|
493 |
open_flags &= ~BDRV_O_RDWR; |
|
494 |
|
|
491 | 495 |
ret = bdrv_open2(bs->backing_hd, backing_filename, open_flags, |
492 | 496 |
back_drv); |
493 |
bs->backing_hd->read_only = (open_flags & BDRV_O_RDWR) == 0; |
|
494 | 497 |
if (ret < 0) { |
495 | 498 |
bdrv_close(bs); |
496 | 499 |
return ret; |
497 | 500 |
} |
501 |
if (bs->is_temporary) { |
|
502 |
bs->backing_hd->keep_read_only = !(flags & BDRV_O_RDWR); |
|
503 |
} else { |
|
504 |
/* base image inherits from "parent" */ |
|
505 |
bs->backing_hd->keep_read_only = bs->keep_read_only; |
|
506 |
} |
|
498 | 507 |
} |
499 | 508 |
|
500 | 509 |
if (!bdrv_key_required(bs)) { |
... | ... | |
570 | 579 |
{ |
571 | 580 |
BlockDriver *drv = bs->drv; |
572 | 581 |
int64_t i, total_sectors; |
573 |
int n, j; |
|
574 |
int ret = 0; |
|
582 |
int n, j, ro, open_flags;
|
|
583 |
int ret = 0, rw_ret = 0;
|
|
575 | 584 |
unsigned char sector[512]; |
585 |
char filename[1024]; |
|
586 |
BlockDriverState *bs_rw, *bs_ro; |
|
576 | 587 |
|
577 | 588 |
if (!drv) |
578 | 589 |
return -ENOMEDIUM; |
579 |
|
|
580 |
if (bs->read_only) {
|
|
581 |
return -EACCES;
|
|
590 |
|
|
591 |
if (!bs->backing_hd) {
|
|
592 |
return -ENOTSUP;
|
|
582 | 593 |
} |
583 | 594 |
|
584 |
if (!bs->backing_hd) { |
|
585 |
return -ENOTSUP; |
|
595 |
if (bs->backing_hd->keep_read_only) { |
|
596 |
return -EACCES; |
|
597 |
} |
|
598 |
|
|
599 |
ro = bs->backing_hd->read_only; |
|
600 |
strncpy(filename, bs->backing_hd->filename, sizeof(filename)); |
|
601 |
open_flags = bs->backing_hd->open_flags; |
|
602 |
|
|
603 |
if (ro) { |
|
604 |
/* re-open as RW */ |
|
605 |
bdrv_delete(bs->backing_hd); |
|
606 |
bs->backing_hd = NULL; |
|
607 |
bs_rw = bdrv_new(""); |
|
608 |
rw_ret = bdrv_open2(bs_rw, filename, open_flags | BDRV_O_RDWR, NULL); |
|
609 |
if (rw_ret < 0) { |
|
610 |
bdrv_delete(bs_rw); |
|
611 |
/* try to re-open read-only */ |
|
612 |
bs_ro = bdrv_new(""); |
|
613 |
ret = bdrv_open2(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL); |
|
614 |
if (ret < 0) { |
|
615 |
bdrv_delete(bs_ro); |
|
616 |
/* drive not functional anymore */ |
|
617 |
bs->drv = NULL; |
|
618 |
return ret; |
|
619 |
} |
|
620 |
bs->backing_hd = bs_ro; |
|
621 |
return rw_ret; |
|
622 |
} |
|
623 |
bs->backing_hd = bs_rw; |
|
586 | 624 |
} |
587 | 625 |
|
588 | 626 |
total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS; |
... | ... | |
590 | 628 |
if (drv->bdrv_is_allocated(bs, i, 65536, &n)) { |
591 | 629 |
for(j = 0; j < n; j++) { |
592 | 630 |
if (bdrv_read(bs, i, sector, 1) != 0) { |
593 |
return -EIO; |
|
631 |
ret = -EIO; |
|
632 |
goto ro_cleanup; |
|
594 | 633 |
} |
595 | 634 |
|
596 | 635 |
if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) { |
597 |
return -EIO; |
|
636 |
ret = -EIO; |
|
637 |
goto ro_cleanup; |
|
598 | 638 |
} |
599 | 639 |
i++; |
600 | 640 |
} |
... | ... | |
614 | 654 |
*/ |
615 | 655 |
if (bs->backing_hd) |
616 | 656 |
bdrv_flush(bs->backing_hd); |
657 |
|
|
658 |
ro_cleanup: |
|
659 |
|
|
660 |
if (ro) { |
|
661 |
/* re-open as RO */ |
|
662 |
bdrv_delete(bs->backing_hd); |
|
663 |
bs->backing_hd = NULL; |
|
664 |
bs_ro = bdrv_new(""); |
|
665 |
ret = bdrv_open2(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL); |
|
666 |
if (ret < 0) { |
|
667 |
bdrv_delete(bs_ro); |
|
668 |
/* drive not functional anymore */ |
|
669 |
bs->drv = NULL; |
|
670 |
return ret; |
|
671 |
} |
|
672 |
bs->backing_hd = bs_ro; |
|
673 |
bs->backing_hd->keep_read_only = 0; |
|
674 |
} |
|
675 |
|
|
617 | 676 |
return ret; |
618 | 677 |
} |
619 | 678 |
|
Also available in: Unified diff