WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

Re: [Xen-devel] Windows Bug Check 0x101 issue

To: Kouya Shimura <kouya@xxxxxxxxxxxxxx>, Alan Cox <alan@xxxxxxxxxxxxxxxxxxx>
Subject: Re: [Xen-devel] Windows Bug Check 0x101 issue
From: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
Date: Thu, 27 Mar 2008 17:39:29 +0000
Cc: xen-devel@xxxxxxxxxxxxxxxxxxx, Keir Fraser <keir.fraser@xxxxxxxxxxxxx>, Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>
Delivery-date: Thu, 27 Mar 2008 10:41:22 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
In-reply-to: <7ktziseo9r.fsf@xxxxxxxxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <7k4pawfnxs.fsf@xxxxxxxxxxxxxxxxxxxxxxxxxx> <C40D3B88.15566%keir.fraser@xxxxxxxxxxxxx> <7k1w5zf50j.fsf@xxxxxxxxxxxxxxxxxxxxxxxxxx> <18408.57824.846687.465435@xxxxxxxxxxxxxxxxxxxxxxxx> <20080325175718.GT4411@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx> <7ky786dkup.fsf@xxxxxxxxxxxxxxxxxxxxxxxxxx> <18410.9596.488204.878357@xxxxxxxxxxxxxxxxxxxxxxxx> <7ktziseo9r.fsf@xxxxxxxxxxxxxxxxxxxxxxxxxx> <20080327090831.2a9f9b05@core> <18411.52353.526441.433440@xxxxxxxxxxxxxxxxxxxxxxxx> <20080327163046.7984cf3f@core>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Alan Cox writes ("Re: [Xen-devel] Windows Bug Check 0x101 issue"):
> Just leave the busy bit set forever, the host will get fed up of waiting,
> reset, rinse repeat a few times and (except for older Linux) then offline
> the device. Older Linux (ie drivers/ide) has problems coping with failed
> drives so will carry on spewing but limp along ok.

Thanks for the advice.  I think the patch below does this.  I have
compiled it but I don't have an easy setup for testing it and there
may be some side-effects on bizarre setups with emulated ide channels
with slaves but no masters.  Comments welcome.

Before we apply this: Kouya Shimra, could you test it and let us know
if it solves your original problem ?

Thanks,
Ian.

Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Modified-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Signed-off-by: Kouya Shimura <kouya@xxxxxxxxxxxxxx>

diff -r b667e220e556 tools/ioemu/block-qcow.c
--- a/tools/ioemu/block-qcow.c  Thu Mar 27 11:39:57 2008 +0000
+++ b/tools/ioemu/block-qcow.c  Thu Mar 27 15:22:33 2008 +0000
@@ -783,6 +783,13 @@ static void qcow_aio_cancel(BlockDriverA
     qemu_aio_release(acb);
 }
 
+static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BDRVQcowState *s = bs->opaque;
+    return bdrv_aio_flush(s->hd, cb, opaque);
+}
+
 static void qcow_close(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
@@ -957,6 +964,7 @@ BlockDriver bdrv_qcow = {
     .bdrv_aio_read = qcow_aio_read,
     .bdrv_aio_write = qcow_aio_write,
     .bdrv_aio_cancel = qcow_aio_cancel,
+    .bdrv_aio_flush = qcow_aio_flush,
     .aiocb_size = sizeof(QCowAIOCB),
     .bdrv_write_compressed = qcow_write_compressed,
     .bdrv_get_info = qcow_get_info,
diff -r b667e220e556 tools/ioemu/block-qcow2.c
--- a/tools/ioemu/block-qcow2.c Thu Mar 27 11:39:57 2008 +0000
+++ b/tools/ioemu/block-qcow2.c Thu Mar 27 15:22:33 2008 +0000
@@ -1005,6 +1005,13 @@ static void qcow_aio_cancel(BlockDriverA
     if (acb->hd_aiocb)
         bdrv_aio_cancel(acb->hd_aiocb);
     qemu_aio_release(acb);
+}
+
+static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BDRVQcowState *s = bs->opaque;
+    return bdrv_aio_flush(s->hd, cb, opaque);
 }
 
 static void qcow_close(BlockDriverState *bs)
@@ -2235,6 +2242,7 @@ BlockDriver bdrv_qcow2 = {
     .bdrv_aio_read = qcow_aio_read,
     .bdrv_aio_write = qcow_aio_write,
     .bdrv_aio_cancel = qcow_aio_cancel,
+    .bdrv_aio_flush = qcow_aio_flush,
     .aiocb_size = sizeof(QCowAIOCB),
     .bdrv_write_compressed = qcow_write_compressed,
 
diff -r b667e220e556 tools/ioemu/block-raw.c
--- a/tools/ioemu/block-raw.c   Thu Mar 27 11:39:57 2008 +0000
+++ b/tools/ioemu/block-raw.c   Thu Mar 27 15:22:33 2008 +0000
@@ -496,6 +496,21 @@ static void raw_aio_cancel(BlockDriverAI
         pacb = &acb->next;
     }
 }
+
+static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    RawAIOCB *acb;
+
+    acb = raw_aio_setup(bs, 0, NULL, 0, cb, opaque);
+    if (!acb)
+        return NULL;
+    if (aio_fsync(O_SYNC, &acb->aiocb) < 0) {
+        qemu_aio_release(acb);
+        return NULL;
+    }
+    return &acb->common;
+}
 #endif
 
 static void raw_close(BlockDriverState *bs)
@@ -621,6 +636,7 @@ BlockDriver bdrv_raw = {
     .bdrv_aio_read = raw_aio_read,
     .bdrv_aio_write = raw_aio_write,
     .bdrv_aio_cancel = raw_aio_cancel,
+    .bdrv_aio_flush = raw_aio_flush,
     .aiocb_size = sizeof(RawAIOCB),
 #endif
     .protocol_name = "file",
@@ -959,6 +975,7 @@ BlockDriver bdrv_host_device = {
     .bdrv_aio_read = raw_aio_read,
     .bdrv_aio_write = raw_aio_write,
     .bdrv_aio_cancel = raw_aio_cancel,
+    .bdrv_aio_flush = raw_aio_flush,
     .aiocb_size = sizeof(RawAIOCB),
 #endif
     .bdrv_pread = raw_pread,
diff -r b667e220e556 tools/ioemu/block.c
--- a/tools/ioemu/block.c       Thu Mar 27 11:39:57 2008 +0000
+++ b/tools/ioemu/block.c       Thu Mar 27 15:22:33 2008 +0000
@@ -48,6 +48,8 @@ static BlockDriverAIOCB *bdrv_aio_write_
         int64_t sector_num, const uint8_t *buf, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque);
 static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
+static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
+        BlockDriverCompletionFunc *cb, void *opaque);
 static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, 
                         uint8_t *buf, int nb_sectors);
 static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
@@ -155,6 +157,8 @@ void bdrv_register(BlockDriver *bdrv)
         bdrv->bdrv_read = bdrv_read_em;
         bdrv->bdrv_write = bdrv_write_em;
     }
+    if (!bdrv->bdrv_aio_flush)
+        bdrv->bdrv_aio_flush = bdrv_aio_flush_em;
     bdrv->next = first_drv;
     first_drv = bdrv;
 }
@@ -1138,6 +1142,17 @@ void bdrv_aio_cancel(BlockDriverAIOCB *a
     drv->bdrv_aio_cancel(acb);
 }
 
+BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, 
+                                 BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BlockDriver *drv = bs->drv;
+
+    if (!drv)
+        return NULL;
+
+    return drv->bdrv_aio_flush(bs, cb, opaque);
+}
+
 
 /**************************************************************/
 /* async block device emulation */
@@ -1213,6 +1228,14 @@ static void bdrv_aio_cancel_em(BlockDriv
     qemu_aio_release(acb);
 }
 #endif /* !QEMU_TOOL */
+
+static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+    bdrv_flush(bs);
+    cb(opaque, 0);
+    return NULL;
+}
 
 /**************************************************************/
 /* sync block device emulation */
diff -r b667e220e556 tools/ioemu/block_int.h
--- a/tools/ioemu/block_int.h   Thu Mar 27 11:39:57 2008 +0000
+++ b/tools/ioemu/block_int.h   Thu Mar 27 15:22:33 2008 +0000
@@ -49,6 +49,8 @@ struct BlockDriver {
         int64_t sector_num, const uint8_t *buf, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque);
     void (*bdrv_aio_cancel)(BlockDriverAIOCB *acb);
+    BlockDriverAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs,
+        BlockDriverCompletionFunc *cb, void *opaque);
     int aiocb_size;
 
     const char *protocol_name;
diff -r b667e220e556 tools/ioemu/hw/ide.c
--- a/tools/ioemu/hw/ide.c      Thu Mar 27 11:39:57 2008 +0000
+++ b/tools/ioemu/hw/ide.c      Thu Mar 27 17:27:59 2008 +0000
@@ -751,6 +751,7 @@ static inline void ide_set_irq(IDEState 
 static inline void ide_set_irq(IDEState *s)
 {
     BMDMAState *bm = s->bmdma;
+    if (!s->bs) return; /* yikes */
     if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) {
         if (bm) {
             bm->status |= BM_STATUS_INT;
@@ -916,6 +917,8 @@ static void ide_read_dma_cb(void *opaque
     int n;
     int64_t sector_num;
 
+    if (!s->bs) return; /* yikes */
+
     n = s->io_buffer_size >> 9;
     sector_num = ide_get_sector(s);
     if (n > 0) {
@@ -1024,6 +1027,8 @@ static void ide_write_dma_cb(void *opaqu
     int n;
     int64_t sector_num;
 
+    if (!s->bs) return; /* yikes */
+
     n = s->io_buffer_size >> 9;
     sector_num = ide_get_sector(s);
     if (n > 0) {
@@ -1070,6 +1075,39 @@ static void ide_sector_write_dma(IDEStat
     s->io_buffer_index = 0;
     s->io_buffer_size = 0;
     ide_dma_start(s, ide_write_dma_cb);
+}
+
+static void ide_device_utterly_broken(IDEState *s) {
+    s->status |= BUSY_STAT;
+    s->bs = NULL;
+    /* This prevents all future commands from working.  All of the
+     * asynchronous callbacks (and ide_set_irq, as a safety measure)
+     * check to see whether this has happened and bail if so.
+     */
+}
+
+static void ide_flush_cb(void *opaque, int ret)
+{
+    IDEState *s = opaque;
+
+    if (!s->bs) return; /* yikes */
+
+    if (ret) {
+        /* We are completely doomed.  The IDE spec does not permit us
+        * to return an error from a flush except via a protocol which
+        * requires us to say where the error is and which
+        * contemplates the guest repeating the flush attempt to
+        * attempt flush the remaining data.  We can't support that
+        * because f(data)sync (which is what the block drivers use
+        * eventually) doesn't report the necessary information or
+        * give us the necessary control.  So we make the disk vanish.
+        */
+       ide_device_utterly_broken(s);
+       return;
+    }
+    else
+        s->status = READY_STAT;
+    ide_set_irq(s);
 }
 
 static void ide_atapi_cmd_ok(IDEState *s)
@@ -1297,6 +1335,8 @@ static void ide_atapi_cmd_read_dma_cb(vo
     BMDMAState *bm = opaque;
     IDEState *s = bm->ide_if;
     int data_offset, n;
+
+    if (!s->bs) return; /* yikes */
 
     if (ret < 0) {
         ide_atapi_io_error(s, ret);
@@ -1703,6 +1743,8 @@ static void cdrom_change_cb(void *opaque
     IDEState *s = opaque;
     int64_t nb_sectors;
 
+    if (!s->bs) return; /* yikes */
+
     /* XXX: send interrupt too */
     bdrv_get_geometry(s->bs, &nb_sectors);
     s->nb_sectors = nb_sectors;
@@ -1806,8 +1848,8 @@ static void ide_ioport_write(void *opaqu
         printf("ide: CMD=%02x\n", val);
 #endif
         s = ide_if->cur_drive;
-        /* ignore commands to non existant slave */
-        if (s != ide_if && !s->bs) 
+        /* ignore commands to non existant device */
+        if (!s->bs) 
             break;
 
         switch(val) {
@@ -1976,10 +2018,8 @@ static void ide_ioport_write(void *opaqu
             break;
         case WIN_FLUSH_CACHE:
         case WIN_FLUSH_CACHE_EXT:
-            if (s->bs)
-                bdrv_flush(s->bs);
-           s->status = READY_STAT;
-            ide_set_irq(s);
+            s->status = BUSY_STAT;
+            bdrv_aio_flush(s->bs, ide_flush_cb, s);
             break;
         case WIN_IDLEIMMEDIATE:
         case WIN_STANDBY:
diff -r b667e220e556 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Thu Mar 27 11:39:57 2008 +0000
+++ b/tools/ioemu/vl.h  Thu Mar 27 15:22:33 2008 +0000
@@ -653,6 +653,8 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDr
                                  const uint8_t *buf, int nb_sectors,
                                  BlockDriverCompletionFunc *cb, void *opaque);
 void bdrv_aio_cancel(BlockDriverAIOCB *acb);
+BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, 
+                                 BlockDriverCompletionFunc *cb, void *opaque);
 
 void qemu_aio_init(void);
 void qemu_aio_poll(void);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel