Revision | 5c0961618d5e8f92d85386cf110117e6ab5dd210 (tree) |
---|---|
Time | 2010-10-12 07:08:39 |
Author | Anthony Liguori <aliguori@us.i...> |
Commiter | Anthony Liguori |
Merge remote branch 'kwolf/for-stable-0.13' into stable-0.13
@@ -35,7 +35,7 @@ typedef struct QEMUSnapshotInfo { | ||
35 | 35 | #define BDRV_O_NO_BACKING 0x0100 /* don't open the backing file */ |
36 | 36 | #define BDRV_O_NO_FLUSH 0x0200 /* disable flushing on this disk */ |
37 | 37 | |
38 | -#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_CACHE_WB) | |
38 | +#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH) | |
39 | 39 | |
40 | 40 | #define BDRV_SECTOR_BITS 9 |
41 | 41 | #define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS) |
@@ -655,7 +655,7 @@ static int write_l2_entries(BlockDriverState *bs, uint64_t *l2_table, | ||
655 | 655 | int ret; |
656 | 656 | |
657 | 657 | BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE); |
658 | - ret = bdrv_pwrite_sync(bs->file, l2_offset + start_offset, | |
658 | + ret = bdrv_pwrite(bs->file, l2_offset + start_offset, | |
659 | 659 | &l2_table[l2_start_index], len); |
660 | 660 | if (ret < 0) { |
661 | 661 | return ret; |
@@ -718,9 +718,17 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) | ||
718 | 718 | goto err; |
719 | 719 | } |
720 | 720 | |
721 | - for (i = 0; i < j; i++) | |
722 | - qcow2_free_any_clusters(bs, | |
723 | - be64_to_cpu(old_cluster[i]) & ~QCOW_OFLAG_COPIED, 1); | |
721 | + /* | |
722 | + * If this was a COW, we need to decrease the refcount of the old cluster. | |
723 | + * Also flush bs->file to get the right order for L2 and refcount update. | |
724 | + */ | |
725 | + if (j != 0) { | |
726 | + bdrv_flush(bs->file); | |
727 | + for (i = 0; i < j; i++) { | |
728 | + qcow2_free_any_clusters(bs, | |
729 | + be64_to_cpu(old_cluster[i]) & ~QCOW_OFLAG_COPIED, 1); | |
730 | + } | |
731 | + } | |
724 | 732 | |
725 | 733 | ret = 0; |
726 | 734 | err: |
@@ -1154,9 +1154,6 @@ static int cdrom_probe_device(const char *filename) | ||
1154 | 1154 | int fd, ret; |
1155 | 1155 | int prio = 0; |
1156 | 1156 | |
1157 | - if (strstart(filename, "/dev/cd", NULL)) | |
1158 | - prio = 50; | |
1159 | - | |
1160 | 1157 | fd = open(filename, O_RDONLY | O_NONBLOCK); |
1161 | 1158 | if (fd < 0) { |
1162 | 1159 | goto out; |
@@ -2665,6 +2665,11 @@ static int vvfat_write(BlockDriverState *bs, int64_t sector_num, | ||
2665 | 2665 | |
2666 | 2666 | DLOG(checkpoint()); |
2667 | 2667 | |
2668 | + /* Check if we're operating in read-only mode */ | |
2669 | + if (s->qcow == NULL) { | |
2670 | + return -EACCES; | |
2671 | + } | |
2672 | + | |
2668 | 2673 | vvfat_close_current_file(s); |
2669 | 2674 | |
2670 | 2675 | /* |
@@ -2763,12 +2768,12 @@ static int vvfat_is_allocated(BlockDriverState *bs, | ||
2763 | 2768 | |
2764 | 2769 | static int write_target_commit(BlockDriverState *bs, int64_t sector_num, |
2765 | 2770 | const uint8_t* buffer, int nb_sectors) { |
2766 | - BDRVVVFATState* s = bs->opaque; | |
2771 | + BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque); | |
2767 | 2772 | return try_commit(s); |
2768 | 2773 | } |
2769 | 2774 | |
2770 | 2775 | static void write_target_close(BlockDriverState *bs) { |
2771 | - BDRVVVFATState* s = bs->opaque; | |
2776 | + BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque); | |
2772 | 2777 | bdrv_delete(s->qcow); |
2773 | 2778 | free(s->qcow_filename); |
2774 | 2779 | } |
@@ -2783,6 +2788,7 @@ static int enable_write_target(BDRVVVFATState *s) | ||
2783 | 2788 | { |
2784 | 2789 | BlockDriver *bdrv_qcow; |
2785 | 2790 | QEMUOptionParameter *options; |
2791 | + int ret; | |
2786 | 2792 | int size = sector2cluster(s, s->sector_count); |
2787 | 2793 | s->used_clusters = calloc(size, 1); |
2788 | 2794 |
@@ -2798,11 +2804,16 @@ static int enable_write_target(BDRVVVFATState *s) | ||
2798 | 2804 | |
2799 | 2805 | if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0) |
2800 | 2806 | return -1; |
2807 | + | |
2801 | 2808 | s->qcow = bdrv_new(""); |
2802 | - if (s->qcow == NULL || | |
2803 | - bdrv_open(s->qcow, s->qcow_filename, BDRV_O_RDWR, bdrv_qcow) < 0) | |
2804 | - { | |
2805 | - return -1; | |
2809 | + if (s->qcow == NULL) { | |
2810 | + return -1; | |
2811 | + } | |
2812 | + | |
2813 | + ret = bdrv_open(s->qcow, s->qcow_filename, | |
2814 | + BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow); | |
2815 | + if (ret < 0) { | |
2816 | + return ret; | |
2806 | 2817 | } |
2807 | 2818 | |
2808 | 2819 | #ifndef _WIN32 |
@@ -2811,7 +2822,8 @@ static int enable_write_target(BDRVVVFATState *s) | ||
2811 | 2822 | |
2812 | 2823 | s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1); |
2813 | 2824 | s->bs->backing_hd->drv = &vvfat_write_target; |
2814 | - s->bs->backing_hd->opaque = s; | |
2825 | + s->bs->backing_hd->opaque = qemu_malloc(sizeof(void*)); | |
2826 | + *(void**)s->bs->backing_hd->opaque = s; | |
2815 | 2827 | |
2816 | 2828 | return 0; |
2817 | 2829 | } |
@@ -485,16 +485,26 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) | ||
485 | 485 | return buflen; |
486 | 486 | } |
487 | 487 | |
488 | -static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p) | |
488 | +static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p, | |
489 | + int page_control) | |
489 | 490 | { |
490 | 491 | SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); |
491 | 492 | BlockDriverState *bdrv = s->bs; |
492 | 493 | int cylinders, heads, secs; |
493 | 494 | |
495 | + /* | |
496 | + * If Changeable Values are requested, a mask denoting those mode parameters | |
497 | + * that are changeable shall be returned. As we currently don't support | |
498 | + * parameter changes via MODE_SELECT all bits are returned set to zero. | |
499 | + * The buffer was already menset to zero by the caller of this function. | |
500 | + */ | |
494 | 501 | switch (page) { |
495 | 502 | case 4: /* Rigid disk device geometry page. */ |
496 | 503 | p[0] = 4; |
497 | 504 | p[1] = 0x16; |
505 | + if (page_control == 1) { /* Changeable Values */ | |
506 | + return p[1] + 2; | |
507 | + } | |
498 | 508 | /* if a geometry hint is available, use it */ |
499 | 509 | bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs); |
500 | 510 | p[2] = (cylinders >> 16) & 0xff; |
@@ -519,11 +529,14 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p) | ||
519 | 529 | /* Medium rotation rate [rpm], 5400 rpm */ |
520 | 530 | p[20] = (5400 >> 8) & 0xff; |
521 | 531 | p[21] = 5400 & 0xff; |
522 | - return 0x16; | |
532 | + return p[1] + 2; | |
523 | 533 | |
524 | 534 | case 5: /* Flexible disk device geometry page. */ |
525 | 535 | p[0] = 5; |
526 | 536 | p[1] = 0x1e; |
537 | + if (page_control == 1) { /* Changeable Values */ | |
538 | + return p[1] + 2; | |
539 | + } | |
527 | 540 | /* Transfer rate [kbit/s], 5Mbit/s */ |
528 | 541 | p[2] = 5000 >> 8; |
529 | 542 | p[3] = 5000 & 0xff; |
@@ -555,21 +568,27 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p) | ||
555 | 568 | /* Medium rotation rate [rpm], 5400 rpm */ |
556 | 569 | p[28] = (5400 >> 8) & 0xff; |
557 | 570 | p[29] = 5400 & 0xff; |
558 | - return 0x1e; | |
571 | + return p[1] + 2; | |
559 | 572 | |
560 | 573 | case 8: /* Caching page. */ |
561 | 574 | p[0] = 8; |
562 | 575 | p[1] = 0x12; |
576 | + if (page_control == 1) { /* Changeable Values */ | |
577 | + return p[1] + 2; | |
578 | + } | |
563 | 579 | if (bdrv_enable_write_cache(s->bs)) { |
564 | 580 | p[2] = 4; /* WCE */ |
565 | 581 | } |
566 | - return 20; | |
582 | + return p[1] + 2; | |
567 | 583 | |
568 | 584 | case 0x2a: /* CD Capabilities and Mechanical Status page. */ |
569 | 585 | if (bdrv_get_type_hint(bdrv) != BDRV_TYPE_CDROM) |
570 | 586 | return 0; |
571 | 587 | p[0] = 0x2a; |
572 | 588 | p[1] = 0x14; |
589 | + if (page_control == 1) { /* Changeable Values */ | |
590 | + return p[1] + 2; | |
591 | + } | |
573 | 592 | p[2] = 3; // CD-R & CD-RW read |
574 | 593 | p[3] = 0; // Writing not supported |
575 | 594 | p[4] = 0x7f; /* Audio, composite, digital out, |
@@ -593,7 +612,7 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p) | ||
593 | 612 | p[19] = (16 * 176) & 0xff; |
594 | 613 | p[20] = (16 * 176) >> 8; // 16x write speed current |
595 | 614 | p[21] = (16 * 176) & 0xff; |
596 | - return 22; | |
615 | + return p[1] + 2; | |
597 | 616 | |
598 | 617 | default: |
599 | 618 | return 0; |
@@ -604,29 +623,46 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf) | ||
604 | 623 | { |
605 | 624 | SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); |
606 | 625 | uint64_t nb_sectors; |
607 | - int page, dbd, buflen; | |
626 | + int page, dbd, buflen, page_control; | |
608 | 627 | uint8_t *p; |
628 | + uint8_t dev_specific_param; | |
609 | 629 | |
610 | 630 | dbd = req->cmd.buf[1] & 0x8; |
611 | 631 | page = req->cmd.buf[2] & 0x3f; |
612 | - DPRINTF("Mode Sense (page %d, len %zd)\n", page, req->cmd.xfer); | |
632 | + page_control = (req->cmd.buf[2] & 0xc0) >> 6; | |
633 | + DPRINTF("Mode Sense(%d) (page %d, len %d, page_control %d)\n", | |
634 | + (req->cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, len, page_control); | |
613 | 635 | memset(outbuf, 0, req->cmd.xfer); |
614 | 636 | p = outbuf; |
615 | 637 | |
616 | - p[1] = 0; /* Default media type. */ | |
617 | - p[3] = 0; /* Block descriptor length. */ | |
618 | 638 | if (bdrv_is_read_only(s->bs)) { |
619 | - p[2] = 0x80; /* Readonly. */ | |
639 | + dev_specific_param = 0x80; /* Readonly. */ | |
640 | + } else { | |
641 | + dev_specific_param = 0x00; | |
642 | + } | |
643 | + | |
644 | + if (req->cmd.buf[0] == MODE_SENSE) { | |
645 | + p[1] = 0; /* Default media type. */ | |
646 | + p[2] = dev_specific_param; | |
647 | + p[3] = 0; /* Block descriptor length. */ | |
648 | + p += 4; | |
649 | + } else { /* MODE_SENSE_10 */ | |
650 | + p[2] = 0; /* Default media type. */ | |
651 | + p[3] = dev_specific_param; | |
652 | + p[6] = p[7] = 0; /* Block descriptor length. */ | |
653 | + p += 8; | |
620 | 654 | } |
621 | - p += 4; | |
622 | 655 | |
623 | 656 | bdrv_get_geometry(s->bs, &nb_sectors); |
624 | - if ((~dbd) & nb_sectors) { | |
625 | - outbuf[3] = 8; /* Block descriptor length */ | |
657 | + if (!dbd && nb_sectors) { | |
658 | + if (req->cmd.buf[0] == MODE_SENSE) { | |
659 | + outbuf[3] = 8; /* Block descriptor length */ | |
660 | + } else { /* MODE_SENSE_10 */ | |
661 | + outbuf[7] = 8; /* Block descriptor length */ | |
662 | + } | |
626 | 663 | nb_sectors /= s->cluster_size; |
627 | - nb_sectors--; | |
628 | 664 | if (nb_sectors > 0xffffff) |
629 | - nb_sectors = 0xffffff; | |
665 | + nb_sectors = 0; | |
630 | 666 | p[0] = 0; /* media density code */ |
631 | 667 | p[1] = (nb_sectors >> 16) & 0xff; |
632 | 668 | p[2] = (nb_sectors >> 8) & 0xff; |
@@ -638,21 +674,37 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf) | ||
638 | 674 | p += 8; |
639 | 675 | } |
640 | 676 | |
677 | + if (page_control == 3) { /* Saved Values */ | |
678 | + return -1; /* ILLEGAL_REQUEST */ | |
679 | + } | |
680 | + | |
641 | 681 | switch (page) { |
642 | 682 | case 0x04: |
643 | 683 | case 0x05: |
644 | 684 | case 0x08: |
645 | 685 | case 0x2a: |
646 | - p += mode_sense_page(req, page, p); | |
686 | + p += mode_sense_page(req, page, p, page_control); | |
647 | 687 | break; |
648 | 688 | case 0x3f: |
649 | - p += mode_sense_page(req, 0x08, p); | |
650 | - p += mode_sense_page(req, 0x2a, p); | |
689 | + p += mode_sense_page(req, 0x08, p, page_control); | |
690 | + p += mode_sense_page(req, 0x2a, p, page_control); | |
651 | 691 | break; |
692 | + default: | |
693 | + return -1; /* ILLEGAL_REQUEST */ | |
652 | 694 | } |
653 | 695 | |
654 | 696 | buflen = p - outbuf; |
655 | - outbuf[0] = buflen - 4; | |
697 | + /* | |
698 | + * The mode data length field specifies the length in bytes of the | |
699 | + * following data that is available to be transferred. The mode data | |
700 | + * length does not include itself. | |
701 | + */ | |
702 | + if (req->cmd.buf[0] == MODE_SENSE) { | |
703 | + outbuf[0] = buflen - 1; | |
704 | + } else { /* MODE_SENSE_10 */ | |
705 | + outbuf[0] = ((buflen - 2) >> 8) & 0xff; | |
706 | + outbuf[1] = (buflen - 2) & 0xff; | |
707 | + } | |
656 | 708 | if (buflen > req->cmd.xfer) |
657 | 709 | buflen = req->cmd.xfer; |
658 | 710 | return buflen; |
@@ -783,7 +783,8 @@ static int img_convert(int argc, char **argv) | ||
783 | 783 | goto out; |
784 | 784 | } |
785 | 785 | |
786 | - out_bs = bdrv_new_open(out_filename, out_fmt, BDRV_O_FLAGS | BDRV_O_RDWR); | |
786 | + out_bs = bdrv_new_open(out_filename, out_fmt, | |
787 | + BDRV_O_FLAGS | BDRV_O_RDWR | BDRV_O_NO_FLUSH); | |
787 | 788 | if (!out_bs) { |
788 | 789 | ret = -1; |
789 | 790 | goto out; |