]> git.proxmox.com Git - mirror_qemu.git/commitdiff
Merge remote-tracking branch 'sstabellini/for_1.1_rc3' into staging
authorAnthony Liguori <aliguori@us.ibm.com>
Tue, 29 May 2012 09:32:13 +0000 (04:32 -0500)
committerAnthony Liguori <aliguori@us.ibm.com>
Tue, 29 May 2012 09:32:13 +0000 (04:32 -0500)
* sstabellini/for_1.1_rc3:
  Call xc_domain_shutdown with the reboot flag when the guest requests a reboot.
  xen: Fix PV-on-HVM
  xen_disk: properly update stats in ioreq_release()
  xen_disk: use bdrv_aio_flush instead of bdrv_flush
  xen_disk: remove syncwrite option
  xen: disable rtc_clock
  xen: do not initialize the interval timer and PCSPK emulator

51 files changed:
VERSION
audio/audio.c
audio/mixeng.c
audio/mixeng_template.h
block/iscsi.c
block/qcow2-cluster.c
block/qcow2.c
block/sheepdog.c
configure
exec-all.h
exec.c
hw/es1370.c
hw/fdc.c
hw/loader.c
hw/loader.h
hw/pc.c
hw/qdev-properties.c
hw/s390-virtio-bus.c
hw/s390-virtio-bus.h
hw/scsi-bus.c
hw/sun4u.c
hw/virtio-balloon.c
hw/virtio-blk.c
hw/virtio-blk.h
hw/virtio-net.c
hw/virtio-pci.c
hw/virtio-pci.h
hw/virtio-scsi.c
hw/virtio-serial-bus.c
hw/virtio.h
linux-user/mmap.c
qapi-schema-guest.json
qapi/qmp-core.h
qapi/qmp-dispatch.c
qapi/qmp-registry.c
qemu-ga.c
qemu-img.texi
qga/commands-posix.c
qga/commands.c
qga/guest-agent-core.h
scripts/qapi-commands.py
slirp/ip.h
slirp/tcp.h
slirp/tcp_output.c
target-microblaze/translate.c
target-mips/translate.c
tcg/ppc/tcg-target.c
tests/Makefile
tests/fdc-test.c
tests/qemu-iotests/035
trace-events

diff --git a/VERSION b/VERSION
index 814eec791cddaa28dec02cb15011f43a3dd0cba8..87903b67dac09b852d0111f1b92def70f7bbd02d 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.92
+1.0.93
index bd9237e9d363026972b1528fd3e42b0c35c0f157..583ee51eab2da98fcf4ba4290bb5ecd34d910275 100644 (file)
@@ -1775,10 +1775,12 @@ static void audio_atexit (void)
     HWVoiceOut *hwo = NULL;
     HWVoiceIn *hwi = NULL;
 
-    while ((hwo = audio_pcm_hw_find_any_enabled_out (hwo))) {
+    while ((hwo = audio_pcm_hw_find_any_out (hwo))) {
         SWVoiceCap *sc;
 
-        hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
+        if (hwo->enabled) {
+            hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
+        }
         hwo->pcm_ops->fini_out (hwo);
 
         for (sc = hwo->cap_head.lh_first; sc; sc = sc->entries.le_next) {
@@ -1791,8 +1793,10 @@ static void audio_atexit (void)
         }
     }
 
-    while ((hwi = audio_pcm_hw_find_any_enabled_in (hwi))) {
-        hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
+    while ((hwi = audio_pcm_hw_find_any_in (hwi))) {
+        if (hwi->enabled) {
+            hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
+        }
         hwi->pcm_ops->fini_in (hwi);
     }
 
index 5446be674f9149c9695687d2d73005f5b4f473d9..02a9d9fb92ba3bdc7c3ba587c77c5a48dda4d73d 100644 (file)
@@ -33,7 +33,8 @@
 #define ENDIAN_CONVERT(v) (v)
 
 /* Signed 8 bit */
-#define IN_T int8_t
+#define BSIZE 8
+#define ITYPE int
 #define IN_MIN SCHAR_MIN
 #define IN_MAX SCHAR_MAX
 #define SIGNED
 #undef SIGNED
 #undef IN_MAX
 #undef IN_MIN
-#undef IN_T
+#undef BSIZE
+#undef ITYPE
 #undef SHIFT
 
 /* Unsigned 8 bit */
-#define IN_T uint8_t
+#define BSIZE 8
+#define ITYPE uint
 #define IN_MIN 0
 #define IN_MAX UCHAR_MAX
 #define SHIFT 8
 #include "mixeng_template.h"
 #undef IN_MAX
 #undef IN_MIN
-#undef IN_T
+#undef BSIZE
+#undef ITYPE
 #undef SHIFT
 
 #undef ENDIAN_CONVERT
 #undef ENDIAN_CONVERSION
 
 /* Signed 16 bit */
-#define IN_T int16_t
+#define BSIZE 16
+#define ITYPE int
 #define IN_MIN SHRT_MIN
 #define IN_MAX SHRT_MAX
 #define SIGNED
 #undef SIGNED
 #undef IN_MAX
 #undef IN_MIN
-#undef IN_T
+#undef BSIZE
+#undef ITYPE
 #undef SHIFT
 
 /* Unsigned 16 bit */
-#define IN_T uint16_t
+#define BSIZE 16
+#define ITYPE uint
 #define IN_MIN 0
 #define IN_MAX USHRT_MAX
 #define SHIFT 16
 #undef ENDIAN_CONVERSION
 #undef IN_MAX
 #undef IN_MIN
-#undef IN_T
+#undef BSIZE
+#undef ITYPE
 #undef SHIFT
 
 /* Signed 32 bit */
-#define IN_T int32_t
+#define BSIZE 32
+#define ITYPE int
 #define IN_MIN INT32_MIN
 #define IN_MAX INT32_MAX
 #define SIGNED
 #undef SIGNED
 #undef IN_MAX
 #undef IN_MIN
-#undef IN_T
+#undef BSIZE
+#undef ITYPE
 #undef SHIFT
 
 /* Unsigned 32 bit */
-#define IN_T uint32_t
+#define BSIZE 32
+#define ITYPE uint
 #define IN_MIN 0
 #define IN_MAX UINT32_MAX
 #define SHIFT 32
 #undef ENDIAN_CONVERSION
 #undef IN_MAX
 #undef IN_MIN
-#undef IN_T
+#undef BSIZE
+#undef ITYPE
 #undef SHIFT
 
 t_sample *mixeng_conv[2][2][2][3] = {
index e644c231ada9e762f7262471b494cfb7893dfa1b..30849a62a1370b1c506ece4c0a3ecd42add245d8 100644 (file)
@@ -31,7 +31,8 @@
 #define HALF (IN_MAX >> 1)
 #endif
 
-#define ET glue (ENDIAN_CONVERSION, glue (_, IN_T))
+#define ET glue (ENDIAN_CONVERSION, glue (glue (glue (_, ITYPE), BSIZE), _t))
+#define IN_T glue (glue (ITYPE, BSIZE), _t)
 
 #ifdef FLOAT_MIXENG
 static mixeng_real inline glue (conv_, ET) (IN_T v)
@@ -150,3 +151,4 @@ static void glue (glue (clip_, ET), _from_mono)
 
 #undef ET
 #undef HALF
+#undef IN_T
index d37c4ee171f1349d87203be5a3ef2bd09951ea27..22888a0845de653d9bde09a67b3c8eb08b701ad5 100644 (file)
 #include "config-host.h"
 
 #include <poll.h>
+#include <arpa/inet.h>
 #include "qemu-common.h"
 #include "qemu-error.h"
 #include "block_int.h"
 #include "trace.h"
+#include "hw/scsi-defs.h"
 
 #include <iscsi/iscsi.h>
 #include <iscsi/scsi-lowlevel.h>
 typedef struct IscsiLun {
     struct iscsi_context *iscsi;
     int lun;
+    enum scsi_inquiry_peripheral_device_type type;
     int block_size;
-    unsigned long num_blocks;
+    uint64_t num_blocks;
+    int events;
 } IscsiLun;
 
 typedef struct IscsiAIOCB {
@@ -104,11 +108,27 @@ static void
 iscsi_set_events(IscsiLun *iscsilun)
 {
     struct iscsi_context *iscsi = iscsilun->iscsi;
+    int ev;
 
-    qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), iscsi_process_read,
-                           (iscsi_which_events(iscsi) & POLLOUT)
-                           ? iscsi_process_write : NULL,
-                           iscsi_process_flush, iscsilun);
+    /* We always register a read handler.  */
+    ev = POLLIN;
+    ev |= iscsi_which_events(iscsi);
+    if (ev != iscsilun->events) {
+        qemu_aio_set_fd_handler(iscsi_get_fd(iscsi),
+                      iscsi_process_read,
+                      (ev & POLLOUT) ? iscsi_process_write : NULL,
+                      iscsi_process_flush,
+                      iscsilun);
+
+    }
+
+    /* If we just added an event, the callback might be delayed
+     * unless we call qemu_notify_event().
+     */
+    if (ev & ~iscsilun->events) {
+        qemu_notify_event();
+    }
+    iscsilun->events = ev;
 }
 
 static void
@@ -161,12 +181,12 @@ iscsi_readv_writev_bh_cb(void *p)
 
 
 static void
-iscsi_aio_write10_cb(struct iscsi_context *iscsi, int status,
+iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
                      void *command_data, void *opaque)
 {
     IscsiAIOCB *acb = opaque;
 
-    trace_iscsi_aio_write10_cb(iscsi, status, acb, acb->canceled);
+    trace_iscsi_aio_write16_cb(iscsi, status, acb, acb->canceled);
 
     g_free(acb->buf);
 
@@ -179,7 +199,7 @@ iscsi_aio_write10_cb(struct iscsi_context *iscsi, int status,
 
     acb->status = 0;
     if (status < 0) {
-        error_report("Failed to write10 data to iSCSI lun. %s",
+        error_report("Failed to write16 data to iSCSI lun. %s",
                      iscsi_get_error(iscsi));
         acb->status = -EIO;
     }
@@ -204,12 +224,9 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
     struct iscsi_context *iscsi = iscsilun->iscsi;
     IscsiAIOCB *acb;
     size_t size;
-    int fua = 0;
-
-    /* set FUA on writes when cache mode is write through */
-    if (!(bs->open_flags & BDRV_O_CACHE_WB)) {
-        fua = 1;
-    }
+    uint32_t num_sectors;
+    uint64_t lba;
+    struct iscsi_data data;
 
     acb = qemu_aio_get(&iscsi_aio_pool, bs, cb, opaque);
     trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);
@@ -219,18 +236,44 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
 
     acb->canceled   = 0;
 
-    /* XXX we should pass the iovec to write10 to avoid the extra copy */
+    /* XXX we should pass the iovec to write16 to avoid the extra copy */
     /* this will allow us to get rid of 'buf' completely */
     size = nb_sectors * BDRV_SECTOR_SIZE;
     acb->buf = g_malloc(size);
     qemu_iovec_to_buffer(acb->qiov, acb->buf);
-    acb->task = iscsi_write10_task(iscsi, iscsilun->lun, acb->buf, size,
-                              sector_qemu2lun(sector_num, iscsilun),
-                              fua, 0, iscsilun->block_size,
-                              iscsi_aio_write10_cb, acb);
+
+
+    acb->task = malloc(sizeof(struct scsi_task));
     if (acb->task == NULL) {
-        error_report("iSCSI: Failed to send write10 command. %s",
-                     iscsi_get_error(iscsi));
+        error_report("iSCSI: Failed to allocate task for scsi WRITE16 "
+                     "command. %s", iscsi_get_error(iscsi));
+        qemu_aio_release(acb);
+        return NULL;
+    }
+    memset(acb->task, 0, sizeof(struct scsi_task));
+
+    acb->task->xfer_dir = SCSI_XFER_WRITE;
+    acb->task->cdb_size = 16;
+    acb->task->cdb[0] = 0x8a;
+    if (!(bs->open_flags & BDRV_O_CACHE_WB)) {
+        /* set FUA on writes when cache mode is write through */
+        acb->task->cdb[1] |= 0x04;
+    }
+    lba = sector_qemu2lun(sector_num, iscsilun);
+    *(uint32_t *)&acb->task->cdb[2]  = htonl(lba >> 32);
+    *(uint32_t *)&acb->task->cdb[6]  = htonl(lba & 0xffffffff);
+    num_sectors = size / iscsilun->block_size;
+    *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
+    acb->task->expxferlen = size;
+
+    data.data = acb->buf;
+    data.size = size;
+
+    if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
+                                 iscsi_aio_write16_cb,
+                                 &data,
+                                 acb) != 0) {
+        scsi_free_scsi_task(acb->task);
         g_free(acb->buf);
         qemu_aio_release(acb);
         return NULL;
@@ -242,12 +285,12 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
 }
 
 static void
-iscsi_aio_read10_cb(struct iscsi_context *iscsi, int status,
+iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
                     void *command_data, void *opaque)
 {
     IscsiAIOCB *acb = opaque;
 
-    trace_iscsi_aio_read10_cb(iscsi, status, acb, acb->canceled);
+    trace_iscsi_aio_read16_cb(iscsi, status, acb, acb->canceled);
 
     if (acb->canceled != 0) {
         qemu_aio_release(acb);
@@ -258,7 +301,7 @@ iscsi_aio_read10_cb(struct iscsi_context *iscsi, int status,
 
     acb->status = 0;
     if (status != 0) {
-        error_report("Failed to read10 data from iSCSI lun. %s",
+        error_report("Failed to read16 data from iSCSI lun. %s",
                      iscsi_get_error(iscsi));
         acb->status = -EIO;
     }
@@ -277,8 +320,10 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
     IscsiLun *iscsilun = bs->opaque;
     struct iscsi_context *iscsi = iscsilun->iscsi;
     IscsiAIOCB *acb;
-    size_t qemu_read_size, lun_read_size;
+    size_t qemu_read_size;
     int i;
+    uint64_t lba;
+    uint32_t num_sectors;
 
     qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;
 
@@ -303,16 +348,44 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
         acb->read_offset  = bdrv_offset % iscsilun->block_size;
     }
 
-    lun_read_size  = (qemu_read_size + iscsilun->block_size
-                     + acb->read_offset - 1)
-                     / iscsilun->block_size * iscsilun->block_size;
-    acb->task = iscsi_read10_task(iscsi, iscsilun->lun,
-                             sector_qemu2lun(sector_num, iscsilun),
-                             lun_read_size, iscsilun->block_size,
-                             iscsi_aio_read10_cb, acb);
+    num_sectors  = (qemu_read_size + iscsilun->block_size
+                    + acb->read_offset - 1)
+                    / iscsilun->block_size;
+
+    acb->task = malloc(sizeof(struct scsi_task));
     if (acb->task == NULL) {
-        error_report("iSCSI: Failed to send read10 command. %s",
-                     iscsi_get_error(iscsi));
+        error_report("iSCSI: Failed to allocate task for scsi READ16 "
+                     "command. %s", iscsi_get_error(iscsi));
+        qemu_aio_release(acb);
+        return NULL;
+    }
+    memset(acb->task, 0, sizeof(struct scsi_task));
+
+    acb->task->xfer_dir = SCSI_XFER_READ;
+    lba = sector_qemu2lun(sector_num, iscsilun);
+    acb->task->expxferlen = qemu_read_size;
+
+    switch (iscsilun->type) {
+    case TYPE_DISK:
+        acb->task->cdb_size = 16;
+        acb->task->cdb[0]  = 0x88;
+        *(uint32_t *)&acb->task->cdb[2]  = htonl(lba >> 32);
+        *(uint32_t *)&acb->task->cdb[6]  = htonl(lba & 0xffffffff);
+        *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
+        break;
+    default:
+        acb->task->cdb_size = 10;
+        acb->task->cdb[0]  = 0x28;
+        *(uint32_t *)&acb->task->cdb[2] = htonl(lba);
+        *(uint16_t *)&acb->task->cdb[7] = htons(num_sectors);
+        break;
+    }
+    
+    if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
+                                 iscsi_aio_read16_cb,
+                                 NULL,
+                                 acb) != 0) {
+        scsi_free_scsi_task(acb->task);
         qemu_aio_release(acb);
         return NULL;
     }
@@ -490,6 +563,98 @@ iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status,
     scsi_free_scsi_task(task);
 }
 
+static void
+iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status,
+                        void *command_data, void *opaque)
+{
+    struct IscsiTask *itask = opaque;
+    struct scsi_readcapacity10 *rc10;
+    struct scsi_task *task = command_data;
+
+    if (status != 0) {
+        error_report("iSCSI: Failed to read capacity of iSCSI lun. %s",
+                     iscsi_get_error(iscsi));
+        itask->status   = 1;
+        itask->complete = 1;
+        scsi_free_scsi_task(task);
+        return;
+    }
+
+    rc10 = scsi_datain_unmarshall(task);
+    if (rc10 == NULL) {
+        error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
+        itask->status   = 1;
+        itask->complete = 1;
+        scsi_free_scsi_task(task);
+        return;
+    }
+
+    itask->iscsilun->block_size = rc10->block_size;
+    itask->iscsilun->num_blocks = rc10->lba + 1;
+    itask->bs->total_sectors    = itask->iscsilun->num_blocks *
+                               itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
+
+    itask->status   = 0;
+    itask->complete = 1;
+    scsi_free_scsi_task(task);
+}
+
+static void
+iscsi_inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data,
+                 void *opaque)
+{
+    struct IscsiTask *itask = opaque;
+    struct scsi_task *task = command_data;
+    struct scsi_inquiry_standard *inq;
+
+    if (status != 0) {
+        itask->status   = 1;
+        itask->complete = 1;
+        scsi_free_scsi_task(task);
+        return;
+    }
+
+    inq = scsi_datain_unmarshall(task);
+    if (inq == NULL) {
+        error_report("iSCSI: Failed to unmarshall inquiry data.");
+        itask->status   = 1;
+        itask->complete = 1;
+        scsi_free_scsi_task(task);
+        return;
+    }
+
+    itask->iscsilun->type = inq->periperal_device_type;
+
+    scsi_free_scsi_task(task);
+
+    switch (itask->iscsilun->type) {
+    case TYPE_DISK:
+        task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun,
+                                   iscsi_readcapacity16_cb, opaque);
+        if (task == NULL) {
+            error_report("iSCSI: failed to send readcapacity16 command.");
+            itask->status   = 1;
+            itask->complete = 1;
+            return;
+        }
+        break;
+    case TYPE_ROM:
+        task = iscsi_readcapacity10_task(iscsi, itask->iscsilun->lun,
+                                   0, 0,
+                                   iscsi_readcapacity10_cb, opaque);
+        if (task == NULL) {
+            error_report("iSCSI: failed to send readcapacity16 command.");
+            itask->status   = 1;
+            itask->complete = 1;
+            return;
+        }
+        break;
+    default:
+        itask->status   = 0;
+        itask->complete = 1;
+    }
+}
+
 static void
 iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
                  void *opaque)
@@ -503,10 +668,11 @@ iscsi_connect_cb(struct iscsi_context *iscsi, int status, void *command_data,
         return;
     }
 
-    task = iscsi_readcapacity16_task(iscsi, itask->iscsilun->lun,
-                                   iscsi_readcapacity16_cb, opaque);
+    task = iscsi_inquiry_task(iscsi, itask->iscsilun->lun,
+                              0, 0, 36,
+                              iscsi_inquiry_cb, opaque);
     if (task == NULL) {
-        error_report("iSCSI: failed to send readcapacity16 command.");
+        error_report("iSCSI: failed to send inquiry command.");
         itask->status   = 1;
         itask->complete = 1;
         return;
index 10c22fe12b4b5f439b5bc3e52be6035f02a6fda8..4b3345b11b3743f68417a15e54238c807896cedc 100644 (file)
@@ -762,7 +762,6 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
     uint64_t *host_offset, unsigned int *nb_clusters)
 {
     BDRVQcowState *s = bs->opaque;
-    int64_t cluster_offset;
     QCowL2Meta *old_alloc;
 
     trace_qcow2_do_alloc_clusters_offset(qemu_coroutine_self(), guest_offset,
@@ -808,17 +807,21 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
     /* Allocate new clusters */
     trace_qcow2_cluster_alloc_phys(qemu_coroutine_self());
     if (*host_offset == 0) {
-        cluster_offset = qcow2_alloc_clusters(bs, *nb_clusters * s->cluster_size);
+        int64_t cluster_offset =
+            qcow2_alloc_clusters(bs, *nb_clusters * s->cluster_size);
+        if (cluster_offset < 0) {
+            return cluster_offset;
+        }
+        *host_offset = cluster_offset;
+        return 0;
     } else {
-        cluster_offset = *host_offset;
-        *nb_clusters = qcow2_alloc_clusters_at(bs, cluster_offset, *nb_clusters);
-    }
-
-    if (cluster_offset < 0) {
-        return cluster_offset;
+        int ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
+        if (ret < 0) {
+            return ret;
+        }
+        *nb_clusters = ret;
+        return 0;
     }
-    *host_offset = cluster_offset;
-    return 0;
 }
 
 /*
index 655799c6a0fa89dc03274d3b66d60175917963fd..c2e49cded3611319848c92041ac76d70843cfb63 100644 (file)
@@ -919,7 +919,8 @@ int qcow2_update_header(BlockDriverState *bs)
         ret = sizeof(*header);
         break;
     default:
-        return -EINVAL;
+        ret = -EINVAL;
+        goto fail;
     }
 
     buf += ret;
index e01d37168029fa45eb9822ab21c8a0dda97a2931..6d52277a89757699e9f0aff73054811c787c9639 100644 (file)
@@ -468,7 +468,7 @@ static int connect_to_sdog(const char *addr, const char *port)
     if (ret) {
         error_report("unable to get address info %s, %s",
                      addr, strerror(errno));
-        return -1;
+        return -errno;
     }
 
     for (res = res0; res; res = res->ai_next) {
@@ -495,7 +495,7 @@ static int connect_to_sdog(const char *addr, const char *port)
         dprintf("connected to %s:%s\n", addr, port);
         goto success;
     }
-    fd = -1;
+    fd = -errno;
     error_report("failed connect to %s:%s", addr, port);
 success:
     freeaddrinfo(res0);
@@ -510,12 +510,13 @@ static int send_req(int sockfd, SheepdogReq *hdr, void *data,
     ret = qemu_send_full(sockfd, hdr, sizeof(*hdr), 0);
     if (ret < sizeof(*hdr)) {
         error_report("failed to send a req, %s", strerror(errno));
-        return ret;
+        return -errno;
     }
 
     ret = qemu_send_full(sockfd, data, *wlen, 0);
     if (ret < *wlen) {
         error_report("failed to send a req, %s", strerror(errno));
+        ret = -errno;
     }
 
     return ret;
@@ -553,6 +554,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
     ret = qemu_recv_full(sockfd, hdr, sizeof(*hdr), 0);
     if (ret < sizeof(*hdr)) {
         error_report("failed to get a rsp, %s", strerror(errno));
+        ret = -errno;
         goto out;
     }
 
@@ -564,6 +566,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
         ret = qemu_recv_full(sockfd, data, *rlen, 0);
         if (ret < *rlen) {
             error_report("failed to get the data, %s", strerror(errno));
+            ret = -errno;
             goto out;
         }
     }
@@ -587,6 +590,7 @@ static int do_co_req(int sockfd, SheepdogReq *hdr, void *data,
     ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr));
     if (ret < sizeof(*hdr)) {
         error_report("failed to get a rsp, %s", strerror(errno));
+        ret = -errno;
         goto out;
     }
 
@@ -598,6 +602,7 @@ static int do_co_req(int sockfd, SheepdogReq *hdr, void *data,
         ret = qemu_co_recv(sockfd, data, *rlen);
         if (ret < *rlen) {
             error_report("failed to get the data, %s", strerror(errno));
+            ret = -errno;
             goto out;
         }
     }
@@ -787,7 +792,7 @@ static int get_sheep_fd(BDRVSheepdogState *s)
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
         error_report("%s", strerror(errno));
-        return -1;
+        return fd;
     }
 
     socket_set_nonblock(fd);
@@ -796,7 +801,7 @@ static int get_sheep_fd(BDRVSheepdogState *s)
     if (ret) {
         error_report("%s", strerror(errno));
         closesocket(fd);
-        return -1;
+        return -errno;
     }
 
     qemu_aio_set_fd_handler(fd, co_read_response, NULL, aio_flush_request, s);
@@ -883,7 +888,7 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
 
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
-        return -1;
+        return fd;
     }
 
     memset(buf, 0, sizeof(buf));
@@ -904,14 +909,17 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
 
     ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
     if (ret) {
-        ret = -1;
         goto out;
     }
 
     if (rsp->result != SD_RES_SUCCESS) {
         error_report("cannot get vdi info, %s, %s %d %s",
                      sd_strerror(rsp->result), filename, snapid, tag);
-        ret = -1;
+        if (rsp->result == SD_RES_NO_VDI) {
+            ret = -ENOENT;
+        } else {
+            ret = -EIO;
+        }
         goto out;
     }
     *vid = rsp->vdi_id;
@@ -980,7 +988,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
     if (ret < 0) {
         qemu_co_mutex_unlock(&s->lock);
         error_report("failed to send a req, %s", strerror(errno));
-        return -EIO;
+        return -errno;
     }
 
     if (wlen) {
@@ -988,7 +996,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
         if (ret < 0) {
             qemu_co_mutex_unlock(&s->lock);
             error_report("failed to send a data, %s", strerror(errno));
-            return -EIO;
+            return -errno;
         }
     }
 
@@ -1038,7 +1046,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
     ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
     if (ret) {
         error_report("failed to send a request to the sheep");
-        return -1;
+        return ret;
     }
 
     switch (rsp->result) {
@@ -1046,7 +1054,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
         return 0;
     default:
         error_report("%s", sd_strerror(rsp->result));
-        return -1;
+        return -EIO;
     }
 }
 
@@ -1082,10 +1090,12 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
     memset(vdi, 0, sizeof(vdi));
     memset(tag, 0, sizeof(tag));
     if (parse_vdiname(s, filename, vdi, &snapid, tag) < 0) {
+        ret = -EINVAL;
         goto out;
     }
     s->fd = get_sheep_fd(s);
     if (s->fd < 0) {
+        ret = s->fd;
         goto out;
     }
 
@@ -1099,11 +1109,12 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
         s->flush_fd = connect_to_sdog(s->addr, s->port);
         if (s->flush_fd < 0) {
             error_report("failed to connect");
+            ret = s->flush_fd;
             goto out;
         }
     }
 
-    if (snapid) {
+    if (snapid || tag[0] != '\0') {
         dprintf("%" PRIx32 " snapshot inode was open.\n", vid);
         s->is_snapshot = 1;
     }
@@ -1111,6 +1122,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
         error_report("failed to connect");
+        ret = fd;
         goto out;
     }
 
@@ -1139,7 +1151,7 @@ out:
         closesocket(s->fd);
     }
     g_free(buf);
-    return -1;
+    return ret;
 }
 
 static int do_sd_create(char *filename, int64_t vdi_size,
@@ -1154,7 +1166,7 @@ static int do_sd_create(char *filename, int64_t vdi_size,
 
     fd = connect_to_sdog(addr, port);
     if (fd < 0) {
-        return -EIO;
+        return fd;
     }
 
     memset(buf, 0, sizeof(buf));
@@ -1177,7 +1189,7 @@ static int do_sd_create(char *filename, int64_t vdi_size,
     closesocket(fd);
 
     if (ret) {
-        return -EIO;
+        return ret;
     }
 
     if (rsp->result != SD_RES_SUCCESS) {
@@ -1237,24 +1249,26 @@ out:
 
 static int sd_create(const char *filename, QEMUOptionParameter *options)
 {
-    int ret;
+    int ret = 0;
     uint32_t vid = 0, base_vid = 0;
     int64_t vdi_size = 0;
     char *backing_file = NULL;
-    BDRVSheepdogState s;
+    BDRVSheepdogState *s;
     char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
     uint32_t snapid;
     int prealloc = 0;
     const char *vdiname;
 
+    s = g_malloc0(sizeof(BDRVSheepdogState));
+
     strstart(filename, "sheepdog:", &vdiname);
 
-    memset(&s, 0, sizeof(s));
     memset(vdi, 0, sizeof(vdi));
     memset(tag, 0, sizeof(tag));
-    if (parse_vdiname(&s, vdiname, vdi, &snapid, tag) < 0) {
+    if (parse_vdiname(s, vdiname, vdi, &snapid, tag) < 0) {
         error_report("invalid filename");
-        return -EINVAL;
+        ret = -EINVAL;
+        goto out;
     }
 
     while (options && options->name) {
@@ -1270,7 +1284,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
             } else {
                 error_report("Invalid preallocation mode: '%s'",
                              options->value.s);
-                return -EINVAL;
+                ret = -EINVAL;
+                goto out;
             }
         }
         options++;
@@ -1278,7 +1293,8 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
 
     if (vdi_size > SD_MAX_VDI_SIZE) {
         error_report("too big image size");
-        return -EINVAL;
+        ret = -EINVAL;
+        goto out;
     }
 
     if (backing_file) {
@@ -1290,31 +1306,37 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
         drv = bdrv_find_protocol(backing_file);
         if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
             error_report("backing_file must be a sheepdog image");
-            return -EINVAL;
+            ret = -EINVAL;
+            goto out;
         }
 
         ret = bdrv_file_open(&bs, backing_file, 0);
-        if (ret < 0)
-            return -EIO;
+        if (ret < 0) {
+            goto out;
+        }
 
         s = bs->opaque;
 
         if (!is_snapshot(&s->inode)) {
             error_report("cannot clone from a non snapshot vdi");
             bdrv_delete(bs);
-            return -EINVAL;
+            ret = -EINVAL;
+            goto out;
         }
 
         base_vid = s->inode.vdi_id;
         bdrv_delete(bs);
     }
 
-    ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
+    ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s->addr, s->port);
     if (!prealloc || ret) {
-        return ret;
+        goto out;
     }
 
-    return sd_prealloc(filename);
+    ret = sd_prealloc(filename);
+out:
+    g_free(s);
+    return ret;
 }
 
 static void sd_close(BlockDriverState *bs)
@@ -1379,7 +1401,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
 
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
-        return -EIO;
+        return fd;
     }
 
     /* we don't need to update entire object */
@@ -1391,10 +1413,9 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
 
     if (ret < 0) {
         error_report("failed to update an inode.");
-        return -EIO;
     }
 
-    return 0;
+    return ret;
 }
 
 /*
@@ -1464,6 +1485,7 @@ static int sd_create_branch(BDRVSheepdogState *s)
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
         error_report("failed to connect");
+        ret = fd;
         goto out;
     }
 
@@ -1606,8 +1628,9 @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
 
     if (bs->growable && sector_num + nb_sectors > bs->total_sectors) {
         /* TODO: shouldn't block here */
-        if (sd_truncate(bs, (sector_num + nb_sectors) * SECTOR_SIZE) < 0) {
-            return -EIO;
+        ret = sd_truncate(bs, (sector_num + nb_sectors) * SECTOR_SIZE);
+        if (ret < 0) {
+            return ret;
         }
         bs->total_sectors = sector_num + nb_sectors;
     }
@@ -1724,7 +1747,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     /* refresh inode. */
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
-        ret = -EIO;
+        ret = fd;
         goto cleanup;
     }
 
@@ -1732,7 +1755,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
                        s->inode.nr_copies, datalen, 0, 0, s->cache_enabled);
     if (ret < 0) {
         error_report("failed to write snapshot's inode.");
-        ret = -EIO;
         goto cleanup;
     }
 
@@ -1741,7 +1763,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     if (ret < 0) {
         error_report("failed to create inode for snapshot. %s",
                      strerror(errno));
-        ret = -EIO;
         goto cleanup;
     }
 
@@ -1752,7 +1773,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
 
     if (ret < 0) {
         error_report("failed to read new inode info. %s", strerror(errno));
-        ret = -EIO;
         goto cleanup;
     }
 
@@ -1773,7 +1793,7 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     char *buf = NULL;
     uint32_t vid;
     uint32_t snapid = 0;
-    int ret = -ENOENT, fd;
+    int ret = 0, fd;
 
     old_s = g_malloc(sizeof(BDRVSheepdogState));
 
@@ -1791,13 +1811,13 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     ret = find_vdi_name(s, vdi, snapid, tag, &vid, 1);
     if (ret) {
         error_report("Failed to find_vdi_name");
-        ret = -ENOENT;
         goto out;
     }
 
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
         error_report("failed to connect");
+        ret = fd;
         goto out;
     }
 
@@ -1808,7 +1828,6 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     closesocket(fd);
 
     if (ret) {
-        ret = -ENOENT;
         goto out;
     }
 
@@ -1861,6 +1880,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
 
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
+        ret = fd;
         goto out;
     }
 
@@ -1888,6 +1908,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
         error_report("failed to connect");
+        ret = fd;
         goto out;
     }
 
@@ -1925,6 +1946,10 @@ out:
 
     g_free(vdi_inuse);
 
+    if (ret < 0) {
+        return ret;
+    }
+
     return found;
 }
 
@@ -1940,8 +1965,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
 
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
-        ret = -EIO;
-        goto cleanup;
+        return fd;
     }
 
     while (size) {
@@ -1965,7 +1989,6 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
 
         if (ret < 0) {
             error_report("failed to save vmstate %s", strerror(errno));
-            ret = -EIO;
             goto cleanup;
         }
 
index b55a792de60190b59c7553abaf03a2dca9474697..1f338f8dcee8fecfcf5512902b0bf75c3a33ebdf 100755 (executable)
--- a/configure
+++ b/configure
@@ -2831,6 +2831,21 @@ if compile_prog "" "" ; then
     linux_magic_h=yes
 fi
 
+########################################
+# check if environ is declared
+
+has_environ=no
+cat > $TMPC << EOF
+#include <unistd.h>
+int main(void) {
+    environ = environ;
+    return 0;
+}
+EOF
+if compile_prog "" "" ; then
+    has_environ=yes
+fi
+
 ##########################################
 # End of CC checks
 # After here, no more $cc or $ld runs
@@ -3342,6 +3357,10 @@ if test "$linux_magic_h" = "yes" ; then
   echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak
 fi
 
+if test "$has_environ" = "yes" ; then
+  echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak
+fi
+
 # USB host support
 case "$usb" in
 linux)
index c1b7e1f263fab8f60e2426df4d88561dc0ccd1a7..9bda7f735451c8d75540dda758940840208fd977 100644 (file)
@@ -96,6 +96,8 @@ void QEMU_NORETURN cpu_loop_exit(CPUArchState *env1);
 int page_unprotect(target_ulong address, uintptr_t pc, void *puc);
 void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
                                    int is_cpu_write_access);
+void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end,
+                              int is_cpu_write_access);
 #if !defined(CONFIG_USER_ONLY)
 /* cputlb.c */
 void tlb_flush_page(CPUArchState *env, target_ulong addr);
diff --git a/exec.c b/exec.c
index 0607c9b6aa9a4b72c32eadbcc2e9e5646dc455ae..a0494c72bfaa2258bb11131432d19e57791afd36 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -1075,6 +1075,23 @@ TranslationBlock *tb_gen_code(CPUArchState *env,
     return tb;
 }
 
+/*
+ * invalidate all TBs which intersect with the target physical pages
+ * starting in range [start;end[. NOTE: start and end may refer to
+ * different physical pages. 'is_cpu_write_access' should be true if called
+ * from a real cpu write access: the virtual CPU will exit the current
+ * TB if code is modified inside this TB.
+ */
+void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end,
+                              int is_cpu_write_access)
+{
+    while (start < end) {
+        tb_invalidate_phys_page_range(start, end, is_cpu_write_access);
+        start &= TARGET_PAGE_MASK;
+        start += TARGET_PAGE_SIZE;
+    }
+}
+
 /* invalidate all TBs which intersect with the target physical page
    starting in range [start;end[. NOTE: start and end must refer to
    the same physical page. 'is_cpu_write_access' should be true if called
index f19cef31a6ca0c622c205c653dbb2560c9ae99be..573f7473623635616f0bd6afdca856d83d264858 100644 (file)
@@ -410,7 +410,7 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl)
 
         if ((old_fmt != new_fmt) || (old_freq != new_freq)) {
             d->shift = (new_fmt & 1) + (new_fmt >> 1);
-            ldebug ("channel %d, freq = %d, nchannels %d, fmt %d, shift %d\n",
+            ldebug ("channel %zu, freq = %d, nchannels %d, fmt %d, shift %d\n",
                     i,
                     new_freq,
                     1 << (new_fmt & 1),
@@ -578,7 +578,7 @@ IO_WRITE_PROTO (es1370_writel)
         d++;
     case ES1370_REG_DAC1_SCOUNT:
         d->scount = (val & 0xffff) | (d->scount & ~0xffff);
-        ldebug ("chan %d CURR_SAMP_CT %d, SAMP_CT %d\n",
+        ldebug ("chan %td CURR_SAMP_CT %d, SAMP_CT %d\n",
                 d - &s->chan[0], val >> 16, (val & 0xffff));
         break;
 
@@ -588,7 +588,7 @@ IO_WRITE_PROTO (es1370_writel)
         d++;
     case ES1370_REG_DAC1_FRAMEADR:
         d->frame_addr = val;
-        ldebug ("chan %d frame address %#x\n", d - &s->chan[0], val);
+        ldebug ("chan %td frame address %#x\n", d - &s->chan[0], val);
         break;
 
     case ES1370_REG_PHANTOM_FRAMECNT:
@@ -605,7 +605,7 @@ IO_WRITE_PROTO (es1370_writel)
     case ES1370_REG_DAC1_FRAMECNT:
         d->frame_cnt = val;
         d->leftover = 0;
-        ldebug ("chan %d frame count %d, buffer size %d\n",
+        ldebug ("chan %td frame count %d, buffer size %d\n",
                 d - &s->chan[0], val >> 16, val & 0xffff);
         break;
 
@@ -745,9 +745,10 @@ IO_READ_PROTO (es1370_readl)
         {
             uint32_t size = ((d->frame_cnt & 0xffff) + 1) << 2;
             uint32_t curr = ((d->frame_cnt >> 16) + 1) << 2;
-            if (curr > size)
+            if (curr > size) {
                 dolog ("read framecnt curr %d, size %d %d\n", curr, size,
                        curr > size);
+            }
         }
 #endif
         break;
index cb4cd25c1164dd117cd2d0ad324dc6b8f496cd45..30d34e3f1ddd6859ac2b3ce8932b88a80e9df2bf 100644 (file)
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -179,12 +179,14 @@ static void fd_revalidate(FDrive *drv)
     FDriveRate rate;
 
     FLOPPY_DPRINTF("revalidate\n");
-    if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
+    if (drv->bs != NULL) {
         ro = bdrv_is_read_only(drv->bs);
         bdrv_get_floppy_geometry_hint(drv->bs, &nb_heads, &max_track,
                                       &last_sect, drv->drive, &drive, &rate);
-        if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
-            FLOPPY_DPRINTF("User defined disk (%d %d %d)",
+        if (!bdrv_is_inserted(drv->bs)) {
+            FLOPPY_DPRINTF("No disk in drive\n");
+        } else if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
+            FLOPPY_DPRINTF("User defined disk (%d %d %d)\n",
                            nb_heads - 1, max_track, last_sect);
         } else {
             FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads,
@@ -201,7 +203,7 @@ static void fd_revalidate(FDrive *drv)
         drv->drive = drive;
         drv->media_rate = rate;
     } else {
-        FLOPPY_DPRINTF("No disk in drive\n");
+        FLOPPY_DPRINTF("No drive connected\n");
         drv->last_sect = 0;
         drv->max_track = 0;
         drv->flags &= ~FDISK_DBL_SIDES;
@@ -709,7 +711,7 @@ static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0)
         FDrive *cur_drv;
         /* A seek clears the disk change line (if a disk is inserted) */
         cur_drv = get_cur_drv(fdctrl);
-        if (cur_drv->max_track) {
+        if (cur_drv->bs != NULL && bdrv_is_inserted(cur_drv->bs)) {
             cur_drv->media_changed = 0;
         }
     }
@@ -1878,7 +1880,7 @@ static int fdctrl_connect_drives(FDCtrl *fdctrl)
         }
 
         fd_init(drive);
-        fd_revalidate(drive);
+        fdctrl_change_cb(drive, 0);
         if (drive->bs) {
             bdrv_set_dev_ops(drive->bs, &fdctrl_block_ops, drive);
         }
index 415cdce534f1453121447ff0f4046068007e8517..7d64113e7f6ebfafb55f5d4596e8b42f2e592221 100644 (file)
@@ -103,7 +103,7 @@ ssize_t read_targphys(const char *name,
 
 /* return the size or -1 if error */
 int load_image_targphys(const char *filename,
-                       target_phys_addr_t addr, int max_sz)
+                        target_phys_addr_t addr, uint64_t max_sz)
 {
     int size;
 
index fbcaba9f0c05417817538fcc5a60de011ae5d37b..6da291e31f5a7172fc5783db3f7b009b43da4a66 100644 (file)
@@ -4,7 +4,8 @@
 /* loader.c */
 int get_image_size(const char *filename);
 int load_image(const char *filename, uint8_t *addr); /* deprecated */
-int load_image_targphys(const char *filename, target_phys_addr_t, int max_sz);
+int load_image_targphys(const char *filename, target_phys_addr_t,
+                        uint64_t max_sz);
 int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
              void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
              uint64_t *highaddr, int big_endian, int elf_machine,
diff --git a/hw/pc.c b/hw/pc.c
index a752a6b2fc63dd2685587fb25b9c7aa96525b032..e81a06c161067b49d5dffd3e2558992016f2bd4b 100644 (file)
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -383,7 +383,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
     if (floppy) {
         fdc_get_bs(fd, floppy);
         for (i = 0; i < 2; i++) {
-            if (fd[i] && bdrv_is_inserted(fd[i])) {
+            if (fd[i]) {
                 bdrv_get_floppy_geometry_hint(fd[i], &nb_heads, &max_track,
                                               &last_sect, FDRIVE_DRV_NONE,
                                               &fd_type[i], &rate);
index c5545dcd37f15c783ae4f9d508a75b603bdf3328..b7b5597c62499eb822a307f531c9f028b33c2425 100644 (file)
@@ -753,10 +753,12 @@ static void set_mac(Object *obj, Visitor *v, void *opaque,
         }
         mac->a[i] = strtol(str+pos, &p, 16);
     }
+    g_free(str);
     return;
 
 inval:
     error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+    g_free(str);
 }
 
 PropertyInfo qdev_prop_macaddr = {
@@ -825,7 +827,7 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
     uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
     unsigned int slot, fn, n;
     Error *local_err = NULL;
-    char *str = (char *)"";
+    char *str;
 
     if (dev->state != DEV_STATE_CREATED) {
         error_set(errp, QERR_PERMISSION_DENIED);
@@ -848,10 +850,12 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
         goto invalid;
     }
     *ptr = slot << 3 | fn;
+    g_free(str);
     return;
 
 invalid:
     error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+    g_free(str);
 }
 
 static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
index 63ccd5c35a37cc04c0910f3ed062b3b09ee8d3d2..1d38a8f5c5f3b32b1a1003ef71417954f41f87a4 100644 (file)
@@ -163,8 +163,7 @@ static int s390_virtio_blk_init(VirtIOS390Device *dev)
 {
     VirtIODevice *vdev;
 
-    vdev = virtio_blk_init((DeviceState *)dev, &dev->block,
-                           &dev->block_serial);
+    vdev = virtio_blk_init((DeviceState *)dev, &dev->blk);
     if (!vdev) {
         return -1;
     }
@@ -400,8 +399,11 @@ static TypeInfo s390_virtio_net = {
 };
 
 static Property s390_virtio_blk_properties[] = {
-    DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, block),
-    DEFINE_PROP_STRING("serial", VirtIOS390Device, block_serial),
+    DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, blk.conf),
+    DEFINE_PROP_STRING("serial", VirtIOS390Device, blk.serial),
+#ifdef __linux__
+    DEFINE_PROP_BIT("scsi", VirtIOS390Device, blk.scsi, 0, true),
+#endif
     DEFINE_PROP_END_OF_LIST(),
 };
 
index 49e6c462df321b4cb870ebfb19cc2e7c994abd44..4b99d02298f85d8af2dd6914cc95e1bcec6b60c4 100644 (file)
@@ -17,6 +17,7 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "virtio-blk.h"
 #include "virtio-net.h"
 #include "virtio-serial.h"
 #include "virtio-scsi.h"
@@ -64,8 +65,7 @@ struct VirtIOS390Device {
     ram_addr_t feat_offs;
     uint8_t feat_len;
     VirtIODevice *vdev;
-    BlockConf block;
-    char *block_serial;
+    VirtIOBlkConf blk;
     NICConf nic;
     uint32_t host_features;
     virtio_serial_conf serial;
index 8ab9bcda869b0589b710762bb9f9e464e5d304c2..f10f3ec25ce3583394103173f987cc0b52ea5c6b 100644 (file)
@@ -1561,7 +1561,7 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-const VMStateInfo vmstate_info_scsi_requests = {
+static const VMStateInfo vmstate_info_scsi_requests = {
     .name = "scsi-requests",
     .get  = get_scsi_requests,
     .put  = put_scsi_requests,
index fe3313890d1ef3f9bb16d0ad6f160a56d98360a2..517bdb818d4adcf0f5c151487e8a02048125606d 100644 (file)
@@ -67,7 +67,6 @@
 
 #define KERNEL_LOAD_ADDR     0x00404000
 #define CMDLINE_ADDR         0x003ff000
-#define INITRD_LOAD_ADDR     0x00300000
 #define PROM_SIZE_MAX        (4 * 1024 * 1024)
 #define PROM_VADDR           0x000ffd00000ULL
 #define APB_SPECIAL_BASE     0x1fe00000000ULL
@@ -181,14 +180,18 @@ static int sun4u_NVRAM_set_params(M48t59State *nvram, uint16_t NVRAM_size,
 
     return 0;
 }
-static unsigned long sun4u_load_kernel(const char *kernel_filename,
-                                       const char *initrd_filename,
-                                       ram_addr_t RAM_size, long *initrd_size)
+
+static uint64_t sun4u_load_kernel(const char *kernel_filename,
+                                  const char *initrd_filename,
+                                  ram_addr_t RAM_size, uint64_t *initrd_size,
+                                  uint64_t *initrd_addr, uint64_t *kernel_addr,
+                                  uint64_t *kernel_entry)
 {
     int linux_boot;
     unsigned int i;
     long kernel_size;
     uint8_t *ptr;
+    uint64_t kernel_top;
 
     linux_boot = (kernel_filename != NULL);
 
@@ -201,29 +204,34 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename,
 #else
         bswap_needed = 0;
 #endif
-        kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
-                               NULL, NULL, 1, ELF_MACHINE, 0);
-        if (kernel_size < 0)
+        kernel_size = load_elf(kernel_filename, NULL, NULL, kernel_entry,
+                               kernel_addr, &kernel_top, 1, ELF_MACHINE, 0);
+        if (kernel_size < 0) {
+            *kernel_addr = KERNEL_LOAD_ADDR;
+            *kernel_entry = KERNEL_LOAD_ADDR;
             kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
                                     RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
                                     TARGET_PAGE_SIZE);
-        if (kernel_size < 0)
+        }
+        if (kernel_size < 0) {
             kernel_size = load_image_targphys(kernel_filename,
                                               KERNEL_LOAD_ADDR,
                                               RAM_size - KERNEL_LOAD_ADDR);
+        }
         if (kernel_size < 0) {
             fprintf(stderr, "qemu: could not load kernel '%s'\n",
                     kernel_filename);
             exit(1);
         }
-
-        /* load initrd */
+        /* load initrd above kernel */
         *initrd_size = 0;
         if (initrd_filename) {
+            *initrd_addr = TARGET_PAGE_ALIGN(kernel_top);
+
             *initrd_size = load_image_targphys(initrd_filename,
-                                               INITRD_LOAD_ADDR,
-                                               RAM_size - INITRD_LOAD_ADDR);
-            if (*initrd_size < 0) {
+                                               *initrd_addr,
+                                               RAM_size - *initrd_addr);
+            if ((int)*initrd_size < 0) {
                 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
                         initrd_filename);
                 exit(1);
@@ -231,9 +239,9 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename,
         }
         if (*initrd_size > 0) {
             for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
-                ptr = rom_ptr(KERNEL_LOAD_ADDR + i);
+                ptr = rom_ptr(*kernel_addr + i);
                 if (ldl_p(ptr + 8) == 0x48647253) { /* HdrS */
-                    stl_p(ptr + 24, INITRD_LOAD_ADDR + KERNEL_LOAD_ADDR - 0x4000);
+                    stl_p(ptr + 24, *initrd_addr + *kernel_addr);
                     stl_p(ptr + 28, *initrd_size);
                     break;
                 }
@@ -788,7 +796,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
     CPUSPARCState *env;
     M48t59State *nvram;
     unsigned int i;
-    long initrd_size, kernel_size;
+    uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
     PCIBus *pci_bus, *pci_bus2, *pci_bus3;
     ISABus *isa_bus;
     qemu_irq *ivec_irqs, *pbm_irqs;
@@ -845,13 +853,15 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
     nvram = m48t59_init_isa(isa_bus, 0x0074, NVRAM_SIZE, 59);
 
     initrd_size = 0;
+    initrd_addr = 0;
     kernel_size = sun4u_load_kernel(kernel_filename, initrd_filename,
-                                    ram_size, &initrd_size);
+                                    ram_size, &initrd_size, &initrd_addr,
+                                    &kernel_addr, &kernel_entry);
 
     sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices,
-                           KERNEL_LOAD_ADDR, kernel_size,
+                           kernel_addr, kernel_size,
                            kernel_cmdline,
-                           INITRD_LOAD_ADDR, initrd_size,
+                           initrd_addr, initrd_size,
                            /* XXX: need an option to load a NVRAM image */
                            0,
                            graphic_width, graphic_height, graphic_depth,
@@ -861,8 +871,8 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
     fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
     fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
     if (kernel_cmdline) {
         fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
                        strlen(kernel_cmdline) + 1);
@@ -872,8 +882,8 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
     } else {
         fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
     }
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
     fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_devices[0]);
 
     fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_WIDTH, graphic_width);
index ce9d2c9759be9a5e9c1572d9077496048e8fd831..075ed87e3745ef0dcb4d62abaf195154042cedc7 100644 (file)
@@ -211,11 +211,15 @@ static void virtio_balloon_save(QEMUFile *f, void *opaque)
 static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
 {
     VirtIOBalloon *s = opaque;
+    int ret;
 
     if (version_id != 1)
         return -EINVAL;
 
-    virtio_load(&s->vdev, f);
+    ret = virtio_load(&s->vdev, f);
+    if (ret) {
+        return ret;
+    }
 
     s->num_pages = qemu_get_be32(f);
     s->actual = qemu_get_be32(f);
index 49990f8efef51efeebf7384606ad4746bdcc1485..f9e1896ea9316f90a5ca891eb13d9ad99bdedcaa 100644 (file)
@@ -29,7 +29,7 @@ typedef struct VirtIOBlock
     void *rq;
     QEMUBH *bh;
     BlockConf *conf;
-    char *serial;
+    VirtIOBlkConf *blk;
     unsigned short sector_mask;
     DeviceState *qdev;
 } VirtIOBlock;
@@ -145,20 +145,12 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
     return req;
 }
 
-#ifdef __linux__
 static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
 {
-    struct sg_io_hdr hdr;
     int ret;
-    int status;
+    int status = VIRTIO_BLK_S_OK;
     int i;
 
-    if ((req->dev->vdev.guest_features & (1 << VIRTIO_BLK_F_SCSI)) == 0) {
-        virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
-        g_free(req);
-        return;
-    }
-
     /*
      * We require at least one output segment each for the virtio_blk_outhdr
      * and the SCSI command block.
@@ -173,20 +165,26 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
     }
 
     /*
-     * No support for bidirection commands yet.
+     * The scsi inhdr is placed in the second-to-last input segment, just
+     * before the regular inhdr.
      */
-    if (req->elem.out_num > 2 && req->elem.in_num > 3) {
-        virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
-        g_free(req);
-        return;
+    req->scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
+
+    if (!req->dev->blk->scsi) {
+        status = VIRTIO_BLK_S_UNSUPP;
+        goto fail;
     }
 
     /*
-     * The scsi inhdr is placed in the second-to-last input segment, just
-     * before the regular inhdr.
+     * No support for bidirection commands yet.
      */
-    req->scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
+    if (req->elem.out_num > 2 && req->elem.in_num > 3) {
+        status = VIRTIO_BLK_S_UNSUPP;
+        goto fail;
+    }
 
+#ifdef __linux__
+    struct sg_io_hdr hdr;
     memset(&hdr, 0, sizeof(struct sg_io_hdr));
     hdr.interface_id = 'S';
     hdr.cmd_len = req->elem.out_sg[1].iov_len;
@@ -230,12 +228,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
     ret = bdrv_ioctl(req->dev->bs, SG_IO, &hdr);
     if (ret) {
         status = VIRTIO_BLK_S_UNSUPP;
-        hdr.status = ret;
-        hdr.resid = hdr.dxfer_len;
-    } else if (hdr.status) {
-        status = VIRTIO_BLK_S_IOERR;
-    } else {
-        status = VIRTIO_BLK_S_OK;
+        goto fail;
     }
 
     /*
@@ -258,14 +251,16 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
 
     virtio_blk_req_complete(req, status);
     g_free(req);
-}
 #else
-static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
-{
-    virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
+    abort();
+#endif
+
+fail:
+    /* Just put anything nonzero so that the ioctl fails in the guest.  */
+    stl_p(&req->scsi->errors, 255);
+    virtio_blk_req_complete(req, status);
     g_free(req);
 }
-#endif /* __linux__ */
 
 typedef struct MultiReqBuffer {
     BlockRequest        blkreq[32];
@@ -394,7 +389,7 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
          * terminated by '\0' only when shorter than buffer.
          */
         strncpy(req->elem.in_sg[0].iov_base,
-                s->serial ? s->serial : "",
+                s->blk->serial ? s->blk->serial : "",
                 MIN(req->elem.in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES));
         virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
         g_free(req);
@@ -509,6 +504,7 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
     features |= (1 << VIRTIO_BLK_F_GEOMETRY);
     features |= (1 << VIRTIO_BLK_F_TOPOLOGY);
     features |= (1 << VIRTIO_BLK_F_BLK_SIZE);
+    features |= (1 << VIRTIO_BLK_F_SCSI);
 
     if (bdrv_enable_write_cache(s->bs))
         features |= (1 << VIRTIO_BLK_F_WCACHE);
@@ -537,11 +533,16 @@ static void virtio_blk_save(QEMUFile *f, void *opaque)
 static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
 {
     VirtIOBlock *s = opaque;
+    int ret;
 
     if (version_id != 2)
         return -EINVAL;
 
-    virtio_load(&s->vdev, f);
+    ret = virtio_load(&s->vdev, f);
+    if (ret) {
+        return ret;
+    }
+
     while (qemu_get_sbyte(f)) {
         VirtIOBlockReq *req = virtio_blk_alloc_request(s);
         qemu_get_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem));
@@ -568,28 +569,27 @@ static const BlockDevOps virtio_block_ops = {
     .resize_cb = virtio_blk_resize,
 };
 
-VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
-                              char **serial)
+VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
 {
     VirtIOBlock *s;
     int cylinders, heads, secs;
     static int virtio_blk_id;
     DriveInfo *dinfo;
 
-    if (!conf->bs) {
+    if (!blk->conf.bs) {
         error_report("drive property not set");
         return NULL;
     }
-    if (!bdrv_is_inserted(conf->bs)) {
+    if (!bdrv_is_inserted(blk->conf.bs)) {
         error_report("Device needs media, but drive is empty");
         return NULL;
     }
 
-    if (!*serial) {
+    if (!blk->serial) {
         /* try to fall back to value set with legacy -drive serial=... */
-        dinfo = drive_get_by_blockdev(conf->bs);
+        dinfo = drive_get_by_blockdev(blk->conf.bs);
         if (*dinfo->serial) {
-            *serial = strdup(dinfo->serial);
+            blk->serial = strdup(dinfo->serial);
         }
     }
 
@@ -600,9 +600,9 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
     s->vdev.get_config = virtio_blk_update_config;
     s->vdev.get_features = virtio_blk_get_features;
     s->vdev.reset = virtio_blk_reset;
-    s->bs = conf->bs;
-    s->conf = conf;
-    s->serial = *serial;
+    s->bs = blk->conf.bs;
+    s->conf = &blk->conf;
+    s->blk = blk;
     s->rq = NULL;
     s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
     bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
@@ -614,10 +614,10 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
     register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
                     virtio_blk_save, virtio_blk_load, s);
     bdrv_set_dev_ops(s->bs, &virtio_block_ops, s);
-    bdrv_set_buffer_alignment(s->bs, conf->logical_block_size);
+    bdrv_set_buffer_alignment(s->bs, s->conf->logical_block_size);
 
     bdrv_iostatus_enable(s->bs);
-    add_boot_device_path(conf->bootindex, dev, "/disk@0,0");
+    add_boot_device_path(s->conf->bootindex, dev, "/disk@0,0");
 
     return &s->vdev;
 }
@@ -626,5 +626,6 @@ void virtio_blk_exit(VirtIODevice *vdev)
 {
     VirtIOBlock *s = to_virtio_blk(vdev);
     unregister_savevm(s->qdev, "virtio-blk", s);
+    blockdev_mark_auto_del(s->bs);
     virtio_cleanup(vdev);
 }
index 244dce45aa31b9f6f85d3135c0d4e6cab3bf9475..d7850012bd023409628a55d9ef03fd45e6427744 100644 (file)
@@ -97,12 +97,14 @@ struct virtio_scsi_inhdr
     uint32_t residual;
 };
 
-#ifdef __linux__
-#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
-        DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
-        DEFINE_PROP_BIT("scsi", _state, _field, VIRTIO_BLK_F_SCSI, true)
-#else
+struct VirtIOBlkConf
+{
+    BlockConf conf;
+    char *serial;
+    uint32_t scsi;
+};
+
 #define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
         DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
-#endif
+
 #endif
index bc5e3a83d17e7b43bcaa9bad7fade5eb1dfefcb6..3f190d417efdd9ee8cd56eb026ae2bf817d32e2b 100644 (file)
@@ -891,11 +891,15 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
 {
     VirtIONet *n = opaque;
     int i;
+    int ret;
 
     if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION)
         return -EINVAL;
 
-    virtio_load(&n->vdev, f);
+    ret = virtio_load(&n->vdev, f);
+    if (ret) {
+        return ret;
+    }
 
     qemu_get_buffer(f, n->mac, ETH_ALEN);
     n->tx_waiting = qemu_get_be32(f);
index 4a4413d52c2bd0294974373f5e7b28a479c7d3e2..79b86f1aada448613e9ace9b738f9eff689dbc92 100644 (file)
@@ -491,7 +491,7 @@ static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
     virtio_config_writel(proxy->vdev, addr, val);
 }
 
-const MemoryRegionPortio virtio_portio[] = {
+static const MemoryRegionPortio virtio_portio[] = {
     { 0, 0x10000, 1, .write = virtio_pci_config_writeb, },
     { 0, 0x10000, 2, .write = virtio_pci_config_writew, },
     { 0, 0x10000, 4, .write = virtio_pci_config_writel, },
@@ -697,8 +697,7 @@ static int virtio_blk_init_pci(PCIDevice *pci_dev)
         proxy->class_code != PCI_CLASS_STORAGE_OTHER)
         proxy->class_code = PCI_CLASS_STORAGE_SCSI;
 
-    vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block,
-                           &proxy->block_serial);
+    vdev = virtio_blk_init(&pci_dev->qdev, &proxy->blk);
     if (!vdev) {
         return -1;
     }
@@ -726,7 +725,6 @@ static int virtio_blk_exit_pci(PCIDevice *pci_dev)
 
     virtio_pci_stop_ioeventfd(proxy);
     virtio_blk_exit(proxy->vdev);
-    blockdev_mark_auto_del(proxy->block.bs);
     return virtio_exit_pci(pci_dev);
 }
 
@@ -814,8 +812,11 @@ static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
 
 static Property virtio_blk_properties[] = {
     DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
-    DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
-    DEFINE_PROP_STRING("serial", VirtIOPCIProxy, block_serial),
+    DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, blk.conf),
+    DEFINE_PROP_STRING("serial", VirtIOPCIProxy, blk.serial),
+#ifdef __linux__
+    DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),
+#endif
     DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
     DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
index e5604282e5baf5f99af7546660916476fe62336d..889e59e4210505fdca7d32419357250b56e7d365 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef QEMU_VIRTIO_PCI_H
 #define QEMU_VIRTIO_PCI_H
 
+#include "virtio-blk.h"
 #include "virtio-net.h"
 #include "virtio-serial.h"
 #include "virtio-scsi.h"
@@ -32,8 +33,7 @@ typedef struct {
     uint32_t flags;
     uint32_t class_code;
     uint32_t nvectors;
-    BlockConf block;
-    char *block_serial;
+    VirtIOBlkConf blk;
     NICConf nic;
     uint32_t host_features;
 #ifdef CONFIG_LINUX
index e8328f46529660b255bb863be486800b1d10be8e..5e39ce93c46c345115b01d0db5a96e8f149f19c1 100644 (file)
@@ -564,7 +564,12 @@ static void virtio_scsi_save(QEMUFile *f, void *opaque)
 static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id)
 {
     VirtIOSCSI *s = opaque;
-    virtio_load(&s->vdev, f);
+    int ret;
+
+    ret = virtio_load(&s->vdev, f);
+    if (ret) {
+        return ret;
+    }
     return 0;
 }
 
index ffbdfc2de185cc7aaa183c6c490d3630cffa0da3..72287d10ce45d378e1515d8d1c7392cb6a8ca986 100644 (file)
@@ -637,13 +637,17 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
     VirtIOSerialPort *port;
     uint32_t max_nr_ports, nr_active_ports, ports_map;
     unsigned int i;
+    int ret;
 
     if (version_id > 3) {
         return -EINVAL;
     }
 
     /* The virtio device */
-    virtio_load(&s->vdev, f);
+    ret = virtio_load(&s->vdev, f);
+    if (ret) {
+        return ret;
+    }
 
     if (version_id < 2) {
         return 0;
index 0aef7d1bc03d3ce39301d1aaf7421c80de3bf24c..85aabe53d84ae4e531b18aa5ec5a159c39f3697f 100644 (file)
@@ -191,8 +191,8 @@ void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
                         void *opaque);
 
 /* Base devices.  */
-VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
-                              char **serial);
+typedef struct VirtIOBlkConf VirtIOBlkConf;
+VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk);
 struct virtio_net_conf;
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
                               struct virtio_net_conf *net);
index 7125d1cd4bc2d1c8b262caf4f4b009b961e2a376..d9468fea908a5c92d266d348b0163207aceb7fa0 100644 (file)
@@ -573,6 +573,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
     page_dump(stdout);
     printf("\n");
 #endif
+    tb_invalidate_phys_range(start, start + len, 0);
     mmap_unlock();
     return start;
 fail:
@@ -675,8 +676,10 @@ int target_munmap(abi_ulong start, abi_ulong len)
         }
     }
 
-    if (ret == 0)
+    if (ret == 0) {
         page_set_flags(start, start + len, 0);
+        tb_invalidate_phys_range(start, start + len, 0);
+    }
     mmap_unlock();
     return ret;
 }
@@ -754,6 +757,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
         page_set_flags(old_addr, old_addr + old_size, 0);
         page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);
     }
+    tb_invalidate_phys_range(new_addr, new_addr + new_size, 0);
     mmap_unlock();
     return new_addr;
 }
index 692b57067505836fe22dede0c5b757cbd46b2080..d4055d262a77c89af7ff2fc4ee415cf56b1b2f8a 100644 (file)
 # @guest-shutdown:
 #
 # Initiate guest-activated shutdown. Note: this is an asynchronous
-# shutdown request, with no guaruntee of successful shutdown. Errors
-# will be logged to guest's syslog.
+# shutdown request, with no guarantee of successful shutdown.
 #
 # @mode: #optional "halt", "powerdown" (default), or "reboot"
 #
-# Returns: Nothing on success
+# This command does NOT return a response on success. Success condition
+# is indicated by the VM exiting with a zero exit status or, when
+# running with --no-shutdown, by issuing the query-status QMP command
+# to confirm the VM status is "shutdown".
 #
 # Since: 0.15.0
 ##
-{ 'command': 'guest-shutdown', 'data': { '*mode': 'str' } }
+{ 'command': 'guest-shutdown', 'data': { '*mode': 'str' },
+  'success-response': 'no' }
 
 ##
 # @guest-file-open:
 # For the best results it's strongly recommended to have the pm-utils
 # package installed in the guest.
 #
-# Returns: nothing on success
+# This command does NOT return a response on success. There is a high chance
+# the command succeeded if the VM exits with a zero exit status or, when
+# running with --no-shutdown, by issuing the query-status QMP command to
+# to confirm the VM status is "shutdown". However, the VM could also exit
+# (or set its status to "shutdown") due to other reasons.
+#
+# The following errors may be returned:
 #          If suspend to disk is not supported, Unsupported
 #
-# Notes: o This is an asynchronous request. There's no guarantee a response
-#          will be sent
-#        o It's strongly recommended to issue the guest-sync command before
-#          sending commands when the guest resumes
+# Notes: It's strongly recommended to issue the guest-sync command before
+#        sending commands when the guest resumes
 #
 # Since: 1.1
 ##
-{ 'command': 'guest-suspend-disk' }
+{ 'command': 'guest-suspend-disk', 'success-response': 'no' }
 
 ##
 # @guest-suspend-ram
 # command.  Thus, it's *required* to query QEMU for the presence of the
 # 'system_wakeup' command before issuing guest-suspend-ram.
 #
-# Returns: nothing on success
+# This command does NOT return a response on success. There are two options
+# to check for success:
+#   1. Wait for the SUSPEND QMP event from QEMU
+#   2. Issue the query-status QMP command to confirm the VM status is
+#      "suspended"
+#
+# The following errors may be returned:
 #          If suspend to ram is not supported, Unsupported
 #
-# Notes: o This is an asynchronous request. There's no guarantee a response
-#          will be sent
-#        o It's strongly recommended to issue the guest-sync command before
-#          sending commands when the guest resumes
+# Notes: It's strongly recommended to issue the guest-sync command before
+#        sending commands when the guest resumes
 #
 # Since: 1.1
 ##
-{ 'command': 'guest-suspend-ram' }
+{ 'command': 'guest-suspend-ram', 'success-response': 'no' }
 
 ##
 # @guest-suspend-hybrid
 # command.  Thus, it's *required* to query QEMU for the presence of the
 # 'system_wakeup' command before issuing guest-suspend-hybrid.
 #
-# Returns: nothing on success
+# This command does NOT return a response on success. There are two options
+# to check for success:
+#   1. Wait for the SUSPEND QMP event from QEMU
+#   2. Issue the query-status QMP command to confirm the VM status is
+#      "suspended"
+#
+# The following errors may be returned:
 #          If hybrid suspend is not supported, Unsupported
 #
-# Notes: o This is an asynchronous request. There's no guarantee a response
-#          will be sent
-#        o It's strongly recommended to issue the guest-sync command before
-#          sending commands when the guest resumes
+# Notes: It's strongly recommended to issue the guest-sync command before
+#        sending commands when the guest resumes
 #
 # Since: 1.1
 ##
-{ 'command': 'guest-suspend-hybrid' }
+{ 'command': 'guest-suspend-hybrid', 'success-response': 'no' }
 
 ##
 # @GuestIpAddressType:
index 431ddbb33730390e8b73b4035cb1b6a0c1029ab1..b0f64ba1ee8a39efa92ebd702eab5705a47df6b9 100644 (file)
@@ -25,16 +25,24 @@ typedef enum QmpCommandType
     QCT_NORMAL,
 } QmpCommandType;
 
+typedef enum QmpCommandOptions
+{
+    QCO_NO_OPTIONS = 0x0,
+    QCO_NO_SUCCESS_RESP = 0x1,
+} QmpCommandOptions;
+
 typedef struct QmpCommand
 {
     const char *name;
     QmpCommandType type;
     QmpCommandFunc *fn;
+    QmpCommandOptions options;
     QTAILQ_ENTRY(QmpCommand) node;
     bool enabled;
 } QmpCommand;
 
-void qmp_register_command(const char *name, QmpCommandFunc *fn);
+void qmp_register_command(const char *name, QmpCommandFunc *fn,
+                          QmpCommandOptions options);
 QmpCommand *qmp_find_command(const char *name);
 QObject *qmp_dispatch(QObject *request);
 void qmp_disable_command(const char *name);
index 43f640a95e702f322365e61c12699986242ca915..122c1a29bac4d1e7388469e0ce233e218eedfed0 100644 (file)
@@ -94,8 +94,12 @@ static QObject *do_qmp_dispatch(QObject *request, Error **errp)
     switch (cmd->type) {
     case QCT_NORMAL:
         cmd->fn(args, &ret, errp);
-        if (!error_is_set(errp) && ret == NULL) {
-            ret = QOBJECT(qdict_new());
+        if (!error_is_set(errp)) {
+            if (cmd->options & QCO_NO_SUCCESS_RESP) {
+                g_assert(!ret);
+            } else if (!ret) {
+                ret = QOBJECT(qdict_new());
+            }
         }
         break;
     }
index 43d5cdeb64fd7171d8469b5d14fdd496e7af4861..54146133772d9483d6d64d07136ca75211d17b70 100644 (file)
@@ -17,7 +17,8 @@
 static QTAILQ_HEAD(QmpCommandList, QmpCommand) qmp_commands =
     QTAILQ_HEAD_INITIALIZER(qmp_commands);
 
-void qmp_register_command(const char *name, QmpCommandFunc *fn)
+void qmp_register_command(const char *name, QmpCommandFunc *fn,
+                          QmpCommandOptions options)
 {
     QmpCommand *cmd = g_malloc0(sizeof(*cmd));
 
@@ -25,6 +26,7 @@ void qmp_register_command(const char *name, QmpCommandFunc *fn)
     cmd->type = QCT_NORMAL;
     cmd->fn = fn;
     cmd->enabled = true;
+    cmd->options = options;
     QTAILQ_INSERT_TAIL(&qmp_commands, cmd, node);
 }
 
index 680997ebd3e57b38bdd7c607bf1ad96565c4bfc0..8199da789cab6445b4a0e59b1378372638fba680 100644 (file)
--- a/qemu-ga.c
+++ b/qemu-ga.c
@@ -104,16 +104,9 @@ static void quit_handler(int sig)
 }
 
 #ifndef _WIN32
-/* reap _all_ terminated children */
-static void child_handler(int sig)
-{
-    int status;
-    while (waitpid(-1, &status, WNOHANG) > 0) /* NOTHING */;
-}
-
 static gboolean register_signal_handlers(void)
 {
-    struct sigaction sigact, sigact_chld;
+    struct sigaction sigact;
     int ret;
 
     memset(&sigact, 0, sizeof(struct sigaction));
@@ -130,15 +123,24 @@ static gboolean register_signal_handlers(void)
         return false;
     }
 
-    memset(&sigact_chld, 0, sizeof(struct sigaction));
-    sigact_chld.sa_handler = child_handler;
-    sigact_chld.sa_flags = SA_NOCLDSTOP;
-    ret = sigaction(SIGCHLD, &sigact_chld, NULL);
-    if (ret == -1) {
-        g_error("error configuring signal handler: %s", strerror(errno));
+    return true;
+}
+
+/* TODO: use this in place of all post-fork() fclose(std*) callers */
+void reopen_fd_to_null(int fd)
+{
+    int nullfd;
+
+    nullfd = open("/dev/null", O_RDWR);
+    if (nullfd < 0) {
+        return;
     }
 
-    return true;
+    dup2(nullfd, fd);
+
+    if (nullfd != fd) {
+        close(nullfd);
+    }
 }
 #endif
 
@@ -167,7 +169,7 @@ static void usage(const char *cmd)
 "  -h, --help        display this help and exit\n"
 "\n"
 "Report bugs to <mdroth@linux.vnet.ibm.com>\n"
-    , cmd, QGA_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT,
+    , cmd, QEMU_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT,
     QGA_STATEDIR_DEFAULT);
 }
 
@@ -428,9 +430,9 @@ static void become_daemon(const char *pidfile)
         goto fail;
     }
 
-    close(STDIN_FILENO);
-    close(STDOUT_FILENO);
-    close(STDERR_FILENO);
+    reopen_fd_to_null(STDIN_FILENO);
+    reopen_fd_to_null(STDOUT_FILENO);
+    reopen_fd_to_null(STDERR_FILENO);
     return;
 
 fail:
@@ -488,8 +490,6 @@ static void process_command(GAState *s, QDict *req)
             g_warning("error sending response: %s", strerror(ret));
         }
         qobject_decref(rsp);
-    } else {
-        g_warning("error getting response");
     }
 }
 
@@ -729,7 +729,7 @@ int main(int argc, char **argv)
             log_level = G_LOG_LEVEL_MASK;
             break;
         case 'V':
-            printf("QEMU Guest Agent %s\n", QGA_VERSION);
+            printf("QEMU Guest Agent %s\n", QEMU_VERSION);
             return 0;
         case 'd':
             daemonize = 1;
@@ -836,12 +836,13 @@ int main(int argc, char **argv)
             become_daemon(pid_filepath);
         }
         if (log_filepath) {
-            s->log_file = fopen(log_filepath, "a");
-            if (!s->log_file) {
+            FILE *log_file = fopen(log_filepath, "a");
+            if (!log_file) {
                 g_critical("unable to open specified log file: %s",
                            strerror(errno));
                 goto out_bad;
             }
+            s->log_file = log_file;
         }
     }
 
index b2ca3a542cd3c7aacc262f3f38a2b3d0d76be55f..6fc3c28e0d6492bfd61fd03ad9346be48677ac14 100644 (file)
@@ -159,6 +159,24 @@ It can be used without an accessible old backing file, i.e. you can use it to
 fix an image whose backing file has already been moved/renamed.
 @end table
 
+You can use @code{rebase} to perform a ``diff'' operation on two
+disk images.  This can be useful when you have copied or cloned
+a guest, and you want to get back to a thin image on top of a
+template or base image.
+
+Say that @code{base.img} has been cloned as @code{modified.img} by
+copying it, and that the @code{modified.img} guest has run so there
+are now some changes compared to @code{base.img}.  To construct a thin
+image called @code{diff.qcow2} that contains just the differences, do:
+
+@example
+qemu-img create -f qcow2 -b modified.img diff.qcow2
+qemu-img rebase -b base.img diff.qcow2
+@end example
+
+At this point, @code{modified.img} can be discarded, since
+@code{base.img + diff.qcow2} contains the same information.
+
 @item resize @var{filename} [+ | -]@var{size}
 
 Change the disk image as if it had been created with @var{size}.
index e448431c66e658068e9dc94b6337e83089c1d296..dab3bf9c9875629806f930cc46693d3f6a8b19de 100644 (file)
 #include <glib.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
+#include <sys/wait.h>
 #include "qga/guest-agent-core.h"
 #include "qga-qmp-commands.h"
 #include "qerror.h"
 #include "qemu-queue.h"
 #include "host-utils.h"
 
+#ifndef CONFIG_HAS_ENVIRON
+extern char **environ;
+#endif
+
 #if defined(__linux__)
 #include <mntent.h>
 #include <linux/fs.h>
 #include <arpa/inet.h>
 #include <sys/socket.h>
 #include <net/if.h>
-#include <sys/wait.h>
 
 #if defined(__linux__) && defined(FIFREEZE)
 #define CONFIG_FSFREEZE
 #endif
 #endif
 
-#if defined(__linux__)
-/* TODO: use this in place of all post-fork() fclose(std*) callers */
-static void reopen_fd_to_null(int fd)
-{
-    int nullfd;
-
-    nullfd = open("/dev/null", O_RDWR);
-    if (nullfd < 0) {
-        return;
-    }
-
-    dup2(nullfd, fd);
-
-    if (nullfd != fd) {
-        close(nullfd);
-    }
-}
-#endif /* defined(__linux__) */
-
 void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
 {
-    int ret;
     const char *shutdown_flag;
+    pid_t rpid, pid;
+    int status;
 
     slog("guest-shutdown called, mode: %s", mode);
     if (!has_mode || strcmp(mode, "powerdown") == 0) {
@@ -71,23 +57,30 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
         return;
     }
 
-    ret = fork();
-    if (ret == 0) {
+    pid = fork();
+    if (pid == 0) {
         /* child, start the shutdown */
         setsid();
-        fclose(stdin);
-        fclose(stdout);
-        fclose(stderr);
-
-        ret = execl("/sbin/shutdown", "shutdown", shutdown_flag, "+0",
-                    "hypervisor initiated shutdown", (char*)NULL);
-        if (ret) {
-            slog("guest-shutdown failed: %s", strerror(errno));
-        }
-        exit(!!ret);
-    } else if (ret < 0) {
-        error_set(err, QERR_UNDEFINED_ERROR);
+        reopen_fd_to_null(0);
+        reopen_fd_to_null(1);
+        reopen_fd_to_null(2);
+
+        execle("/sbin/shutdown", "shutdown", shutdown_flag, "+0",
+               "hypervisor initiated shutdown", (char*)NULL, environ);
+        _exit(EXIT_FAILURE);
+    } else if (pid < 0) {
+        goto exit_err;
+    }
+
+    do {
+        rpid = waitpid(pid, &status, 0);
+    } while (rpid == -1 && errno == EINTR);
+    if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) {
+        return;
     }
+
+exit_err:
+    error_set(err, QERR_UNDEFINED_ERROR);
 }
 
 typedef struct GuestFileHandle {
@@ -531,117 +524,88 @@ static void guest_fsfreeze_cleanup(void)
 #define SUSPEND_SUPPORTED 0
 #define SUSPEND_NOT_SUPPORTED 1
 
-/**
- * This function forks twice and the information about the mode support
- * status is passed to the qemu-ga process via a pipe.
- *
- * This approach allows us to keep the way we reap terminated children
- * in qemu-ga quite simple.
- */
 static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg,
                                const char *sysfile_str, Error **err)
 {
-    pid_t pid;
-    ssize_t ret;
     char *pmutils_path;
-    int status, pipefds[2];
-
-    if (pipe(pipefds) < 0) {
-        error_set(err, QERR_UNDEFINED_ERROR);
-        return;
-    }
+    pid_t pid, rpid;
+    int status;
 
     pmutils_path = g_find_program_in_path(pmutils_bin);
 
     pid = fork();
     if (!pid) {
-        struct sigaction act;
-
-        memset(&act, 0, sizeof(act));
-        act.sa_handler = SIG_DFL;
-        sigaction(SIGCHLD, &act, NULL);
+        char buf[32]; /* hopefully big enough */
+        ssize_t ret;
+        int fd;
 
         setsid();
-        close(pipefds[0]);
         reopen_fd_to_null(0);
         reopen_fd_to_null(1);
         reopen_fd_to_null(2);
 
-        pid = fork();
-        if (!pid) {
-            int fd;
-            char buf[32]; /* hopefully big enough */
-
-            if (pmutils_path) {
-                execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
-            }
-
-            /*
-             * If we get here either pm-utils is not installed or execle() has
-             * failed. Let's try the manual method if the caller wants it.
-             */
-
-            if (!sysfile_str) {
-                _exit(SUSPEND_NOT_SUPPORTED);
-            }
-
-            fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
-            if (fd < 0) {
-                _exit(SUSPEND_NOT_SUPPORTED);
-            }
+        if (pmutils_path) {
+            execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
+        }
 
-            ret = read(fd, buf, sizeof(buf)-1);
-            if (ret <= 0) {
-                _exit(SUSPEND_NOT_SUPPORTED);
-            }
-            buf[ret] = '\0';
+        /*
+         * If we get here either pm-utils is not installed or execle() has
+         * failed. Let's try the manual method if the caller wants it.
+         */
 
-            if (strstr(buf, sysfile_str)) {
-                _exit(SUSPEND_SUPPORTED);
-            }
+        if (!sysfile_str) {
+            _exit(SUSPEND_NOT_SUPPORTED);
+        }
 
+        fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
+        if (fd < 0) {
             _exit(SUSPEND_NOT_SUPPORTED);
         }
 
-        if (pid > 0) {
-            wait(&status);
-        } else {
-            status = SUSPEND_NOT_SUPPORTED;
+        ret = read(fd, buf, sizeof(buf)-1);
+        if (ret <= 0) {
+            _exit(SUSPEND_NOT_SUPPORTED);
         }
+        buf[ret] = '\0';
 
-        ret = write(pipefds[1], &status, sizeof(status));
-        if (ret != sizeof(status)) {
-            _exit(EXIT_FAILURE);
+        if (strstr(buf, sysfile_str)) {
+            _exit(SUSPEND_SUPPORTED);
         }
 
-        _exit(EXIT_SUCCESS);
+        _exit(SUSPEND_NOT_SUPPORTED);
     }
 
-    close(pipefds[1]);
     g_free(pmutils_path);
 
     if (pid < 0) {
-        error_set(err, QERR_UNDEFINED_ERROR);
-        goto out;
-    }
-
-    ret = read(pipefds[0], &status, sizeof(status));
-    if (ret == sizeof(status) && WIFEXITED(status) &&
-        WEXITSTATUS(status) == SUSPEND_SUPPORTED) {
-            goto out;
+        goto undef_err;
+    }
+
+    do {
+        rpid = waitpid(pid, &status, 0);
+    } while (rpid == -1 && errno == EINTR);
+    if (rpid == pid && WIFEXITED(status)) {
+        switch (WEXITSTATUS(status)) {
+        case SUSPEND_SUPPORTED:
+            return;
+        case SUSPEND_NOT_SUPPORTED:
+            error_set(err, QERR_UNSUPPORTED);
+            return;
+        default:
+            goto undef_err;
+        }
     }
 
-    error_set(err, QERR_UNSUPPORTED);
-
-out:
-    close(pipefds[0]);
+undef_err:
+    error_set(err, QERR_UNDEFINED_ERROR);
 }
 
 static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
                           Error **err)
 {
-    pid_t pid;
     char *pmutils_path;
+    pid_t rpid, pid;
+    int status;
 
     pmutils_path = g_find_program_in_path(pmutils_bin);
 
@@ -683,9 +647,18 @@ static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
     g_free(pmutils_path);
 
     if (pid < 0) {
-        error_set(err, QERR_UNDEFINED_ERROR);
+        goto exit_err;
+    }
+
+    do {
+        rpid = waitpid(pid, &status, 0);
+    } while (rpid == -1 && errno == EINTR);
+    if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) {
         return;
     }
+
+exit_err:
+    error_set(err, QERR_UNDEFINED_ERROR);
 }
 
 void qmp_guest_suspend_disk(Error **err)
index 5bcceaae34a2ca2ecb4a6bd970ff4ea0e9add99b..46b0b083bc409c3e53963f870a3dc7f85340f58f 100644 (file)
@@ -52,7 +52,7 @@ struct GuestAgentInfo *qmp_guest_info(Error **err)
     GuestAgentCommandInfoList *cmd_info_list;
     char **cmd_list_head, **cmd_list;
 
-    info->version = g_strdup(QGA_VERSION);
+    info->version = g_strdup(QEMU_VERSION);
 
     cmd_list_head = cmd_list = qmp_get_command_list();
     if (*cmd_list_head == NULL) {
index bbb8b9b125056655bf9db11a74c7972650f5aaa0..49a7abee955d750665dfb36b22aefc6dee9898fa 100644 (file)
@@ -13,7 +13,6 @@
 #include "qapi/qmp-core.h"
 #include "qemu-common.h"
 
-#define QGA_VERSION "1.0"
 #define QGA_READ_COUNT_DEFAULT 4096
 
 typedef struct GAState GAState;
@@ -35,3 +34,7 @@ void ga_set_response_delimited(GAState *s);
 bool ga_is_frozen(GAState *s);
 void ga_set_frozen(GAState *s);
 void ga_unset_frozen(GAState *s);
+
+#ifndef _WIN32
+void reopen_fd_to_null(int fd);
+#endif
index 0b4f0a0fe117b950a0e43bee2268d0e3286ecf90..9eed40e18ae6096b21b59627ce91035ccd59d8b3 100644 (file)
@@ -291,14 +291,24 @@ out:
 
     return ret
 
+def option_value_matches(opt, val, cmd):
+    if opt in cmd and cmd[opt] == val:
+        return True
+    return False
+
 def gen_registry(commands):
     registry=""
     push_indent()
     for cmd in commands:
+        options = 'QCO_NO_OPTIONS'
+        if option_value_matches('success-response', 'no', cmd):
+            options = 'QCO_NO_SUCCESS_RESP'
+
         registry += mcgen('''
-qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s);
+qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s, %(opts)s);
 ''',
-                     name=cmd['command'], c_name=c_fun(cmd['command']))
+                     name=cmd['command'], c_name=c_fun(cmd['command']),
+                     opts=options)
     pop_indent()
     ret = mcgen('''
 static void qmp_init_marshal(void)
index 88c903fccd186e7746a267741c58e28e440407a8..e2ee5e304cc520b795fc8195b0c029a13a6f5aee 100644 (file)
 #define _IP_H_
 
 #ifdef HOST_WORDS_BIGENDIAN
-# ifndef NTOHL
-#  define NTOHL(d)
-# endif
-# ifndef NTOHS
-#  define NTOHS(d)
-# endif
-# ifndef HTONL
-#  define HTONL(d)
-# endif
-# ifndef HTONS
-#  define HTONS(d)
-# endif
+# undef NTOHL
+# undef NTOHS
+# undef HTONL
+# undef HTONS
+# define NTOHL(d)
+# define NTOHS(d)
+# define HTONL(d)
+# define HTONS(d)
 #else
 # ifndef NTOHL
 #  define NTOHL(d) ((d) = ntohl((d)))
index 82996031e0f894b99843d9592f5c4517cb6ac7f0..2e2b4033a6c9a2bc8b6e21cc0d58a398dc32ae92 100644 (file)
@@ -79,20 +79,23 @@ struct tcphdr {
 #define        TCPOPT_EOL              0
 #define        TCPOPT_NOP              1
 #define        TCPOPT_MAXSEG           2
-#define    TCPOLEN_MAXSEG              4
 #define TCPOPT_WINDOW          3
-#define    TCPOLEN_WINDOW              3
 #define TCPOPT_SACK_PERMITTED  4               /* Experimental */
-#define    TCPOLEN_SACK_PERMITTED      2
 #define TCPOPT_SACK            5               /* Experimental */
 #define TCPOPT_TIMESTAMP       8
-#define    TCPOLEN_TIMESTAMP           10
-#define    TCPOLEN_TSTAMP_APPA         (TCPOLEN_TIMESTAMP+2) /* appendix A */
 
 #define TCPOPT_TSTAMP_HDR      \
     (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
 #endif
 
+#ifndef TCPOLEN_MAXSEG
+#define    TCPOLEN_MAXSEG              4
+#define    TCPOLEN_WINDOW              3
+#define    TCPOLEN_SACK_PERMITTED      2
+#define    TCPOLEN_TIMESTAMP           10
+#define    TCPOLEN_TSTAMP_APPA         (TCPOLEN_TIMESTAMP+2) /* appendix A */
+#endif
+
 /*
  * Default maximum segment size for TCP.
  * With an IP MSS of 576, this is 536,
index 779314bf9a1a48015ce8e7effc667d68cadc63cd..8aa3d90470b0672acc4cd26dfe475add5571635d 100644 (file)
@@ -47,6 +47,7 @@ static const u_char  tcp_outflags[TCP_NSTATES] = {
 };
 
 
+#undef MAX_TCPOPTLEN
 #define MAX_TCPOPTLEN  32      /* max # bytes that go in options */
 
 /*
index 742b3957c0cba06963e663eb4cace70def053273..a362938e41ee2cb479b6218dcc03ce6e768435d7 100644 (file)
@@ -743,7 +743,7 @@ static void dec_bit(DisasContext *dc)
     unsigned int op;
     int mem_index = cpu_mmu_index(dc->env);
 
-    op = dc->ir & ((1 << 8) - 1);
+    op = dc->ir & ((1 << 9) - 1);
     switch (op) {
         case 0x21:
             /* src.  */
@@ -825,6 +825,16 @@ static void dec_bit(DisasContext *dc)
                 gen_helper_clz(cpu_R[dc->rd], cpu_R[dc->ra]);
             }
             break;
+        case 0x1e0:
+            /* swapb */
+            LOG_DIS("swapb r%d r%d\n", dc->rd, dc->ra);
+            tcg_gen_bswap32_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
+            break;
+        case 0x1e1:
+            /*swaph */
+            LOG_DIS("swaph r%d r%d\n", dc->rd, dc->ra);
+            tcg_gen_rotri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 16);
+            break;
         default:
             cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
                      dc->pc, op, dc->rd, dc->ra, dc->rb);
index f5297b039200cf583821f162ccef3a298dbacad6..0c563eedfa433ac3bcd76226ac9f511be5c15a7b 100644 (file)
@@ -6099,7 +6099,7 @@ static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t
             TCGv_i32 t1 = tcg_temp_new_i32();
             tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
             tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
-            tcg_gen_nor_i32(t0, t0, t1);
+            tcg_gen_nand_i32(t0, t0, t1);
             tcg_temp_free_i32(t1);
             tcg_gen_andi_i32(t0, t0, 1);
             tcg_gen_extu_i32_tl(bcond, t0);
@@ -6123,11 +6123,11 @@ static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t
             TCGv_i32 t1 = tcg_temp_new_i32();
             tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
             tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
-            tcg_gen_or_i32(t0, t0, t1);
+            tcg_gen_and_i32(t0, t0, t1);
             tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
-            tcg_gen_or_i32(t0, t0, t1);
+            tcg_gen_and_i32(t0, t0, t1);
             tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
-            tcg_gen_nor_i32(t0, t0, t1);
+            tcg_gen_nand_i32(t0, t0, t1);
             tcg_temp_free_i32(t1);
             tcg_gen_andi_i32(t0, t0, 1);
             tcg_gen_extu_i32_tl(bcond, t0);
index 4cde48d2fd21fa03cbb9be2da6aaadf1d7204373..d26569715b8a23fa006406d94193f93363dd6d91 100644 (file)
 
 static uint8_t *tb_ret_addr;
 
-#ifdef _CALL_DARWIN
+#if defined _CALL_DARWIN || defined __APPLE__
+#define TCG_TARGET_CALL_DARWIN
+#endif
+
+#ifdef TCG_TARGET_CALL_DARWIN
 #define LINKAGE_AREA_SIZE 24
 #define LR_OFFSET 8
 #elif defined _CALL_AIX
@@ -99,7 +103,7 @@ static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_R29,
     TCG_REG_R30,
     TCG_REG_R31,
-#ifdef _CALL_DARWIN
+#ifdef TCG_TARGET_CALL_DARWIN
     TCG_REG_R2,
 #endif
     TCG_REG_R3,
@@ -110,7 +114,7 @@ static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_R8,
     TCG_REG_R9,
     TCG_REG_R10,
-#ifndef _CALL_DARWIN
+#ifndef TCG_TARGET_CALL_DARWIN
     TCG_REG_R11,
 #endif
     TCG_REG_R12,
@@ -140,7 +144,7 @@ static const int tcg_target_call_oarg_regs[2] = {
 };
 
 static const int tcg_target_callee_save_regs[] = {
-#ifdef _CALL_DARWIN
+#ifdef TCG_TARGET_CALL_DARWIN
     TCG_REG_R11,
     TCG_REG_R13,
 #endif
@@ -1965,7 +1969,7 @@ static void tcg_target_init(TCGContext *s)
     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
     tcg_regset_set32(tcg_target_call_clobber_regs, 0,
                      (1 << TCG_REG_R0) |
-#ifdef _CALL_DARWIN
+#ifdef TCG_TARGET_CALL_DARWIN
                      (1 << TCG_REG_R2) |
 #endif
                      (1 << TCG_REG_R3) |
@@ -1983,7 +1987,7 @@ static void tcg_target_init(TCGContext *s)
     tcg_regset_clear(s->reserved_regs);
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);
-#ifndef _CALL_DARWIN
+#ifndef TCG_TARGET_CALL_DARWIN
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2);
 #endif
 #ifdef _CALL_SYSV
index 20e4da9fb2616b0ac7623c0940deb44fcfd4c29a..ab7f6670098f793396b6d489ed652ea6bfcc7e02 100644 (file)
@@ -18,8 +18,8 @@ check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
 # All QTests for now are POSIX-only, but the dependencies are
 # really in libqtest, not in the testcases themselves.
-check-qtest-i386-y = tests/rtc-test$(EXESUF)
 check-qtest-i386-y = tests/fdc-test$(EXESUF)
+check-qtest-i386-y += tests/rtc-test$(EXESUF)
 check-qtest-x86_64-y = $(check-qtest-i386-y)
 check-qtest-sparc-y = tests/m48t59-test$(EXESUF)
 check-qtest-sparc64-y = tests/m48t59-test$(EXESUF)
@@ -68,7 +68,7 @@ tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marsh
 
 tests/rtc-test$(EXESUF): tests/rtc-test.o $(trace-obj-y)
 tests/m48t59-test$(EXESUF): tests/m48t59-test.o $(trace-obj-y)
-tests/fdc-test$(EXESUF): tests/fdc-test.o tests/libqtest.o
+tests/fdc-test$(EXESUF): tests/fdc-test.o tests/libqtest.o $(trace-obj-y)
 
 # QTest rules
 
index 5b5dd7481f47ae530ed6b7955d4d163ee5918d95..22d24ac7dc4a459138e1f8edabe5af01c423feee 100644 (file)
@@ -63,6 +63,12 @@ char test_image[] = "/tmp/qtest.XXXXXX";
 #define assert_bit_set(data, mask) g_assert_cmphex((data) & (mask), ==, (mask))
 #define assert_bit_clear(data, mask) g_assert_cmphex((data) & (mask), ==, 0)
 
+static uint8_t base = 0x70;
+
+enum {
+    CMOS_FLOPPY     = 0x10,
+};
+
 static void floppy_send(uint8_t byte)
 {
     uint8_t msr;
@@ -108,34 +114,43 @@ static void send_step_pulse(void)
     cyl = (cyl + 1) % 4;
 }
 
-static void test_media_change(void)
+static uint8_t cmos_read(uint8_t reg)
 {
-    uint8_t dir;
+    outb(base + 0, reg);
+    return inb(base + 1);
+}
 
-    /* Media changed bit must be up-to-date after step pulse. Do two SEEKs
-     * because we may already happen to be on the right cylinder initially. */
-    send_step_pulse();
-    send_step_pulse();
-    dir = inb(FLOPPY_BASE + reg_dir);
-    assert_bit_clear(dir, DSKCHG);
+static void test_cmos(void)
+{
+    uint8_t cmos;
 
-    /* Eject the floppy and check that DSKCHG is set. Reading it out doesn't
-     * reset the bit. */
-    qmp("{'execute':'eject', 'arguments':{ 'device':'floppy0' }}");
-    qmp(""); /* ignore event */
+    cmos = cmos_read(CMOS_FLOPPY);
+    g_assert(cmos == 0x40);
+}
 
+static void test_no_media_on_start(void)
+{
+    uint8_t dir;
+
+    /* Media changed bit must be set all time after start if there is
+     * no media in drive. */
     dir = inb(FLOPPY_BASE + reg_dir);
     assert_bit_set(dir, DSKCHG);
     dir = inb(FLOPPY_BASE + reg_dir);
     assert_bit_set(dir, DSKCHG);
-
+    send_step_pulse();
     send_step_pulse();
     dir = inb(FLOPPY_BASE + reg_dir);
     assert_bit_set(dir, DSKCHG);
     dir = inb(FLOPPY_BASE + reg_dir);
     assert_bit_set(dir, DSKCHG);
+}
+
+static void test_media_change(void)
+{
+    uint8_t dir;
 
-    /* And then insert it again. DSKCHK should not be reset until a step pulse
+    /* Insert media in drive. DSKCHK should not be reset until a step pulse
      * is sent. */
     qmp("{'execute':'change', 'arguments':{ 'device':'floppy0', "
         "'target': '%s' }}", test_image);
@@ -152,6 +167,22 @@ static void test_media_change(void)
     assert_bit_clear(dir, DSKCHG);
     dir = inb(FLOPPY_BASE + reg_dir);
     assert_bit_clear(dir, DSKCHG);
+
+    /* Eject the floppy and check that DSKCHG is set. Reading it out doesn't
+     * reset the bit. */
+    qmp("{'execute':'eject', 'arguments':{ 'device':'floppy0' }}");
+    qmp(""); /* ignore event */
+
+    dir = inb(FLOPPY_BASE + reg_dir);
+    assert_bit_set(dir, DSKCHG);
+    dir = inb(FLOPPY_BASE + reg_dir);
+    assert_bit_set(dir, DSKCHG);
+
+    send_step_pulse();
+    dir = inb(FLOPPY_BASE + reg_dir);
+    assert_bit_set(dir, DSKCHG);
+    dir = inb(FLOPPY_BASE + reg_dir);
+    assert_bit_set(dir, DSKCHG);
 }
 
 int main(int argc, char **argv)
@@ -177,12 +208,12 @@ int main(int argc, char **argv)
     /* Run the tests */
     g_test_init(&argc, &argv, NULL);
 
-    cmdline = g_strdup_printf("-vnc none "
-        "-drive file=%s,if=floppy,cache=writeback ",
-        test_image);
+    cmdline = g_strdup_printf("-vnc none ");
 
     qtest_start(cmdline);
     qtest_irq_intercept_in(global_qtest, "ioapic");
+    qtest_add_func("/fdc/cmos", test_cmos);
+    qtest_add_func("/fdc/no_media_on_start", test_no_media_on_start);
     qtest_add_func("/fdc/media_change", test_media_change);
 
     ret = g_test_run();
index 56616a1b7d9a05e01dde4c63afb4895f828a1b3f..9d2d3472e775bf2baddf4f69e2b46f42baef1bd9 100755 (executable)
@@ -39,7 +39,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 . ./common.rc
 . ./common.filter
 
-_supported_fmt generic
+_supported_fmt qcow2
 _supported_proto generic
 _supported_os Linux
 
index 87cb96cabf87bc26ed255ddac34609c1461999fd..45c6bc1271c5685f036609a27594cb69135cc534 100644 (file)
@@ -602,9 +602,9 @@ escc_kbd_command(int val) "Command %d"
 escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x"
 
 # block/iscsi.c
-iscsi_aio_write10_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
+iscsi_aio_write16_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
 iscsi_aio_writev(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, void *acb) "iscsi %p sector_num %"PRId64" nb_sectors %d opaque %p acb %p"
-iscsi_aio_read10_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
+iscsi_aio_read16_cb(void *iscsi, int status, void *acb, int canceled) "iscsi %p status %d acb %p canceled %d"
 iscsi_aio_readv(void *iscsi, int64_t sector_num, int nb_sectors, void *opaque, void *acb) "iscsi %p sector_num %"PRId64" nb_sectors %d opaque %p acb %p"
 
 # hw/esp.c