From: Minchan Kim <minchan@kernel.org>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org,
Minchan Kim <minchan@kernel.org>,
Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Subject: [PATCH] zsmalloc: keep first object offset in struct page
Date: Mon, 13 Jun 2016 12:20:15 +0900 [thread overview]
Message-ID: <1465788015-23195-1-git-send-email-minchan@kernel.org> (raw)
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@gmail.com>
Signed-off-by: Minchan Kim <minchan@kernel.org>
---
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@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
WARNING: multiple messages have this Message-ID (diff)
From: Minchan Kim <minchan@kernel.org>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org,
Minchan Kim <minchan@kernel.org>,
Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Subject: [PATCH] zsmalloc: keep first object offset in struct page
Date: Mon, 13 Jun 2016 12:20:15 +0900 [thread overview]
Message-ID: <1465788015-23195-1-git-send-email-minchan@kernel.org> (raw)
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@gmail.com>
Signed-off-by: Minchan Kim <minchan@kernel.org>
---
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
next reply other threads:[~2016-06-13 3:20 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-06-13 3:20 Minchan Kim [this message]
2016-06-13 3:20 ` [PATCH] zsmalloc: keep first object offset in struct page Minchan Kim
2016-06-13 3:37 ` Minchan Kim
2016-06-13 3:37 ` Minchan Kim
2016-06-14 1:15 ` Sergey Senozhatsky
2016-06-14 1:15 ` Sergey Senozhatsky
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1465788015-23195-1-git-send-email-minchan@kernel.org \
--to=minchan@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=sergey.senozhatsky@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.