Re: [PATCH] drivers/staging/zcache: support multiple clients, prep for RAMster and KVM
From: Konrad Rzeszutek Wilk <hidden>
Date: 2011-06-27 16:06:42
Also in:
kvm
quoted hunk ↗ jump to hunk
@@ -503,15 +529,13 @@ static void tmem_pampd_destroy_all_in_ob * always flushes for simplicity. */ int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, - struct page *page) + char *data, size_t size, bool raw, int ephemeral)
why not make ephemeral bool?
quoted hunk ↗ jump to hunk
{ struct tmem_obj *obj = NULL, *objfound = NULL, *objnew = NULL; void *pampd = NULL, *pampd_del = NULL; int ret = -ENOMEM; - bool ephemeral; struct tmem_hashbucket *hb; - ephemeral = is_ephemeral(pool); hb = &pool->hashbucket[tmem_oid_hash(oidp)]; spin_lock(&hb->lock); obj = objfound = tmem_obj_find(hb, oidp);@@ -521,7 +545,7 @@ int tmem_put(struct tmem_pool *pool, str /* if found, is a dup put, flush the old one */ pampd_del = tmem_pampd_delete_from_obj(obj, index); BUG_ON(pampd_del != pampd); - (*tmem_pamops.free)(pampd, pool); + (*tmem_pamops.free)(pampd, pool, oidp, index); if (obj->pampd_count == 0) { objnew = obj; objfound = NULL;@@ -538,7 +562,8 @@ int tmem_put(struct tmem_pool *pool, str } BUG_ON(obj == NULL); BUG_ON(((objnew != obj) && (objfound != obj)) || (objnew == objfound)); - pampd = (*tmem_pamops.create)(obj->pool, &obj->oid, index, page); + pampd = (*tmem_pamops.create)(data, size, raw, ephemeral, + obj->pool, &obj->oid, index); if (unlikely(pampd == NULL)) goto free; ret = tmem_pampd_add_to_obj(obj, index, pampd);@@ -551,7 +576,7 @@ delete_and_free: (void)tmem_pampd_delete_from_obj(obj, index); free: if (pampd) - (*tmem_pamops.free)(pampd, pool); + (*tmem_pamops.free)(pampd, pool, NULL, 0); if (objnew) { tmem_obj_free(objnew, hb); (*tmem_hostops.obj_free)(objnew, pool);@@ -573,41 +598,52 @@ out: * "put" done with the same handle). */ -int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp, - uint32_t index, struct page *page) +int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, + char *data, size_t *size, bool raw, int get_and_free)
And also here.. make get_and_free be bool?
{
struct tmem_obj *obj;
void *pampd;
bool ephemeral = is_ephemeral(pool);
uint32_t ret = -1;
struct tmem_hashbucket *hb;
+ bool free = (get_and_free == 1) || ((get_and_free == 0) && ephemeral);
+ bool lock_held = 0;
hb = &pool->hashbucket[tmem_oid_hash(oidp)];
spin_lock(&hb->lock);
+ lock_held = 1;true, not 1.
obj = tmem_obj_find(hb, oidp);
if (obj == NULL)
goto out;
- ephemeral = is_ephemeral(pool);
- if (ephemeral)
+ if (free)
pampd = tmem_pampd_delete_from_obj(obj, index);
else
pampd = tmem_pampd_lookup_in_obj(obj, index);
if (pampd == NULL)
goto out;
- ret = (*tmem_pamops.get_data)(page, pampd, pool);
- if (ret < 0)
- goto out;
- if (ephemeral) {
- (*tmem_pamops.free)(pampd, pool);
+ if (free) {
if (obj->pampd_count == 0) {
tmem_obj_free(obj, hb);
(*tmem_hostops.obj_free)(obj, pool);
obj = NULL;
}
}
+ if (tmem_pamops.is_remote(pampd)) {
+ lock_held = 0;false.
quoted hunk ↗ jump to hunk
+ spin_unlock(&hb->lock); + } + if (free) + ret = (*tmem_pamops.get_data_and_free)( + data, size, raw, pampd, pool, oidp, index); + else + ret = (*tmem_pamops.get_data)( + data, size, raw, pampd, pool, oidp, index); + if (ret < 0) + goto out; ret = 0; out: - spin_unlock(&hb->lock); + if (lock_held) + spin_unlock(&hb->lock); return ret; }@@ -632,7 +668,7 @@ int tmem_flush_page(struct tmem_pool *po pampd = tmem_pampd_delete_from_obj(obj, index); if (pampd == NULL) goto out; - (*tmem_pamops.free)(pampd, pool); + (*tmem_pamops.free)(pampd, pool, oidp, index); if (obj->pampd_count == 0) { tmem_obj_free(obj, hb); (*tmem_hostops.obj_free)(obj, pool);@@ -645,6 +681,30 @@ out: } /* + * If a page in tmem matches the handle, replace the page so that any + * subsequent "get" gets the new page. Returns the new page if + * there was a page to replace, else returns NULL.
uh, you return -1 not NULL.
quoted hunk ↗ jump to hunk
+ */ +int tmem_replace(struct tmem_pool *pool, struct tmem_oid *oidp, + uint32_t index, void *new_pampd) +{ + struct tmem_obj *obj; + int ret = -1; + struct tmem_hashbucket *hb; + + hb = &pool->hashbucket[tmem_oid_hash(oidp)]; + spin_lock(&hb->lock); + obj = tmem_obj_find(hb, oidp); + if (obj == NULL) + goto out; + new_pampd = tmem_pampd_replace_in_obj(obj, index, new_pampd); + ret = (*tmem_pamops.replace_in_obj)(new_pampd, obj); +out: + spin_unlock(&hb->lock); + return ret; +} + +/* * "Flush" all pages in tmem matching this oid. */ int tmem_flush_object(struct tmem_pool *pool, struct tmem_oid *oidp) diff -Napur -X linux-3.0-rc1/Documentation/dontdiff linux-3.0-rc4/drivers/staging/zcache/tmem.h linux-3.0-rc4-zcache/drivers/staging/zcache/tmem.h--- linux-3.0-rc4/drivers/staging/zcache/tmem.h 2011-06-20 21:25:46.000000000 -0600 +++ linux-3.0-rc4-zcache/drivers/staging/zcache/tmem.h 2011-06-25 15:43:20.236906477 -0600@@ -147,6 +147,7 @@ struct tmem_obj { unsigned int objnode_tree_height; unsigned long objnode_count; long pampd_count; + void *extra; /* for private use by pampd implementation */ DECL_SENTINEL };@@ -166,10 +167,18 @@ struct tmem_objnode { /* pampd abstract datatype methods provided by the PAM implementation */ struct tmem_pamops { - void *(*create)(struct tmem_pool *, struct tmem_oid *, uint32_t, - struct page *); - int (*get_data)(struct page *, void *, struct tmem_pool *); - void (*free)(void *, struct tmem_pool *); + void *(*create)(char *, size_t, bool, int, + struct tmem_pool *, struct tmem_oid *, uint32_t); + int (*get_data)(char *, size_t *, bool, void *, struct tmem_pool *, + struct tmem_oid *, uint32_t); + int (*get_data_and_free)(char *, size_t *, bool, void *, + struct tmem_pool *, struct tmem_oid *, + uint32_t); + void (*free)(void *, struct tmem_pool *, struct tmem_oid *, uint32_t); + void (*free_obj)(struct tmem_pool *, struct tmem_obj *); + bool (*is_remote)(void *); + void (*new_obj)(struct tmem_obj *); + int (*replace_in_obj)(void *, struct tmem_obj *); }; extern void tmem_register_pamops(struct tmem_pamops *m);@@ -184,9 +193,11 @@ extern void tmem_register_hostops(struct /* core tmem accessor functions */ extern int tmem_put(struct tmem_pool *, struct tmem_oid *, uint32_t index, - struct page *page); + char *, size_t, bool, int); extern int tmem_get(struct tmem_pool *, struct tmem_oid *, uint32_t index, - struct page *page); + char *, size_t *, bool, int); +extern int tmem_replace(struct tmem_pool *, struct tmem_oid *, uint32_t index, + void *); extern int tmem_flush_page(struct tmem_pool *, struct tmem_oid *, uint32_t index); extern int tmem_flush_object(struct tmem_pool *, struct tmem_oid *);diff -Napur -X linux-3.0-rc1/Documentation/dontdiff linux-3.0-rc4/drivers/staging/zcache/zcache.c linux-3.0-rc4-zcache/drivers/staging/zcache/zcache.c--- linux-3.0-rc4/drivers/staging/zcache/zcache.c 2011-06-20 21:25:46.000000000 -0600 +++ linux-3.0-rc4-zcache/drivers/staging/zcache/zcache.c 2011-06-25 15:45:55.016705466 -0600@@ -49,6 +49,32 @@ (__GFP_FS | __GFP_NORETRY | __GFP_NOWARN | __GFP_NOMEMALLOC) #endif +#define MAX_POOLS_PER_CLIENT 16 + +#define MAX_CLIENTS 16 +#define LOCAL_CLIENT ((uint16_t)-1) +struct zcache_client { + struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT]; + struct xv_pool *xvpool; + bool allocated; + atomic_t refcount; +}; + +static struct zcache_client zcache_host; +static struct zcache_client zcache_clients[MAX_CLIENTS]; + +static inline uint16_t get_client_id_from_client(struct zcache_client *cli) +{ + if (cli == &zcache_host) + return LOCAL_CLIENT;
What if cli is NULL?
quoted hunk ↗ jump to hunk
+ return cli - &zcache_clients[0]; +} + +static inline bool is_local_client(struct zcache_client *cli) +{ + return cli == &zcache_host; +} + /********** * Compression buddies ("zbud") provides for packing two (or, possibly * in the future, more) compressed ephemeral pages into a single "raw"@@ -72,7 +98,8 @@ #define ZBUD_MAX_BUDS 2 struct zbud_hdr { - uint32_t pool_id; + uint16_t client_id; + uint16_t pool_id; struct tmem_oid oid; uint32_t index; uint16_t size; /* compressed size in bytes, zero means unused */@@ -294,7 +321,8 @@ static void zbud_free_and_delist(struct } } -static struct zbud_hdr *zbud_create(uint32_t pool_id, struct tmem_oid *oid, +static struct zbud_hdr *zbud_create(uint16_t client_id, uint16_t pool_id, + struct tmem_oid *oid, uint32_t index, struct page *page, void *cdata, unsigned size) {@@ -353,6 +381,7 @@ init_zh: zh->index = index; zh->oid = *oid; zh->pool_id = pool_id; + zh->client_id = client_id; /* can wait to copy the data until the list locks are dropped */ spin_unlock(&zbud_budlists_spinlock);@@ -407,7 +436,8 @@ static unsigned long zcache_evicted_raw_ static unsigned long zcache_evicted_buddied_pages; static unsigned long zcache_evicted_unbuddied_pages; -static struct tmem_pool *zcache_get_pool_by_id(uint32_t poolid); +static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, + uint16_t poolid); static void zcache_put_pool(struct tmem_pool *pool); /*@@ -417,7 +447,8 @@ static void zbud_evict_zbpg(struct zbud_ { struct zbud_hdr *zh; int i, j; - uint32_t pool_id[ZBUD_MAX_BUDS], index[ZBUD_MAX_BUDS]; + uint32_t pool_id[ZBUD_MAX_BUDS], client_id[ZBUD_MAX_BUDS]; + uint32_t index[ZBUD_MAX_BUDS]; struct tmem_oid oid[ZBUD_MAX_BUDS]; struct tmem_pool *pool;@@ -426,6 +457,7 @@ static void zbud_evict_zbpg(struct zbud_ for (i = 0, j = 0; i < ZBUD_MAX_BUDS; i++) { zh = &zbpg->buddy[i]; if (zh->size) { + client_id[j] = zh->client_id; pool_id[j] = zh->pool_id; oid[j] = zh->oid; index[j] = zh->index;@@ -435,7 +467,7 @@ static void zbud_evict_zbpg(struct zbud_ } spin_unlock(&zbpg->lock); for (i = 0; i < j; i++) { - pool = zcache_get_pool_by_id(pool_id[i]); + pool = zcache_get_pool_by_id(client_id[i], pool_id[i]); if (pool != NULL) { tmem_flush_page(pool, &oid[i], index[i]); zcache_put_pool(pool);@@ -677,36 +709,70 @@ static unsigned long zcache_flobj_found; static unsigned long zcache_failed_eph_puts; static unsigned long zcache_failed_pers_puts; -#define MAX_POOLS_PER_CLIENT 16 - -static struct { - struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT]; - struct xv_pool *xvpool; -} zcache_client; - /* * Tmem operations assume the poolid implies the invoking client. - * Zcache only has one client (the kernel itself), so translate - * the poolid into the tmem_pool allocated for it. A KVM version + * Zcache only has one client (the kernel itself): LOCAL_CLIENT. + * RAMster has each client numbered by cluster node, and a KVM version * of zcache would have one client per guest and each client might * have a poolid==N. */ -static struct tmem_pool *zcache_get_pool_by_id(uint32_t poolid) +static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, uint16_t poolid) { struct tmem_pool *pool = NULL; + struct zcache_client *cli = NULL; - if (poolid >= 0) { - pool = zcache_client.tmem_pools[poolid]; + if (cli_id == LOCAL_CLIENT) + cli = &zcache_host; + else { + if (cli_id >= MAX_CLIENTS) + goto out; + cli = &zcache_clients[cli_id]; + if (cli == NULL) + goto out; + atomic_inc(&cli->refcount); + } + if (poolid < MAX_POOLS_PER_CLIENT) { + pool = cli->tmem_pools[poolid]; if (pool != NULL) atomic_inc(&pool->refcount); } +out: return pool; } static void zcache_put_pool(struct tmem_pool *pool) { - if (pool != NULL) - atomic_dec(&pool->refcount); + struct zcache_client *cli = NULL; + + if (pool == NULL) + BUG(); + cli = pool->client; + atomic_dec(&pool->refcount); + atomic_dec(&cli->refcount); +} + +int zcache_new_client(uint16_t cli_id) +{ + struct zcache_client *cli = NULL; + int ret = -1; + + if (cli_id == LOCAL_CLIENT) + cli = &zcache_host; + else if ((unsigned int)cli_id < MAX_CLIENTS) + cli = &zcache_clients[cli_id]; + if (cli == NULL) + goto out; + if (cli->allocated) + goto out; + cli->allocated = 1; +#ifdef CONFIG_FRONTSWAP + cli->xvpool = xv_create_pool(); + if (cli->xvpool == NULL) + goto out; +#endif + ret = 0; +out: + return ret; } /* counters for debugging */@@ -901,26 +967,28 @@ static unsigned long zcache_curr_pers_pa /* forward reference */ static int zcache_compress(struct page *from, void **out_va, size_t *out_len); -static void *zcache_pampd_create(struct tmem_pool *pool, struct tmem_oid *oid, - uint32_t index, struct page *page) +static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph, + struct tmem_pool *pool, struct tmem_oid *oid, + uint32_t index) { void *pampd = NULL, *cdata; size_t clen; int ret; - bool ephemeral = is_ephemeral(pool); unsigned long count; + struct page *page = virt_to_page(data); + struct zcache_client *cli = pool->client; + uint16_t client_id = get_client_id_from_client(cli); - if (ephemeral) { + if (eph) { ret = zcache_compress(page, &cdata, &clen); if (ret == 0) - goto out; if (clen == 0 || clen > zbud_max_buddy_size()) { zcache_compress_poor++; goto out; } - pampd = (void *)zbud_create(pool->pool_id, oid, index, - page, cdata, clen); + pampd = (void *)zbud_create(client_id, pool->pool_id, oid, + index, page, cdata, clen); if (pampd != NULL) { count = atomic_inc_return(&zcache_curr_eph_pampd_count); if (count > zcache_curr_eph_pampd_count_max)@@ -942,7 +1010,7 @@ static void *zcache_pampd_create(struct zcache_compress_poor++; goto out; } - pampd = (void *)zv_create(zcache_client.xvpool, pool->pool_id, + pampd = (void *)zv_create(cli->xvpool, pool->pool_id, oid, index, cdata, clen); if (pampd == NULL) goto out;@@ -958,15 +1026,31 @@ out: * fill the pageframe corresponding to the struct page with the data * from the passed pampd */ -static int zcache_pampd_get_data(struct page *page, void *pampd, - struct tmem_pool *pool) +static int zcache_pampd_get_data(char *data, size_t *bufsize, bool raw, + void *pampd, struct tmem_pool *pool, + struct tmem_oid *oid, uint32_t index) { int ret = 0; - if (is_ephemeral(pool)) - ret = zbud_decompress(page, pampd); - else - zv_decompress(page, pampd); + BUG_ON(is_ephemeral(pool)); + zv_decompress(virt_to_page(data), pampd); + return ret; +} + +/* + * fill the pageframe corresponding to the struct page with the data + * from the passed pampd + */ +static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw, + void *pampd, struct tmem_pool *pool, + struct tmem_oid *oid, uint32_t index) +{ + int ret = 0; + + BUG_ON(!is_ephemeral(pool)); + zbud_decompress(virt_to_page(data), pampd); + zbud_free_and_delist((struct zbud_hdr *)pampd); + atomic_dec(&zcache_curr_eph_pampd_count); return ret; }@@ -974,23 +1058,49 @@ static int zcache_pampd_get_data(struct * free the pampd and remove it from any zcache lists * pampd must no longer be pointed to from any tmem data structures! */ -static void zcache_pampd_free(void *pampd, struct tmem_pool *pool) +static void zcache_pampd_free(void *pampd, struct tmem_pool *pool, + struct tmem_oid *oid, uint32_t index) { + struct zcache_client *cli = pool->client; + if (is_ephemeral(pool)) { zbud_free_and_delist((struct zbud_hdr *)pampd); atomic_dec(&zcache_curr_eph_pampd_count); BUG_ON(atomic_read(&zcache_curr_eph_pampd_count) < 0); } else { - zv_free(zcache_client.xvpool, (struct zv_hdr *)pampd); + zv_free(cli->xvpool, (struct zv_hdr *)pampd); atomic_dec(&zcache_curr_pers_pampd_count); BUG_ON(atomic_read(&zcache_curr_pers_pampd_count) < 0); } } +static void zcache_pampd_free_obj(struct tmem_pool *pool, struct tmem_obj *obj) +{ +} + +static void zcache_pampd_new_obj(struct tmem_obj *obj) +{ +} + +static int zcache_pampd_replace_in_obj(void *pampd, struct tmem_obj *obj) +{ + return -1; +} + +static bool zcache_pampd_is_remote(void *pampd) +{ + return 0; +} + static struct tmem_pamops zcache_pamops = { .create = zcache_pampd_create, .get_data = zcache_pampd_get_data, + .get_data_and_free = zcache_pampd_get_data_and_free, .free = zcache_pampd_free, + .free_obj = zcache_pampd_free_obj, + .new_obj = zcache_pampd_new_obj, + .replace_in_obj = zcache_pampd_replace_in_obj, + .is_remote = zcache_pampd_is_remote, }; /*@@ -1212,19 +1322,20 @@ static struct shrinker zcache_shrinker = * zcache shims between cleancache/frontswap ops and tmem */ -static int zcache_put_page(int pool_id, struct tmem_oid *oidp, +static int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp, uint32_t index, struct page *page) { struct tmem_pool *pool; int ret = -1; BUG_ON(!irqs_disabled()); - pool = zcache_get_pool_by_id(pool_id); + pool = zcache_get_pool_by_id(cli_id, pool_id); if (unlikely(pool == NULL)) goto out; if (!zcache_freeze && zcache_do_preload(pool) == 0) { /* preload does preempt_disable on success */ - ret = tmem_put(pool, oidp, index, page); + ret = tmem_put(pool, oidp, index, page_address(page), + PAGE_SIZE, 0, is_ephemeral(pool)); if (ret < 0) { if (is_ephemeral(pool)) zcache_failed_eph_puts++;@@ -1244,25 +1355,28 @@ out: return ret; } -static int zcache_get_page(int pool_id, struct tmem_oid *oidp, +static int zcache_get_page(int cli_id, int pool_id, struct tmem_oid *oidp, uint32_t index, struct page *page) { struct tmem_pool *pool; int ret = -1; unsigned long flags; + size_t size = PAGE_SIZE; local_irq_save(flags); - pool = zcache_get_pool_by_id(pool_id); + pool = zcache_get_pool_by_id(cli_id, pool_id); if (likely(pool != NULL)) { if (atomic_read(&pool->obj_count) > 0) - ret = tmem_get(pool, oidp, index, page); + ret = tmem_get(pool, oidp, index, page_address(page), + &size, 0, is_ephemeral(pool)); zcache_put_pool(pool); } local_irq_restore(flags); return ret; } -static int zcache_flush_page(int pool_id, struct tmem_oid *oidp, uint32_t index) +static int zcache_flush_page(int cli_id, int pool_id, + struct tmem_oid *oidp, uint32_t index) { struct tmem_pool *pool; int ret = -1;@@ -1270,7 +1384,7 @@ static int zcache_flush_page(int pool_id local_irq_save(flags); zcache_flush_total++; - pool = zcache_get_pool_by_id(pool_id); + pool = zcache_get_pool_by_id(cli_id, pool_id); if (likely(pool != NULL)) { if (atomic_read(&pool->obj_count) > 0) ret = tmem_flush_page(pool, oidp, index);@@ -1282,7 +1396,8 @@ static int zcache_flush_page(int pool_id return ret; } -static int zcache_flush_object(int pool_id, struct tmem_oid *oidp) +static int zcache_flush_object(int cli_id, int pool_id, + struct tmem_oid *oidp) { struct tmem_pool *pool; int ret = -1;@@ -1290,7 +1405,7 @@ static int zcache_flush_object(int pool_ local_irq_save(flags); zcache_flobj_total++; - pool = zcache_get_pool_by_id(pool_id); + pool = zcache_get_pool_by_id(cli_id, pool_id); if (likely(pool != NULL)) { if (atomic_read(&pool->obj_count) > 0) ret = tmem_flush_object(pool, oidp);@@ -1302,34 +1417,52 @@ static int zcache_flush_object(int pool_ return ret; } -static int zcache_destroy_pool(int pool_id) +static int zcache_destroy_pool(int cli_id, int pool_id) { struct tmem_pool *pool = NULL; + struct zcache_client *cli = NULL; int ret = -1; if (pool_id < 0) goto out; - pool = zcache_client.tmem_pools[pool_id]; + if (cli_id == LOCAL_CLIENT) + cli = &zcache_host; + else if ((unsigned int)cli_id < MAX_CLIENTS) + cli = &zcache_clients[cli_id]; + if (cli == NULL) + goto out; + atomic_inc(&cli->refcount); + pool = cli->tmem_pools[pool_id]; if (pool == NULL) goto out; - zcache_client.tmem_pools[pool_id] = NULL; + cli->tmem_pools[pool_id] = NULL; /* wait for pool activity on other cpus to quiesce */ while (atomic_read(&pool->refcount) != 0) ; + atomic_dec(&cli->refcount); local_bh_disable(); ret = tmem_destroy_pool(pool); local_bh_enable(); kfree(pool); - pr_info("zcache: destroyed pool id=%d\n", pool_id); + pr_info("zcache: destroyed pool id=%d, cli_id=%d\n", + pool_id, cli_id); out: return ret; } -static int zcache_new_pool(uint32_t flags) +static int zcache_new_pool(uint16_t cli_id, uint32_t flags) { int poolid = -1; struct tmem_pool *pool; + struct zcache_client *cli = NULL; + if (cli_id == LOCAL_CLIENT) + cli = &zcache_host; + else if ((unsigned int)cli_id < MAX_CLIENTS) + cli = &zcache_clients[cli_id]; + if (cli == NULL) + goto out; + atomic_inc(&cli->refcount); pool = kmalloc(sizeof(struct tmem_pool), GFP_KERNEL); if (pool == NULL) { pr_info("zcache: pool creation failed: out of memory\n");@@ -1337,7 +1470,7 @@ static int zcache_new_pool(uint32_t flag } for (poolid = 0; poolid < MAX_POOLS_PER_CLIENT; poolid++) - if (zcache_client.tmem_pools[poolid] == NULL) + if (cli->tmem_pools[poolid] == NULL) break; if (poolid >= MAX_POOLS_PER_CLIENT) { pr_info("zcache: pool creation failed: max exceeded\n");@@ -1346,14 +1479,16 @@ static int zcache_new_pool(uint32_t flag goto out; } atomic_set(&pool->refcount, 0); - pool->client = &zcache_client; + pool->client = cli; pool->pool_id = poolid; tmem_new_pool(pool, flags); - zcache_client.tmem_pools[poolid] = pool; - pr_info("zcache: created %s tmem pool, id=%d\n", + cli->tmem_pools[poolid] = pool; + pr_info("zcache: created %s tmem pool, id=%d, client=%d\n", flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral", - poolid); + poolid, cli_id); out: + if (cli != NULL) + atomic_dec(&cli->refcount); return poolid; }@@ -1374,7 +1509,7 @@ static void zcache_cleancache_put_page(i struct tmem_oid oid = *(struct tmem_oid *)&key; if (likely(ind == index)) - (void)zcache_put_page(pool_id, &oid, index, page); + (void)zcache_put_page(LOCAL_CLIENT, pool_id, &oid, index, page); } static int zcache_cleancache_get_page(int pool_id,@@ -1386,7 +1521,7 @@ static int zcache_cleancache_get_page(in int ret = -1; if (likely(ind == index)) - ret = zcache_get_page(pool_id, &oid, index, page); + ret = zcache_get_page(LOCAL_CLIENT, pool_id, &oid, index, page); return ret; }@@ -1398,7 +1533,7 @@ static void zcache_cleancache_flush_page struct tmem_oid oid = *(struct tmem_oid *)&key; if (likely(ind == index)) - (void)zcache_flush_page(pool_id, &oid, ind); + (void)zcache_flush_page(LOCAL_CLIENT, pool_id, &oid, ind); } static void zcache_cleancache_flush_inode(int pool_id,@@ -1406,13 +1541,13 @@ static void zcache_cleancache_flush_inod { struct tmem_oid oid = *(struct tmem_oid *)&key; - (void)zcache_flush_object(pool_id, &oid); + (void)zcache_flush_object(LOCAL_CLIENT, pool_id, &oid); } static void zcache_cleancache_flush_fs(int pool_id) { if (pool_id >= 0) - (void)zcache_destroy_pool(pool_id); + (void)zcache_destroy_pool(LOCAL_CLIENT, pool_id); } static int zcache_cleancache_init_fs(size_t pagesize)@@ -1420,7 +1555,7 @@ static int zcache_cleancache_init_fs(siz BUG_ON(sizeof(struct cleancache_filekey) != sizeof(struct tmem_oid)); BUG_ON(pagesize != PAGE_SIZE); - return zcache_new_pool(0); + return zcache_new_pool(LOCAL_CLIENT, 0); } static int zcache_cleancache_init_shared_fs(char *uuid, size_t pagesize)@@ -1429,7 +1564,7 @@ static int zcache_cleancache_init_shared BUG_ON(sizeof(struct cleancache_filekey) != sizeof(struct tmem_oid)); BUG_ON(pagesize != PAGE_SIZE); - return zcache_new_pool(0); + return zcache_new_pool(LOCAL_CLIENT, 0); } static struct cleancache_ops zcache_cleancache_ops = {@@ -1483,8 +1618,8 @@ static int zcache_frontswap_put_page(uns BUG_ON(!PageLocked(page)); if (likely(ind64 == ind)) { local_irq_save(flags); - ret = zcache_put_page(zcache_frontswap_poolid, &oid, - iswiz(ind), page); + ret = zcache_put_page(LOCAL_CLIENT, zcache_frontswap_poolid, + &oid, iswiz(ind), page); local_irq_restore(flags); } return ret;@@ -1502,8 +1637,8 @@ static int zcache_frontswap_get_page(uns BUG_ON(!PageLocked(page)); if (likely(ind64 == ind)) - ret = zcache_get_page(zcache_frontswap_poolid, &oid, - iswiz(ind), page); + ret = zcache_get_page(LOCAL_CLIENT, zcache_frontswap_poolid, + &oid, iswiz(ind), page); return ret; }@@ -1515,8 +1650,8 @@ static void zcache_frontswap_flush_page( struct tmem_oid oid = oswiz(type, ind); if (likely(ind64 == ind)) - (void)zcache_flush_page(zcache_frontswap_poolid, &oid, - iswiz(ind)); + (void)zcache_flush_page(LOCAL_CLIENT, zcache_frontswap_poolid, + &oid, iswiz(ind)); } /* flush all pages from the passed swaptype */@@ -1527,7 +1662,8 @@ static void zcache_frontswap_flush_area( for (ind = SWIZ_MASK; ind >= 0; ind--) { oid = oswiz(type, ind); - (void)zcache_flush_object(zcache_frontswap_poolid, &oid); + (void)zcache_flush_object(LOCAL_CLIENT, + zcache_frontswap_poolid, &oid); } }@@ -1535,7 +1671,8 @@ static void zcache_frontswap_init(unsign { /* a single tmem poolid is used for all frontswap "types" (swapfiles) */ if (zcache_frontswap_poolid < 0) - zcache_frontswap_poolid = zcache_new_pool(TMEM_POOL_PERSIST); + zcache_frontswap_poolid = + zcache_new_pool(LOCAL_CLIENT, TMEM_POOL_PERSIST); } static struct frontswap_ops zcache_frontswap_ops = {@@ -1624,6 +1761,11 @@ static int __init zcache_init(void) sizeof(struct tmem_objnode), 0, 0, NULL); zcache_obj_cache = kmem_cache_create("zcache_obj", sizeof(struct tmem_obj), 0, 0, NULL); + ret = zcache_new_client(LOCAL_CLIENT); + if (ret) { + pr_err("zcache: can't create client\n"); + goto out; + } #endif #ifdef CONFIG_CLEANCACHE if (zcache_enabled && use_cleancache) {@@ -1642,11 +1784,6 @@ static int __init zcache_init(void) if (zcache_enabled && use_frontswap) { struct frontswap_ops old_ops; - zcache_client.xvpool = xv_create_pool(); - if (zcache_client.xvpool == NULL) { - pr_err("zcache: can't create xvpool\n"); - goto out; - } old_ops = zcache_frontswap_register_ops(); pr_info("zcache: frontswap enabled using kernel " "transcendent memory and xvmalloc\n");
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>