Revision 4dca4b63

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

  
b/block_int.h
130 130
    int64_t total_sectors; /* if we are reading a disk image, give its
131 131
                              size in sectors */
132 132
    int read_only; /* if true, the media is read only */
133
    int keep_read_only; /* if true, the media was requested to stay read only */
134
    int open_flags; /* flags used to open the file, re-used for re-open */
133 135
    int removable; /* if true, the media can be removed */
134 136
    int locked;    /* if true, the media cannot temporarily be ejected */
135 137
    int encrypted; /* if true, the media is encrypted */

Also available in: Unified diff