beegfs/client_module/source/toolkit/FhgfsPageListVec.h
2025-08-10 01:34:16 +02:00

160 lines
3.8 KiB
C

#ifndef FHGFSPAGELISTVEC_H_
#define FHGFSPAGELISTVEC_H_
#include <linux/mempool.h>
#include "FhgfsPage.h"
// max pages in a single pageVec, but by using pageVecList's many of these may be used
#ifdef BEEGFS_DEBUG
#define BEEGFS_LIST_VEC_MAX_PAGES 16 // if debugging is enable we make sure lists are tested
#else
#define BEEGFS_LIST_VEC_MAX_PAGES 32
#endif
struct FhgfsPageListVec;
typedef struct FhgfsPageListVec FhgfsPageListVec;
static inline FhgfsPageListVec* FhgfsPageListVec_create(struct kmem_cache* pageVecCache,
mempool_t* pageListPool, bool* outIsPoolAlloc);
static inline void FhgfsPageListVec_destroy(FhgfsPageListVec* this,
struct kmem_cache* pageVecCache, mempool_t* pageVecPool);
static inline void FhgfsPageListVec_init(FhgfsPageListVec* this);
static inline void FhgfsPageListVec_uninit(FhgfsPageListVec* this);
static inline bool FhgfsPageListVec_pushPage(FhgfsPageListVec* this, struct page* page,
int usedPageLength);
static inline size_t FhgfsPageListVec_getMaxPages(FhgfsPageListVec* this);
static inline FhgfsPage* FhgfsPageListVec_getFhgfsPage(FhgfsPageListVec* this, size_t index);
struct FhgfsPageListVec
{
FhgfsPage fhgfsPages[BEEGFS_LIST_VEC_MAX_PAGES];
size_t usedPages; // number of used pages of this vector
struct list_head list;
};
/**
* Constructor
*
* @param pageVecPool is only set if this is the first allocation from FhgfsChunkPageVec, as
* this allocation must not fail.
* @param outIsPoolAlloc is supposed to be initialized to false
*/
FhgfsPageListVec* FhgfsPageListVec_create(struct kmem_cache* pageVecCache,
mempool_t* pageVecPool, bool* outIsPoolAlloc)
{
FhgfsPageListVec* this;
#ifdef BEEGFS_DEBUG
// test cache alloc failures in debug mode
if (jiffies & 1) // odd jiffies simulate an allocation error
this = NULL;
else
this = (FhgfsPageListVec*) kmem_cache_alloc(pageVecCache, GFP_NOFS);
#else
this = (FhgfsPageListVec*) kmem_cache_alloc(pageVecCache, GFP_NOFS);
#endif
if (unlikely(!this) )
{
if (pageVecPool)
{
this = mempool_alloc(pageVecPool, GFP_NOFS);
if (unlikely(!this) )
{
printk_fhgfs(KERN_WARNING, "%s: mempool_alloc unexpectedly failed\n", __func__);
return NULL;
}
*outIsPoolAlloc = true;
}
else
return NULL;
}
FhgfsPageListVec_init(this);
return this;
}
/**
* Destructor
*/
void FhgfsPageListVec_destroy(FhgfsPageListVec* this, struct kmem_cache* pageVecCache,
mempool_t* pageVecPool)
{
FhgfsPageListVec_uninit(this);
if (pageVecPool)
mempool_free(this, pageVecPool);
else
kmem_cache_free(pageVecCache, this);
}
/**
* Initialize FhgfsPageListVec
*/
void FhgfsPageListVec_init(FhgfsPageListVec* this)
{
this->usedPages = 0;
INIT_LIST_HEAD(&this->list);
}
/**
* Uninitialize FhgfsPageListVec
*/
void FhgfsPageListVec_uninit(FhgfsPageListVec* this)
{
// no-op
}
/**
* Add (append) a kernel page to this pageListVec
*
* @return false if the pageListVec is full, true if adding succeeded
*/
bool FhgfsPageListVec_pushPage(FhgfsPageListVec* this, struct page* page, int usedPageLength)
{
FhgfsPage* fhgfsPage;
if (this->usedPages == BEEGFS_LIST_VEC_MAX_PAGES)
return false;
fhgfsPage = &this->fhgfsPages[this->usedPages];
this->usedPages++;
fhgfsPage->page = page;
fhgfsPage->data = kmap(page);
fhgfsPage->length = usedPageLength;
return true;
}
/**
* Return the number of max pages of this vector
*/
size_t FhgfsPageListVec_getMaxPages(FhgfsPageListVec* this)
{
return BEEGFS_LIST_VEC_MAX_PAGES;
}
/**
* Return the page at the given index
*/
FhgfsPage* FhgfsPageListVec_getFhgfsPage(FhgfsPageListVec* this, size_t index)
{
return &this->fhgfsPages[index];
}
#endif // FHGFSPAGELISTVEC_H_