Merge remote-tracking branch 'afaerber-or/cocoa-for-upstream' into staging

* afaerber-or/cocoa-for-upstream:
  cocoa: Suppress Cocoa frontend for -qtest
  arch_init: Fix AltiVec build on Darwin/ppc
diff --git a/block/iscsi.c b/block/iscsi.c
index d37c4ee..22888a0 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -25,10 +25,12 @@
 #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>
@@ -37,8 +39,10 @@
 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 @@
 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 @@
 
 
 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 @@
 
     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 @@
     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 @@
 
     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 @@
 }
 
 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 @@
 
     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 @@
     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 @@
         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;
     }
@@ -491,6 +564,98 @@
 }
 
 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 @@
         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;
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 10c22fe..4b3345b 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -762,7 +762,6 @@
     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 @@
     /* 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);
+        int ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
+        if (ret < 0) {
+            return ret;
+        }
+        *nb_clusters = ret;
+        return 0;
     }
-
-    if (cluster_offset < 0) {
-        return cluster_offset;
-    }
-    *host_offset = cluster_offset;
-    return 0;
 }
 
 /*
diff --git a/block/qcow2.c b/block/qcow2.c
index 655799c..c2e49cd 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -919,7 +919,8 @@
         ret = sizeof(*header);
         break;
     default:
-        return -EINVAL;
+        ret = -EINVAL;
+        goto fail;
     }
 
     buf += ret;
diff --git a/block/sheepdog.c b/block/sheepdog.c
index e01d371..6d52277 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -468,7 +468,7 @@
     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 @@
         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 @@
     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 @@
     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 @@
         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 @@
     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 @@
         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 @@
     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 @@
     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 @@
 
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
-        return -1;
+        return fd;
     }
 
     memset(buf, 0, sizeof(buf));
@@ -904,14 +909,17 @@
 
     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 @@
     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 @@
         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 @@
     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 @@
         return 0;
     default:
         error_report("%s", sd_strerror(rsp->result));
-        return -1;
+        return -EIO;
     }
 }
 
@@ -1082,10 +1090,12 @@
     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 @@
         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 @@
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
         error_report("failed to connect");
+        ret = fd;
         goto out;
     }
 
@@ -1139,7 +1151,7 @@
         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 @@
 
     fd = connect_to_sdog(addr, port);
     if (fd < 0) {
-        return -EIO;
+        return fd;
     }
 
     memset(buf, 0, sizeof(buf));
@@ -1177,7 +1189,7 @@
     closesocket(fd);
 
     if (ret) {
-        return -EIO;
+        return ret;
     }
 
     if (rsp->result != SD_RES_SUCCESS) {
@@ -1237,24 +1249,26 @@
 
 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 @@
             } else {
                 error_report("Invalid preallocation mode: '%s'",
                              options->value.s);
-                return -EINVAL;
+                ret = -EINVAL;
+                goto out;
             }
         }
         options++;
@@ -1278,7 +1293,8 @@
 
     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 @@
         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 @@
 
     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 @@
 
     if (ret < 0) {
         error_report("failed to update an inode.");
-        return -EIO;
     }
 
-    return 0;
+    return ret;
 }
 
 /*
@@ -1464,6 +1485,7 @@
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
         error_report("failed to connect");
+        ret = fd;
         goto out;
     }
 
@@ -1606,8 +1628,9 @@
 
     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 @@
     /* refresh inode. */
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
-        ret = -EIO;
+        ret = fd;
         goto cleanup;
     }
 
@@ -1732,7 +1755,6 @@
                        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 @@
     if (ret < 0) {
         error_report("failed to create inode for snapshot. %s",
                      strerror(errno));
-        ret = -EIO;
         goto cleanup;
     }
 
@@ -1752,7 +1773,6 @@
 
     if (ret < 0) {
         error_report("failed to read new inode info. %s", strerror(errno));
-        ret = -EIO;
         goto cleanup;
     }
 
@@ -1773,7 +1793,7 @@
     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 @@
     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 @@
     closesocket(fd);
 
     if (ret) {
-        ret = -ENOENT;
         goto out;
     }
 
@@ -1861,6 +1880,7 @@
 
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
+        ret = fd;
         goto out;
     }
 
@@ -1888,6 +1908,7 @@
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
         error_report("failed to connect");
+        ret = fd;
         goto out;
     }
 
@@ -1925,6 +1946,10 @@
 
     g_free(vdi_inuse);
 
+    if (ret < 0) {
+        return ret;
+    }
+
     return found;
 }
 
@@ -1940,8 +1965,7 @@
 
     fd = connect_to_sdog(s->addr, s->port);
     if (fd < 0) {
-        ret = -EIO;
-        goto cleanup;
+        return fd;
     }
 
     while (size) {
@@ -1965,7 +1989,6 @@
 
         if (ret < 0) {
             error_report("failed to save vmstate %s", strerror(errno));
-            ret = -EIO;
             goto cleanup;
         }
 
diff --git a/configure b/configure
index b55a792..1f338f8 100755
--- a/configure
+++ b/configure
@@ -2831,6 +2831,21 @@
     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 @@
   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)
diff --git a/hw/fdc.c b/hw/fdc.c
index cb4cd25..30d34e3 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -179,12 +179,14 @@
     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 @@
         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 @@
         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 @@
         }
 
         fd_init(drive);
-        fd_revalidate(drive);
+        fdctrl_change_cb(drive, 0);
         if (drive->bs) {
             bdrv_set_dev_ops(drive->bs, &fdctrl_block_ops, drive);
         }
diff --git a/hw/pc.c b/hw/pc.c
index 4d34a33..e81a06c 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -47,6 +47,7 @@
 #include "ui/qemu-spice.h"
 #include "memory.h"
 #include "exec-memory.h"
+#include "arch_init.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -382,7 +383,7 @@
     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);
@@ -1097,7 +1098,7 @@
     qemu_irq pit_alt_irq = NULL;
     qemu_irq rtc_irq = NULL;
     qemu_irq *a20_line;
-    ISADevice *i8042, *port92, *vmmouse, *pit;
+    ISADevice *i8042, *port92, *vmmouse, *pit = NULL;
     qemu_irq *cpu_exit_irq;
 
     register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
@@ -1126,16 +1127,18 @@
 
     qemu_register_boot_set(pc_boot_set, *rtc_state);
 
-    if (kvm_irqchip_in_kernel()) {
-        pit = kvm_pit_init(isa_bus, 0x40);
-    } else {
-        pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
+    if (!xen_enabled()) {
+        if (kvm_irqchip_in_kernel()) {
+            pit = kvm_pit_init(isa_bus, 0x40);
+        } else {
+            pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
+        }
+        if (hpet) {
+            /* connect PIT to output control line of the HPET */
+            qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));
+        }
+        pcspk_init(isa_bus, pit);
     }
-    if (hpet) {
-        /* connect PIT to output control line of the HPET */
-        qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));
-    }
-    pcspk_init(isa_bus, pit);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 8ab9bcd..f10f3ec 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -1561,7 +1561,7 @@
     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,
diff --git a/hw/xen_common.h b/hw/xen_common.h
index 7043c14..fe7f227 100644
--- a/hw/xen_common.h
+++ b/hw/xen_common.h
@@ -148,6 +148,6 @@
 }
 #endif
 
-void destroy_hvm_domain(void);
+void destroy_hvm_domain(bool reboot);
 
 #endif /* QEMU_HW_XEN_COMMON_H */
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 22dbd10..07594bc 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -48,7 +48,6 @@
 
 /* ------------------------------------------------------------- */
 
-static int syncwrite    = 0;
 static int batch_maps   = 0;
 
 static int max_requests = 32;
@@ -67,6 +66,7 @@
     QEMUIOVector        v;
     int                 presync;
     int                 postsync;
+    uint8_t             mapped;
 
     /* grant mapping */
     uint32_t            domids[BLKIF_MAX_SEGMENTS_PER_REQUEST];
@@ -154,7 +154,7 @@
     blkdev->requests_finished++;
 }
 
-static void ioreq_release(struct ioreq *ioreq)
+static void ioreq_release(struct ioreq *ioreq, bool finish)
 {
     struct XenBlkDev *blkdev = ioreq->blkdev;
 
@@ -162,7 +162,11 @@
     memset(ioreq, 0, sizeof(*ioreq));
     ioreq->blkdev = blkdev;
     QLIST_INSERT_HEAD(&blkdev->freelist, ioreq, list);
-    blkdev->requests_finished--;
+    if (finish) {
+        blkdev->requests_finished--;
+    } else {
+        blkdev->requests_inflight--;
+    }
 }
 
 /*
@@ -189,15 +193,10 @@
             ioreq->presync = 1;
             return 0;
         }
-        if (!syncwrite) {
-            ioreq->presync = ioreq->postsync = 1;
-        }
+        ioreq->presync = ioreq->postsync = 1;
         /* fall through */
     case BLKIF_OP_WRITE:
         ioreq->prot = PROT_READ; /* from memory */
-        if (syncwrite) {
-            ioreq->postsync = 1;
-        }
         break;
     default:
         xen_be_printf(&blkdev->xendev, 0, "error: unknown operation (%d)\n",
@@ -248,7 +247,7 @@
     XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev;
     int i;
 
-    if (ioreq->v.niov == 0) {
+    if (ioreq->v.niov == 0 || ioreq->mapped == 0) {
         return;
     }
     if (batch_maps) {
@@ -274,6 +273,7 @@
             ioreq->page[i] = NULL;
         }
     }
+    ioreq->mapped = 0;
 }
 
 static int ioreq_map(struct ioreq *ioreq)
@@ -281,7 +281,7 @@
     XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev;
     int i;
 
-    if (ioreq->v.niov == 0) {
+    if (ioreq->v.niov == 0 || ioreq->mapped == 1) {
         return 0;
     }
     if (batch_maps) {
@@ -313,9 +313,12 @@
             ioreq->blkdev->cnt_map++;
         }
     }
+    ioreq->mapped = 1;
     return 0;
 }
 
+static int ioreq_runio_qemu_aio(struct ioreq *ioreq);
+
 static void qemu_aio_complete(void *opaque, int ret)
 {
     struct ioreq *ioreq = opaque;
@@ -327,11 +330,19 @@
     }
 
     ioreq->aio_inflight--;
+    if (ioreq->presync) {
+        ioreq->presync = 0;
+        ioreq_runio_qemu_aio(ioreq);
+        return;
+    }
     if (ioreq->aio_inflight > 0) {
         return;
     }
     if (ioreq->postsync) {
-        bdrv_flush(ioreq->blkdev->bs);
+        ioreq->postsync = 0;
+        ioreq->aio_inflight++;
+        bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq);
+        return;
     }
 
     ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY;
@@ -351,7 +362,8 @@
 
     ioreq->aio_inflight++;
     if (ioreq->presync) {
-        bdrv_flush(blkdev->bs); /* FIXME: aio_flush() ??? */
+        bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq);
+        return 0;
     }
 
     switch (ioreq->req.operation) {
@@ -449,7 +461,7 @@
     while (!QLIST_EMPTY(&blkdev->finished)) {
         ioreq = QLIST_FIRST(&blkdev->finished);
         send_notify += blk_send_response_one(ioreq);
-        ioreq_release(ioreq);
+        ioreq_release(ioreq, true);
     }
     if (send_notify) {
         xen_be_send_notify(&blkdev->xendev);
@@ -505,7 +517,7 @@
             if (blk_send_response_one(ioreq)) {
                 xen_be_send_notify(&blkdev->xendev);
             }
-            ioreq_release(ioreq);
+            ioreq_release(ioreq, false);
             continue;
         }
 
diff --git a/qemu-img.texi b/qemu-img.texi
index b2ca3a5..6fc3c28 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -159,6 +159,24 @@
 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}.
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 7664be1..dab3bf9 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -14,12 +14,17 @@
 #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>
@@ -27,7 +32,6 @@
 #include <arpa/inet.h>
 #include <sys/socket.h>
 #include <net/if.h>
-#include <sys/wait.h>
 
 #if defined(__linux__) && defined(FIFREEZE)
 #define CONFIG_FSFREEZE
diff --git a/slirp/ip.h b/slirp/ip.h
index 88c903f..e2ee5e3 100644
--- a/slirp/ip.h
+++ b/slirp/ip.h
@@ -34,18 +34,14 @@
 #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)))
diff --git a/slirp/tcp.h b/slirp/tcp.h
index 8299603..2e2b403 100644
--- a/slirp/tcp.h
+++ b/slirp/tcp.h
@@ -79,20 +79,23 @@
 #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,
diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c
index 779314b..8aa3d90 100644
--- a/slirp/tcp_output.c
+++ b/slirp/tcp_output.c
@@ -47,6 +47,7 @@
 };
 
 
+#undef MAX_TCPOPTLEN
 #define MAX_TCPOPTLEN	32	/* max # bytes that go in options */
 
 /*
diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index 5b5dd74..22d24ac 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -63,6 +63,12 @@
 #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,14 +114,57 @@
     cyl = (cyl + 1) % 4;
 }
 
+static uint8_t cmos_read(uint8_t reg)
+{
+    outb(base + 0, reg);
+    return inb(base + 1);
+}
+
+static void test_cmos(void)
+{
+    uint8_t cmos;
+
+    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;
 
-    /* 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. */
+    /* 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);
+    qmp(""); /* ignore event (FIXME open -> open transition?!) */
+    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();
-    send_step_pulse();
+    dir = inb(FLOPPY_BASE + reg_dir);
+    assert_bit_clear(dir, DSKCHG);
     dir = inb(FLOPPY_BASE + reg_dir);
     assert_bit_clear(dir, DSKCHG);
 
@@ -134,24 +183,6 @@
     assert_bit_set(dir, DSKCHG);
     dir = inb(FLOPPY_BASE + reg_dir);
     assert_bit_set(dir, DSKCHG);
-
-    /* And then insert it again. DSKCHK should not be reset until a step pulse
-     * is sent. */
-    qmp("{'execute':'change', 'arguments':{ 'device':'floppy0', "
-        "'target': '%s' }}", test_image);
-    qmp(""); /* ignore event (FIXME open -> open transition?!) */
-    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_clear(dir, DSKCHG);
-    dir = inb(FLOPPY_BASE + reg_dir);
-    assert_bit_clear(dir, DSKCHG);
 }
 
 int main(int argc, char **argv)
@@ -177,12 +208,12 @@
     /* 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();
diff --git a/tests/qemu-iotests/035 b/tests/qemu-iotests/035
index 56616a1..9d2d347 100755
--- a/tests/qemu-iotests/035
+++ b/tests/qemu-iotests/035
@@ -39,7 +39,7 @@
 . ./common.rc
 . ./common.filter
 
-_supported_fmt generic
+_supported_fmt qcow2
 _supported_proto generic
 _supported_os Linux
 
diff --git a/trace-events b/trace-events
index 87cb96c..45c6bc1 100644
--- a/trace-events
+++ b/trace-events
@@ -602,9 +602,9 @@
 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
diff --git a/xen-all.c b/xen-all.c
index bdf9c0f..b5220cc 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -603,6 +603,10 @@
         qemu_register_reset(xen_reset_vcpu, first_cpu);
         xen_reset_vcpu(first_cpu);
     }
+    /* if rtc_clock is left to default (host_clock), disable it */
+    if (rtc_clock == host_clock) {
+        qemu_clock_enable(rtc_clock, false);
+    }
 }
 
 /* get the ioreq packets from share mem */
@@ -856,7 +860,7 @@
                     "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
                     req->state, req->data_is_ptr, req->addr,
                     req->data, req->count, req->size);
-            destroy_hvm_domain();
+            destroy_hvm_domain(false);
             return;
         }
 
@@ -870,10 +874,11 @@
          */
         if (runstate_is_running()) {
             if (qemu_shutdown_requested_get()) {
-                destroy_hvm_domain();
+                destroy_hvm_domain(false);
             }
             if (qemu_reset_requested_get()) {
                 qemu_system_reset(VMRESET_REPORT);
+                destroy_hvm_domain(true);
             }
         }
 
@@ -1159,7 +1164,7 @@
     return 0;
 }
 
-void destroy_hvm_domain(void)
+void destroy_hvm_domain(bool reboot)
 {
     XenXC xc_handle;
     int sts;
@@ -1168,12 +1173,15 @@
     if (xc_handle == XC_HANDLER_INITIAL_VALUE) {
         fprintf(stderr, "Cannot acquire xenctrl handle\n");
     } else {
-        sts = xc_domain_shutdown(xc_handle, xen_domid, SHUTDOWN_poweroff);
+        sts = xc_domain_shutdown(xc_handle, xen_domid,
+                                 reboot ? SHUTDOWN_reboot : SHUTDOWN_poweroff);
         if (sts != 0) {
-            fprintf(stderr, "? xc_domain_shutdown failed to issue poweroff, "
-                    "sts %d, %s\n", sts, strerror(errno));
+            fprintf(stderr, "xc_domain_shutdown failed to issue %s, "
+                    "sts %d, %s\n", reboot ? "reboot" : "poweroff",
+                    sts, strerror(errno));
         } else {
-            fprintf(stderr, "Issued domain %d poweroff\n", xen_domid);
+            fprintf(stderr, "Issued domain %d %s\n", xen_domid,
+                    reboot ? "reboot" : "poweroff");
         }
         xc_interface_close(xc_handle);
     }