diff --git a/include/os/windows/spl/sys/lookasidelist.h b/include/os/windows/spl/sys/lookasidelist.h index dc66f49ff456..15ef1a7e737c 100644 --- a/include/os/windows/spl/sys/lookasidelist.h +++ b/include/os/windows/spl/sys/lookasidelist.h @@ -6,13 +6,19 @@ extern void osif_free(void*, uint64_t); #define ZFS_LookAsideList_DRV_TAG '!SFZ' +#define LOOKASIDELIST_CACHE_NAMELEN 31 + typedef struct lookasidelist_cache { - ULONG cache_active_allocations; + uint64_t cache_active_allocations; + uint64_t total_alloc; + uint64_t total_free; size_t cache_chunksize; // cache object size + kstat_t *cache_kstat; + char cache_name[LOOKASIDELIST_CACHE_NAMELEN + 1]; LOOKASIDE_LIST_EX lookasideField; } lookasidelist_cache_t; -lookasidelist_cache_t *lookasidelist_cache_create(size_t size); +lookasidelist_cache_t *lookasidelist_cache_create(char *name, size_t size); void lookasidelist_cache_destroy(lookasidelist_cache_t *pLookasidelist_cache); void* lookasidelist_cache_alloc(lookasidelist_cache_t *pLookasidelist_cache); void lookasidelist_cache_free(lookasidelist_cache_t *pLookasidelist_cache, diff --git a/module/os/windows/spl/spl-lookasidelist.c b/module/os/windows/spl/spl-lookasidelist.c index 4a784ab06c4d..926f07f9ef19 100644 --- a/module/os/windows/spl/spl-lookasidelist.c +++ b/module/os/windows/spl/spl-lookasidelist.c @@ -1,6 +1,46 @@ #include #include +typedef struct lookasidelist_stats { + kstat_named_t lookasidestat_active_alloc; + kstat_named_t lookasidestat_total_alloc; + kstat_named_t lookasidestat_total_free; + kstat_named_t lookasidestat_chunk_size; +} lookasidelist_stats_t; + +static lookasidelist_stats_t lookasidelist_stats = { + /* Number of active allocations */ + { "active_alloc", KSTAT_DATA_UINT64 }, + /* The total number of allocations */ + { "total_alloc", KSTAT_DATA_UINT64 }, + /* The total number of frees */ + { "total_free", KSTAT_DATA_UINT64 }, + /* The size of each object/chunk in lookaside list */ + { "chunk_size", KSTAT_DATA_UINT64 }, +}; + +static int +lookaside_kstat_update(kstat_t *ksp, int rw) +{ + lookasidelist_stats_t *ks = ksp->ks_data; + lookasidelist_cache_t *cp = ksp->ks_private; + + if (rw == KSTAT_WRITE) { + return (EACCES); + } + + ks->lookasidestat_active_alloc.value.ui64 = + cp->cache_active_allocations; + ks->lookasidestat_total_alloc.value.ui64 = + cp->total_alloc; + ks->lookasidestat_total_free.value.ui64 = + cp->total_free; + ks->lookasidestat_chunk_size.value.ui64 = + cp->cache_chunksize; + + return (0); +} + void * allocate_func( __in POOL_TYPE PoolType, @@ -15,9 +55,8 @@ allocate_func( ASSERT(buf != NULL); if (buf != NULL) { - atomic_inc_32(&pLookasidelist_cache->cache_active_allocations); - // can also be calculated from the Lookaside list as below - // Lookaside->L.TotalAllocates - Lookaside->L.TotalFrees + atomic_inc_64(&pLookasidelist_cache->cache_active_allocations); + atomic_inc_64(&pLookasidelist_cache->total_alloc); } return (buf); @@ -31,17 +70,27 @@ void free_func( pLookasidelist_cache = CONTAINING_RECORD(Lookaside, lookasidelist_cache_t, lookasideField); osif_free(Buffer, pLookasidelist_cache->cache_chunksize); - atomic_dec_32(&pLookasidelist_cache->cache_active_allocations); + atomic_dec_64(&pLookasidelist_cache->cache_active_allocations); + atomic_inc_64(&pLookasidelist_cache->total_free); } lookasidelist_cache_t * -lookasidelist_cache_create(size_t size) +lookasidelist_cache_create(char *name, /* descriptive name for this cache */ + size_t size) /* size of the objects it manages */ { lookasidelist_cache_t *pLookasidelist_cache; pLookasidelist_cache = ExAllocatePoolWithTag(NonPagedPool, sizeof (lookasidelist_cache_t), ZFS_LookAsideList_DRV_TAG); if (pLookasidelist_cache != NULL) { + bzero(pLookasidelist_cache, sizeof (lookasidelist_cache_t)); + pLookasidelist_cache->cache_chunksize = size; + + if (name != NULL) { + strncpy(pLookasidelist_cache->cache_name, name, + LOOKASIDELIST_CACHE_NAMELEN); + } + NTSTATUS retval = ExInitializeLookasideListEx( &pLookasidelist_cache->lookasideField, allocate_func, @@ -54,16 +103,29 @@ lookasidelist_cache_create(size_t size) ASSERT(retval == STATUS_SUCCESS); - if (retval == STATUS_SUCCESS) { - pLookasidelist_cache->cache_chunksize = size; - pLookasidelist_cache->cache_active_allocations = 0; - } else { + if (retval != STATUS_SUCCESS) { ExFreePoolWithTag(pLookasidelist_cache, ZFS_LookAsideList_DRV_TAG); pLookasidelist_cache = NULL; } } + if (pLookasidelist_cache != NULL) { + kstat_t *ksp = kstat_create("spl", 0, + pLookasidelist_cache->cache_name, + "lookasidelist_cache", KSTAT_TYPE_NAMED, + sizeof (lookasidelist_stats) / sizeof (kstat_named_t), + KSTAT_FLAG_VIRTUAL); + + if (ksp != NULL) { + ksp->ks_data = &lookasidelist_stats; + ksp->ks_update = lookaside_kstat_update; + ksp->ks_private = pLookasidelist_cache; + pLookasidelist_cache->cache_kstat = ksp; + kstat_install(ksp); + } + } + return (pLookasidelist_cache); } @@ -75,6 +137,11 @@ lookasidelist_cache_destroy(lookasidelist_cache_t *pLookasidelist_cache) ExDeleteLookasideListEx(&pLookasidelist_cache->lookasideField); ExFreePoolWithTag(pLookasidelist_cache, ZFS_LookAsideList_DRV_TAG); + + if (pLookasidelist_cache->cache_kstat != NULL) { + kstat_delete(pLookasidelist_cache->cache_kstat); + pLookasidelist_cache->cache_kstat = NULL; + } } } diff --git a/module/os/windows/zfs/abd_os.c b/module/os/windows/zfs/abd_os.c index 737ab5054307..ae9cde315702 100644 --- a/module/os/windows/zfs/abd_os.c +++ b/module/os/windows/zfs/abd_os.c @@ -271,7 +271,8 @@ abd_free_zero_scatter(void) void abd_init(void) { - abd_chunk_cache = lookasidelist_cache_create(zfs_abd_chunk_size); + abd_chunk_cache = lookasidelist_cache_create("abd_chunk", + zfs_abd_chunk_size); abd_ksp = kstat_create("zfs", 0, "abdstats", "misc", KSTAT_TYPE_NAMED, sizeof (abd_stats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);