[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |