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