Commit 22328d71 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Dave Chinner

xfs: embedd mru_elem into parent structure

There is no need to do a separate allocation for each mru element, just
embedd the structure into the parent one in the user.  Besides saving
a memory allocation and the infrastructure required for it this also
simplifies the API.

While we do major surgery on xfs_mru_cache.c also de-typedef it and
make struct mru_cache private to the implementation file.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent ce695c65
...@@ -118,6 +118,7 @@ static kmem_zone_t *item_zone; ...@@ -118,6 +118,7 @@ static kmem_zone_t *item_zone;
*/ */
typedef struct fstrm_item typedef struct fstrm_item
{ {
struct xfs_mru_cache_elem mru;
xfs_agnumber_t ag; /* AG currently in use for the file/directory. */ xfs_agnumber_t ag; /* AG currently in use for the file/directory. */
xfs_inode_t *ip; /* inode self-pointer. */ xfs_inode_t *ip; /* inode self-pointer. */
xfs_inode_t *pip; /* Parent directory inode pointer. */ xfs_inode_t *pip; /* Parent directory inode pointer. */
...@@ -335,10 +336,10 @@ _xfs_filestream_update_ag( ...@@ -335,10 +336,10 @@ _xfs_filestream_update_ag(
{ {
int err = 0; int err = 0;
xfs_mount_t *mp; xfs_mount_t *mp;
xfs_mru_cache_t *cache;
fstrm_item_t *item; fstrm_item_t *item;
xfs_agnumber_t old_ag; xfs_agnumber_t old_ag;
xfs_inode_t *old_pip; xfs_inode_t *old_pip;
struct xfs_mru_cache_elem *mru;
/* /*
* Either ip is a regular file and pip is a directory, or ip is a * Either ip is a regular file and pip is a directory, or ip is a
...@@ -349,16 +350,17 @@ _xfs_filestream_update_ag( ...@@ -349,16 +350,17 @@ _xfs_filestream_update_ag(
(S_ISDIR(ip->i_d.di_mode) && !pip))); (S_ISDIR(ip->i_d.di_mode) && !pip)));
mp = ip->i_mount; mp = ip->i_mount;
cache = mp->m_filestream;
item = xfs_mru_cache_lookup(cache, ip->i_ino); mru = xfs_mru_cache_lookup(mp->m_filestream, ip->i_ino);
if (item) { if (mru) {
item = container_of(mru, fstrm_item_t, mru);
ASSERT(item->ip == ip); ASSERT(item->ip == ip);
old_ag = item->ag; old_ag = item->ag;
item->ag = ag; item->ag = ag;
old_pip = item->pip; old_pip = item->pip;
item->pip = pip; item->pip = pip;
xfs_mru_cache_done(cache); xfs_mru_cache_done(mp->m_filestream);
/* /*
* If the AG has changed, drop the old ref and take a new one, * If the AG has changed, drop the old ref and take a new one,
...@@ -391,7 +393,7 @@ _xfs_filestream_update_ag( ...@@ -391,7 +393,7 @@ _xfs_filestream_update_ag(
item->ip = ip; item->ip = ip;
item->pip = pip; item->pip = pip;
err = xfs_mru_cache_insert(cache, ip->i_ino, item); err = xfs_mru_cache_insert(mp->m_filestream, ip->i_ino, &item->mru);
if (err) { if (err) {
kmem_zone_free(item_zone, item); kmem_zone_free(item_zone, item);
return err; return err;
...@@ -422,14 +424,12 @@ _xfs_filestream_update_ag( ...@@ -422,14 +424,12 @@ _xfs_filestream_update_ag(
/* xfs_fstrm_free_func(): callback for freeing cached stream items. */ /* xfs_fstrm_free_func(): callback for freeing cached stream items. */
STATIC void STATIC void
xfs_fstrm_free_func( xfs_fstrm_free_func(
unsigned long ino, struct xfs_mru_cache_elem *mru)
void *data)
{ {
fstrm_item_t *item = (fstrm_item_t *)data; fstrm_item_t *item =
container_of(mru, fstrm_item_t, mru);
xfs_inode_t *ip = item->ip; xfs_inode_t *ip = item->ip;
ASSERT(ip->i_ino == ino);
xfs_iflags_clear(ip, XFS_IFILESTREAM); xfs_iflags_clear(ip, XFS_IFILESTREAM);
/* Drop the reference taken on the AG when the item was added. */ /* Drop the reference taken on the AG when the item was added. */
...@@ -532,7 +532,8 @@ xfs_agnumber_t ...@@ -532,7 +532,8 @@ xfs_agnumber_t
xfs_filestream_lookup_ag( xfs_filestream_lookup_ag(
xfs_inode_t *ip) xfs_inode_t *ip)
{ {
xfs_mru_cache_t *cache; struct xfs_mount *mp = ip->i_mount;
struct xfs_mru_cache_elem *mru;
fstrm_item_t *item; fstrm_item_t *item;
xfs_agnumber_t ag; xfs_agnumber_t ag;
int ref; int ref;
...@@ -542,17 +543,17 @@ xfs_filestream_lookup_ag( ...@@ -542,17 +543,17 @@ xfs_filestream_lookup_ag(
return NULLAGNUMBER; return NULLAGNUMBER;
} }
cache = ip->i_mount->m_filestream; mru = xfs_mru_cache_lookup(mp->m_filestream, ip->i_ino);
item = xfs_mru_cache_lookup(cache, ip->i_ino); if (!mru) {
if (!item) {
TRACE_LOOKUP(ip->i_mount, ip, NULL, NULLAGNUMBER, 0); TRACE_LOOKUP(ip->i_mount, ip, NULL, NULLAGNUMBER, 0);
return NULLAGNUMBER; return NULLAGNUMBER;
} }
item = container_of(mru, fstrm_item_t, mru);
ASSERT(ip == item->ip); ASSERT(ip == item->ip);
ag = item->ag; ag = item->ag;
ref = xfs_filestream_peek_ag(ip->i_mount, ag); ref = xfs_filestream_peek_ag(ip->i_mount, ag);
xfs_mru_cache_done(cache); xfs_mru_cache_done(mp->m_filestream);
TRACE_LOOKUP(ip->i_mount, ip, item->pip, ag, ref); TRACE_LOOKUP(ip->i_mount, ip, item->pip, ag, ref);
return ag; return ag;
...@@ -573,8 +574,8 @@ xfs_filestream_associate( ...@@ -573,8 +574,8 @@ xfs_filestream_associate(
xfs_inode_t *pip, xfs_inode_t *pip,
xfs_inode_t *ip) xfs_inode_t *ip)
{ {
struct xfs_mru_cache_elem *mru;
xfs_mount_t *mp; xfs_mount_t *mp;
xfs_mru_cache_t *cache;
fstrm_item_t *item; fstrm_item_t *item;
xfs_agnumber_t ag, rotorstep, startag; xfs_agnumber_t ag, rotorstep, startag;
int err = 0; int err = 0;
...@@ -585,7 +586,6 @@ xfs_filestream_associate( ...@@ -585,7 +586,6 @@ xfs_filestream_associate(
return -EINVAL; return -EINVAL;
mp = pip->i_mount; mp = pip->i_mount;
cache = mp->m_filestream;
/* /*
* We have a problem, Houston. * We have a problem, Houston.
...@@ -606,11 +606,13 @@ xfs_filestream_associate( ...@@ -606,11 +606,13 @@ xfs_filestream_associate(
return 1; return 1;
/* If the parent directory is already in the cache, use its AG. */ /* If the parent directory is already in the cache, use its AG. */
item = xfs_mru_cache_lookup(cache, pip->i_ino); mru = xfs_mru_cache_lookup(mp->m_filestream, pip->i_ino);
if (item) { if (mru) {
item = container_of(mru, fstrm_item_t, mru);
ASSERT(item->ip == pip); ASSERT(item->ip == pip);
ag = item->ag; ag = item->ag;
xfs_mru_cache_done(cache); xfs_mru_cache_done(mp->m_filestream);
TRACE_LOOKUP(mp, pip, pip, ag, xfs_filestream_peek_ag(mp, ag)); TRACE_LOOKUP(mp, pip, pip, ag, xfs_filestream_peek_ag(mp, ag));
err = _xfs_filestream_update_ag(ip, pip, ag); err = _xfs_filestream_update_ag(ip, pip, ag);
...@@ -671,17 +673,16 @@ xfs_filestream_new_ag( ...@@ -671,17 +673,16 @@ xfs_filestream_new_ag(
struct xfs_bmalloca *ap, struct xfs_bmalloca *ap,
xfs_agnumber_t *agp) xfs_agnumber_t *agp)
{ {
struct xfs_mru_cache_elem *mru, *mru2;
int flags, err; int flags, err;
xfs_inode_t *ip, *pip = NULL; xfs_inode_t *ip, *pip = NULL;
xfs_mount_t *mp; xfs_mount_t *mp;
xfs_mru_cache_t *cache;
xfs_extlen_t minlen; xfs_extlen_t minlen;
fstrm_item_t *dir, *file; fstrm_item_t *dir, *file;
xfs_agnumber_t ag = NULLAGNUMBER; xfs_agnumber_t ag = NULLAGNUMBER;
ip = ap->ip; ip = ap->ip;
mp = ip->i_mount; mp = ip->i_mount;
cache = mp->m_filestream;
minlen = ap->length; minlen = ap->length;
*agp = NULLAGNUMBER; *agp = NULLAGNUMBER;
...@@ -689,8 +690,9 @@ xfs_filestream_new_ag( ...@@ -689,8 +690,9 @@ xfs_filestream_new_ag(
* Look for the file in the cache, removing it if it's found. Doing * Look for the file in the cache, removing it if it's found. Doing
* this allows it to be held across the dir lookup that follows. * this allows it to be held across the dir lookup that follows.
*/ */
file = xfs_mru_cache_remove(cache, ip->i_ino); mru = xfs_mru_cache_remove(mp->m_filestream, ip->i_ino);
if (file) { if (mru) {
file = container_of(mru, fstrm_item_t, mru);
ASSERT(ip == file->ip); ASSERT(ip == file->ip);
/* Save the file's parent inode and old AG number for later. */ /* Save the file's parent inode and old AG number for later. */
...@@ -698,8 +700,9 @@ xfs_filestream_new_ag( ...@@ -698,8 +700,9 @@ xfs_filestream_new_ag(
ag = file->ag; ag = file->ag;
/* Look for the file's directory in the cache. */ /* Look for the file's directory in the cache. */
dir = xfs_mru_cache_lookup(cache, pip->i_ino); mru2 = xfs_mru_cache_lookup(mp->m_filestream, pip->i_ino);
if (dir) { if (mru2) {
dir = container_of(mru2, fstrm_item_t, mru);
ASSERT(pip == dir->ip); ASSERT(pip == dir->ip);
/* /*
...@@ -714,7 +717,7 @@ xfs_filestream_new_ag( ...@@ -714,7 +717,7 @@ xfs_filestream_new_ag(
*agp = file->ag = dir->ag; *agp = file->ag = dir->ag;
} }
xfs_mru_cache_done(cache); xfs_mru_cache_done(mp->m_filestream);
} }
/* /*
...@@ -722,9 +725,9 @@ xfs_filestream_new_ag( ...@@ -722,9 +725,9 @@ xfs_filestream_new_ag(
* function needs to be called to tidy up in the same way as if * function needs to be called to tidy up in the same way as if
* the item had simply expired from the cache. * the item had simply expired from the cache.
*/ */
err = xfs_mru_cache_insert(cache, ip->i_ino, file); err = xfs_mru_cache_insert(mp->m_filestream, ip->i_ino, mru);
if (err) { if (err) {
xfs_fstrm_free_func(ip->i_ino, file); xfs_fstrm_free_func(mru);
return err; return err;
} }
...@@ -818,7 +821,5 @@ void ...@@ -818,7 +821,5 @@ void
xfs_filestream_deassociate( xfs_filestream_deassociate(
xfs_inode_t *ip) xfs_inode_t *ip)
{ {
xfs_mru_cache_t *cache = ip->i_mount->m_filestream; xfs_mru_cache_delete(ip->i_mount->m_filestream, ip->i_ino);
xfs_mru_cache_delete(cache, ip->i_ino);
} }
...@@ -100,14 +100,20 @@ ...@@ -100,14 +100,20 @@
* likely result in a loop in one of the lists. That's a sure-fire recipe for * likely result in a loop in one of the lists. That's a sure-fire recipe for
* an infinite loop in the code. * an infinite loop in the code.
*/ */
typedef struct xfs_mru_cache_elem struct xfs_mru_cache {
{ struct radix_tree_root store; /* Core storage data structure. */
struct list_head list_node; struct list_head *lists; /* Array of lists, one per grp. */
unsigned long key; struct list_head reap_list; /* Elements overdue for reaping. */
void *value; spinlock_t lock; /* Lock to protect this struct. */
} xfs_mru_cache_elem_t; unsigned int grp_count; /* Number of discrete groups. */
unsigned int grp_time; /* Time period spanned by grps. */
unsigned int lru_grp; /* Group containing time zero. */
unsigned long time_zero; /* Time first element was added. */
xfs_mru_cache_free_func_t free_func; /* Function pointer for freeing. */
struct delayed_work work; /* Workqueue data for reaping. */
unsigned int queued; /* work has been queued */
};
static kmem_zone_t *xfs_mru_elem_zone;
static struct workqueue_struct *xfs_mru_reap_wq; static struct workqueue_struct *xfs_mru_reap_wq;
/* /*
...@@ -129,7 +135,7 @@ static struct workqueue_struct *xfs_mru_reap_wq; ...@@ -129,7 +135,7 @@ static struct workqueue_struct *xfs_mru_reap_wq;
*/ */
STATIC unsigned long STATIC unsigned long
_xfs_mru_cache_migrate( _xfs_mru_cache_migrate(
xfs_mru_cache_t *mru, struct xfs_mru_cache *mru,
unsigned long now) unsigned long now)
{ {
unsigned int grp; unsigned int grp;
...@@ -193,8 +199,8 @@ _xfs_mru_cache_migrate( ...@@ -193,8 +199,8 @@ _xfs_mru_cache_migrate(
*/ */
STATIC void STATIC void
_xfs_mru_cache_list_insert( _xfs_mru_cache_list_insert(
xfs_mru_cache_t *mru, struct xfs_mru_cache *mru,
xfs_mru_cache_elem_t *elem) struct xfs_mru_cache_elem *elem)
{ {
unsigned int grp = 0; unsigned int grp = 0;
unsigned long now = jiffies; unsigned long now = jiffies;
...@@ -231,10 +237,10 @@ _xfs_mru_cache_list_insert( ...@@ -231,10 +237,10 @@ _xfs_mru_cache_list_insert(
*/ */
STATIC void STATIC void
_xfs_mru_cache_clear_reap_list( _xfs_mru_cache_clear_reap_list(
xfs_mru_cache_t *mru) __releases(mru->lock) __acquires(mru->lock) struct xfs_mru_cache *mru)
__releases(mru->lock) __acquires(mru->lock)
{ {
xfs_mru_cache_elem_t *elem, *next; struct xfs_mru_cache_elem *elem, *next;
struct list_head tmp; struct list_head tmp;
INIT_LIST_HEAD(&tmp); INIT_LIST_HEAD(&tmp);
...@@ -252,15 +258,8 @@ _xfs_mru_cache_clear_reap_list( ...@@ -252,15 +258,8 @@ _xfs_mru_cache_clear_reap_list(
spin_unlock(&mru->lock); spin_unlock(&mru->lock);
list_for_each_entry_safe(elem, next, &tmp, list_node) { list_for_each_entry_safe(elem, next, &tmp, list_node) {
/* Remove the element from the reap list. */
list_del_init(&elem->list_node); list_del_init(&elem->list_node);
mru->free_func(elem);
/* Call the client's free function with the key and value pointer. */
mru->free_func(elem->key, elem->value);
/* Free the element structure. */
kmem_zone_free(xfs_mru_elem_zone, elem);
} }
spin_lock(&mru->lock); spin_lock(&mru->lock);
...@@ -277,7 +276,8 @@ STATIC void ...@@ -277,7 +276,8 @@ STATIC void
_xfs_mru_cache_reap( _xfs_mru_cache_reap(
struct work_struct *work) struct work_struct *work)
{ {
xfs_mru_cache_t *mru = container_of(work, xfs_mru_cache_t, work.work); struct xfs_mru_cache *mru =
container_of(work, struct xfs_mru_cache, work.work);
unsigned long now, next; unsigned long now, next;
ASSERT(mru && mru->lists); ASSERT(mru && mru->lists);
...@@ -304,28 +304,16 @@ _xfs_mru_cache_reap( ...@@ -304,28 +304,16 @@ _xfs_mru_cache_reap(
int int
xfs_mru_cache_init(void) xfs_mru_cache_init(void)
{ {
xfs_mru_elem_zone = kmem_zone_init(sizeof(xfs_mru_cache_elem_t),
"xfs_mru_cache_elem");
if (!xfs_mru_elem_zone)
goto out;
xfs_mru_reap_wq = alloc_workqueue("xfs_mru_cache", WQ_MEM_RECLAIM, 1); xfs_mru_reap_wq = alloc_workqueue("xfs_mru_cache", WQ_MEM_RECLAIM, 1);
if (!xfs_mru_reap_wq) if (!xfs_mru_reap_wq)
goto out_destroy_mru_elem_zone;
return 0;
out_destroy_mru_elem_zone:
kmem_zone_destroy(xfs_mru_elem_zone);
out:
return -ENOMEM; return -ENOMEM;
return 0;
} }
void void
xfs_mru_cache_uninit(void) xfs_mru_cache_uninit(void)
{ {
destroy_workqueue(xfs_mru_reap_wq); destroy_workqueue(xfs_mru_reap_wq);
kmem_zone_destroy(xfs_mru_elem_zone);
} }
/* /*
...@@ -336,12 +324,12 @@ xfs_mru_cache_uninit(void) ...@@ -336,12 +324,12 @@ xfs_mru_cache_uninit(void)
*/ */
int int
xfs_mru_cache_create( xfs_mru_cache_create(
xfs_mru_cache_t **mrup, struct xfs_mru_cache **mrup,
unsigned int lifetime_ms, unsigned int lifetime_ms,
unsigned int grp_count, unsigned int grp_count,
xfs_mru_cache_free_func_t free_func) xfs_mru_cache_free_func_t free_func)
{ {
xfs_mru_cache_t *mru = NULL; struct xfs_mru_cache *mru = NULL;
int err = 0, grp; int err = 0, grp;
unsigned int grp_time; unsigned int grp_time;
...@@ -400,7 +388,7 @@ xfs_mru_cache_create( ...@@ -400,7 +388,7 @@ xfs_mru_cache_create(
*/ */
static void static void
xfs_mru_cache_flush( xfs_mru_cache_flush(
xfs_mru_cache_t *mru) struct xfs_mru_cache *mru)
{ {
if (!mru || !mru->lists) if (!mru || !mru->lists)
return; return;
...@@ -420,7 +408,7 @@ xfs_mru_cache_flush( ...@@ -420,7 +408,7 @@ xfs_mru_cache_flush(
void void
xfs_mru_cache_destroy( xfs_mru_cache_destroy(
xfs_mru_cache_t *mru) struct xfs_mru_cache *mru)
{ {
if (!mru || !mru->lists) if (!mru || !mru->lists)
return; return;
...@@ -438,45 +426,29 @@ xfs_mru_cache_destroy( ...@@ -438,45 +426,29 @@ xfs_mru_cache_destroy(
*/ */
int int
xfs_mru_cache_insert( xfs_mru_cache_insert(
xfs_mru_cache_t *mru, struct xfs_mru_cache *mru,
unsigned long key, unsigned long key,
void *value) struct xfs_mru_cache_elem *elem)
{ {
xfs_mru_cache_elem_t *elem;
int error; int error;
ASSERT(mru && mru->lists); ASSERT(mru && mru->lists);
if (!mru || !mru->lists) if (!mru || !mru->lists)
return EINVAL; return EINVAL;
elem = kmem_zone_zalloc(xfs_mru_elem_zone, KM_SLEEP); if (radix_tree_preload(GFP_KERNEL))
if (!elem)
return ENOMEM; return ENOMEM;
if (radix_tree_preload(GFP_KERNEL)) {
error = ENOMEM;
goto out_free_item;
}
INIT_LIST_HEAD(&elem->list_node); INIT_LIST_HEAD(&elem->list_node);
elem->key = key; elem->key = key;
elem->value = value;
spin_lock(&mru->lock); spin_lock(&mru->lock);
error = -radix_tree_insert(&mru->store, key, elem); error = -radix_tree_insert(&mru->store, key, elem);
radix_tree_preload_end(); radix_tree_preload_end();
if (error) { if (!error)
spin_unlock(&mru->lock);
goto out_free_item;
}
_xfs_mru_cache_list_insert(mru, elem); _xfs_mru_cache_list_insert(mru, elem);
spin_unlock(&mru->lock); spin_unlock(&mru->lock);
return 0;
out_free_item:
kmem_zone_free(xfs_mru_elem_zone, elem);
return error; return error;
} }
...@@ -486,13 +458,12 @@ xfs_mru_cache_insert( ...@@ -486,13 +458,12 @@ xfs_mru_cache_insert(
* the client data pointer for the removed element is returned, otherwise this * the client data pointer for the removed element is returned, otherwise this
* function will return a NULL pointer. * function will return a NULL pointer.
*/ */
void * struct xfs_mru_cache_elem *
xfs_mru_cache_remove( xfs_mru_cache_remove(
xfs_mru_cache_t *mru, struct xfs_mru_cache *mru,
unsigned long key) unsigned long key)
{ {
xfs_mru_cache_elem_t *elem; struct xfs_mru_cache_elem *elem;
void *value = NULL;
ASSERT(mru && mru->lists); ASSERT(mru && mru->lists);
if (!mru || !mru->lists) if (!mru || !mru->lists)
...@@ -500,17 +471,11 @@ xfs_mru_cache_remove( ...@@ -500,17 +471,11 @@ xfs_mru_cache_remove(
spin_lock(&mru->lock); spin_lock(&mru->lock);
elem = radix_tree_delete(&mru->store, key); elem = radix_tree_delete(&mru->store, key);
if (elem) { if (elem)
value = elem->value;
list_del(&elem->list_node); list_del(&elem->list_node);
}
spin_unlock(&mru->lock); spin_unlock(&mru->lock);
if (elem) return elem;
kmem_zone_free(xfs_mru_elem_zone, elem);
return value;
} }
/* /*
...@@ -519,13 +484,14 @@ xfs_mru_cache_remove( ...@@ -519,13 +484,14 @@ xfs_mru_cache_remove(
*/ */
void void
xfs_mru_cache_delete( xfs_mru_cache_delete(
xfs_mru_cache_t *mru, struct xfs_mru_cache *mru,
unsigned long key) unsigned long key)
{ {
void *value = xfs_mru_cache_remove(mru, key); struct xfs_mru_cache_elem *elem;
if (value) elem = xfs_mru_cache_remove(mru, key);
mru->free_func(key, value); if (elem)
mru->free_func(elem);
} }
/* /*
...@@ -548,12 +514,12 @@ xfs_mru_cache_delete( ...@@ -548,12 +514,12 @@ xfs_mru_cache_delete(
* status, we need to help it get it right by annotating the path that does * status, we need to help it get it right by annotating the path that does
* not release the lock. * not release the lock.
*/ */
void * struct xfs_mru_cache_elem *
xfs_mru_cache_lookup( xfs_mru_cache_lookup(
xfs_mru_cache_t *mru, struct xfs_mru_cache *mru,
unsigned long key) unsigned long key)
{ {
xfs_mru_cache_elem_t *elem; struct xfs_mru_cache_elem *elem;
ASSERT(mru && mru->lists); ASSERT(mru && mru->lists);
if (!mru || !mru->lists) if (!mru || !mru->lists)
...@@ -568,7 +534,7 @@ xfs_mru_cache_lookup( ...@@ -568,7 +534,7 @@ xfs_mru_cache_lookup(
} else } else
spin_unlock(&mru->lock); spin_unlock(&mru->lock);
return elem ? elem->value : NULL; return elem;
} }
/* /*
...@@ -578,7 +544,8 @@ xfs_mru_cache_lookup( ...@@ -578,7 +544,8 @@ xfs_mru_cache_lookup(
*/ */
void void
xfs_mru_cache_done( xfs_mru_cache_done(
xfs_mru_cache_t *mru) __releases(mru->lock) struct xfs_mru_cache *mru)
__releases(mru->lock)
{ {
spin_unlock(&mru->lock); spin_unlock(&mru->lock);
} }
...@@ -18,24 +18,15 @@ ...@@ -18,24 +18,15 @@
#ifndef __XFS_MRU_CACHE_H__ #ifndef __XFS_MRU_CACHE_H__
#define __XFS_MRU_CACHE_H__ #define __XFS_MRU_CACHE_H__
struct xfs_mru_cache;
/* Function pointer type for callback to free a client's data pointer. */ struct xfs_mru_cache_elem {
typedef void (*xfs_mru_cache_free_func_t)(unsigned long, void*); struct list_head list_node;
unsigned long key;
};
typedef struct xfs_mru_cache /* Function pointer type for callback to free a client's data pointer. */
{ typedef void (*xfs_mru_cache_free_func_t)(struct xfs_mru_cache_elem *elem);
struct radix_tree_root store; /* Core storage data structure. */
struct list_head *lists; /* Array of lists, one per grp. */
struct list_head reap_list; /* Elements overdue for reaping. */
spinlock_t lock; /* Lock to protect this struct. */
unsigned int grp_count; /* Number of discrete groups. */
unsigned int grp_time; /* Time period spanned by grps. */
unsigned int lru_grp; /* Group containing time zero. */
unsigned long time_zero; /* Time first element was added. */
xfs_mru_cache_free_func_t free_func; /* Function pointer for freeing. */
struct delayed_work work; /* Workqueue data for reaping. */
unsigned int queued; /* work has been queued */
} xfs_mru_cache_t;
int xfs_mru_cache_init(void); int xfs_mru_cache_init(void);
void xfs_mru_cache_uninit(void); void xfs_mru_cache_uninit(void);
...@@ -44,10 +35,12 @@ int xfs_mru_cache_create(struct xfs_mru_cache **mrup, unsigned int lifetime_ms, ...@@ -44,10 +35,12 @@ int xfs_mru_cache_create(struct xfs_mru_cache **mrup, unsigned int lifetime_ms,
xfs_mru_cache_free_func_t free_func); xfs_mru_cache_free_func_t free_func);
void xfs_mru_cache_destroy(struct xfs_mru_cache *mru); void xfs_mru_cache_destroy(struct xfs_mru_cache *mru);
int xfs_mru_cache_insert(struct xfs_mru_cache *mru, unsigned long key, int xfs_mru_cache_insert(struct xfs_mru_cache *mru, unsigned long key,
void *value); struct xfs_mru_cache_elem *elem);
void * xfs_mru_cache_remove(struct xfs_mru_cache *mru, unsigned long key); struct xfs_mru_cache_elem *
xfs_mru_cache_remove(struct xfs_mru_cache *mru, unsigned long key);
void xfs_mru_cache_delete(struct xfs_mru_cache *mru, unsigned long key); void xfs_mru_cache_delete(struct xfs_mru_cache *mru, unsigned long key);
void *xfs_mru_cache_lookup(struct xfs_mru_cache *mru, unsigned long key); struct xfs_mru_cache_elem *
xfs_mru_cache_lookup(struct xfs_mru_cache *mru, unsigned long key);
void xfs_mru_cache_done(struct xfs_mru_cache *mru); void xfs_mru_cache_done(struct xfs_mru_cache *mru);
#endif /* __XFS_MRU_CACHE_H__ */ #endif /* __XFS_MRU_CACHE_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment