zbud_pool has an lru list for tracking zbud pages and they are strung together via zhdr->lru. If we reuse page->lru for linking zbud pages instead of it, the lru field in zbud_header can be dropped. Signed-off-by: Heesub Shin <heesub.shin@xxxxxxxxxxx> --- mm/zbud.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/mm/zbud.c b/mm/zbud.c index 0f5add0..a2390f6 100644 --- a/mm/zbud.c +++ b/mm/zbud.c @@ -100,13 +100,11 @@ struct zbud_pool { * struct zbud_header - zbud page metadata occupying the first chunk of each * zbud page. * @buddy: links the zbud page into the unbuddied lists in the pool - * @lru: links the zbud page into the lru list in the pool * @first_chunks: the size of the first buddy in chunks, 0 if free * @last_chunks: the size of the last buddy in chunks, 0 if free */ struct zbud_header { struct list_head buddy; - struct list_head lru; unsigned int first_chunks; unsigned int last_chunks; bool under_reclaim; @@ -224,7 +222,7 @@ static struct zbud_header *init_zbud_page(struct page *page) zhdr->first_chunks = 0; zhdr->last_chunks = 0; INIT_LIST_HEAD(&zhdr->buddy); - INIT_LIST_HEAD(&zhdr->lru); + INIT_LIST_HEAD(&page->lru); zhdr->under_reclaim = 0; return zhdr; } @@ -352,6 +350,7 @@ int zbud_alloc(struct zbud_pool *pool, size_t size, gfp_t gfp, if (!list_empty(&pool->unbuddied[i])) { zhdr = list_first_entry(&pool->unbuddied[i], struct zbud_header, buddy); + page = virt_to_page(zhdr); list_del(&zhdr->buddy); goto found; } @@ -382,9 +381,9 @@ found: } /* Add/move zbud page to beginning of LRU */ - if (!list_empty(&zhdr->lru)) - list_del(&zhdr->lru); - list_add(&zhdr->lru, &pool->lru); + if (!list_empty(&page->lru)) + list_del(&page->lru); + list_add(&page->lru, &pool->lru); *handle = encode_handle(zhdr, bud); spin_unlock(&pool->lock); @@ -405,10 +404,12 @@ found: void zbud_free(struct zbud_pool *pool, unsigned long handle) { struct zbud_header *zhdr; + struct page *page; int freechunks; spin_lock(&pool->lock); zhdr = handle_to_zbud_header(handle); + page = virt_to_page(zhdr); /* If first buddy, handle will be page aligned */ if ((handle - ZHDR_SIZE_ALIGNED) & ~PAGE_MASK) @@ -426,7 +427,7 @@ void zbud_free(struct zbud_pool *pool, unsigned long handle) /* Remove from existing unbuddied list */ list_del(&zhdr->buddy); /* zbud page is empty, free */ - list_del(&zhdr->lru); + list_del(&page->lru); free_zbud_page(zhdr); pool->pages_nr--; } else { @@ -479,6 +480,7 @@ void zbud_free(struct zbud_pool *pool, unsigned long handle) int zbud_reclaim_page(struct zbud_pool *pool, unsigned int retries) { int i, ret, freechunks; + struct page *page; struct zbud_header *zhdr; unsigned long first_handle, last_handle; @@ -489,8 +491,9 @@ int zbud_reclaim_page(struct zbud_pool *pool, unsigned int retries) return -EINVAL; } for (i = 0; i < retries; i++) { - zhdr = list_tail_entry(&pool->lru, struct zbud_header, lru); - list_del(&zhdr->lru); + page = list_tail_entry(&pool->lru, struct page, lru); + zhdr = page_address(page); + list_del(&page->lru); list_del(&zhdr->buddy); /* Protect zbud page against free */ zhdr->under_reclaim = true; @@ -537,7 +540,7 @@ next: } /* add to beginning of LRU */ - list_add(&zhdr->lru, &pool->lru); + list_add(&page->lru, &pool->lru); } spin_unlock(&pool->lock); return -EAGAIN; -- 1.9.1 -- 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>