[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH] Add a Cap parameter to the XENBUS_CACHE Create method



There is currently no parameter to prevent a single cache from growing to
consume all available kernel memory. This patch adds such a parameter and
also adjusts the XENBUS_GNTTAB CreateCache method to take a similar
parameter.

These will allow client drivers to place limits on their caches to avoid,
for example, XENVBD starving XENVIF of grant table space.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 include/cache_interface.h  |  34 ++++++++++++++-
 include/gnttab_interface.h |  39 +++++++++++++++--
 include/revision.h         |   3 +-
 src/xenbus/cache.c         | 105 +++++++++++++++++++++++++++++++++++++++------
 src/xenbus/gnttab.c        |  58 ++++++++++++++++++++++++-
 5 files changed, 218 insertions(+), 21 deletions(-)

diff --git a/include/cache_interface.h b/include/cache_interface.h
index dae3ac6..ce50f4e 100644
--- a/include/cache_interface.h
+++ b/include/cache_interface.h
@@ -123,6 +123,20 @@ typedef VOID
     IN  PVOID   Argument
     );
 
+typedef NTSTATUS
+(*XENBUS_CACHE_CREATE_V1)(
+    IN  PINTERFACE                  Interface,
+    IN  const CHAR                  *Name,
+    IN  ULONG                       Size,
+    IN  ULONG                       Reservation,
+    IN  XENBUS_CACHE_CTOR           Ctor,
+    IN  XENBUS_CACHE_DTOR           Dtor,
+    IN  XENBUS_CACHE_ACQUIRE_LOCK   AcquireLock,
+    IN  XENBUS_CACHE_RELEASE_LOCK   ReleaseLock,
+    IN  PVOID                       Argument OPTIONAL,
+    OUT PXENBUS_CACHE               *Cache
+    );
+
 /*! \typedef XENBUS_CACHE_CREATE
     \brief Create a cache of objects of the given \a Size
 
@@ -130,6 +144,7 @@ typedef VOID
     \param Name A name for the cache which will be used in debug output
     \param Size The size of each object in bytes
     \param Reservation The target minimum population of the cache
+    \param Cap The maximum population of the cache
     \param Ctor A callback which is invoked when a new object created
     \param Dtor A callback which is invoked when an object is destroyed
     \param AcquireLock A callback invoked to acquire a spinlock
@@ -146,6 +161,7 @@ typedef NTSTATUS
     IN  const CHAR                  *Name,
     IN  ULONG                       Size,
     IN  ULONG                       Reservation,
+    IN  ULONG                       Cap,
     IN  XENBUS_CACHE_CTOR           Ctor,
     IN  XENBUS_CACHE_DTOR           Dtor,
     IN  XENBUS_CACHE_ACQUIRE_LOCK   AcquireLock,
@@ -211,13 +227,27 @@ struct _XENBUS_CACHE_INTERFACE_V1 {
     INTERFACE               Interface;
     XENBUS_CACHE_ACQUIRE    CacheAcquire;
     XENBUS_CACHE_RELEASE    CacheRelease;
+    XENBUS_CACHE_CREATE_V1  CacheCreateVersion1;
+    XENBUS_CACHE_GET        CacheGet;
+    XENBUS_CACHE_PUT        CachePut;
+    XENBUS_CACHE_DESTROY    CacheDestroy;
+};
+
+/*! \struct _XENBUS_CACHE_INTERFACE_V2
+    \brief CACHE interface version 1
+    \ingroup interfaces
+*/
+struct _XENBUS_CACHE_INTERFACE_V2 {
+    INTERFACE               Interface;
+    XENBUS_CACHE_ACQUIRE    CacheAcquire;
+    XENBUS_CACHE_RELEASE    CacheRelease;
     XENBUS_CACHE_CREATE     CacheCreate;
     XENBUS_CACHE_GET        CacheGet;
     XENBUS_CACHE_PUT        CachePut;
     XENBUS_CACHE_DESTROY    CacheDestroy;
 };
 
-typedef struct _XENBUS_CACHE_INTERFACE_V1 XENBUS_CACHE_INTERFACE, 
*PXENBUS_CACHE_INTERFACE;
+typedef struct _XENBUS_CACHE_INTERFACE_V2 XENBUS_CACHE_INTERFACE, 
*PXENBUS_CACHE_INTERFACE;
 
 /*! \def XENBUS_CACHE
     \brief Macro at assist in method invocation
@@ -228,6 +258,6 @@ typedef struct _XENBUS_CACHE_INTERFACE_V1 
XENBUS_CACHE_INTERFACE, *PXENBUS_CACHE
 #endif  // _WINDLL
 
 #define XENBUS_CACHE_INTERFACE_VERSION_MIN  1
-#define XENBUS_CACHE_INTERFACE_VERSION_MAX  1
+#define XENBUS_CACHE_INTERFACE_VERSION_MAX  2
 
 #endif  // _XENBUS_CACHE_INTERFACE_H
diff --git a/include/gnttab_interface.h b/include/gnttab_interface.h
index 61272ab..c34dbd0 100644
--- a/include/gnttab_interface.h
+++ b/include/gnttab_interface.h
@@ -72,12 +72,24 @@ typedef VOID
     IN  PINTERFACE  Interface
     );
 
+typedef NTSTATUS
+(*XENBUS_GNTTAB_CREATE_CACHE_V1)(
+    IN  PINTERFACE                  Interface,
+    IN  const CHAR                  *Name,
+    IN  ULONG                       Reservation,
+    IN  XENBUS_CACHE_ACQUIRE_LOCK   AcquireLock,
+    IN  XENBUS_CACHE_RELEASE_LOCK   ReleaseLock,
+    IN  PVOID                       Argument OPTIONAL,
+    OUT PXENBUS_GNTTAB_CACHE        *Cache
+    );
+
 /*! \typedef XENBUS_GNTTAB_CREATE_CACHE
     \brief Create a cache of grant table entries
 
     \param Interface The interface header
     \param Name A name for the cache which will be used in debug output
     \param Reservation The target minimum population of the cache
+    \param Cap The maximum population of the cache
     \param AcquireLock A callback invoked to acquire a spinlock
     \param ReleaseLock A callback invoked to release the spinlock
     \param Argument An optional context argument passed to the callbacks
@@ -88,6 +100,7 @@ typedef NTSTATUS
     IN  PINTERFACE                  Interface,
     IN  const CHAR                  *Name,
     IN  ULONG                       Reservation,
+    IN  ULONG                       Cap,
     IN  XENBUS_CACHE_ACQUIRE_LOCK   AcquireLock,
     IN  XENBUS_CACHE_RELEASE_LOCK   ReleaseLock,
     IN  PVOID                       Argument OPTIONAL,
@@ -228,7 +241,7 @@ struct _XENBUS_GNTTAB_INTERFACE_V1 {
     INTERFACE                           Interface;
     XENBUS_GNTTAB_ACQUIRE               GnttabAcquire;
     XENBUS_GNTTAB_RELEASE               GnttabRelease;
-    XENBUS_GNTTAB_CREATE_CACHE          GnttabCreateCache;
+    XENBUS_GNTTAB_CREATE_CACHE_V1       GnttabCreateCacheVersion1;
     XENBUS_GNTTAB_PERMIT_FOREIGN_ACCESS GnttabPermitForeignAccess;
     XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS GnttabRevokeForeignAccess;
     XENBUS_GNTTAB_GET_REFERENCE         GnttabGetReference;
@@ -243,7 +256,7 @@ struct _XENBUS_GNTTAB_INTERFACE_V2 {
     INTERFACE                           Interface;
     XENBUS_GNTTAB_ACQUIRE               GnttabAcquire;
     XENBUS_GNTTAB_RELEASE               GnttabRelease;
-    XENBUS_GNTTAB_CREATE_CACHE          GnttabCreateCache;
+    XENBUS_GNTTAB_CREATE_CACHE_V1       GnttabCreateCacheVersion1;
     XENBUS_GNTTAB_PERMIT_FOREIGN_ACCESS GnttabPermitForeignAccess;
     XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS GnttabRevokeForeignAccess;
     XENBUS_GNTTAB_GET_REFERENCE         GnttabGetReference;
@@ -260,6 +273,24 @@ struct _XENBUS_GNTTAB_INTERFACE_V3 {
     INTERFACE                           Interface;
     XENBUS_GNTTAB_ACQUIRE               GnttabAcquire;
     XENBUS_GNTTAB_RELEASE               GnttabRelease;
+    XENBUS_GNTTAB_CREATE_CACHE_V1       GnttabCreateCacheVersion1;
+    XENBUS_GNTTAB_PERMIT_FOREIGN_ACCESS GnttabPermitForeignAccess;
+    XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS GnttabRevokeForeignAccess;
+    XENBUS_GNTTAB_GET_REFERENCE         GnttabGetReference;
+    XENBUS_GNTTAB_QUERY_REFERENCE       GnttabQueryReference;
+    XENBUS_GNTTAB_DESTROY_CACHE         GnttabDestroyCache;
+    XENBUS_GNTTAB_MAP_FOREIGN_PAGES     GnttabMapForeignPages;
+    XENBUS_GNTTAB_UNMAP_FOREIGN_PAGES   GnttabUnmapForeignPages;
+};
+
+/*! \struct _XENBUS_GNTTAB_INTERFACE_V4
+    \brief GNTTAB interface version 4
+    \ingroup interfaces
+*/
+struct _XENBUS_GNTTAB_INTERFACE_V4 {
+    INTERFACE                           Interface;
+    XENBUS_GNTTAB_ACQUIRE               GnttabAcquire;
+    XENBUS_GNTTAB_RELEASE               GnttabRelease;
     XENBUS_GNTTAB_CREATE_CACHE          GnttabCreateCache;
     XENBUS_GNTTAB_PERMIT_FOREIGN_ACCESS GnttabPermitForeignAccess;
     XENBUS_GNTTAB_REVOKE_FOREIGN_ACCESS GnttabRevokeForeignAccess;
@@ -270,7 +301,7 @@ struct _XENBUS_GNTTAB_INTERFACE_V3 {
     XENBUS_GNTTAB_UNMAP_FOREIGN_PAGES   GnttabUnmapForeignPages;
 };
 
-typedef struct _XENBUS_GNTTAB_INTERFACE_V3 XENBUS_GNTTAB_INTERFACE, 
*PXENBUS_GNTTAB_INTERFACE;
+typedef struct _XENBUS_GNTTAB_INTERFACE_V4 XENBUS_GNTTAB_INTERFACE, 
*PXENBUS_GNTTAB_INTERFACE;
 
 /*! \def XENBUS_GNTTAB
     \brief Macro at assist in method invocation
@@ -281,7 +312,7 @@ typedef struct _XENBUS_GNTTAB_INTERFACE_V3 
XENBUS_GNTTAB_INTERFACE, *PXENBUS_GNT
 #endif  // _WINDLL
 
 #define XENBUS_GNTTAB_INTERFACE_VERSION_MIN 1
-#define XENBUS_GNTTAB_INTERFACE_VERSION_MAX 3
+#define XENBUS_GNTTAB_INTERFACE_VERSION_MAX 4
 
 #endif  // _XENBUS_GNTTAB_INTERFACE_H
 
diff --git a/include/revision.h b/include/revision.h
index ea489f5..28ee461 100644
--- a/include/revision.h
+++ b/include/revision.h
@@ -54,6 +54,7 @@
     DEFINE_REVISION(0x09000001,  1,  2,  6,  1,  2,  1,  1,  2,  1,  1,  1), \
     DEFINE_REVISION(0x09000002,  1,  2,  7,  1,  2,  1,  1,  2,  1,  1,  1), \
     DEFINE_REVISION(0x09000003,  1,  2,  8,  1,  2,  1,  1,  2,  1,  1,  1), \
-    DEFINE_REVISION(0x09000004,  1,  2,  8,  1,  2,  1,  1,  3,  1,  1,  1)
+    DEFINE_REVISION(0x09000004,  1,  2,  8,  1,  2,  1,  1,  3,  1,  1,  1), \
+    DEFINE_REVISION(0x09000005,  1,  2,  8,  1,  2,  1,  2,  4,  1,  1,  1)
 
 #endif  // _REVISION_H
diff --git a/src/xenbus/cache.c b/src/xenbus/cache.c
index 68bfb39..a0f4135 100644
--- a/src/xenbus/cache.c
+++ b/src/xenbus/cache.c
@@ -76,6 +76,7 @@ struct _XENBUS_CACHE {
     CHAR                    Name[MAXNAMELEN];
     ULONG                   Size;
     ULONG                   Reservation;
+    ULONG                   Cap;
     NTSTATUS                (*Ctor)(PVOID, PVOID);
     VOID                    (*Dtor)(PVOID, PVOID);
     VOID                    (*AcquireLock)(PVOID);
@@ -234,6 +235,7 @@ CacheCreateSlab(
 {
     PXENBUS_CACHE_SLAB  Slab;
     ULONG               NumberOfBytes;
+    ULONG               Count;
     LARGE_INTEGER       LowAddress;
     LARGE_INTEGER       HighAddress;
     LARGE_INTEGER       Boundary;
@@ -243,6 +245,13 @@ CacheCreateSlab(
     NumberOfBytes = P2ROUNDUP(FIELD_OFFSET(XENBUS_CACHE_SLAB, Buffer) +
                               Cache->Size,
                               PAGE_SIZE);
+    Count = (NumberOfBytes - FIELD_OFFSET(XENBUS_CACHE_SLAB, Buffer)) /
+            Cache->Size;
+    ASSERT(Count != 0);
+
+    status = STATUS_INSUFFICIENT_RESOURCES;
+    if (Cache->Count + Count > Cache->Cap)
+        goto fail1;
 
     LowAddress.QuadPart = 0ull;
     HighAddress.QuadPart = ~0ull;
@@ -257,31 +266,30 @@ CacheCreateSlab(
 
     status = STATUS_NO_MEMORY;
     if (Slab == NULL)
-        goto fail1;
+        goto fail2;
 
     RtlZeroMemory(Slab, NumberOfBytes);
 
     Slab->Magic = XENBUS_CACHE_SLAB_MAGIC;
     Slab->Cache = Cache;
-    Slab->Count = (NumberOfBytes -
-                   FIELD_OFFSET(XENBUS_CACHE_SLAB, Buffer)) /
-                  Cache->Size;
-    ASSERT(Slab->Count != 0);
+    Slab->Count = Count;
 
     for (Index = 0; Index < (LONG)Slab->Count; Index++) {
         PVOID Object = (PVOID)&Slab->Buffer[Index * Cache->Size];
 
         status = __CacheCtor(Cache, Object);
         if (!NT_SUCCESS(status))
-            goto fail2;
+            goto fail3;
     }
 
     CacheInsertSlab(Cache, Slab);
-    Cache->Count += Slab->Count;
+    Cache->Count += Count;
 
     return Slab;
 
-fail2:
+fail3:
+    Error("fail3\n");
+
     while (--Index >= 0) {
         PVOID Object = (PVOID)&Slab->Buffer[Index * Cache->Size];
 
@@ -290,6 +298,9 @@ fail2:
 
     MmFreeContiguousMemory(Slab);
 
+fail2:
+    Error("fail2\n");
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -566,6 +577,7 @@ CacheCreate(
     IN  const CHAR          *Name,
     IN  ULONG               Size,
     IN  ULONG               Reservation,
+    IN  ULONG               Cap,
     IN  NTSTATUS            (*Ctor)(PVOID, PVOID),
     IN  VOID                (*Dtor)(PVOID, PVOID),
     IN  VOID                (*AcquireLock)(PVOID),
@@ -596,8 +608,12 @@ CacheCreate(
     Size = __max(Size, MINIMUM_OBJECT_SIZE);
     Size = P2ROUNDUP(Size, sizeof (ULONG_PTR));
 
+    if (Cap == 0)
+        Cap = ULONG_MAX;
+
     (*Cache)->Size = Size;
     (*Cache)->Reservation = Reservation;
+    (*Cache)->Cap = Cap;
     (*Cache)->Ctor = Ctor;
     (*Cache)->Dtor = Dtor;
     (*Cache)->AcquireLock = AcquireLock;
@@ -606,10 +622,14 @@ CacheCreate(
 
     InitializeListHead(&(*Cache)->SlabList);
 
+    status = STATUS_INVALID_PARAMETER;
+    if ((*Cache)->Reservation > (*Cache)->Cap)
+        goto fail3;
+
     if ((*Cache)->Reservation != 0) {
         status = __CacheFill(*Cache);
         if (!NT_SUCCESS(status))
-            goto fail3;
+            goto fail4;
     }
 
     (*Cache)->MagazineCount = 
KeQueryMaximumProcessorCountEx(ALL_PROCESSOR_GROUPS);
@@ -617,7 +637,7 @@ CacheCreate(
 
     status = STATUS_NO_MEMORY;
     if ((*Cache)->Magazine == NULL)
-        goto fail4;
+        goto fail5;
 
     KeAcquireSpinLock(&Context->Lock, &Irql);
     InsertTailList(&Context->List, &(*Cache)->ListEntry);
@@ -627,13 +647,16 @@ CacheCreate(
 
     return STATUS_SUCCESS;
 
-fail4:
-    Error("fail4\n");
+fail5:
+    Error("fail5\n");
 
     (*Cache)->MagazineCount = 0;
 
     __CacheEmpty(*Cache);
 
+fail4:
+    Error("fail4\n");
+
 fail3:
     Error("fail3\n");
 
@@ -645,6 +668,8 @@ fail3:
     (*Cache)->AcquireLock = NULL;
     (*Cache)->Dtor = NULL;
     (*Cache)->Ctor = NULL;
+    (*Cache)->Cap = 0;
+    (*Cache)->Reservation = 0;
     (*Cache)->Size = 0;
 
 fail2:
@@ -661,6 +686,33 @@ fail1:
     return status;    
 }
 
+static NTSTATUS
+CacheCreateVersion1(
+    IN  PINTERFACE          Interface,
+    IN  const CHAR          *Name,
+    IN  ULONG               Size,
+    IN  ULONG               Reservation,
+    IN  NTSTATUS            (*Ctor)(PVOID, PVOID),
+    IN  VOID                (*Dtor)(PVOID, PVOID),
+    IN  VOID                (*AcquireLock)(PVOID),
+    IN  VOID                (*ReleaseLock)(PVOID),
+    IN  PVOID               Argument,
+    OUT PXENBUS_CACHE       *Cache
+    )
+{
+    return CacheCreate(Interface,
+                       Name,
+                       Size,
+                       Reservation,
+                       0,
+                       Ctor,
+                       Dtor,
+                       AcquireLock,
+                       ReleaseLock,
+                       Argument,
+                       Cache);
+}
+
 static VOID
 CacheDestroy(
     IN  PINTERFACE          Interface,
@@ -696,6 +748,8 @@ CacheDestroy(
     Cache->AcquireLock = NULL;
     Cache->Dtor = NULL;
     Cache->Ctor = NULL;
+    Cache->Cap = 0;
+    Cache->Reservation = 0;
     Cache->Size = 0;
 
     RtlZeroMemory(Cache->Name, sizeof (Cache->Name));
@@ -826,6 +880,16 @@ static struct _XENBUS_CACHE_INTERFACE_V1 
CacheInterfaceVersion1 = {
     { sizeof (struct _XENBUS_CACHE_INTERFACE_V1), 1, NULL, NULL, NULL },
     CacheAcquire,
     CacheRelease,
+    CacheCreateVersion1,
+    CacheGet,
+    CachePut,
+    CacheDestroy
+};
+
+static struct _XENBUS_CACHE_INTERFACE_V2 CacheInterfaceVersion2 = {
+    { sizeof (struct _XENBUS_CACHE_INTERFACE_V2), 2, NULL, NULL, NULL },
+    CacheAcquire,
+    CacheRelease,
     CacheCreate,
     CacheGet,
     CachePut,
@@ -900,6 +964,23 @@ CacheGetInterface(
         status = STATUS_SUCCESS;
         break;
     }
+    case 2: {
+        struct _XENBUS_CACHE_INTERFACE_V2   *CacheInterface;
+
+        CacheInterface = (struct _XENBUS_CACHE_INTERFACE_V2 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENBUS_CACHE_INTERFACE_V2))
+            break;
+
+        *CacheInterface = CacheInterfaceVersion2;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
     default:
         status = STATUS_NOT_SUPPORTED;
         break;
diff --git a/src/xenbus/gnttab.c b/src/xenbus/gnttab.c
index ca60a48..e590a5c 100644
--- a/src/xenbus/gnttab.c
+++ b/src/xenbus/gnttab.c
@@ -327,6 +327,7 @@ GnttabCreateCache(
     IN  PINTERFACE              Interface,
     IN  const CHAR              *Name,
     IN  ULONG                   Reservation,
+    IN  ULONG                   Cap,
     IN  VOID                    (*AcquireLock)(PVOID),
     IN  VOID                    (*ReleaseLock)(PVOID),
     IN  PVOID                   Argument,
@@ -361,6 +362,7 @@ GnttabCreateCache(
                           (*Cache)->Name,
                           sizeof (XENBUS_GNTTAB_ENTRY),
                           Reservation,
+                          Cap,
                           GnttabEntryCtor,
                           GnttabEntryDtor,
                           GnttabAcquireLock,
@@ -399,6 +401,27 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+GnttabCreateCacheVersion1(
+    IN  PINTERFACE              Interface,
+    IN  const CHAR              *Name,
+    IN  ULONG                   Reservation,
+    IN  VOID                    (*AcquireLock)(PVOID),
+    IN  VOID                    (*ReleaseLock)(PVOID),
+    IN  PVOID                   Argument,
+    OUT PXENBUS_GNTTAB_CACHE    *Cache
+    )
+{
+    return GnttabCreateCache(Interface,
+                             Name,
+                             Reservation,
+                             0,
+                             AcquireLock,
+                             ReleaseLock,
+                             Argument,
+                             Cache);
+}
+
 static VOID
 GnttabDestroyCache(
     IN  PINTERFACE              Interface,
@@ -960,7 +983,7 @@ static struct _XENBUS_GNTTAB_INTERFACE_V1   
GnttabInterfaceVersion1 = {
     { sizeof (struct _XENBUS_GNTTAB_INTERFACE_V1), 1, NULL, NULL, NULL },
     GnttabAcquire,
     GnttabRelease,
-    GnttabCreateCache,
+    GnttabCreateCacheVersion1,
     GnttabPermitForeignAccess,
     GnttabRevokeForeignAccess,
     GnttabGetReference,
@@ -971,7 +994,7 @@ static struct _XENBUS_GNTTAB_INTERFACE_V2   
GnttabInterfaceVersion2 = {
     { sizeof (struct _XENBUS_GNTTAB_INTERFACE_V2), 2, NULL, NULL, NULL },
     GnttabAcquire,
     GnttabRelease,
-    GnttabCreateCache,
+    GnttabCreateCacheVersion1,
     GnttabPermitForeignAccess,
     GnttabRevokeForeignAccess,
     GnttabGetReference,
@@ -984,6 +1007,20 @@ static struct _XENBUS_GNTTAB_INTERFACE_V3   
GnttabInterfaceVersion3 = {
     { sizeof (struct _XENBUS_GNTTAB_INTERFACE_V3), 3, NULL, NULL, NULL },
     GnttabAcquire,
     GnttabRelease,
+    GnttabCreateCacheVersion1,
+    GnttabPermitForeignAccess,
+    GnttabRevokeForeignAccess,
+    GnttabGetReference,
+    GnttabQueryReference,
+    GnttabDestroyCache,
+    GnttabMapForeignPages,
+    GnttabUnmapForeignPages
+};
+
+static struct _XENBUS_GNTTAB_INTERFACE_V4   GnttabInterfaceVersion4 = {
+    { sizeof (struct _XENBUS_GNTTAB_INTERFACE_V4), 4, NULL, NULL, NULL },
+    GnttabAcquire,
+    GnttabRelease,
     GnttabCreateCache,
     GnttabPermitForeignAccess,
     GnttabRevokeForeignAccess,
@@ -1124,6 +1161,23 @@ GnttabGetInterface(
         status = STATUS_SUCCESS;
         break;
     }
+    case 4: {
+        struct _XENBUS_GNTTAB_INTERFACE_V4  *GnttabInterface;
+
+        GnttabInterface = (struct _XENBUS_GNTTAB_INTERFACE_V4 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENBUS_GNTTAB_INTERFACE_V4))
+            break;
+
+        *GnttabInterface = GnttabInterfaceVersion4;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
     default:
         status = STATUS_NOT_SUPPORTED;
         break;
-- 
2.5.3


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.