In early draft of zspage migration, we couldn't use page._mapcount because it was used for storing movable flag so we added runtime calculation to get first object offset in a page but it causes rather many instruction and even bug. Since then, we don't use page._mapcount as page flag any more so now there is no problem to use the field to store first object offset. Cc: Sergey Senozhatsky <sergey.senozhatsky@xxxxxxxxx> Signed-off-by: Minchan Kim <minchan@xxxxxxxxxx> --- mm/zsmalloc.c | 44 ++++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c index 6a58edc9a015..4b70fcbfb69b 100644 --- a/mm/zsmalloc.c +++ b/mm/zsmalloc.c @@ -512,6 +512,16 @@ static inline struct page *get_first_page(struct zspage *zspage) return first_page; } +static inline int get_first_obj_offset(struct page *page) +{ + return page->units; +} + +static inline void set_first_obj_offset(struct page *page, int offset) +{ + page->units = offset; +} + static inline unsigned int get_freeobj(struct zspage *zspage) { return zspage->freeobj; @@ -872,31 +882,6 @@ static struct page *get_next_page(struct page *page) return page->freelist; } -/* Get byte offset of first object in the @page */ -static int get_first_obj_offset(struct size_class *class, - struct page *first_page, struct page *page) -{ - int pos; - int page_idx = 0; - int ofs = 0; - struct page *cursor = first_page; - - if (first_page == page) - goto out; - - while (page != cursor) { - page_idx++; - cursor = get_next_page(cursor); - } - - pos = class->objs_per_zspage * class->size * - page_idx / class->pages_per_zspage; - - ofs = (pos + class->size) % PAGE_SIZE; -out: - return ofs; -} - /** * obj_to_location - get (<page>, <obj_idx>) from encoded object value * @page: page object resides in zspage @@ -966,6 +951,7 @@ static void reset_page(struct page *page) clear_bit(PG_private, &page->flags); clear_bit(PG_private_2, &page->flags); set_page_private(page, 0); + page_mapcount_reset(page); ClearPageHugeObject(page); page->freelist = NULL; } @@ -1064,6 +1050,8 @@ static void init_zspage(struct size_class *class, struct zspage *zspage) struct link_free *link; void *vaddr; + set_first_obj_offset(page, off); + vaddr = kmap_atomic(page); link = (struct link_free *)vaddr + off / sizeof(*link); @@ -1762,9 +1750,8 @@ static unsigned long find_alloced_obj(struct size_class *class, int offset = 0; unsigned long handle = 0; void *addr = kmap_atomic(page); - struct zspage *zspage = get_zspage(page); - offset = get_first_obj_offset(class, get_first_page(zspage), page); + offset = get_first_obj_offset(page); offset += class->size * index; while (offset < PAGE_SIZE) { @@ -1976,6 +1963,7 @@ static void replace_sub_page(struct size_class *class, struct zspage *zspage, } while ((page = get_next_page(page)) != NULL); create_page_chain(class, zspage, pages); + set_first_obj_offset(newpage, get_first_obj_offset(oldpage)); if (unlikely(PageHugeObject(oldpage))) newpage->index = oldpage->index; __SetPageMovable(newpage, page_mapping(oldpage)); @@ -2062,7 +2050,7 @@ int zs_page_migrate(struct address_space *mapping, struct page *newpage, get_zspage_mapping(zspage, &class_idx, &fullness); pool = mapping->private_data; class = pool->size_class[class_idx]; - offset = get_first_obj_offset(class, get_first_page(zspage), page); + offset = get_first_obj_offset(page); spin_lock(&class->lock); if (!get_zspage_inuse(zspage)) { -- 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>