On Tue, Oct 08, 2013 at 03:29:35PM +0200, Krzysztof Kozlowski wrote: > Use page reference counter for zbud pages. The ref counter replaces > zbud_header.under_reclaim flag and ensures that zbud page won't be freed > when zbud_free() is called during reclaim. It allows implementation of > additional reclaim paths. > > The page count is incremented when: > - a handle is created and passed to zswap (in zbud_alloc()), > - user-supplied eviction callback is called (in zbud_reclaim_page()). > > Signed-off-by: Krzysztof Kozlowski <k.kozlowski@xxxxxxxxxxx> > Signed-off-by: Tomasz Stanislawski <t.stanislaws@xxxxxxxxxxx> > Reviewed-by: Bob Liu <bob.liu@xxxxxxxxxx> Other than the nit below: Acked-by: Seth Jennings <sjenning@xxxxxxxxxxxxxxxxxx> > --- > mm/zbud.c | 117 +++++++++++++++++++++++++++++++++---------------------------- > 1 file changed, 64 insertions(+), 53 deletions(-) > > diff --git a/mm/zbud.c b/mm/zbud.c > index 9451361..7574289 100644 > --- a/mm/zbud.c > +++ b/mm/zbud.c > @@ -109,7 +109,6 @@ struct zbud_header { > struct list_head lru; > unsigned int first_chunks; > unsigned int last_chunks; > - bool under_reclaim; > }; > > /***************** > @@ -138,16 +137,9 @@ static struct zbud_header *init_zbud_page(struct page *page) > zhdr->last_chunks = 0; > INIT_LIST_HEAD(&zhdr->buddy); > INIT_LIST_HEAD(&zhdr->lru); > - zhdr->under_reclaim = 0; > return zhdr; > } > > -/* Resets the struct page fields and frees the page */ > -static void free_zbud_page(struct zbud_header *zhdr) > -{ > - __free_page(virt_to_page(zhdr)); > -} > - > /* > * Encodes the handle of a particular buddy within a zbud page > * Pool lock should be held as this function accesses first|last_chunks > @@ -188,6 +180,31 @@ static int num_free_chunks(struct zbud_header *zhdr) > return NCHUNKS - zhdr->first_chunks - zhdr->last_chunks - 1; > } > > +/* > + * Increases ref count for zbud page. > + */ > +static void get_zbud_page(struct zbud_header *zhdr) > +{ > + get_page(virt_to_page(zhdr)); > +} > + > +/* > + * Decreases ref count for zbud page and frees the page if it reaches 0 > + * (no external references, e.g. handles). > + * > + * Returns 1 if page was freed and 0 otherwise. > + */ > +static int put_zbud_page(struct zbud_header *zhdr) > +{ > + struct page *page = virt_to_page(zhdr); > + if (put_page_testzero(page)) { > + free_hot_cold_page(page, 0); > + return 1; > + } > + return 0; > +} > + > + > /***************** > * API Functions > *****************/ > @@ -273,6 +290,7 @@ int zbud_alloc(struct zbud_pool *pool, int size, gfp_t gfp, > bud = FIRST; > else > bud = LAST; > + get_zbud_page(zhdr); > goto found; > } > } > @@ -284,6 +302,10 @@ int zbud_alloc(struct zbud_pool *pool, int size, gfp_t gfp, > return -ENOMEM; > spin_lock(&pool->lock); > pool->pages_nr++; > + /* > + * We will be using zhdr instead of page, so > + * don't increase the page count. > + */ This comment isn't very clear. I think what you mean to say is that we already have the page ref'ed for this entry because of the initial ref count done by alloc_page(). So maybe: /* * Page count is incremented by alloc_page() for the initial * reference so no need to call zbud_get_page() here. */ Thanks, Seth -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>