Skip to contentSkip to conversation

ide_dma_cancel will result in partial DMA transfer (resend #4)

PATCH Applied Andrea Arcangeli 4 participants 10 messages Jul 27, 2010 – Jul 30, 2010

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ide_dma_cancel will result in partial DMA transfer (resend #4)

Subject: avoid canceling ide dma

From: Andrea Arcangeli <[email protected]>

The reason for not actually canceling the I/O is because with virtualization and lots of VM running, a guest fs may mistake a overload of the host, as an IDE timeout. So rather than canceling the I/O, it's safer to wait I/O completion and simulate that the I/O has completed just before the io cancellation was requested by the guest. This way if ntfs or an app writes data without checking for -EIO retval, and it thinks the write has succeeded, it's less likely to run into troubles. Similar issues for reads.

Furthermore because the DMA operation is splitted into many synchronous aio_read/write if there's more than one entry in the SG table, without this patch the DMA would be cancelled in the middle, something we've no idea if it happens on real hardware too or not. Overall this seems a great risk for zero gain.

This approach is sure safer than previous code given we can't pretend all guest fs code out there to check for errors and reply the DMA if it was completed partially, given a timeout would never materialize on a real harddisk unless there are defective blocks (and defective blocks are practically only an issue for reads never for writes in any recent hardware as writing to blocks is the way to fix them) or the harddisk breaks as a whole.

---

hw/ide/pci.c +19 -2
index 780fc5f..9f6d42a 100644
@@ -40,8 +40,25 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
     printf("%s: 0x%08x\n", __func__, val);
 #endif
     if (!(val & BM_CMD_START)) {
-        /* XXX: do it better */
-        ide_dma_cancel(bm);
+        /*
+	 * We can't cancel Scatter Gather DMA in the middle of the
+	 * operation or a partial (not full) DMA transfer would reach
+	 * the storage so we wait for completion instead (we beahve
+	 * like if the DMA was completed by the time the guest trying
+	 * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
+	 * set).
+	 *
+	 * In the future we'll be able to safely cancel the I/O if the
+	 * whole DMA operation will be submitted to disk with a single
+	 * aio operation with preadv/pwritev.
+	 */
+	if (bm->aiocb) {
+		qemu_aio_flush();
+		if (bm->aiocb)
+			printf("ide_dma_cancel: aiocb still pending");
+		if (bm->status & BM_STATUS_DMAING)
+			printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
+	}
         bm->cmd = val & 0x09;
     } else {
         if (!(bm->status & BM_STATUS_DMAING)) {
#1 lore raw
Quoted 49 lines · Andrea Arcangeli

Subject: avoid canceling ide dma

From: Andrea Arcangeli<[email protected]>

The reason for not actually canceling the I/O is because with virtualization and lots of VM running, a guest fs may mistake a overload of the host, as an IDE timeout. So rather than canceling the I/O, it's safer to wait I/O completion and simulate that the I/O has completed just before the io cancellation was requested by the guest. This way if ntfs or an app writes data without checking for -EIO retval, and it thinks the write has succeeded, it's less likely to run into troubles. Similar issues for reads.

Furthermore because the DMA operation is splitted into many synchronous aio_read/write if there's more than one entry in the SG table, without this patch the DMA would be cancelled in the middle, something we've no idea if it happens on real hardware too or not. Overall this seems a great risk for zero gain.

This approach is sure safer than previous code given we can't pretend all guest fs code out there to check for errors and reply the DMA if it was completed partially, given a timeout would never materialize on a real harddisk unless there are defective blocks (and defective blocks are practically only an issue for reads never for writes in any recent hardware as writing to blocks is the way to fix them) or the harddisk breaks as a whole.

---

hw/ide/pci.c +9 -2
index 780fc5f..9f6d42a 100644
@@ -40,8 +40,25 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
      printf("%s: 0x%08x\n", __func__, val);
  #endif
      if (!(val&  BM_CMD_START)) {
-        /* XXX: do it better */
-        ide_dma_cancel(bm);
+        /*
+	 * We can't cancel Scatter Gather DMA in the middle of the
+	 * operation or a partial (not full) DMA transfer would reach
+	 * the storage so we wait for completion instead (we beahve
+	 * like if the DMA was completed by the time the guest trying
+	 * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
+	 * set).
+	 *
+	 * In the future we'll be able to safely cancel the I/O if the

hw/ide/pci.c void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) · line 61

Quoted 10 lines
hw/ide/pci.c +9 -0
+	 * whole DMA operation will be submitted to disk with a single
+	 * aio operation with preadv/pwritev.
+	 */
+	if (bm->aiocb) {
+		qemu_aio_flush();
+		if (bm->aiocb)
+			printf("ide_dma_cancel: aiocb still pending");
+		if (bm->status&  BM_STATUS_DMAING)
+			printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
 

printf()s?

Regards,

Anthony Liguori

Quoted 7 lines
hw/ide/pci.c +1 -0
+	}
          bm->cmd = val&  0x09;
      } else {
          if (!(bm->status&  BM_STATUS_DMAING)) {
#2 lore raw
Quoted 1 line · Anthony Liguori

printf()s?

I see plenty of printf in that file, do you want them only under #ifdef DEBUG_IDE?

#3 lore raw
Quoted 7 lines · Andrea Arcangeli
Quoted 2 lines · Anthony Liguori

printf()s?

I see plenty of printf in that file, do you want them only under #ifdef DEBUG_IDE?

Yes.

Regards,

Anthony Liguori

#4 lore raw
Quoted 10 lines · Anthony Liguori
Quoted 7 lines · Andrea Arcangeli
Quoted 2 lines · Anthony Liguori

printf()s?

I see plenty of printf in that file, do you want them only under #ifdef DEBUG_IDE?

Yes.

Indented with 4 spaces too, but there are tabs, hope that's ok otherwise I need to undo my editor settings optimized for kernel (develock has quite an opinion on the tab/space issue ;).

=====
Subject: avoid canceling ide dma

From: Andrea Arcangeli <[email protected]>

The reason for not actually canceling the I/O is because with virtualization and lots of VM running, a guest fs may mistake a overload of the host, as an IDE timeout. So rather than canceling the I/O, it's safer to wait I/O completion and simulate that the I/O has completed just before the io cancellation was requested by the guest. This way if ntfs or an app writes data without checking for -EIO retval, and it thinks the write has succeeded, it's less likely to run into troubles. Similar issues for reads.

Furthermore because the DMA operation is splitted into many synchronous aio_read/write if there's more than one entry in the SG table, without this patch the DMA would be cancelled in the middle, something we've no idea if it happens on real hardware too or not. Overall this seems a great risk for zero gain.

This approach is sure safer than previous code given we can't pretend all guest fs code out there to check for errors and reply the DMA if it was completed partially, given a timeout would never materialize on a real harddisk unless there are defective blocks (and defective blocks are practically only an issue for reads never for writes in any recent hardware as writing to blocks is the way to fix them) or the harddisk breaks as a whole.

---

hw/ide/pci.c +21 -2
index 4331d77..a019e0d 100644
@@ -40,8 +40,27 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
     printf("%s: 0x%08x\n", __func__, val);
 #endif
     if (!(val & BM_CMD_START)) {
-        /* XXX: do it better */
-        ide_dma_cancel(bm);
+	/*
+	 * We can't cancel Scatter Gather DMA in the middle of the
+	 * operation or a partial (not full) DMA transfer would reach
+	 * the storage so we wait for completion instead (we beahve
+	 * like if the DMA was completed by the time the guest trying
+	 * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
+	 * set).
+	 *
+	 * In the future we'll be able to safely cancel the I/O if the
+	 * whole DMA operation will be submitted to disk with a single
+	 * aio operation with preadv/pwritev.
+	 */
+	if (bm->aiocb) {
+	    qemu_aio_flush();
+#ifdef DEBUG_IDE
+	    if (bm->aiocb)
+		printf("ide_dma_cancel: aiocb still pending");
+	    if (bm->status & BM_STATUS_DMAING)
+		printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
+#endif
+	}
         bm->cmd = val & 0x09;
     } else {
         if (!(bm->status & BM_STATUS_DMAING)) {
#5 lore raw
Quoted 14 lines · Andrea Arcangeli
Quoted 12 lines · Anthony Liguori
Quoted 10 lines · Andrea Arcangeli
Quoted 3 lines · Anthony Liguori

printf()s?

I see plenty of printf in that file, do you want them only under #ifdef DEBUG_IDE?

Quoted 6 lines
Quoted 2 lines

Yes.

Indented with 4 spaces too, but there are tabs, hope that's ok otherwise I need to undo my editor settings optimized for kernel (develock has quite an opinion on the tab/space issue ;).

No tabs, see CODING_STYLE.

Thanks.

Regards,

Anthony Liguori

Quoted 66 lines

=====
Subject: avoid canceling ide dma

From: Andrea Arcangeli<[email protected]>

The reason for not actually canceling the I/O is because with virtualization and lots of VM running, a guest fs may mistake a overload of the host, as an IDE timeout. So rather than canceling the I/O, it's safer to wait I/O completion and simulate that the I/O has completed just before the io cancellation was requested by the guest. This way if ntfs or an app writes data without checking for -EIO retval, and it thinks the write has succeeded, it's less likely to run into troubles. Similar issues for reads.

Furthermore because the DMA operation is splitted into many synchronous aio_read/write if there's more than one entry in the SG table, without this patch the DMA would be cancelled in the middle, something we've no idea if it happens on real hardware too or not. Overall this seems a great risk for zero gain.

This approach is sure safer than previous code given we can't pretend all guest fs code out there to check for errors and reply the DMA if it was completed partially, given a timeout would never materialize on a real harddisk unless there are defective blocks (and defective blocks are practically only an issue for reads never for writes in any recent hardware as writing to blocks is the way to fix them) or the harddisk breaks as a whole.

---

hw/ide/pci.c +21 -2
index 4331d77..a019e0d 100644
@@ -40,8 +40,27 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
      printf("%s: 0x%08x\n", __func__, val);
  #endif
      if (!(val&  BM_CMD_START)) {
-        /* XXX: do it better */
-        ide_dma_cancel(bm);
+	/*
+	 * We can't cancel Scatter Gather DMA in the middle of the
+	 * operation or a partial (not full) DMA transfer would reach
+	 * the storage so we wait for completion instead (we beahve
+	 * like if the DMA was completed by the time the guest trying
+	 * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
+	 * set).
+	 *
+	 * In the future we'll be able to safely cancel the I/O if the
+	 * whole DMA operation will be submitted to disk with a single
+	 * aio operation with preadv/pwritev.
+	 */
+	if (bm->aiocb) {
+	    qemu_aio_flush();
+#ifdef DEBUG_IDE
+	    if (bm->aiocb)
+		printf("ide_dma_cancel: aiocb still pending");
+	    if (bm->status&  BM_STATUS_DMAING)
+		printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
+#endif
+	}
          bm->cmd = val&  0x09;
      } else {
          if (!(bm->status&  BM_STATUS_DMAING)) {
#6 lore raw

Subject: avoid canceling ide dma

From: Andrea Arcangeli <[email protected]>

The reason for not actually canceling the I/O is because with virtualization and lots of VM running, a guest fs may mistake a overload of the host, as an IDE timeout. So rather than canceling the I/O, it's safer to wait I/O completion and simulate that the I/O has completed just before the io cancellation was requested by the guest. This way if ntfs or an app writes data without checking for -EIO retval, and it thinks the write has succeeded, it's less likely to run into troubles. Similar issues for reads.

Furthermore because the DMA operation is splitted into many synchronous aio_read/write if there's more than one entry in the SG table, without this patch the DMA would be cancelled in the middle, something we've no idea if it happens on real hardware too or not. Overall this seems a great risk for zero gain.

This approach is sure safer than previous code given we can't pretend all guest fs code out there to check for errors and reply the DMA if it was completed partially, given a timeout would never materialize on a real harddisk unless there are defective blocks (and defective blocks are practically only an issue for reads never for writes in any recent hardware as writing to blocks is the way to fix them) or the harddisk breaks as a whole.

---

hw/ide/pci.c +21 -2
index 4331d77..ec90f26 100644
@@ -40,8 +40,27 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
     printf("%s: 0x%08x\n", __func__, val);
 #endif
     if (!(val & BM_CMD_START)) {
-        /* XXX: do it better */
-        ide_dma_cancel(bm);
+        /*
+         * We can't cancel Scatter Gather DMA in the middle of the
+         * operation or a partial (not full) DMA transfer would reach
+         * the storage so we wait for completion instead (we beahve
+         * like if the DMA was completed by the time the guest trying
+         * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
+         * set).
+         *
+         * In the future we'll be able to safely cancel the I/O if the
+         * whole DMA operation will be submitted to disk with a single
+         * aio operation with preadv/pwritev.
+         */
+        if (bm->aiocb) {
+            qemu_aio_flush();
+#ifdef DEBUG_IDE
+            if (bm->aiocb)
+                printf("ide_dma_cancel: aiocb still pending");
+            if (bm->status & BM_STATUS_DMAING)
+                printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
+#endif
+        }
         bm->cmd = val & 0x09;
     } else {
         if (!(bm->status & BM_STATUS_DMAING)) {
Applied
#7 lore raw

Am 27.07.2010 21:04, schrieb Andrea Arcangeli:

Quoted 26 lines

Subject: avoid canceling ide dma

From: Andrea Arcangeli <[email protected]>

The reason for not actually canceling the I/O is because with virtualization and lots of VM running, a guest fs may mistake a overload of the host, as an IDE timeout. So rather than canceling the I/O, it's safer to wait I/O completion and simulate that the I/O has completed just before the io cancellation was requested by the guest. This way if ntfs or an app writes data without checking for -EIO retval, and it thinks the write has succeeded, it's less likely to run into troubles. Similar issues for reads.

Furthermore because the DMA operation is splitted into many synchronous aio_read/write if there's more than one entry in the SG table, without this patch the DMA would be cancelled in the middle, something we've no idea if it happens on real hardware too or not. Overall this seems a great risk for zero gain.

This approach is sure safer than previous code given we can't pretend all guest fs code out there to check for errors and reply the DMA if it was completed partially, given a timeout would never materialize on a real harddisk unless there are defective blocks (and defective blocks are practically only an issue for reads never for writes in any recent hardware as writing to blocks is the way to fix them) or the harddisk breaks as a whole.

Quoted 2 lines

Thanks, applied to the block branch.

Kevin

#8 lore raw
In reply to Andrea Arcangeli
Quoted 10 lines · Andrea Arcangeli
Quoted 9 lines · Anthony Liguori
Quoted 7 lines · Andrea Arcangeli
Quoted 2 lines · Anthony Liguori

printf()s?

I see plenty of printf in that file, do you want them only under #ifdef DEBUG_IDE?

Quoted 5 lines
Quoted 1 line

Yes.

Indented with 4 spaces too, but there are tabs, hope that's ok otherwise I need to undo my editor settings optimized for kernel (develock has quite an opinion on the tab/space issue ;).

No, it's not okay. Unfortunatelly when i hexdump -Ced previous submission the presence of tabs escaped me, sorry.

[..snip..]

Signature · 1 line
mailto:[email protected]
#9 lore raw
In reply to Andrea Arcangeli
Quoted 49 lines · Andrea Arcangeli

Subject: avoid canceling ide dma

From: Andrea Arcangeli <[email protected]>

The reason for not actually canceling the I/O is because with virtualization and lots of VM running, a guest fs may mistake a overload of the host, as an IDE timeout. So rather than canceling the I/O, it's safer to wait I/O completion and simulate that the I/O has completed just before the io cancellation was requested by the guest. This way if ntfs or an app writes data without checking for -EIO retval, and it thinks the write has succeeded, it's less likely to run into troubles. Similar issues for reads.

Furthermore because the DMA operation is splitted into many synchronous aio_read/write if there's more than one entry in the SG table, without this patch the DMA would be cancelled in the middle, something we've no idea if it happens on real hardware too or not. Overall this seems a great risk for zero gain.

This approach is sure safer than previous code given we can't pretend all guest fs code out there to check for errors and reply the DMA if it was completed partially, given a timeout would never materialize on a real harddisk unless there are defective blocks (and defective blocks are practically only an issue for reads never for writes in any recent hardware as writing to blocks is the way to fix them) or the harddisk breaks as a whole.

---

hw/ide/pci.c +9 -2
index 780fc5f..9f6d42a 100644
@@ -40,8 +40,25 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
     printf("%s: 0x%08x\n", __func__, val);
 #endif
     if (!(val & BM_CMD_START)) {
-        /* XXX: do it better */
-        ide_dma_cancel(bm);
+        /*
+	 * We can't cancel Scatter Gather DMA in the middle of the
+	 * operation or a partial (not full) DMA transfer would reach
+	 * the storage so we wait for completion instead (we beahve
+	 * like if the DMA was completed by the time the guest trying
+	 * to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
+	 * set).
+	 *
+	 * In the future we'll be able to safely cancel the I/O if the

hw/ide/pci.c void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) · line 61

Quoted 10 lines
hw/ide/pci.c +10 -0
+	 * whole DMA operation will be submitted to disk with a single
+	 * aio operation with preadv/pwritev.
+	 */
+	if (bm->aiocb) {
+		qemu_aio_flush();
+		if (bm->aiocb)
+			printf("ide_dma_cancel: aiocb still pending");
+		if (bm->status & BM_STATUS_DMAING)
+			printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
+	}

Indentation is off.

Quoted 5 lines
hw/ide/pci.c +0 -0
         bm->cmd = val & 0x09;
     } else {
         if (!(bm->status & BM_STATUS_DMAING)) {
Signature · 1 line
mailto:[email protected]