Compare commits
14 Commits
v0.13.0-rc
...
v0.13.0-rc
Author | SHA1 | Date | |
---|---|---|---|
|
5c0961618d | ||
|
a3c4a01fb2 | ||
|
345a6d2b54 | ||
|
1b191088ae | ||
|
2c25b81316 | ||
|
5a0d460c35 | ||
|
78b6890828 | ||
|
375d40709e | ||
|
e632519ab8 | ||
|
d65741acf4 | ||
|
5aa0e6cb56 | ||
|
3bc5aa187f | ||
|
5105d99b7f | ||
|
b422f4194d |
2
block.h
2
block.h
@@ -35,7 +35,7 @@ typedef struct QEMUSnapshotInfo {
|
||||
#define BDRV_O_NO_BACKING 0x0100 /* don't open the backing file */
|
||||
#define BDRV_O_NO_FLUSH 0x0200 /* disable flushing on this disk */
|
||||
|
||||
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_CACHE_WB)
|
||||
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH)
|
||||
|
||||
#define BDRV_SECTOR_BITS 9
|
||||
#define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS)
|
||||
|
@@ -655,7 +655,7 @@ static int write_l2_entries(BlockDriverState *bs, uint64_t *l2_table,
|
||||
int ret;
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
|
||||
ret = bdrv_pwrite_sync(bs->file, l2_offset + start_offset,
|
||||
ret = bdrv_pwrite(bs->file, l2_offset + start_offset,
|
||||
&l2_table[l2_start_index], len);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -718,9 +718,17 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < j; i++)
|
||||
qcow2_free_any_clusters(bs,
|
||||
be64_to_cpu(old_cluster[i]) & ~QCOW_OFLAG_COPIED, 1);
|
||||
/*
|
||||
* If this was a COW, we need to decrease the refcount of the old cluster.
|
||||
* Also flush bs->file to get the right order for L2 and refcount update.
|
||||
*/
|
||||
if (j != 0) {
|
||||
bdrv_flush(bs->file);
|
||||
for (i = 0; i < j; i++) {
|
||||
qcow2_free_any_clusters(bs,
|
||||
be64_to_cpu(old_cluster[i]) & ~QCOW_OFLAG_COPIED, 1);
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
err:
|
||||
|
@@ -1154,9 +1154,6 @@ static int cdrom_probe_device(const char *filename)
|
||||
int fd, ret;
|
||||
int prio = 0;
|
||||
|
||||
if (strstart(filename, "/dev/cd", NULL))
|
||||
prio = 50;
|
||||
|
||||
fd = open(filename, O_RDONLY | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
goto out;
|
||||
|
@@ -2665,6 +2665,11 @@ static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
DLOG(checkpoint());
|
||||
|
||||
/* Check if we're operating in read-only mode */
|
||||
if (s->qcow == NULL) {
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
vvfat_close_current_file(s);
|
||||
|
||||
/*
|
||||
@@ -2763,12 +2768,12 @@ static int vvfat_is_allocated(BlockDriverState *bs,
|
||||
|
||||
static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
|
||||
const uint8_t* buffer, int nb_sectors) {
|
||||
BDRVVVFATState* s = bs->opaque;
|
||||
BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
|
||||
return try_commit(s);
|
||||
}
|
||||
|
||||
static void write_target_close(BlockDriverState *bs) {
|
||||
BDRVVVFATState* s = bs->opaque;
|
||||
BDRVVVFATState* s = *((BDRVVVFATState**) bs->opaque);
|
||||
bdrv_delete(s->qcow);
|
||||
free(s->qcow_filename);
|
||||
}
|
||||
@@ -2783,6 +2788,7 @@ static int enable_write_target(BDRVVVFATState *s)
|
||||
{
|
||||
BlockDriver *bdrv_qcow;
|
||||
QEMUOptionParameter *options;
|
||||
int ret;
|
||||
int size = sector2cluster(s, s->sector_count);
|
||||
s->used_clusters = calloc(size, 1);
|
||||
|
||||
@@ -2798,11 +2804,16 @@ static int enable_write_target(BDRVVVFATState *s)
|
||||
|
||||
if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0)
|
||||
return -1;
|
||||
|
||||
s->qcow = bdrv_new("");
|
||||
if (s->qcow == NULL ||
|
||||
bdrv_open(s->qcow, s->qcow_filename, BDRV_O_RDWR, bdrv_qcow) < 0)
|
||||
{
|
||||
return -1;
|
||||
if (s->qcow == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = bdrv_open(s->qcow, s->qcow_filename,
|
||||
BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
@@ -2811,7 +2822,8 @@ static int enable_write_target(BDRVVVFATState *s)
|
||||
|
||||
s->bs->backing_hd = calloc(sizeof(BlockDriverState), 1);
|
||||
s->bs->backing_hd->drv = &vvfat_write_target;
|
||||
s->bs->backing_hd->opaque = s;
|
||||
s->bs->backing_hd->opaque = qemu_malloc(sizeof(void*));
|
||||
*(void**)s->bs->backing_hd->opaque = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -485,16 +485,26 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
|
||||
return buflen;
|
||||
}
|
||||
|
||||
static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p)
|
||||
static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p,
|
||||
int page_control)
|
||||
{
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
|
||||
BlockDriverState *bdrv = s->bs;
|
||||
int cylinders, heads, secs;
|
||||
|
||||
/*
|
||||
* If Changeable Values are requested, a mask denoting those mode parameters
|
||||
* that are changeable shall be returned. As we currently don't support
|
||||
* parameter changes via MODE_SELECT all bits are returned set to zero.
|
||||
* The buffer was already menset to zero by the caller of this function.
|
||||
*/
|
||||
switch (page) {
|
||||
case 4: /* Rigid disk device geometry page. */
|
||||
p[0] = 4;
|
||||
p[1] = 0x16;
|
||||
if (page_control == 1) { /* Changeable Values */
|
||||
return p[1] + 2;
|
||||
}
|
||||
/* if a geometry hint is available, use it */
|
||||
bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
|
||||
p[2] = (cylinders >> 16) & 0xff;
|
||||
@@ -519,11 +529,14 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p)
|
||||
/* Medium rotation rate [rpm], 5400 rpm */
|
||||
p[20] = (5400 >> 8) & 0xff;
|
||||
p[21] = 5400 & 0xff;
|
||||
return 0x16;
|
||||
return p[1] + 2;
|
||||
|
||||
case 5: /* Flexible disk device geometry page. */
|
||||
p[0] = 5;
|
||||
p[1] = 0x1e;
|
||||
if (page_control == 1) { /* Changeable Values */
|
||||
return p[1] + 2;
|
||||
}
|
||||
/* Transfer rate [kbit/s], 5Mbit/s */
|
||||
p[2] = 5000 >> 8;
|
||||
p[3] = 5000 & 0xff;
|
||||
@@ -555,21 +568,27 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p)
|
||||
/* Medium rotation rate [rpm], 5400 rpm */
|
||||
p[28] = (5400 >> 8) & 0xff;
|
||||
p[29] = 5400 & 0xff;
|
||||
return 0x1e;
|
||||
return p[1] + 2;
|
||||
|
||||
case 8: /* Caching page. */
|
||||
p[0] = 8;
|
||||
p[1] = 0x12;
|
||||
if (page_control == 1) { /* Changeable Values */
|
||||
return p[1] + 2;
|
||||
}
|
||||
if (bdrv_enable_write_cache(s->bs)) {
|
||||
p[2] = 4; /* WCE */
|
||||
}
|
||||
return 20;
|
||||
return p[1] + 2;
|
||||
|
||||
case 0x2a: /* CD Capabilities and Mechanical Status page. */
|
||||
if (bdrv_get_type_hint(bdrv) != BDRV_TYPE_CDROM)
|
||||
return 0;
|
||||
p[0] = 0x2a;
|
||||
p[1] = 0x14;
|
||||
if (page_control == 1) { /* Changeable Values */
|
||||
return p[1] + 2;
|
||||
}
|
||||
p[2] = 3; // CD-R & CD-RW read
|
||||
p[3] = 0; // Writing not supported
|
||||
p[4] = 0x7f; /* Audio, composite, digital out,
|
||||
@@ -593,7 +612,7 @@ static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p)
|
||||
p[19] = (16 * 176) & 0xff;
|
||||
p[20] = (16 * 176) >> 8; // 16x write speed current
|
||||
p[21] = (16 * 176) & 0xff;
|
||||
return 22;
|
||||
return p[1] + 2;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
@@ -604,29 +623,46 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
|
||||
{
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
|
||||
uint64_t nb_sectors;
|
||||
int page, dbd, buflen;
|
||||
int page, dbd, buflen, page_control;
|
||||
uint8_t *p;
|
||||
uint8_t dev_specific_param;
|
||||
|
||||
dbd = req->cmd.buf[1] & 0x8;
|
||||
page = req->cmd.buf[2] & 0x3f;
|
||||
DPRINTF("Mode Sense (page %d, len %zd)\n", page, req->cmd.xfer);
|
||||
page_control = (req->cmd.buf[2] & 0xc0) >> 6;
|
||||
DPRINTF("Mode Sense(%d) (page %d, len %d, page_control %d)\n",
|
||||
(req->cmd.buf[0] == MODE_SENSE) ? 6 : 10, page, len, page_control);
|
||||
memset(outbuf, 0, req->cmd.xfer);
|
||||
p = outbuf;
|
||||
|
||||
p[1] = 0; /* Default media type. */
|
||||
p[3] = 0; /* Block descriptor length. */
|
||||
if (bdrv_is_read_only(s->bs)) {
|
||||
p[2] = 0x80; /* Readonly. */
|
||||
dev_specific_param = 0x80; /* Readonly. */
|
||||
} else {
|
||||
dev_specific_param = 0x00;
|
||||
}
|
||||
|
||||
if (req->cmd.buf[0] == MODE_SENSE) {
|
||||
p[1] = 0; /* Default media type. */
|
||||
p[2] = dev_specific_param;
|
||||
p[3] = 0; /* Block descriptor length. */
|
||||
p += 4;
|
||||
} else { /* MODE_SENSE_10 */
|
||||
p[2] = 0; /* Default media type. */
|
||||
p[3] = dev_specific_param;
|
||||
p[6] = p[7] = 0; /* Block descriptor length. */
|
||||
p += 8;
|
||||
}
|
||||
p += 4;
|
||||
|
||||
bdrv_get_geometry(s->bs, &nb_sectors);
|
||||
if ((~dbd) & nb_sectors) {
|
||||
outbuf[3] = 8; /* Block descriptor length */
|
||||
if (!dbd && nb_sectors) {
|
||||
if (req->cmd.buf[0] == MODE_SENSE) {
|
||||
outbuf[3] = 8; /* Block descriptor length */
|
||||
} else { /* MODE_SENSE_10 */
|
||||
outbuf[7] = 8; /* Block descriptor length */
|
||||
}
|
||||
nb_sectors /= s->cluster_size;
|
||||
nb_sectors--;
|
||||
if (nb_sectors > 0xffffff)
|
||||
nb_sectors = 0xffffff;
|
||||
nb_sectors = 0;
|
||||
p[0] = 0; /* media density code */
|
||||
p[1] = (nb_sectors >> 16) & 0xff;
|
||||
p[2] = (nb_sectors >> 8) & 0xff;
|
||||
@@ -638,21 +674,37 @@ static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
|
||||
p += 8;
|
||||
}
|
||||
|
||||
if (page_control == 3) { /* Saved Values */
|
||||
return -1; /* ILLEGAL_REQUEST */
|
||||
}
|
||||
|
||||
switch (page) {
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x08:
|
||||
case 0x2a:
|
||||
p += mode_sense_page(req, page, p);
|
||||
p += mode_sense_page(req, page, p, page_control);
|
||||
break;
|
||||
case 0x3f:
|
||||
p += mode_sense_page(req, 0x08, p);
|
||||
p += mode_sense_page(req, 0x2a, p);
|
||||
p += mode_sense_page(req, 0x08, p, page_control);
|
||||
p += mode_sense_page(req, 0x2a, p, page_control);
|
||||
break;
|
||||
default:
|
||||
return -1; /* ILLEGAL_REQUEST */
|
||||
}
|
||||
|
||||
buflen = p - outbuf;
|
||||
outbuf[0] = buflen - 4;
|
||||
/*
|
||||
* The mode data length field specifies the length in bytes of the
|
||||
* following data that is available to be transferred. The mode data
|
||||
* length does not include itself.
|
||||
*/
|
||||
if (req->cmd.buf[0] == MODE_SENSE) {
|
||||
outbuf[0] = buflen - 1;
|
||||
} else { /* MODE_SENSE_10 */
|
||||
outbuf[0] = ((buflen - 2) >> 8) & 0xff;
|
||||
outbuf[1] = (buflen - 2) & 0xff;
|
||||
}
|
||||
if (buflen > req->cmd.xfer)
|
||||
buflen = req->cmd.xfer;
|
||||
return buflen;
|
||||
|
@@ -783,7 +783,8 @@ static int img_convert(int argc, char **argv)
|
||||
goto out;
|
||||
}
|
||||
|
||||
out_bs = bdrv_new_open(out_filename, out_fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
|
||||
out_bs = bdrv_new_open(out_filename, out_fmt,
|
||||
BDRV_O_FLAGS | BDRV_O_RDWR | BDRV_O_NO_FLUSH);
|
||||
if (!out_bs) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
|
Reference in New Issue
Block a user