]> xenbits.xensource.com Git - pvdrivers/win/xenvbd.git/commitdiff
Try to avoid dumping non-RAM pages
authorPaul Durrant <paul.durrant@citrix.com>
Fri, 26 Apr 2019 08:53:34 +0000 (09:53 +0100)
committerPaul Durrant <paul.durrant@citrix.com>
Fri, 26 Apr 2019 09:28:15 +0000 (10:28 +0100)
When XENCRSH sets up blkif requests they may end up referring to PFNs that
are ballooned out. When these requests reach the backend driver, it will
unsurprisingly encounter failures when trying to map or copy the data from
these PFNs, generally resulting in the request as a whole being failed and
a lot of noise being emitted to various logs.

This patch adds a check into PrepareReadWrite() to check the P2M type of
PFNs being dumped. If the type is found to be anything other than writable
RAM then the PFN is substituted with a buffer PFN, which will just contain
zeroes. The storage backend will be able to map or copy these pages, so
stalls in the dump process and useless log messages will be avoided.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
src/xencrsh/buffer.c
src/xencrsh/hvm.c
src/xencrsh/hvm.h
src/xencrsh/pdo.c

index 6c158b4e94a9af1510b3dafbe30b5d3e9e4352d5..530dacac7d60d27d2801be031c17b51c743c6398 100644 (file)
@@ -107,7 +107,7 @@ BufferGet(
     PXENVBD_BUFFER  Buf;
 
     if (__Buffer.Next == 0) {
-        // Warn!
+        LogWarning("failed to get buffer\n");
         return FALSE;
     }
     // find a free buffer, copy Buffer@Length into the buffer, return the BufferId and Pfn
index 77a9ba67b9bb091f9bba498bc42aacb1c4c4bf02..47fcc5bcd61c961b8c33a9acccd9788afcb542ea 100644 (file)
@@ -359,3 +359,34 @@ fail1:
 
     return status;
 }
+
+NTSTATUS
+HvmGetMemoryType(
+    IN  PFN_NUMBER              Pfn,
+    OUT ULONG                   *Type
+    )
+{
+    struct xen_hvm_get_mem_type op;
+    LONG_PTR                rc;
+    NTSTATUS                status;
+
+    RtlZeroMemory(&op, sizeof(struct xen_hvm_get_mem_type));
+
+    op.domid = DOMID_SELF;
+    op.pfn = Pfn;
+
+    rc = HvmOp(HVMOP_get_mem_type, &op);
+
+    if (rc < 0)
+        goto fail1;
+
+    *Type = op.mem_type;
+
+    return STATUS_SUCCESS;
+
+fail1:
+    ERRNO_TO_STATUS(-rc, status);
+    LogError("fail1 (%08x)\n", status);
+
+    return status;
+}
index 9b8f1dfb8ba36c8a5f7dab7c662218230f3afdd4..433d73a892a534dac1eaea5e9cf1404387740b5f 100644 (file)
@@ -59,4 +59,10 @@ HvmSetParameter(
     IN  ULONGLONG       Value
     );
 
+NTSTATUS
+HvmGetMemoryType(
+    IN  PFN_NUMBER      Pfn,
+    OUT ULONG           *Type
+    );
+
 #endif // _XENVBD_HVM_H
index 2ab764b600c7ffeab4316c50add6fc4fd24c9c50..c3a930091cc55fa4a9311fc482e3b862ef693aaa 100644 (file)
 #include "pdoinquiry.h"
 
 #include "austere.h"
+#include "hvm.h"
 #include "store.h"
 #include "gnttab.h"
 #include "evtchn.h"
 
+#include <xen/hvm/hvm_op.h>
 #include <xencdb.h>
 #include "log.h"
 #include "assert.h"
@@ -226,12 +228,17 @@ __CleanupRequest(
 
         // free bounce buffer
         if (Request->Segments[Index].BufferId) {
-            if (Request->Operation == BLKIF_OP_READ && CopyOut) {
-                BufferCopyOut(Request->Segments[Index].BufferId, (PUCHAR)Request->Segments[Index].Buffer, Request->Segments[Index].Length);
+            if (Request->Operation == BLKIF_OP_READ && CopyOut &&
+                Request->Segments[Index].Buffer) {
+                BufferCopyOut(Request->Segments[Index].BufferId,
+                              (PUCHAR)Request->Segments[Index].Buffer,
+                              Request->Segments[Index].Length);
             } 
             BufferPut(Request->Segments[Index].BufferId);
             Request->Segments[Index].BufferId = 0;
-            MmUnmapLockedPages(Request->Segments[Index].Buffer, &Request->Segments[Index].Mdl);
+            if (Request->Segments[Index].Buffer)
+                MmUnmapLockedPages(Request->Segments[Index].Buffer,
+                                   &Request->Segments[Index].Mdl);
         }
     }
 
@@ -428,6 +435,8 @@ PrepareReadWrite(
             SGIndex.LastLength = 0;
             __GetPhysAddr(SGList, &SGIndex, &PhysAddr, &PhysLen);
             if (__PhysAddrIsAligned(PhysAddr, PhysLen, SectorSize - 1)) {
+                ULONG Type;
+
                 // get first sector, last sector and count
                 FirstSector = (__Offset(PhysAddr) + SectorSize - 1) / SectorSize;
                 SectorsNow  = __Min(NumSectors - SectorsDone, SectorsPerPage - FirstSector);
@@ -438,6 +447,21 @@ PrepareReadWrite(
                
                 // simples - grab Pfn of PhysAddr
                 Pfn         = __Pfn(PhysAddr);
+
+                Status = HvmGetMemoryType(Pfn, &Type);
+                if (!NT_SUCCESS(Status))
+                    LogWarning("Unable to get type for PFN %lx\n", Pfn);
+                else if (Type != HVMMEM_ram_rw) {
+                    ULONG BufferId;
+
+                    if (!BufferGet(&BufferId, &Pfn)) {
+                        Pdo->NeedsWake = TRUE;
+                        __CleanupSrb(Srb);
+                        return STATUS_INSUFFICIENT_RESOURCES;
+                    }
+
+                    Request->Segments[Index2].BufferId = BufferId;
+                }
             } else {
                 PMDL        Mdl;
                 ULONG       BufferId;
@@ -1177,4 +1201,4 @@ PdoEvtchnInterruptHandler(
     )
 {
     FrontendEvtchnCallback(&Pdo->Frontend);
-}
\ No newline at end of file
+}