* [PATCH 01/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
@ 2024-06-28 3:11 ` alexs
2024-06-30 13:45 ` Hyeonggon Yoo
2024-06-28 3:11 ` [PATCH 02/20] mm/zsmalloc: use zpdesc in trylock_zspage/lock_zspage alexs
` (19 subsequent siblings)
20 siblings, 1 reply; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Alex Shi <alexs@kernel.org>
The 1st patch introduces new memory decriptor zpdesc and rename
zspage.first_page to zspage.first_zpdesc, no functional change.
Originally-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zpdesc.h | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++
mm/zsmalloc.c | 19 ++++++++---------
2 files changed, 66 insertions(+), 9 deletions(-)
create mode 100644 mm/zpdesc.h
diff --git a/mm/zpdesc.h b/mm/zpdesc.h
new file mode 100644
index 000000000000..a1ab5ebaa936
--- /dev/null
+++ b/mm/zpdesc.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* zpdesc.h: zswap.zpool memory descriptor
+ *
+ * Written by Alex Shi <alexs@kernel.org>
+ * Hyeonggon Yoo <42.hyeyoo@gmail.com>
+ */
+#ifndef __MM_ZPDESC_H__
+#define __MM_ZPDESC_H__
+
+/*
+ * struct zpdesc - Memory descriptor for zpool memory, now is for zsmalloc
+ * @flags: Page flags, PG_private: identifies the first component page
+ * @lru: Indirected used by page migration
+ * @next: Next zpdesc in a zspage in zsmalloc zpool
+ * @handle: For huge zspage in zsmalloc zpool
+ * @zspage: Pointer to zspage in zsmalloc
+ *
+ * This struct overlays struct page for now. Do not modify without a good
+ * understanding of the issues.
+ */
+struct zpdesc {
+ unsigned long flags;
+ struct list_head lru;
+ unsigned long _zp_pad_1;
+ union {
+ /* Next zpdescs in a zspage in zsmalloc zpool */
+ struct zpdesc *next;
+ /* For huge zspage in zsmalloc zpool */
+ unsigned long handle;
+ };
+ struct zspage *zspage;
+};
+#define ZPDESC_MATCH(pg, zp) \
+ static_assert(offsetof(struct page, pg) == offsetof(struct zpdesc, zp))
+
+ZPDESC_MATCH(flags, flags);
+ZPDESC_MATCH(lru, lru);
+ZPDESC_MATCH(index, next);
+ZPDESC_MATCH(index, handle);
+ZPDESC_MATCH(private, zspage);
+#undef ZPDESC_MATCH
+static_assert(sizeof(struct zpdesc) <= sizeof(struct page));
+
+#define zpdesc_page(zp) (_Generic((zp), \
+ const struct zpdesc *: (const struct page *)(zp), \
+ struct zpdesc *: (struct page *)(zp)))
+
+#define zpdesc_folio(zp) (_Generic((zp), \
+ const struct zpdesc *: (const struct folio *)(zp), \
+ struct zpdesc *: (struct folio *)(zp)))
+
+#define page_zpdesc(p) (_Generic((p), \
+ const struct page *: (const struct zpdesc *)(p), \
+ struct page *: (struct zpdesc *)(p)))
+
+#endif
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index fec1a39e5bbe..67bb80b7413a 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -13,17 +13,17 @@
/*
* Following is how we use various fields and flags of underlying
- * struct page(s) to form a zspage.
+ * struct zpdesc(page) to form a zspage.
*
- * Usage of struct page fields:
- * page->private: points to zspage
- * page->index: links together all component pages of a zspage
+ * Usage of struct zpdesc fields:
+ * zpdesc->zspage: points to zspage
+ * zpdesc->next: links together all component pages of a zspage
* For the huge page, this is always 0, so we use this field
* to store handle.
* page->page_type: PG_zsmalloc, lower 16 bit locate the first object
* offset in a subpage of a zspage
*
- * Usage of struct page flags:
+ * Usage of struct zpdesc(page) flags:
* PG_private: identifies the first component page
* PG_owner_priv_1: identifies the huge component page
*
@@ -64,6 +64,7 @@
#include <linux/pagemap.h>
#include <linux/fs.h>
#include <linux/local_lock.h>
+#include "zpdesc.h"
#define ZSPAGE_MAGIC 0x58
@@ -253,7 +254,7 @@ struct zspage {
};
unsigned int inuse;
unsigned int freeobj;
- struct page *first_page;
+ struct zpdesc *first_zpdesc;
struct list_head list; /* fullness list */
struct zs_pool *pool;
rwlock_t lock;
@@ -448,7 +449,7 @@ static inline void mod_zspage_inuse(struct zspage *zspage, int val)
static inline struct page *get_first_page(struct zspage *zspage)
{
- struct page *first_page = zspage->first_page;
+ struct page *first_page = zpdesc_page(zspage->first_zpdesc);
VM_BUG_ON_PAGE(!is_first_page(first_page), first_page);
return first_page;
@@ -948,7 +949,7 @@ static void create_page_chain(struct size_class *class, struct zspage *zspage,
set_page_private(page, (unsigned long)zspage);
page->index = 0;
if (i == 0) {
- zspage->first_page = page;
+ zspage->first_zpdesc = page_zpdesc(page);
SetPagePrivate(page);
if (unlikely(class->objs_per_zspage == 1 &&
class->pages_per_zspage == 1))
@@ -1325,7 +1326,7 @@ static unsigned long obj_malloc(struct zs_pool *pool,
link->handle = handle;
else
/* record handle to page->index */
- zspage->first_page->index = handle;
+ zspage->first_zpdesc->handle = handle;
kunmap_atomic(vaddr);
mod_zspage_inuse(zspage, 1);
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* Re: [PATCH 01/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool
2024-06-28 3:11 ` [PATCH 01/20] " alexs
@ 2024-06-30 13:45 ` Hyeonggon Yoo
2024-07-01 3:03 ` Alex Shi
0 siblings, 1 reply; 28+ messages in thread
From: Hyeonggon Yoo @ 2024-06-30 13:45 UTC (permalink / raw)
To: alexs
Cc: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david
On Fri, Jun 28, 2024 at 12:06 PM <alexs@kernel.org> wrote:
>
> From: Alex Shi <alexs@kernel.org>
>
> The 1st patch introduces new memory decriptor zpdesc and rename
> zspage.first_page to zspage.first_zpdesc, no functional change.
>
> Originally-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
> Signed-off-by: Alex Shi <alexs@kernel.org>
> ---
> mm/zpdesc.h | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++
> mm/zsmalloc.c | 19 ++++++++---------
> 2 files changed, 66 insertions(+), 9 deletions(-)
> create mode 100644 mm/zpdesc.h
Hi Alex, thanks for your effort in pushing this forward!
> diff --git a/mm/zpdesc.h b/mm/zpdesc.h
> new file mode 100644
> index 000000000000..a1ab5ebaa936
> --- /dev/null
> +++ b/mm/zpdesc.h
> @@ -0,0 +1,56 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* zpdesc.h: zswap.zpool memory descriptor
> + *
> + * Written by Alex Shi <alexs@kernel.org>
> + * Hyeonggon Yoo <42.hyeyoo@gmail.com>
> + */
> +#ifndef __MM_ZPDESC_H__
> +#define __MM_ZPDESC_H__
> +
> +/*
> + * struct zpdesc - Memory descriptor for zpool memory, now is for zsmalloc
> + * @flags: Page flags, PG_private: identifies the first component page
> + * @lru: Indirected used by page migration
maybe Indirected -> Indirectly?
> + * @next: Next zpdesc in a zspage in zsmalloc zpool
> + * @handle: For huge zspage in zsmalloc zpool
> + * @zspage: Pointer to zspage in zsmalloc
> + *
> + * This struct overlays struct page for now. Do not modify without a good
> + * understanding of the issues.
> + */
> +struct zpdesc {
> + unsigned long flags;
> + struct list_head lru;
> + unsigned long _zp_pad_1;
for understanding, I think it'd be better to replace _zp_pad_1 with movable ops,
because mops reuses this 'mapping' field.
> + union {
> + /* Next zpdescs in a zspage in zsmalloc zpool */
> + struct zpdesc *next;
> + /* For huge zspage in zsmalloc zpool */
> + unsigned long handle;
> + };
> + struct zspage *zspage;
There was a discussion with Yosry on including memcg_data on zpdesc
even if it's not used at the moment.
Maybe you can look at:
https://lore.kernel.org/linux-mm/CAB=+i9Quz9iP2-Lq=oQfKVVnzPDtOaKMm=hUPbnRg5hRxH+qaA@mail.gmail.com/
> diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
> index fec1a39e5bbe..67bb80b7413a 100644
> --- a/mm/zsmalloc.c
> +++ b/mm/zsmalloc.c
> @@ -13,17 +13,17 @@
>
> /*
> * Following is how we use various fields and flags of underlying
> - * struct page(s) to form a zspage.
> + * struct zpdesc(page) to form a zspage.
> *
> - * Usage of struct page fields:
> - * page->private: points to zspage
> - * page->index: links together all component pages of a zspage
> + * Usage of struct zpdesc fields:
> + * zpdesc->zspage: points to zspage
> + * zpdesc->next: links together all component pages of a zspage
> * For the huge page, this is always 0, so we use this field
> * to store handle.
> * page->page_type: PG_zsmalloc, lower 16 bit locate the first object
> * offset in a subpage of a zspage
> *
> - * Usage of struct page flags:
> + * Usage of struct zpdesc(page) flags:
> * PG_private: identifies the first component page
> * PG_owner_priv_1: identifies the huge component page
the comment for PG_owner_priv_1 can safely be removed as it's not used
after commit a41ec880aa7b ("zsmalloc: move huge compressed obj from
page to zspage")
> @@ -948,7 +949,7 @@ static void create_page_chain(struct size_class *class, struct zspage *zspage,
> set_page_private(page, (unsigned long)zspage);
> page->index = 0;
> if (i == 0) {
> - zspage->first_page = page;
> + zspage->first_zpdesc = page_zpdesc(page);
> SetPagePrivate(page);
> if (unlikely(class->objs_per_zspage == 1 &&
> class->pages_per_zspage == 1))
> @@ -1325,7 +1326,7 @@ static unsigned long obj_malloc(struct zs_pool *pool,
> link->handle = handle;
> else
> /* record handle to page->index */
> - zspage->first_page->index = handle;
> + zspage->first_zpdesc->handle = handle;
FYI this line seems to conflict with
bcc6116e39f512 ("mm/zsmalloc: move record_obj() into obj_malloc()")
on mm-unstable.
Best,
Hyeonggon
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 01/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool
2024-06-30 13:45 ` Hyeonggon Yoo
@ 2024-07-01 3:03 ` Alex Shi
2024-07-01 3:40 ` Alex Shi
2024-07-01 13:42 ` Yosry Ahmed
0 siblings, 2 replies; 28+ messages in thread
From: Alex Shi @ 2024-07-01 3:03 UTC (permalink / raw)
To: Hyeonggon Yoo, alexs
Cc: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david
On 6/30/24 9:45 PM, Hyeonggon Yoo wrote:
> On Fri, Jun 28, 2024 at 12:06 PM <alexs@kernel.org> wrote:
>>
>> From: Alex Shi <alexs@kernel.org>
>>
>> The 1st patch introduces new memory decriptor zpdesc and rename
>> zspage.first_page to zspage.first_zpdesc, no functional change.
>>
>> Originally-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
>> Signed-off-by: Alex Shi <alexs@kernel.org>
>> ---
>> mm/zpdesc.h | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++
>> mm/zsmalloc.c | 19 ++++++++---------
>> 2 files changed, 66 insertions(+), 9 deletions(-)
>> create mode 100644 mm/zpdesc.h
>
> Hi Alex, thanks for your effort in pushing this forward!
>
>> diff --git a/mm/zpdesc.h b/mm/zpdesc.h
>> new file mode 100644
>> index 000000000000..a1ab5ebaa936
>> --- /dev/null
>> +++ b/mm/zpdesc.h
>> @@ -0,0 +1,56 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/* zpdesc.h: zswap.zpool memory descriptor
>> + *
>> + * Written by Alex Shi <alexs@kernel.org>
>> + * Hyeonggon Yoo <42.hyeyoo@gmail.com>
>> + */
>> +#ifndef __MM_ZPDESC_H__
>> +#define __MM_ZPDESC_H__
>> +
>> +/*
>> + * struct zpdesc - Memory descriptor for zpool memory, now is for zsmalloc
>> + * @flags: Page flags, PG_private: identifies the first component page
>> + * @lru: Indirected used by page migration
>
> maybe Indirected -> Indirectly?
Hi Yoo,
Thanks for comments! Yes Indirectly is better. I will update it in next version.
>
>> + * @next: Next zpdesc in a zspage in zsmalloc zpool
>> + * @handle: For huge zspage in zsmalloc zpool
>> + * @zspage: Pointer to zspage in zsmalloc
>> + *
>> + * This struct overlays struct page for now. Do not modify without a good
>> + * understanding of the issues.
>> + */
>> +struct zpdesc {
>> + unsigned long flags;
>> + struct list_head lru;
>> + unsigned long _zp_pad_1;
>
> for understanding, I think it'd be better to replace _zp_pad_1 with movable ops,
> because mops reuses this 'mapping' field.
Right, 'mops' looks a bit more clear.
>
>> + union {
>> + /* Next zpdescs in a zspage in zsmalloc zpool */
>> + struct zpdesc *next;
>> + /* For huge zspage in zsmalloc zpool */
>> + unsigned long handle;
>> + };
>> + struct zspage *zspage;
>
> There was a discussion with Yosry on including memcg_data on zpdesc
> even if it's not used at the moment.
>
> Maybe you can look at:
> https://lore.kernel.org/linux-mm/CAB=+i9Quz9iP2-Lq=oQfKVVnzPDtOaKMm=hUPbnRg5hRxH+qaA@mail.gmail.com/
Thanks for notice.
The memcg_data isn't used for zpdesc. And I have a bit confusion since Yosry said: "I think to drop memcg_data we need to enlighten the code that ...". So we actually don't need to have this unused member, is this right, Yosry?
>
>> diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
>> index fec1a39e5bbe..67bb80b7413a 100644
>> --- a/mm/zsmalloc.c
>> +++ b/mm/zsmalloc.c
>> @@ -13,17 +13,17 @@
>>
>> /*
>> * Following is how we use various fields and flags of underlying
>> - * struct page(s) to form a zspage.
>> + * struct zpdesc(page) to form a zspage.
>> *
>> - * Usage of struct page fields:
>> - * page->private: points to zspage
>> - * page->index: links together all component pages of a zspage
>> + * Usage of struct zpdesc fields:
>> + * zpdesc->zspage: points to zspage
>> + * zpdesc->next: links together all component pages of a zspage
>> * For the huge page, this is always 0, so we use this field
>> * to store handle.
>> * page->page_type: PG_zsmalloc, lower 16 bit locate the first object
>> * offset in a subpage of a zspage
>> *
>> - * Usage of struct page flags:
>> + * Usage of struct zpdesc(page) flags:
>> * PG_private: identifies the first component page
>> * PG_owner_priv_1: identifies the huge component page
>
> the comment for PG_owner_priv_1 can safely be removed as it's not used
> after commit a41ec880aa7b ("zsmalloc: move huge compressed obj from
> page to zspage")
Right, thanks for info!
>
>> @@ -948,7 +949,7 @@ static void create_page_chain(struct size_class *class, struct zspage *zspage,
>> set_page_private(page, (unsigned long)zspage);
>> page->index = 0;
>> if (i == 0) {
>> - zspage->first_page = page;
>> + zspage->first_zpdesc = page_zpdesc(page);
>> SetPagePrivate(page);
>> if (unlikely(class->objs_per_zspage == 1 &&
>> class->pages_per_zspage == 1))
>> @@ -1325,7 +1326,7 @@ static unsigned long obj_malloc(struct zs_pool *pool,
>> link->handle = handle;
>> else
>> /* record handle to page->index */
>> - zspage->first_page->index = handle;
>> + zspage->first_zpdesc->handle = handle;
>
> FYI this line seems to conflict with
> bcc6116e39f512 ("mm/zsmalloc: move record_obj() into obj_malloc()")
> on mm-unstable.
yes, a new commit made this conflict. will update this in next version.
Thanks
Alex
>
> Best,
> Hyeonggon
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 01/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool
2024-07-01 3:03 ` Alex Shi
@ 2024-07-01 3:40 ` Alex Shi
2024-07-01 13:42 ` Yosry Ahmed
1 sibling, 0 replies; 28+ messages in thread
From: Alex Shi @ 2024-07-01 3:40 UTC (permalink / raw)
To: Hyeonggon Yoo, alexs
Cc: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, Nhat Pham, Yosry Ahmed
Ops,
Sorry for missing Yosry and Nhat. How stupid I am!
Here is the first patch on lore: https://lore.kernel.org/all/20240628031138.429622-1-alexs@kernel.org/
Sorry for this!
Alex
On 7/1/24 11:03 AM, Alex Shi wrote:
>
>
> On 6/30/24 9:45 PM, Hyeonggon Yoo wrote:
>> On Fri, Jun 28, 2024 at 12:06 PM <alexs@kernel.org> wrote:
>>>
>>> From: Alex Shi <alexs@kernel.org>
>>>
>>> The 1st patch introduces new memory decriptor zpdesc and rename
>>> zspage.first_page to zspage.first_zpdesc, no functional change.
>>>
>>> Originally-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
>>> Signed-off-by: Alex Shi <alexs@kernel.org>
>>> ---
>>> mm/zpdesc.h | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>> mm/zsmalloc.c | 19 ++++++++---------
>>> 2 files changed, 66 insertions(+), 9 deletions(-)
>>> create mode 100644 mm/zpdesc.h
>>
>> Hi Alex, thanks for your effort in pushing this forward!
>>
>>> diff --git a/mm/zpdesc.h b/mm/zpdesc.h
>>> new file mode 100644
>>> index 000000000000..a1ab5ebaa936
>>> --- /dev/null
>>> +++ b/mm/zpdesc.h
>>> @@ -0,0 +1,56 @@
>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>> +/* zpdesc.h: zswap.zpool memory descriptor
>>> + *
>>> + * Written by Alex Shi <alexs@kernel.org>
>>> + * Hyeonggon Yoo <42.hyeyoo@gmail.com>
>>> + */
>>> +#ifndef __MM_ZPDESC_H__
>>> +#define __MM_ZPDESC_H__
>>> +
>>> +/*
>>> + * struct zpdesc - Memory descriptor for zpool memory, now is for zsmalloc
>>> + * @flags: Page flags, PG_private: identifies the first component page
>>> + * @lru: Indirected used by page migration
>>
>> maybe Indirected -> Indirectly?
>
> Hi Yoo,
>
> Thanks for comments! Yes Indirectly is better. I will update it in next version.
>
>>
>>> + * @next: Next zpdesc in a zspage in zsmalloc zpool
>>> + * @handle: For huge zspage in zsmalloc zpool
>>> + * @zspage: Pointer to zspage in zsmalloc
>>> + *
>>> + * This struct overlays struct page for now. Do not modify without a good
>>> + * understanding of the issues.
>>> + */
>>> +struct zpdesc {
>>> + unsigned long flags;
>>> + struct list_head lru;
>>> + unsigned long _zp_pad_1;
>>
>> for understanding, I think it'd be better to replace _zp_pad_1 with movable ops,
>> because mops reuses this 'mapping' field.
>
> Right, 'mops' looks a bit more clear.
>
>>
>>> + union {
>>> + /* Next zpdescs in a zspage in zsmalloc zpool */
>>> + struct zpdesc *next;
>>> + /* For huge zspage in zsmalloc zpool */
>>> + unsigned long handle;
>>> + };
>>> + struct zspage *zspage;
>>
>> There was a discussion with Yosry on including memcg_data on zpdesc
>> even if it's not used at the moment.
>>
>> Maybe you can look at:
>> https://lore.kernel.org/linux-mm/CAB=+i9Quz9iP2-Lq=oQfKVVnzPDtOaKMm=hUPbnRg5hRxH+qaA@mail.gmail.com/
>
> Thanks for notice.
> The memcg_data isn't used for zpdesc. And I have a bit confusion since Yosry said: "I think to drop memcg_data we need to enlighten the code that ...". So we actually don't need to have this unused member, is this right, Yosry?
>
>>
>>> diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
>>> index fec1a39e5bbe..67bb80b7413a 100644
>>> --- a/mm/zsmalloc.c
>>> +++ b/mm/zsmalloc.c
>>> @@ -13,17 +13,17 @@
>>>
>>> /*
>>> * Following is how we use various fields and flags of underlying
>>> - * struct page(s) to form a zspage.
>>> + * struct zpdesc(page) to form a zspage.
>>> *
>>> - * Usage of struct page fields:
>>> - * page->private: points to zspage
>>> - * page->index: links together all component pages of a zspage
>>> + * Usage of struct zpdesc fields:
>>> + * zpdesc->zspage: points to zspage
>>> + * zpdesc->next: links together all component pages of a zspage
>>> * For the huge page, this is always 0, so we use this field
>>> * to store handle.
>>> * page->page_type: PG_zsmalloc, lower 16 bit locate the first object
>>> * offset in a subpage of a zspage
>>> *
>>> - * Usage of struct page flags:
>>> + * Usage of struct zpdesc(page) flags:
>>> * PG_private: identifies the first component page
>>> * PG_owner_priv_1: identifies the huge component page
>>
>> the comment for PG_owner_priv_1 can safely be removed as it's not used
>> after commit a41ec880aa7b ("zsmalloc: move huge compressed obj from
>> page to zspage")
>
> Right, thanks for info!
>
>>
>>> @@ -948,7 +949,7 @@ static void create_page_chain(struct size_class *class, struct zspage *zspage,
>>> set_page_private(page, (unsigned long)zspage);
>>> page->index = 0;
>>> if (i == 0) {
>>> - zspage->first_page = page;
>>> + zspage->first_zpdesc = page_zpdesc(page);
>>> SetPagePrivate(page);
>>> if (unlikely(class->objs_per_zspage == 1 &&
>>> class->pages_per_zspage == 1))
>>> @@ -1325,7 +1326,7 @@ static unsigned long obj_malloc(struct zs_pool *pool,
>>> link->handle = handle;
>>> else
>>> /* record handle to page->index */
>>> - zspage->first_page->index = handle;
>>> + zspage->first_zpdesc->handle = handle;
>>
>> FYI this line seems to conflict with
>> bcc6116e39f512 ("mm/zsmalloc: move record_obj() into obj_malloc()")
>> on mm-unstable.
>
> yes, a new commit made this conflict. will update this in next version.
>
> Thanks
> Alex
>>
>> Best,
>> Hyeonggon
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 01/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool
2024-07-01 3:03 ` Alex Shi
2024-07-01 3:40 ` Alex Shi
@ 2024-07-01 13:42 ` Yosry Ahmed
2024-07-02 2:39 ` Alex Shi
1 sibling, 1 reply; 28+ messages in thread
From: Yosry Ahmed @ 2024-07-01 13:42 UTC (permalink / raw)
To: Alex Shi
Cc: Hyeonggon Yoo, alexs, Vitaly Wool, Miaohe Lin, Andrew Morton,
linux-kernel, linux-mm, minchan, willy, senozhatsky, david
[..]
> >> + union {
> >> + /* Next zpdescs in a zspage in zsmalloc zpool */
> >> + struct zpdesc *next;
> >> + /* For huge zspage in zsmalloc zpool */
> >> + unsigned long handle;
> >> + };
> >> + struct zspage *zspage;
> >
> > There was a discussion with Yosry on including memcg_data on zpdesc
> > even if it's not used at the moment.
> >
> > Maybe you can look at:
> > https://lore.kernel.org/linux-mm/CAB=+i9Quz9iP2-Lq=oQfKVVnzPDtOaKMm=hUPbnRg5hRxH+qaA@mail.gmail.com/
>
> Thanks for notice.
> The memcg_data isn't used for zpdesc. And I have a bit confusion since Yosry said: "I think to drop memcg_data we need to enlighten the code that ...". So we actually don't need to have this unused member, is this right, Yosry?
I think we need to have it, at least for now. When the pages are
freed, put_page() -> folio_put() -> __folio_put() will call
mem_cgroup_uncharge(). The latter will call folio_memcg() (which reads
folio->memcg_data) to figure out if uncharging needs to be done.
There are also other similar code paths that will check
folio->memcg_data. It is currently expected to be present for all
folios. So until we have custom code paths per-folio type for
allocation/freeing/etc, we need to keep folio->memcg_data present and
properly initialized.
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 01/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool
2024-07-01 13:42 ` Yosry Ahmed
@ 2024-07-02 2:39 ` Alex Shi
0 siblings, 0 replies; 28+ messages in thread
From: Alex Shi @ 2024-07-02 2:39 UTC (permalink / raw)
To: Yosry Ahmed
Cc: Hyeonggon Yoo, alexs, Vitaly Wool, Miaohe Lin, Andrew Morton,
linux-kernel, linux-mm, minchan, willy, senozhatsky, david
On 7/1/24 9:42 PM, Yosry Ahmed wrote:
> [..]
>>>> + union {
>>>> + /* Next zpdescs in a zspage in zsmalloc zpool */
>>>> + struct zpdesc *next;
>>>> + /* For huge zspage in zsmalloc zpool */
>>>> + unsigned long handle;
>>>> + };
>>>> + struct zspage *zspage;
>>>
>>> There was a discussion with Yosry on including memcg_data on zpdesc
>>> even if it's not used at the moment.
>>>
>>> Maybe you can look at:
>>> https://lore.kernel.org/linux-mm/CAB=+i9Quz9iP2-Lq=oQfKVVnzPDtOaKMm=hUPbnRg5hRxH+qaA@mail.gmail.com/
>>
>> Thanks for notice.
>> The memcg_data isn't used for zpdesc. And I have a bit confusion since Yosry said: "I think to drop memcg_data we need to enlighten the code that ...". So we actually don't need to have this unused member, is this right, Yosry?
>
> I think we need to have it, at least for now. When the pages are
> freed, put_page() -> folio_put() -> __folio_put() will call
> mem_cgroup_uncharge(). The latter will call folio_memcg() (which reads
> folio->memcg_data) to figure out if uncharging needs to be done.
>
> There are also other similar code paths that will check
> folio->memcg_data. It is currently expected to be present for all
> folios. So until we have custom code paths per-folio type for
> allocation/freeing/etc, we need to keep folio->memcg_data present and
> properly initialized.
Hi Yosry,
Many thanks for detailed comments and requirements!
I'm going to add this member in next version, maybe tomorrow, unless there are more comments for this patchset. :)
Thank a lot!
Alex
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 02/20] mm/zsmalloc: use zpdesc in trylock_zspage/lock_zspage
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
2024-06-28 3:11 ` [PATCH 01/20] " alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 03/20] mm/zsmalloc: convert __zs_map_object/__zs_unmap_object to use zpdesc alexs
` (18 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Alex Shi <alexs@kernel.org>
To use zpdesc in trylock_zspage/lock_zspage funcs, we add couple of helpers:
zpdesc_lock/zpdesc_unlock/zpdesc_trylock/zpdesc_wait_locked and
zpdesc_get/zpdesc_put for this purpose.
Here we use the folio series func in guts for 2 reasons, one zswap.zpool
only get single page, and use folio could save some compound_head checking;
two, folio_put could bypass devmap checking that we don't need.
Originally-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zpdesc.h | 30 ++++++++++++++++++++++++
mm/zsmalloc.c | 64 ++++++++++++++++++++++++++++++++++-----------------
2 files changed, 73 insertions(+), 21 deletions(-)
diff --git a/mm/zpdesc.h b/mm/zpdesc.h
index a1ab5ebaa936..fd95277843d5 100644
--- a/mm/zpdesc.h
+++ b/mm/zpdesc.h
@@ -53,4 +53,34 @@ static_assert(sizeof(struct zpdesc) <= sizeof(struct page));
const struct page *: (const struct zpdesc *)(p), \
struct page *: (struct zpdesc *)(p)))
+static inline void zpdesc_lock(struct zpdesc *zpdesc)
+{
+ folio_lock(zpdesc_folio(zpdesc));
+}
+
+static inline bool zpdesc_trylock(struct zpdesc *zpdesc)
+{
+ return folio_trylock(zpdesc_folio(zpdesc));
+}
+
+static inline void zpdesc_unlock(struct zpdesc *zpdesc)
+{
+ folio_unlock(zpdesc_folio(zpdesc));
+}
+
+static inline void zpdesc_wait_locked(struct zpdesc *zpdesc)
+{
+ folio_wait_locked(zpdesc_folio(zpdesc));
+}
+
+static inline void zpdesc_get(struct zpdesc *zpdesc)
+{
+ folio_get(zpdesc_folio(zpdesc));
+}
+
+static inline void zpdesc_put(struct zpdesc *zpdesc)
+{
+ folio_put(zpdesc_folio(zpdesc));
+}
+
#endif
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 67bb80b7413a..9835121109d1 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -435,13 +435,17 @@ static __maybe_unused int is_first_page(struct page *page)
return PagePrivate(page);
}
+static int is_first_zpdesc(struct zpdesc *zpdesc)
+{
+ return PagePrivate(zpdesc_page(zpdesc));
+}
+
/* Protected by class->lock */
static inline int get_zspage_inuse(struct zspage *zspage)
{
return zspage->inuse;
}
-
static inline void mod_zspage_inuse(struct zspage *zspage, int val)
{
zspage->inuse += val;
@@ -455,6 +459,14 @@ static inline struct page *get_first_page(struct zspage *zspage)
return first_page;
}
+static struct zpdesc *get_first_zpdesc(struct zspage *zspage)
+{
+ struct zpdesc *first_zpdesc = zspage->first_zpdesc;
+
+ VM_BUG_ON_PAGE(!is_first_zpdesc(first_zpdesc), zpdesc_page(first_zpdesc));
+ return first_zpdesc;
+}
+
#define FIRST_OBJ_PAGE_TYPE_MASK 0xffff
static inline void reset_first_obj_offset(struct page *page)
@@ -747,6 +759,16 @@ static struct page *get_next_page(struct page *page)
return (struct page *)page->index;
}
+static struct zpdesc *get_next_zpdesc(struct zpdesc *zpdesc)
+{
+ struct zspage *zspage = get_zspage(zpdesc_page(zpdesc));
+
+ if (unlikely(ZsHugePage(zspage)))
+ return NULL;
+
+ return zpdesc->next;
+}
+
/**
* obj_to_location - get (<page>, <obj_idx>) from encoded object value
* @obj: the encoded object value
@@ -817,11 +839,11 @@ static void reset_page(struct page *page)
static int trylock_zspage(struct zspage *zspage)
{
- struct page *cursor, *fail;
+ struct zpdesc *cursor, *fail;
- for (cursor = get_first_page(zspage); cursor != NULL; cursor =
- get_next_page(cursor)) {
- if (!trylock_page(cursor)) {
+ for (cursor = get_first_zpdesc(zspage); cursor != NULL; cursor =
+ get_next_zpdesc(cursor)) {
+ if (!zpdesc_trylock(cursor)) {
fail = cursor;
goto unlock;
}
@@ -829,9 +851,9 @@ static int trylock_zspage(struct zspage *zspage)
return 1;
unlock:
- for (cursor = get_first_page(zspage); cursor != fail; cursor =
- get_next_page(cursor))
- unlock_page(cursor);
+ for (cursor = get_first_zpdesc(zspage); cursor != fail; cursor =
+ get_next_zpdesc(cursor))
+ zpdesc_unlock(cursor);
return 0;
}
@@ -1663,7 +1685,7 @@ static int putback_zspage(struct size_class *class, struct zspage *zspage)
*/
static void lock_zspage(struct zspage *zspage)
{
- struct page *curr_page, *page;
+ struct zpdesc *curr_zpdesc, *zpdesc;
/*
* Pages we haven't locked yet can be migrated off the list while we're
@@ -1675,24 +1697,24 @@ static void lock_zspage(struct zspage *zspage)
*/
while (1) {
migrate_read_lock(zspage);
- page = get_first_page(zspage);
- if (trylock_page(page))
+ zpdesc = get_first_zpdesc(zspage);
+ if (zpdesc_trylock(zpdesc))
break;
- get_page(page);
+ zpdesc_get(zpdesc);
migrate_read_unlock(zspage);
- wait_on_page_locked(page);
- put_page(page);
+ zpdesc_wait_locked(zpdesc);
+ zpdesc_put(zpdesc);
}
- curr_page = page;
- while ((page = get_next_page(curr_page))) {
- if (trylock_page(page)) {
- curr_page = page;
+ curr_zpdesc = zpdesc;
+ while ((zpdesc = get_next_zpdesc(curr_zpdesc))) {
+ if (zpdesc_trylock(zpdesc)) {
+ curr_zpdesc = zpdesc;
} else {
- get_page(page);
+ zpdesc_get(zpdesc);
migrate_read_unlock(zspage);
- wait_on_page_locked(page);
- put_page(page);
+ zpdesc_wait_locked(zpdesc);
+ zpdesc_put(zpdesc);
migrate_read_lock(zspage);
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 03/20] mm/zsmalloc: convert __zs_map_object/__zs_unmap_object to use zpdesc
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
2024-06-28 3:11 ` [PATCH 01/20] " alexs
2024-06-28 3:11 ` [PATCH 02/20] mm/zsmalloc: use zpdesc in trylock_zspage/lock_zspage alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 04/20] mm/zsmalloc: add and use pfn/zpdesc seeking funcs alexs
` (17 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
These two functions take pointer to an array of struct page. Introduce
zpdesc_kmap_atomic() and make __zs_{map,unmap}_object() take pointer
to an array of zpdesc instead of page.
Add silly type casting when calling them. Casting will be removed late.
Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zsmalloc.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 9835121109d1..cedd3dfb9124 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -245,6 +245,11 @@ struct zs_pool {
atomic_t compaction_in_progress;
};
+static inline void *zpdesc_kmap_atomic(struct zpdesc *zpdesc)
+{
+ return kmap_atomic(zpdesc_page(zpdesc));
+}
+
struct zspage {
struct {
unsigned int huge:HUGE_BITS;
@@ -1063,7 +1068,7 @@ static inline void __zs_cpu_down(struct mapping_area *area)
}
static void *__zs_map_object(struct mapping_area *area,
- struct page *pages[2], int off, int size)
+ struct zpdesc *zpdescs[2], int off, int size)
{
int sizes[2];
void *addr;
@@ -1080,10 +1085,10 @@ static void *__zs_map_object(struct mapping_area *area,
sizes[1] = size - sizes[0];
/* copy object to per-cpu buffer */
- addr = kmap_atomic(pages[0]);
+ addr = zpdesc_kmap_atomic(zpdescs[0]);
memcpy(buf, addr + off, sizes[0]);
kunmap_atomic(addr);
- addr = kmap_atomic(pages[1]);
+ addr = zpdesc_kmap_atomic(zpdescs[1]);
memcpy(buf + sizes[0], addr, sizes[1]);
kunmap_atomic(addr);
out:
@@ -1091,7 +1096,7 @@ static void *__zs_map_object(struct mapping_area *area,
}
static void __zs_unmap_object(struct mapping_area *area,
- struct page *pages[2], int off, int size)
+ struct zpdesc *zpdescs[2], int off, int size)
{
int sizes[2];
void *addr;
@@ -1110,10 +1115,10 @@ static void __zs_unmap_object(struct mapping_area *area,
sizes[1] = size - sizes[0];
/* copy per-cpu buffer to object */
- addr = kmap_atomic(pages[0]);
+ addr = zpdesc_kmap_atomic(zpdescs[0]);
memcpy(addr + off, buf, sizes[0]);
kunmap_atomic(addr);
- addr = kmap_atomic(pages[1]);
+ addr = zpdesc_kmap_atomic(zpdescs[1]);
memcpy(addr, buf + sizes[0], sizes[1]);
kunmap_atomic(addr);
@@ -1254,7 +1259,7 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle,
pages[1] = get_next_page(page);
BUG_ON(!pages[1]);
- ret = __zs_map_object(area, pages, off, class->size);
+ ret = __zs_map_object(area, (struct zpdesc **)pages, off, class->size);
out:
if (likely(!ZsHugePage(zspage)))
ret += ZS_HANDLE_SIZE;
@@ -1289,7 +1294,7 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle)
pages[1] = get_next_page(page);
BUG_ON(!pages[1]);
- __zs_unmap_object(area, pages, off, class->size);
+ __zs_unmap_object(area, (struct zpdesc **)pages, off, class->size);
}
local_unlock(&zs_map_area.lock);
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 04/20] mm/zsmalloc: add and use pfn/zpdesc seeking funcs
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (2 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 03/20] mm/zsmalloc: convert __zs_map_object/__zs_unmap_object to use zpdesc alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 05/20] mm/zsmalloc: convert obj_malloc() to use zpdesc alexs
` (16 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Add pfn_zpdesc conversion, convert obj_to_location() to take zpdesc
and also convert its users to use zpdesc.
Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zpdesc.h | 9 +++++++
mm/zsmalloc.c | 75 ++++++++++++++++++++++++++-------------------------
2 files changed, 47 insertions(+), 37 deletions(-)
diff --git a/mm/zpdesc.h b/mm/zpdesc.h
index fd95277843d5..3c0ebdc78ff8 100644
--- a/mm/zpdesc.h
+++ b/mm/zpdesc.h
@@ -83,4 +83,13 @@ static inline void zpdesc_put(struct zpdesc *zpdesc)
folio_put(zpdesc_folio(zpdesc));
}
+static inline unsigned long zpdesc_pfn(struct zpdesc *zpdesc)
+{
+ return page_to_pfn(zpdesc_page(zpdesc));
+}
+
+static inline struct zpdesc *pfn_zpdesc(unsigned long pfn)
+{
+ return page_zpdesc(pfn_to_page(pfn));
+}
#endif
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index cedd3dfb9124..efb1d58b3c36 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -775,15 +775,15 @@ static struct zpdesc *get_next_zpdesc(struct zpdesc *zpdesc)
}
/**
- * obj_to_location - get (<page>, <obj_idx>) from encoded object value
+ * obj_to_location - get (<zpdesc>, <obj_idx>) from encoded object value
* @obj: the encoded object value
- * @page: page object resides in zspage
+ * @zpdesc: zpdesc object resides in zspage
* @obj_idx: object index
*/
-static void obj_to_location(unsigned long obj, struct page **page,
+static void obj_to_location(unsigned long obj, struct zpdesc **zpdesc,
unsigned int *obj_idx)
{
- *page = pfn_to_page(obj >> OBJ_INDEX_BITS);
+ *zpdesc = pfn_zpdesc(obj >> OBJ_INDEX_BITS);
*obj_idx = (obj & OBJ_INDEX_MASK);
}
@@ -1210,13 +1210,13 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle,
enum zs_mapmode mm)
{
struct zspage *zspage;
- struct page *page;
+ struct zpdesc *zpdesc;
unsigned long obj, off;
unsigned int obj_idx;
struct size_class *class;
struct mapping_area *area;
- struct page *pages[2];
+ struct zpdesc *zpdescs[2];
void *ret;
/*
@@ -1229,8 +1229,8 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle,
/* It guarantees it can get zspage from handle safely */
read_lock(&pool->migrate_lock);
obj = handle_to_obj(handle);
- obj_to_location(obj, &page, &obj_idx);
- zspage = get_zspage(page);
+ obj_to_location(obj, &zpdesc, &obj_idx);
+ zspage = get_zspage(zpdesc_page(zpdesc));
/*
* migration cannot move any zpages in this zspage. Here, class->lock
@@ -1249,17 +1249,17 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle,
area->vm_mm = mm;
if (off + class->size <= PAGE_SIZE) {
/* this object is contained entirely within a page */
- area->vm_addr = kmap_atomic(page);
+ area->vm_addr = zpdesc_kmap_atomic(zpdesc);
ret = area->vm_addr + off;
goto out;
}
/* this object spans two pages */
- pages[0] = page;
- pages[1] = get_next_page(page);
- BUG_ON(!pages[1]);
+ zpdescs[0] = zpdesc;
+ zpdescs[1] = get_next_zpdesc(zpdesc);
+ BUG_ON(!zpdescs[1]);
- ret = __zs_map_object(area, (struct zpdesc **)pages, off, class->size);
+ ret = __zs_map_object(area, zpdescs, off, class->size);
out:
if (likely(!ZsHugePage(zspage)))
ret += ZS_HANDLE_SIZE;
@@ -1271,7 +1271,7 @@ EXPORT_SYMBOL_GPL(zs_map_object);
void zs_unmap_object(struct zs_pool *pool, unsigned long handle)
{
struct zspage *zspage;
- struct page *page;
+ struct zpdesc *zpdesc;
unsigned long obj, off;
unsigned int obj_idx;
@@ -1279,8 +1279,8 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle)
struct mapping_area *area;
obj = handle_to_obj(handle);
- obj_to_location(obj, &page, &obj_idx);
- zspage = get_zspage(page);
+ obj_to_location(obj, &zpdesc, &obj_idx);
+ zspage = get_zspage(zpdesc_page(zpdesc));
class = zspage_class(pool, zspage);
off = offset_in_page(class->size * obj_idx);
@@ -1288,13 +1288,13 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle)
if (off + class->size <= PAGE_SIZE)
kunmap_atomic(area->vm_addr);
else {
- struct page *pages[2];
+ struct zpdesc *zpdescs[2];
- pages[0] = page;
- pages[1] = get_next_page(page);
- BUG_ON(!pages[1]);
+ zpdescs[0] = zpdesc;
+ zpdescs[1] = get_next_zpdesc(zpdesc);
+ BUG_ON(!zpdescs[1]);
- __zs_unmap_object(area, (struct zpdesc **)pages, off, class->size);
+ __zs_unmap_object(area, zpdescs, off, class->size);
}
local_unlock(&zs_map_area.lock);
@@ -1438,23 +1438,24 @@ static void obj_free(int class_size, unsigned long obj)
{
struct link_free *link;
struct zspage *zspage;
- struct page *f_page;
+ struct zpdesc *f_zpdesc;
unsigned long f_offset;
unsigned int f_objidx;
void *vaddr;
- obj_to_location(obj, &f_page, &f_objidx);
+
+ obj_to_location(obj, &f_zpdesc, &f_objidx);
f_offset = offset_in_page(class_size * f_objidx);
- zspage = get_zspage(f_page);
+ zspage = get_zspage(zpdesc_page(f_zpdesc));
- vaddr = kmap_atomic(f_page);
+ vaddr = zpdesc_kmap_atomic(f_zpdesc);
link = (struct link_free *)(vaddr + f_offset);
/* Insert this object in containing zspage's freelist */
if (likely(!ZsHugePage(zspage)))
link->next = get_freeobj(zspage) << OBJ_TAG_BITS;
else
- f_page->index = 0;
+ f_zpdesc->next = NULL;
set_freeobj(zspage, f_objidx);
kunmap_atomic(vaddr);
@@ -1499,7 +1500,7 @@ EXPORT_SYMBOL_GPL(zs_free);
static void zs_object_copy(struct size_class *class, unsigned long dst,
unsigned long src)
{
- struct page *s_page, *d_page;
+ struct zpdesc *s_zpdesc, *d_zpdesc;
unsigned int s_objidx, d_objidx;
unsigned long s_off, d_off;
void *s_addr, *d_addr;
@@ -1508,8 +1509,8 @@ static void zs_object_copy(struct size_class *class, unsigned long dst,
s_size = d_size = class->size;
- obj_to_location(src, &s_page, &s_objidx);
- obj_to_location(dst, &d_page, &d_objidx);
+ obj_to_location(src, &s_zpdesc, &s_objidx);
+ obj_to_location(dst, &d_zpdesc, &d_objidx);
s_off = offset_in_page(class->size * s_objidx);
d_off = offset_in_page(class->size * d_objidx);
@@ -1520,8 +1521,8 @@ static void zs_object_copy(struct size_class *class, unsigned long dst,
if (d_off + class->size > PAGE_SIZE)
d_size = PAGE_SIZE - d_off;
- s_addr = kmap_atomic(s_page);
- d_addr = kmap_atomic(d_page);
+ s_addr = zpdesc_kmap_atomic(s_zpdesc);
+ d_addr = zpdesc_kmap_atomic(d_zpdesc);
while (1) {
size = min(s_size, d_size);
@@ -1546,17 +1547,17 @@ static void zs_object_copy(struct size_class *class, unsigned long dst,
if (s_off >= PAGE_SIZE) {
kunmap_atomic(d_addr);
kunmap_atomic(s_addr);
- s_page = get_next_page(s_page);
- s_addr = kmap_atomic(s_page);
- d_addr = kmap_atomic(d_page);
+ s_zpdesc = get_next_zpdesc(s_zpdesc);
+ s_addr = zpdesc_kmap_atomic(s_zpdesc);
+ d_addr = zpdesc_kmap_atomic(d_zpdesc);
s_size = class->size - written;
s_off = 0;
}
if (d_off >= PAGE_SIZE) {
kunmap_atomic(d_addr);
- d_page = get_next_page(d_page);
- d_addr = kmap_atomic(d_page);
+ d_zpdesc = get_next_zpdesc(d_zpdesc);
+ d_addr = zpdesc_kmap_atomic(d_zpdesc);
d_size = class->size - written;
d_off = 0;
}
@@ -1796,7 +1797,7 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
struct zs_pool *pool;
struct size_class *class;
struct zspage *zspage;
- struct page *dummy;
+ struct zpdesc *dummy;
void *s_addr, *d_addr, *addr;
unsigned int offset;
unsigned long handle;
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 05/20] mm/zsmalloc: convert obj_malloc() to use zpdesc
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (3 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 04/20] mm/zsmalloc: add and use pfn/zpdesc seeking funcs alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 06/20] mm/zsmalloc: convert create_page_chain() and its users " alexs
` (15 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Use get_first_zpdesc/get_next_zpdesc to replace
get_first_page/get_next_page. no functional change.
Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zsmalloc.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index efb1d58b3c36..137b36515acf 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -1324,12 +1324,12 @@ EXPORT_SYMBOL_GPL(zs_huge_class_size);
static unsigned long obj_malloc(struct zs_pool *pool,
struct zspage *zspage, unsigned long handle)
{
- int i, nr_page, offset;
+ int i, nr_zpdesc, offset;
unsigned long obj;
struct link_free *link;
struct size_class *class;
- struct page *m_page;
+ struct zpdesc *m_zpdesc;
unsigned long m_offset;
void *vaddr;
@@ -1338,14 +1338,14 @@ static unsigned long obj_malloc(struct zs_pool *pool,
obj = get_freeobj(zspage);
offset = obj * class->size;
- nr_page = offset >> PAGE_SHIFT;
+ nr_zpdesc = offset >> PAGE_SHIFT;
m_offset = offset_in_page(offset);
- m_page = get_first_page(zspage);
+ m_zpdesc = get_first_zpdesc(zspage);
- for (i = 0; i < nr_page; i++)
- m_page = get_next_page(m_page);
+ for (i = 0; i < nr_zpdesc; i++)
+ m_zpdesc = get_next_zpdesc(m_zpdesc);
- vaddr = kmap_atomic(m_page);
+ vaddr = zpdesc_kmap_atomic(m_zpdesc);
link = (struct link_free *)vaddr + m_offset / sizeof(*link);
set_freeobj(zspage, link->next >> OBJ_TAG_BITS);
if (likely(!ZsHugePage(zspage)))
@@ -1358,7 +1358,7 @@ static unsigned long obj_malloc(struct zs_pool *pool,
kunmap_atomic(vaddr);
mod_zspage_inuse(zspage, 1);
- obj = location_to_obj(m_page, obj);
+ obj = location_to_obj(zpdesc_page(m_zpdesc), obj);
return obj;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 06/20] mm/zsmalloc: convert create_page_chain() and its users to use zpdesc
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (4 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 05/20] mm/zsmalloc: convert obj_malloc() to use zpdesc alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 07/20] mm/zsmalloc: convert obj_allocated() and related helpers " alexs
` (14 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Alex Shi <alexs@kernel.org>
Introduce a few helper functions for conversion to convert create_page_chain()
to use zpdesc, then use zpdesc in replace_sub_page() too.
Originally-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zpdesc.h | 6 +++
mm/zsmalloc.c | 115 +++++++++++++++++++++++++++++++++-----------------
2 files changed, 82 insertions(+), 39 deletions(-)
diff --git a/mm/zpdesc.h b/mm/zpdesc.h
index 3c0ebdc78ff8..f998d65c59d6 100644
--- a/mm/zpdesc.h
+++ b/mm/zpdesc.h
@@ -92,4 +92,10 @@ static inline struct zpdesc *pfn_zpdesc(unsigned long pfn)
{
return page_zpdesc(pfn_to_page(pfn));
}
+
+static inline void __zpdesc_set_movable(struct zpdesc *zpdesc,
+ const struct movable_operations *mops)
+{
+ __SetPageMovable(zpdesc_page(zpdesc), mops);
+}
#endif
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 137b36515acf..ee890d513f6f 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -250,6 +250,41 @@ static inline void *zpdesc_kmap_atomic(struct zpdesc *zpdesc)
return kmap_atomic(zpdesc_page(zpdesc));
}
+static inline void zpdesc_set_zspage(struct zpdesc *zpdesc,
+ struct zspage *zspage)
+{
+ zpdesc->zspage = zspage;
+}
+
+static inline void zpdesc_set_first(struct zpdesc *zpdesc)
+{
+ SetPagePrivate(zpdesc_page(zpdesc));
+}
+
+static inline void zpdesc_inc_zone_page_state(struct zpdesc *zpdesc)
+{
+ inc_zone_page_state(zpdesc_page(zpdesc), NR_ZSPAGES);
+}
+
+static inline void zpdesc_dec_zone_page_state(struct zpdesc *zpdesc)
+{
+ dec_zone_page_state(zpdesc_page(zpdesc), NR_ZSPAGES);
+}
+
+static inline struct zpdesc *alloc_zpdesc(gfp_t gfp)
+{
+ struct page *page = alloc_page(gfp);
+
+ return page_zpdesc(page);
+}
+
+static inline void free_zpdesc(struct zpdesc *zpdesc)
+{
+ struct page *page = zpdesc_page(zpdesc);
+
+ __free_page(page);
+}
+
struct zspage {
struct {
unsigned int huge:HUGE_BITS;
@@ -956,35 +991,35 @@ static void init_zspage(struct size_class *class, struct zspage *zspage)
}
static void create_page_chain(struct size_class *class, struct zspage *zspage,
- struct page *pages[])
+ struct zpdesc *zpdescs[])
{
int i;
- struct page *page;
- struct page *prev_page = NULL;
- int nr_pages = class->pages_per_zspage;
+ struct zpdesc *zpdesc;
+ struct zpdesc *prev_zpdesc = NULL;
+ int nr_zpdescs = class->pages_per_zspage;
/*
* Allocate individual pages and link them together as:
- * 1. all pages are linked together using page->index
- * 2. each sub-page point to zspage using page->private
+ * 1. all pages are linked together using zpdesc->next
+ * 2. each sub-page point to zspage using zpdesc->zspage
*
- * we set PG_private to identify the first page (i.e. no other sub-page
+ * we set PG_private to identify the first zpdesc (i.e. no other zpdesc
* has this flag set).
*/
- for (i = 0; i < nr_pages; i++) {
- page = pages[i];
- set_page_private(page, (unsigned long)zspage);
- page->index = 0;
+ for (i = 0; i < nr_zpdescs; i++) {
+ zpdesc = zpdescs[i];
+ zpdesc_set_zspage(zpdesc, zspage);
+ zpdesc->next = NULL;
if (i == 0) {
- zspage->first_zpdesc = page_zpdesc(page);
- SetPagePrivate(page);
+ zspage->first_zpdesc = zpdesc;
+ zpdesc_set_first(zpdesc);
if (unlikely(class->objs_per_zspage == 1 &&
class->pages_per_zspage == 1))
SetZsHugePage(zspage);
} else {
- prev_page->index = (unsigned long)page;
+ prev_zpdesc->next = zpdesc;
}
- prev_page = page;
+ prev_zpdesc = zpdesc;
}
}
@@ -996,7 +1031,7 @@ static struct zspage *alloc_zspage(struct zs_pool *pool,
gfp_t gfp)
{
int i;
- struct page *pages[ZS_MAX_PAGES_PER_ZSPAGE];
+ struct zpdesc *zpdescs[ZS_MAX_PAGES_PER_ZSPAGE];
struct zspage *zspage = cache_alloc_zspage(pool, gfp);
if (!zspage)
@@ -1006,25 +1041,25 @@ static struct zspage *alloc_zspage(struct zs_pool *pool,
migrate_lock_init(zspage);
for (i = 0; i < class->pages_per_zspage; i++) {
- struct page *page;
+ struct zpdesc *zpdesc;
- page = alloc_page(gfp);
- if (!page) {
+ zpdesc = alloc_zpdesc(gfp);
+ if (!zpdesc) {
while (--i >= 0) {
- dec_zone_page_state(pages[i], NR_ZSPAGES);
- __ClearPageZsmalloc(pages[i]);
- __free_page(pages[i]);
+ zpdesc_dec_zone_page_state(zpdescs[i]);
+ __ClearPageZsmalloc(zpdesc_page(zpdescs[i]));
+ free_zpdesc(zpdescs[i]);
}
cache_free_zspage(pool, zspage);
return NULL;
}
- __SetPageZsmalloc(page);
+ __SetPageZsmalloc(zpdesc_page(zpdesc));
- inc_zone_page_state(page, NR_ZSPAGES);
- pages[i] = page;
+ zpdesc_inc_zone_page_state(zpdesc);
+ zpdescs[i] = zpdesc;
}
- create_page_chain(class, zspage, pages);
+ create_page_chain(class, zspage, zpdescs);
init_zspage(class, zspage);
zspage->pool = pool;
zspage->class = class->index;
@@ -1758,26 +1793,28 @@ static void migrate_write_unlock(struct zspage *zspage)
static const struct movable_operations zsmalloc_mops;
static void replace_sub_page(struct size_class *class, struct zspage *zspage,
- struct page *newpage, struct page *oldpage)
+ struct zpdesc *newzpdesc, struct zpdesc *oldzpdesc)
{
- struct page *page;
- struct page *pages[ZS_MAX_PAGES_PER_ZSPAGE] = {NULL, };
+ struct zpdesc *zpdesc;
+ struct zpdesc *zpdescs[ZS_MAX_PAGES_PER_ZSPAGE] = {NULL, };
+ unsigned int first_obj_offset;
int idx = 0;
- page = get_first_page(zspage);
+ zpdesc = get_first_zpdesc(zspage);
do {
- if (page == oldpage)
- pages[idx] = newpage;
+ if (zpdesc == oldzpdesc)
+ zpdescs[idx] = newzpdesc;
else
- pages[idx] = page;
+ zpdescs[idx] = zpdesc;
idx++;
- } while ((page = get_next_page(page)) != NULL);
+ } while ((zpdesc = get_next_zpdesc(zpdesc)) != NULL);
- create_page_chain(class, zspage, pages);
- set_first_obj_offset(newpage, get_first_obj_offset(oldpage));
+ create_page_chain(class, zspage, zpdescs);
+ first_obj_offset = get_first_obj_offset(zpdesc_page(oldzpdesc));
+ set_first_obj_offset(zpdesc_page(newzpdesc), first_obj_offset);
if (unlikely(ZsHugePage(zspage)))
- newpage->index = oldpage->index;
- __SetPageMovable(newpage, &zsmalloc_mops);
+ newzpdesc->handle = oldzpdesc->handle;
+ __zpdesc_set_movable(newzpdesc, &zsmalloc_mops);
}
static bool zs_page_isolate(struct page *page, isolate_mode_t mode)
@@ -1850,7 +1887,7 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
}
kunmap_atomic(s_addr);
- replace_sub_page(class, zspage, newpage, page);
+ replace_sub_page(class, zspage, page_zpdesc(newpage), page_zpdesc(page));
/*
* Since we complete the data copy and set up new zspage structure,
* it's okay to release migration_lock.
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 07/20] mm/zsmalloc: convert obj_allocated() and related helpers to use zpdesc
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (5 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 06/20] mm/zsmalloc: convert create_page_chain() and its users " alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 08/20] mm/zsmalloc: convert init_zspage() " alexs
` (13 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Convert obj_allocated(), and related helpers to take zpdesc. Also make
its callers to cast (struct page *) to (struct zpdesc *) when calling them.
The users will be converted gradually as there are many.
Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zsmalloc.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index ee890d513f6f..6efaa6279687 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -847,15 +847,15 @@ static unsigned long handle_to_obj(unsigned long handle)
return *(unsigned long *)handle;
}
-static inline bool obj_allocated(struct page *page, void *obj,
+static inline bool obj_allocated(struct zpdesc *zpdesc, void *obj,
unsigned long *phandle)
{
unsigned long handle;
- struct zspage *zspage = get_zspage(page);
+ struct zspage *zspage = get_zspage(zpdesc_page(zpdesc));
if (unlikely(ZsHugePage(zspage))) {
- VM_BUG_ON_PAGE(!is_first_page(page), page);
- handle = page->index;
+ VM_BUG_ON_PAGE(!is_first_zpdesc(zpdesc), zpdesc_page(zpdesc));
+ handle = zpdesc->handle;
} else
handle = *(unsigned long *)obj;
@@ -1607,18 +1607,18 @@ static void zs_object_copy(struct size_class *class, unsigned long dst,
* return handle.
*/
static unsigned long find_alloced_obj(struct size_class *class,
- struct page *page, int *obj_idx)
+ struct zpdesc *zpdesc, int *obj_idx)
{
unsigned int offset;
int index = *obj_idx;
unsigned long handle = 0;
- void *addr = kmap_atomic(page);
+ void *addr = zpdesc_kmap_atomic(zpdesc);
- offset = get_first_obj_offset(page);
+ offset = get_first_obj_offset(zpdesc_page(zpdesc));
offset += class->size * index;
while (offset < PAGE_SIZE) {
- if (obj_allocated(page, addr + offset, &handle))
+ if (obj_allocated(zpdesc, addr + offset, &handle))
break;
offset += class->size;
@@ -1642,7 +1642,7 @@ static void migrate_zspage(struct zs_pool *pool, struct zspage *src_zspage,
struct size_class *class = pool->size_class[src_zspage->class];
while (1) {
- handle = find_alloced_obj(class, s_page, &obj_idx);
+ handle = find_alloced_obj(class, page_zpdesc(s_page), &obj_idx);
if (!handle) {
s_page = get_next_page(s_page);
if (!s_page)
@@ -1876,7 +1876,7 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
for (addr = s_addr + offset; addr < s_addr + PAGE_SIZE;
addr += class->size) {
- if (obj_allocated(page, addr, &handle)) {
+ if (obj_allocated(page_zpdesc(page), addr, &handle)) {
old_obj = handle_to_obj(handle);
obj_to_location(old_obj, &dummy, &obj_idx);
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 08/20] mm/zsmalloc: convert init_zspage() to use zpdesc
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (6 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 07/20] mm/zsmalloc: convert obj_allocated() and related helpers " alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 09/20] mm/zsmalloc: convert obj_to_page() and zs_free() " alexs
` (12 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Replace get_first/next_page func series and kmap_atomic to new helper,
no functional change.
Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zsmalloc.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 6efaa6279687..e90e3a638068 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -950,16 +950,16 @@ static void init_zspage(struct size_class *class, struct zspage *zspage)
{
unsigned int freeobj = 1;
unsigned long off = 0;
- struct page *page = get_first_page(zspage);
+ struct zpdesc *zpdesc = get_first_zpdesc(zspage);
- while (page) {
- struct page *next_page;
+ while (zpdesc) {
+ struct zpdesc *next_zpdesc;
struct link_free *link;
void *vaddr;
- set_first_obj_offset(page, off);
+ set_first_obj_offset(zpdesc_page(zpdesc), off);
- vaddr = kmap_atomic(page);
+ vaddr = zpdesc_kmap_atomic(zpdesc);
link = (struct link_free *)vaddr + off / sizeof(*link);
while ((off += class->size) < PAGE_SIZE) {
@@ -972,8 +972,8 @@ static void init_zspage(struct size_class *class, struct zspage *zspage)
* page, which must point to the first object on the next
* page (if present)
*/
- next_page = get_next_page(page);
- if (next_page) {
+ next_zpdesc = get_next_zpdesc(zpdesc);
+ if (next_zpdesc) {
link->next = freeobj++ << OBJ_TAG_BITS;
} else {
/*
@@ -983,7 +983,7 @@ static void init_zspage(struct size_class *class, struct zspage *zspage)
link->next = -1UL << OBJ_TAG_BITS;
}
kunmap_atomic(vaddr);
- page = next_page;
+ zpdesc = next_zpdesc;
off %= PAGE_SIZE;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 09/20] mm/zsmalloc: convert obj_to_page() and zs_free() to use zpdesc
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (7 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 08/20] mm/zsmalloc: convert init_zspage() " alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 10/20] mm/zsmalloc: add zpdesc_is_isolated/zpdesc_zone helper for zs_page_migrate alexs
` (11 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Rename obj_to_page() to obj_to_zpdesc() and also convert it and
its user zs_free() to use zpdesc.
Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zsmalloc.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index e90e3a638068..3ef8e13fb9e6 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -822,9 +822,9 @@ static void obj_to_location(unsigned long obj, struct zpdesc **zpdesc,
*obj_idx = (obj & OBJ_INDEX_MASK);
}
-static void obj_to_page(unsigned long obj, struct page **page)
+static void obj_to_zpdesc(unsigned long obj, struct zpdesc **zpdesc)
{
- *page = pfn_to_page(obj >> OBJ_INDEX_BITS);
+ *zpdesc = pfn_zpdesc(obj >> OBJ_INDEX_BITS);
}
/**
@@ -1500,7 +1500,7 @@ static void obj_free(int class_size, unsigned long obj)
void zs_free(struct zs_pool *pool, unsigned long handle)
{
struct zspage *zspage;
- struct page *f_page;
+ struct zpdesc *f_zpdesc;
unsigned long obj;
struct size_class *class;
int fullness;
@@ -1514,8 +1514,8 @@ void zs_free(struct zs_pool *pool, unsigned long handle)
*/
read_lock(&pool->migrate_lock);
obj = handle_to_obj(handle);
- obj_to_page(obj, &f_page);
- zspage = get_zspage(f_page);
+ obj_to_zpdesc(obj, &f_zpdesc);
+ zspage = get_zspage(zpdesc_page(f_zpdesc));
class = zspage_class(pool, zspage);
spin_lock(&class->lock);
read_unlock(&pool->migrate_lock);
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 10/20] mm/zsmalloc: add zpdesc_is_isolated/zpdesc_zone helper for zs_page_migrate
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (8 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 09/20] mm/zsmalloc: convert obj_to_page() and zs_free() " alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 11/20] mm/zsmalloc: rename reset_page to reset_zpdesc and use zpdesc in it alexs
` (10 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
To convert page to zpdesc in zs_page_migrate(), we added
zpdesc_is_isolated/zpdesc_zone helpers. No functional change.
Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zpdesc.h | 11 +++++++++++
mm/zsmalloc.c | 30 ++++++++++++++++--------------
2 files changed, 27 insertions(+), 14 deletions(-)
diff --git a/mm/zpdesc.h b/mm/zpdesc.h
index f998d65c59d6..2e35b8220e05 100644
--- a/mm/zpdesc.h
+++ b/mm/zpdesc.h
@@ -98,4 +98,15 @@ static inline void __zpdesc_set_movable(struct zpdesc *zpdesc,
{
__SetPageMovable(zpdesc_page(zpdesc), mops);
}
+
+static inline bool zpdesc_is_isolated(struct zpdesc *zpdesc)
+{
+ return PageIsolated(zpdesc_page(zpdesc));
+}
+
+static inline struct zone *zpdesc_zone(struct zpdesc *zpdesc)
+{
+ return page_zone(zpdesc_page(zpdesc));
+}
+
#endif
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 3ef8e13fb9e6..251a6e63e58a 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -1835,19 +1835,21 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
struct size_class *class;
struct zspage *zspage;
struct zpdesc *dummy;
+ struct zpdesc *newzpdesc = page_zpdesc(newpage);
+ struct zpdesc *zpdesc = page_zpdesc(page);
void *s_addr, *d_addr, *addr;
unsigned int offset;
unsigned long handle;
unsigned long old_obj, new_obj;
unsigned int obj_idx;
- VM_BUG_ON_PAGE(!PageIsolated(page), page);
+ VM_BUG_ON_PAGE(!zpdesc_is_isolated(zpdesc), zpdesc_page(zpdesc));
/* We're committed, tell the world that this is a Zsmalloc page. */
- __SetPageZsmalloc(newpage);
+ __SetPageZsmalloc(zpdesc_page(newzpdesc));
/* The page is locked, so this pointer must remain valid */
- zspage = get_zspage(page);
+ zspage = get_zspage(zpdesc_page(zpdesc));
pool = zspage->pool;
/*
@@ -1864,30 +1866,30 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
/* the migrate_write_lock protects zpage access via zs_map_object */
migrate_write_lock(zspage);
- offset = get_first_obj_offset(page);
- s_addr = kmap_atomic(page);
+ offset = get_first_obj_offset(zpdesc_page(zpdesc));
+ s_addr = zpdesc_kmap_atomic(zpdesc);
/*
* Here, any user cannot access all objects in the zspage so let's move.
*/
- d_addr = kmap_atomic(newpage);
+ d_addr = zpdesc_kmap_atomic(newzpdesc);
copy_page(d_addr, s_addr);
kunmap_atomic(d_addr);
for (addr = s_addr + offset; addr < s_addr + PAGE_SIZE;
addr += class->size) {
- if (obj_allocated(page_zpdesc(page), addr, &handle)) {
+ if (obj_allocated(zpdesc, addr, &handle)) {
old_obj = handle_to_obj(handle);
obj_to_location(old_obj, &dummy, &obj_idx);
- new_obj = (unsigned long)location_to_obj(newpage,
+ new_obj = (unsigned long)location_to_obj(zpdesc_page(newzpdesc),
obj_idx);
record_obj(handle, new_obj);
}
}
kunmap_atomic(s_addr);
- replace_sub_page(class, zspage, page_zpdesc(newpage), page_zpdesc(page));
+ replace_sub_page(class, zspage, newzpdesc, zpdesc);
/*
* Since we complete the data copy and set up new zspage structure,
* it's okay to release migration_lock.
@@ -1896,14 +1898,14 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
spin_unlock(&class->lock);
migrate_write_unlock(zspage);
- get_page(newpage);
- if (page_zone(newpage) != page_zone(page)) {
- dec_zone_page_state(page, NR_ZSPAGES);
- inc_zone_page_state(newpage, NR_ZSPAGES);
+ zpdesc_get(newzpdesc);
+ if (zpdesc_zone(newzpdesc) != zpdesc_zone(zpdesc)) {
+ zpdesc_dec_zone_page_state(zpdesc);
+ zpdesc_inc_zone_page_state(newzpdesc);
}
reset_page(page);
- put_page(page);
+ zpdesc_put(zpdesc);
return MIGRATEPAGE_SUCCESS;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 11/20] mm/zsmalloc: rename reset_page to reset_zpdesc and use zpdesc in it
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (9 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 10/20] mm/zsmalloc: add zpdesc_is_isolated/zpdesc_zone helper for zs_page_migrate alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 12/20] mm/zsmalloc: convert __free_zspage() to use zdsesc alexs
` (9 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Alex Shi <alexs@kernel.org>
zpdesc.zspage matches with page.private, zpdesc.next matches with
page.index. They will be reset in reset_page() wich is called prior to
free base pages of a zspage.
Use zpdesc to replace page struct and rename it to reset_zpdesc(), few
page helper still left since they are used too widely.
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zsmalloc.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 251a6e63e58a..216f8e6950ef 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -867,12 +867,14 @@ static inline bool obj_allocated(struct zpdesc *zpdesc, void *obj,
return true;
}
-static void reset_page(struct page *page)
+static void reset_zpdesc(struct zpdesc *zpdesc)
{
+ struct page *page = zpdesc_page(zpdesc);
+
__ClearPageMovable(page);
ClearPagePrivate(page);
- set_page_private(page, 0);
- page->index = 0;
+ zpdesc->zspage = NULL;
+ zpdesc->next = NULL;
reset_first_obj_offset(page);
__ClearPageZsmalloc(page);
}
@@ -912,7 +914,7 @@ static void __free_zspage(struct zs_pool *pool, struct size_class *class,
do {
VM_BUG_ON_PAGE(!PageLocked(page), page);
next = get_next_page(page);
- reset_page(page);
+ reset_zpdesc(page_zpdesc(page));
unlock_page(page);
dec_zone_page_state(page, NR_ZSPAGES);
put_page(page);
@@ -1904,7 +1906,7 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
zpdesc_inc_zone_page_state(newzpdesc);
}
- reset_page(page);
+ reset_zpdesc(zpdesc);
zpdesc_put(zpdesc);
return MIGRATEPAGE_SUCCESS;
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 12/20] mm/zsmalloc: convert __free_zspage() to use zdsesc
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (10 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 11/20] mm/zsmalloc: rename reset_page to reset_zpdesc and use zpdesc in it alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 13/20] mm/zsmalloc: convert location_to_obj() to take zpdesc alexs
` (8 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Introduce zpdesc_is_locked() and convert __free_zspage() to use zpdesc.
Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zpdesc.h | 4 ++++
mm/zsmalloc.c | 20 ++++++++++----------
2 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/mm/zpdesc.h b/mm/zpdesc.h
index 2e35b8220e05..186ff9711ffb 100644
--- a/mm/zpdesc.h
+++ b/mm/zpdesc.h
@@ -109,4 +109,8 @@ static inline struct zone *zpdesc_zone(struct zpdesc *zpdesc)
return page_zone(zpdesc_page(zpdesc));
}
+static inline bool zpdesc_is_locked(struct zpdesc *zpdesc)
+{
+ return PageLocked(zpdesc_page(zpdesc));
+}
#endif
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 216f8e6950ef..bf5a1b63bb17 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -903,23 +903,23 @@ static int trylock_zspage(struct zspage *zspage)
static void __free_zspage(struct zs_pool *pool, struct size_class *class,
struct zspage *zspage)
{
- struct page *page, *next;
+ struct zpdesc *zpdesc, *next;
assert_spin_locked(&class->lock);
VM_BUG_ON(get_zspage_inuse(zspage));
VM_BUG_ON(zspage->fullness != ZS_INUSE_RATIO_0);
- next = page = get_first_page(zspage);
+ next = zpdesc = get_first_zpdesc(zspage);
do {
- VM_BUG_ON_PAGE(!PageLocked(page), page);
- next = get_next_page(page);
- reset_zpdesc(page_zpdesc(page));
- unlock_page(page);
- dec_zone_page_state(page, NR_ZSPAGES);
- put_page(page);
- page = next;
- } while (page != NULL);
+ VM_BUG_ON_PAGE(!zpdesc_is_locked(zpdesc), zpdesc_page(zpdesc));
+ next = get_next_zpdesc(zpdesc);
+ reset_zpdesc(zpdesc);
+ zpdesc_unlock(zpdesc);
+ zpdesc_dec_zone_page_state(zpdesc);
+ zpdesc_put(zpdesc);
+ zpdesc = next;
+ } while (zpdesc != NULL);
cache_free_zspage(pool, zspage);
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 13/20] mm/zsmalloc: convert location_to_obj() to take zpdesc
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (11 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 12/20] mm/zsmalloc: convert __free_zspage() to use zdsesc alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 14/20] mm/zsmalloc: convert migrate_zspage() to use zpdesc alexs
` (7 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
As all users of location_to_obj() now use zpdesc, convert
location_to_obj() to take zpdesc.
Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zsmalloc.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index bf5a1b63bb17..e8af01768ae0 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -828,15 +828,15 @@ static void obj_to_zpdesc(unsigned long obj, struct zpdesc **zpdesc)
}
/**
- * location_to_obj - get obj value encoded from (<page>, <obj_idx>)
- * @page: page object resides in zspage
+ * location_to_obj - get obj value encoded from (<zpdesc>, <obj_idx>)
+ * @zpdesc: zpdesc object resides in zspage
* @obj_idx: object index
*/
-static unsigned long location_to_obj(struct page *page, unsigned int obj_idx)
+static unsigned long location_to_obj(struct zpdesc *zpdesc, unsigned int obj_idx)
{
unsigned long obj;
- obj = page_to_pfn(page) << OBJ_INDEX_BITS;
+ obj = zpdesc_pfn(zpdesc) << OBJ_INDEX_BITS;
obj |= obj_idx & OBJ_INDEX_MASK;
return obj;
@@ -1395,7 +1395,7 @@ static unsigned long obj_malloc(struct zs_pool *pool,
kunmap_atomic(vaddr);
mod_zspage_inuse(zspage, 1);
- obj = location_to_obj(zpdesc_page(m_zpdesc), obj);
+ obj = location_to_obj(m_zpdesc, obj);
return obj;
}
@@ -1884,8 +1884,7 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
old_obj = handle_to_obj(handle);
obj_to_location(old_obj, &dummy, &obj_idx);
- new_obj = (unsigned long)location_to_obj(zpdesc_page(newzpdesc),
- obj_idx);
+ new_obj = (unsigned long)location_to_obj(newzpdesc, obj_idx);
record_obj(handle, new_obj);
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 14/20] mm/zsmalloc: convert migrate_zspage() to use zpdesc
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (12 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 13/20] mm/zsmalloc: convert location_to_obj() to take zpdesc alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 15/20] mm/zsmalloc: convert get_zspage() to take zpdesc alexs
` (6 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Use get_first_zpdesc/get_next_zpdesc to replace get_first/next_page. No
functional change.
Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zsmalloc.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index e8af01768ae0..a10af49d8d08 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -1640,14 +1640,14 @@ static void migrate_zspage(struct zs_pool *pool, struct zspage *src_zspage,
unsigned long used_obj, free_obj;
unsigned long handle;
int obj_idx = 0;
- struct page *s_page = get_first_page(src_zspage);
+ struct zpdesc *s_zpdesc = get_first_zpdesc(src_zspage);
struct size_class *class = pool->size_class[src_zspage->class];
while (1) {
- handle = find_alloced_obj(class, page_zpdesc(s_page), &obj_idx);
+ handle = find_alloced_obj(class, s_zpdesc, &obj_idx);
if (!handle) {
- s_page = get_next_page(s_page);
- if (!s_page)
+ s_zpdesc = get_next_zpdesc(s_zpdesc);
+ if (!s_zpdesc)
break;
obj_idx = 0;
continue;
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 15/20] mm/zsmalloc: convert get_zspage() to take zpdesc
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (13 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 14/20] mm/zsmalloc: convert migrate_zspage() to use zpdesc alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 16/20] mm/zsmalloc: convert SetZsPageMovable and remove unused funcs alexs
` (5 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Now that all users except get_next_page() (which will be removed in
later patch) use zpdesc, convert get_zspage() to take zpdesc instead
of page.
Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zsmalloc.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index a10af49d8d08..c136124adb10 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -781,9 +781,9 @@ static int fix_fullness_group(struct size_class *class, struct zspage *zspage)
return newfg;
}
-static struct zspage *get_zspage(struct page *page)
+static struct zspage *get_zspage(struct zpdesc *zpdesc)
{
- struct zspage *zspage = (struct zspage *)page_private(page);
+ struct zspage *zspage = zpdesc->zspage;
BUG_ON(zspage->magic != ZSPAGE_MAGIC);
return zspage;
@@ -791,7 +791,7 @@ static struct zspage *get_zspage(struct page *page)
static struct page *get_next_page(struct page *page)
{
- struct zspage *zspage = get_zspage(page);
+ struct zspage *zspage = get_zspage(page_zpdesc(page));
if (unlikely(ZsHugePage(zspage)))
return NULL;
@@ -801,7 +801,7 @@ static struct page *get_next_page(struct page *page)
static struct zpdesc *get_next_zpdesc(struct zpdesc *zpdesc)
{
- struct zspage *zspage = get_zspage(zpdesc_page(zpdesc));
+ struct zspage *zspage = get_zspage(zpdesc);
if (unlikely(ZsHugePage(zspage)))
return NULL;
@@ -851,7 +851,7 @@ static inline bool obj_allocated(struct zpdesc *zpdesc, void *obj,
unsigned long *phandle)
{
unsigned long handle;
- struct zspage *zspage = get_zspage(zpdesc_page(zpdesc));
+ struct zspage *zspage = get_zspage(zpdesc);
if (unlikely(ZsHugePage(zspage))) {
VM_BUG_ON_PAGE(!is_first_zpdesc(zpdesc), zpdesc_page(zpdesc));
@@ -1267,7 +1267,7 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle,
read_lock(&pool->migrate_lock);
obj = handle_to_obj(handle);
obj_to_location(obj, &zpdesc, &obj_idx);
- zspage = get_zspage(zpdesc_page(zpdesc));
+ zspage = get_zspage(zpdesc);
/*
* migration cannot move any zpages in this zspage. Here, class->lock
@@ -1317,7 +1317,7 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle)
obj = handle_to_obj(handle);
obj_to_location(obj, &zpdesc, &obj_idx);
- zspage = get_zspage(zpdesc_page(zpdesc));
+ zspage = get_zspage(zpdesc);
class = zspage_class(pool, zspage);
off = offset_in_page(class->size * obj_idx);
@@ -1483,7 +1483,7 @@ static void obj_free(int class_size, unsigned long obj)
obj_to_location(obj, &f_zpdesc, &f_objidx);
f_offset = offset_in_page(class_size * f_objidx);
- zspage = get_zspage(zpdesc_page(f_zpdesc));
+ zspage = get_zspage(f_zpdesc);
vaddr = zpdesc_kmap_atomic(f_zpdesc);
link = (struct link_free *)(vaddr + f_offset);
@@ -1517,7 +1517,7 @@ void zs_free(struct zs_pool *pool, unsigned long handle)
read_lock(&pool->migrate_lock);
obj = handle_to_obj(handle);
obj_to_zpdesc(obj, &f_zpdesc);
- zspage = get_zspage(zpdesc_page(f_zpdesc));
+ zspage = get_zspage(f_zpdesc);
class = zspage_class(pool, zspage);
spin_lock(&class->lock);
read_unlock(&pool->migrate_lock);
@@ -1851,7 +1851,7 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
__SetPageZsmalloc(zpdesc_page(newzpdesc));
/* The page is locked, so this pointer must remain valid */
- zspage = get_zspage(zpdesc_page(zpdesc));
+ zspage = get_zspage(zpdesc);
pool = zspage->pool;
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 16/20] mm/zsmalloc: convert SetZsPageMovable and remove unused funcs
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (14 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 15/20] mm/zsmalloc: convert get_zspage() to take zpdesc alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 17/20] mm/zsmalloc: convert get/set_first_obj_offset() to take zpdesc alexs
` (4 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Alex Shi <alexs@kernel.org>
Convert SetZsPageMovable() to use zpdesc, and then remove unused
funcs:get_next_page/get_first_page/is_first_page.
Originally-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zsmalloc.c | 33 +++++----------------------------
1 file changed, 5 insertions(+), 28 deletions(-)
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index c136124adb10..951292dbcae4 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -470,11 +470,6 @@ static DEFINE_PER_CPU(struct mapping_area, zs_map_area) = {
.lock = INIT_LOCAL_LOCK(lock),
};
-static __maybe_unused int is_first_page(struct page *page)
-{
- return PagePrivate(page);
-}
-
static int is_first_zpdesc(struct zpdesc *zpdesc)
{
return PagePrivate(zpdesc_page(zpdesc));
@@ -491,14 +486,6 @@ static inline void mod_zspage_inuse(struct zspage *zspage, int val)
zspage->inuse += val;
}
-static inline struct page *get_first_page(struct zspage *zspage)
-{
- struct page *first_page = zpdesc_page(zspage->first_zpdesc);
-
- VM_BUG_ON_PAGE(!is_first_page(first_page), first_page);
- return first_page;
-}
-
static struct zpdesc *get_first_zpdesc(struct zspage *zspage)
{
struct zpdesc *first_zpdesc = zspage->first_zpdesc;
@@ -789,16 +776,6 @@ static struct zspage *get_zspage(struct zpdesc *zpdesc)
return zspage;
}
-static struct page *get_next_page(struct page *page)
-{
- struct zspage *zspage = get_zspage(page_zpdesc(page));
-
- if (unlikely(ZsHugePage(zspage)))
- return NULL;
-
- return (struct page *)page->index;
-}
-
static struct zpdesc *get_next_zpdesc(struct zpdesc *zpdesc)
{
struct zspage *zspage = get_zspage(zpdesc);
@@ -1974,13 +1951,13 @@ static void init_deferred_free(struct zs_pool *pool)
static void SetZsPageMovable(struct zs_pool *pool, struct zspage *zspage)
{
- struct page *page = get_first_page(zspage);
+ struct zpdesc *zpdesc = get_first_zpdesc(zspage);
do {
- WARN_ON(!trylock_page(page));
- __SetPageMovable(page, &zsmalloc_mops);
- unlock_page(page);
- } while ((page = get_next_page(page)) != NULL);
+ WARN_ON(!zpdesc_trylock(zpdesc));
+ __zpdesc_set_movable(zpdesc, &zsmalloc_mops);
+ zpdesc_unlock(zpdesc);
+ } while ((zpdesc = get_next_zpdesc(zpdesc)) != NULL);
}
#else
static inline void zs_flush_migration(struct zs_pool *pool) { }
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 17/20] mm/zsmalloc: convert get/set_first_obj_offset() to take zpdesc
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (15 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 16/20] mm/zsmalloc: convert SetZsPageMovable and remove unused funcs alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 18/20] mm/zsmalloc: introduce __zpdesc_clear_movable alexs
` (3 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Now that all users of get/set_first_obj_offset() are converted
to use zpdesc, convert them to take zpdesc.
Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zpdesc.h | 3 +++
mm/zsmalloc.c | 32 ++++++++++++++++----------------
2 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/mm/zpdesc.h b/mm/zpdesc.h
index 186ff9711ffb..17941774c46e 100644
--- a/mm/zpdesc.h
+++ b/mm/zpdesc.h
@@ -14,6 +14,7 @@
* @next: Next zpdesc in a zspage in zsmalloc zpool
* @handle: For huge zspage in zsmalloc zpool
* @zspage: Pointer to zspage in zsmalloc
+ * @first_obj_offset: First object offset in zsmalloc zpool
*
* This struct overlays struct page for now. Do not modify without a good
* understanding of the issues.
@@ -29,6 +30,7 @@ struct zpdesc {
unsigned long handle;
};
struct zspage *zspage;
+ unsigned int first_obj_offset;
};
#define ZPDESC_MATCH(pg, zp) \
static_assert(offsetof(struct page, pg) == offsetof(struct zpdesc, zp))
@@ -38,6 +40,7 @@ ZPDESC_MATCH(lru, lru);
ZPDESC_MATCH(index, next);
ZPDESC_MATCH(index, handle);
ZPDESC_MATCH(private, zspage);
+ZPDESC_MATCH(page_type, first_obj_offset);
#undef ZPDESC_MATCH
static_assert(sizeof(struct zpdesc) <= sizeof(struct page));
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 951292dbcae4..3ce49f0372cc 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -496,26 +496,26 @@ static struct zpdesc *get_first_zpdesc(struct zspage *zspage)
#define FIRST_OBJ_PAGE_TYPE_MASK 0xffff
-static inline void reset_first_obj_offset(struct page *page)
+static inline void reset_first_obj_offset(struct zpdesc *zpdesc)
{
- VM_WARN_ON_ONCE(!PageZsmalloc(page));
- page->page_type |= FIRST_OBJ_PAGE_TYPE_MASK;
+ VM_WARN_ON_ONCE(!PageZsmalloc(zpdesc_page(zpdesc)));
+ zpdesc->first_obj_offset |= FIRST_OBJ_PAGE_TYPE_MASK;
}
-static inline unsigned int get_first_obj_offset(struct page *page)
+static inline unsigned int get_first_obj_offset(struct zpdesc *zpdesc)
{
- VM_WARN_ON_ONCE(!PageZsmalloc(page));
- return page->page_type & FIRST_OBJ_PAGE_TYPE_MASK;
+ VM_WARN_ON_ONCE(!PageZsmalloc(zpdesc_page(zpdesc)));
+ return zpdesc->first_obj_offset & FIRST_OBJ_PAGE_TYPE_MASK;
}
-static inline void set_first_obj_offset(struct page *page, unsigned int offset)
+static inline void set_first_obj_offset(struct zpdesc *zpdesc, unsigned int offset)
{
/* With 16 bit available, we can support offsets into 64 KiB pages. */
BUILD_BUG_ON(PAGE_SIZE > SZ_64K);
- VM_WARN_ON_ONCE(!PageZsmalloc(page));
+ VM_WARN_ON_ONCE(!PageZsmalloc(zpdesc_page(zpdesc)));
VM_WARN_ON_ONCE(offset & ~FIRST_OBJ_PAGE_TYPE_MASK);
- page->page_type &= ~FIRST_OBJ_PAGE_TYPE_MASK;
- page->page_type |= offset & FIRST_OBJ_PAGE_TYPE_MASK;
+ zpdesc->first_obj_offset &= ~FIRST_OBJ_PAGE_TYPE_MASK;
+ zpdesc->first_obj_offset |= offset & FIRST_OBJ_PAGE_TYPE_MASK;
}
static inline unsigned int get_freeobj(struct zspage *zspage)
@@ -852,7 +852,7 @@ static void reset_zpdesc(struct zpdesc *zpdesc)
ClearPagePrivate(page);
zpdesc->zspage = NULL;
zpdesc->next = NULL;
- reset_first_obj_offset(page);
+ reset_first_obj_offset(zpdesc);
__ClearPageZsmalloc(page);
}
@@ -936,7 +936,7 @@ static void init_zspage(struct size_class *class, struct zspage *zspage)
struct link_free *link;
void *vaddr;
- set_first_obj_offset(zpdesc_page(zpdesc), off);
+ set_first_obj_offset(zpdesc, off);
vaddr = zpdesc_kmap_atomic(zpdesc);
link = (struct link_free *)vaddr + off / sizeof(*link);
@@ -1593,7 +1593,7 @@ static unsigned long find_alloced_obj(struct size_class *class,
unsigned long handle = 0;
void *addr = zpdesc_kmap_atomic(zpdesc);
- offset = get_first_obj_offset(zpdesc_page(zpdesc));
+ offset = get_first_obj_offset(zpdesc);
offset += class->size * index;
while (offset < PAGE_SIZE) {
@@ -1789,8 +1789,8 @@ static void replace_sub_page(struct size_class *class, struct zspage *zspage,
} while ((zpdesc = get_next_zpdesc(zpdesc)) != NULL);
create_page_chain(class, zspage, zpdescs);
- first_obj_offset = get_first_obj_offset(zpdesc_page(oldzpdesc));
- set_first_obj_offset(zpdesc_page(newzpdesc), first_obj_offset);
+ first_obj_offset = get_first_obj_offset(oldzpdesc);
+ set_first_obj_offset(newzpdesc, first_obj_offset);
if (unlikely(ZsHugePage(zspage)))
newzpdesc->handle = oldzpdesc->handle;
__zpdesc_set_movable(newzpdesc, &zsmalloc_mops);
@@ -1845,7 +1845,7 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
/* the migrate_write_lock protects zpage access via zs_map_object */
migrate_write_lock(zspage);
- offset = get_first_obj_offset(zpdesc_page(zpdesc));
+ offset = get_first_obj_offset(zpdesc);
s_addr = zpdesc_kmap_atomic(zpdesc);
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 18/20] mm/zsmalloc: introduce __zpdesc_clear_movable
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (16 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 17/20] mm/zsmalloc: convert get/set_first_obj_offset() to take zpdesc alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 19/20] mm/zsmalloc: introduce __zpdesc_clear_zsmalloc alexs
` (2 subsequent siblings)
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Alex Shi <alexs@kernel.org>
Add a helper __zpdesc_clear_movable() for __ClearPageMovable(), and use it
in callers to make code clear.
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zpdesc.h | 5 +++++
mm/zsmalloc.c | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/mm/zpdesc.h b/mm/zpdesc.h
index 17941774c46e..c6a44fe04f97 100644
--- a/mm/zpdesc.h
+++ b/mm/zpdesc.h
@@ -102,6 +102,11 @@ static inline void __zpdesc_set_movable(struct zpdesc *zpdesc,
__SetPageMovable(zpdesc_page(zpdesc), mops);
}
+static inline void __zpdesc_clear_movable(struct zpdesc *zpdesc)
+{
+ __ClearPageMovable(zpdesc_page(zpdesc));
+}
+
static inline bool zpdesc_is_isolated(struct zpdesc *zpdesc)
{
return PageIsolated(zpdesc_page(zpdesc));
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 3ce49f0372cc..abecc8a5c566 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -848,7 +848,7 @@ static void reset_zpdesc(struct zpdesc *zpdesc)
{
struct page *page = zpdesc_page(zpdesc);
- __ClearPageMovable(page);
+ __zpdesc_clear_movable(zpdesc);
ClearPagePrivate(page);
zpdesc->zspage = NULL;
zpdesc->next = NULL;
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 19/20] mm/zsmalloc: introduce __zpdesc_clear_zsmalloc
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (17 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 18/20] mm/zsmalloc: introduce __zpdesc_clear_movable alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 3:11 ` [PATCH 20/20] mm/zsmalloc: introduce __zpdesc_set_zsmalloc() alexs
2024-06-28 7:26 ` [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool Alex Shi
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Alex Shi <alexs@kernel.org>
Add a helper __zpdesc_clear_zsmalloc() for __ClearPageZsmalloc(), and use
it in callers to make code clear.
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zpdesc.h | 5 +++++
mm/zsmalloc.c | 4 ++--
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/mm/zpdesc.h b/mm/zpdesc.h
index c6a44fe04f97..e346b39aba59 100644
--- a/mm/zpdesc.h
+++ b/mm/zpdesc.h
@@ -107,6 +107,11 @@ static inline void __zpdesc_clear_movable(struct zpdesc *zpdesc)
__ClearPageMovable(zpdesc_page(zpdesc));
}
+static inline void __zpdesc_clear_zsmalloc(struct zpdesc *zpdesc)
+{
+ __ClearPageZsmalloc(zpdesc_page(zpdesc));
+}
+
static inline bool zpdesc_is_isolated(struct zpdesc *zpdesc)
{
return PageIsolated(zpdesc_page(zpdesc));
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index abecc8a5c566..eaf8dad04f2c 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -853,7 +853,7 @@ static void reset_zpdesc(struct zpdesc *zpdesc)
zpdesc->zspage = NULL;
zpdesc->next = NULL;
reset_first_obj_offset(zpdesc);
- __ClearPageZsmalloc(page);
+ __zpdesc_clear_zsmalloc(zpdesc);
}
static int trylock_zspage(struct zspage *zspage)
@@ -1026,7 +1026,7 @@ static struct zspage *alloc_zspage(struct zs_pool *pool,
if (!zpdesc) {
while (--i >= 0) {
zpdesc_dec_zone_page_state(zpdescs[i]);
- __ClearPageZsmalloc(zpdesc_page(zpdescs[i]));
+ __zpdesc_clear_zsmalloc(zpdescs[i]);
free_zpdesc(zpdescs[i]);
}
cache_free_zspage(pool, zspage);
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH 20/20] mm/zsmalloc: introduce __zpdesc_set_zsmalloc()
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (18 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 19/20] mm/zsmalloc: introduce __zpdesc_clear_zsmalloc alexs
@ 2024-06-28 3:11 ` alexs
2024-06-28 7:26 ` [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool Alex Shi
20 siblings, 0 replies; 28+ messages in thread
From: alexs @ 2024-06-28 3:11 UTC (permalink / raw)
To: Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel, linux-mm,
minchan, willy, senozhatsky, david, 42.hyeyoo
Cc: Alex Shi
From: Alex Shi <alexs@kernel.org>
Add a helper __zpdesc_set_zsmalloc() for __SetPageZsmalloc(), and use
it in callers to make code clear.
Signed-off-by: Alex Shi <alexs@kernel.org>
---
mm/zpdesc.h | 5 +++++
mm/zsmalloc.c | 4 ++--
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/mm/zpdesc.h b/mm/zpdesc.h
index e346b39aba59..ef36fc3de75d 100644
--- a/mm/zpdesc.h
+++ b/mm/zpdesc.h
@@ -107,6 +107,11 @@ static inline void __zpdesc_clear_movable(struct zpdesc *zpdesc)
__ClearPageMovable(zpdesc_page(zpdesc));
}
+static inline void __zpdesc_set_zsmalloc(struct zpdesc *zpdesc)
+{
+ __SetPageZsmalloc(zpdesc_page(zpdesc));
+}
+
static inline void __zpdesc_clear_zsmalloc(struct zpdesc *zpdesc)
{
__ClearPageZsmalloc(zpdesc_page(zpdesc));
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index eaf8dad04f2c..e2a506f53957 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -1032,7 +1032,7 @@ static struct zspage *alloc_zspage(struct zs_pool *pool,
cache_free_zspage(pool, zspage);
return NULL;
}
- __SetPageZsmalloc(zpdesc_page(zpdesc));
+ __zpdesc_set_zsmalloc(zpdesc);
zpdesc_inc_zone_page_state(zpdesc);
zpdescs[i] = zpdesc;
@@ -1825,7 +1825,7 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
VM_BUG_ON_PAGE(!zpdesc_is_isolated(zpdesc), zpdesc_page(zpdesc));
/* We're committed, tell the world that this is a Zsmalloc page. */
- __SetPageZsmalloc(zpdesc_page(newzpdesc));
+ __zpdesc_set_zsmalloc(newzpdesc);
/* The page is locked, so this pointer must remain valid */
zspage = get_zspage(zpdesc);
--
2.43.0
^ permalink raw reply related [flat|nested] 28+ messages in thread* Re: [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool
2024-06-28 3:11 [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool alexs
` (19 preceding siblings ...)
2024-06-28 3:11 ` [PATCH 20/20] mm/zsmalloc: introduce __zpdesc_set_zsmalloc() alexs
@ 2024-06-28 7:26 ` Alex Shi
2024-06-28 7:30 ` Alex Shi
20 siblings, 1 reply; 28+ messages in thread
From: Alex Shi @ 2024-06-28 7:26 UTC (permalink / raw)
To: alexs, Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel,
linux-mm, minchan, willy, senozhatsky, david, 42.hyeyoo
On 6/28/24 11:11 AM, alexs@kernel.org wrote:
> From: Alex Shi <alexs@kernel.org>
>
> According to Metthew's plan, the page descriptor will be replace by a 8
> bytes mem_desc on destination purpose.
> https://lore.kernel.org/lkml/YvV1KTyzZ+Jrtj9x@casper.infradead.org/
>
> Here is a implement on zsmalloc to replace page descriptor by 'zpdesc',
> which is still overlay on struct page now. but it's a step move forward
> above destination.
>
> To name the struct zpdesc instead of zsdesc, since there are still 3
> zpools under zswap: zbud, z3fold, zsmalloc for now(z3fold maybe removed
> soon), and we could easyly extend it to other zswap.zpool in needs.
>
> For all zswap.zpools, they are all using single page since often used
> under memory pressure. So the conversion via folio series helper is
> better than page's for compound_head check saving.
>
> For now, all zpools are using some page struct members, like page.flags
> for PG_private/PG_locked. and list_head lru, page.mapping for page migration.
>
> This patachset could save 123Kbyetes zsmalloc.o size.
This patchset is based on next/mm-unstable.
Thanks
Alex
>
> Thanks
> Alex
>
> Alex Shi (8):
> mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool
> mm/zsmalloc: use zpdesc in trylock_zspage/lock_zspage
> mm/zsmalloc: convert create_page_chain() and its users to use zpdesc
> mm/zsmalloc: rename reset_page to reset_zpdesc and use zpdesc in it
> mm/zsmalloc: convert SetZsPageMovable and remove unused funcs
> mm/zsmalloc: introduce __zpdesc_clear_movable
> mm/zsmalloc: introduce __zpdesc_clear_zsmalloc
> mm/zsmalloc: introduce __zpdesc_set_zsmalloc()
>
> Hyeonggon Yoo (12):
> mm/zsmalloc: convert __zs_map_object/__zs_unmap_object to use zpdesc
> mm/zsmalloc: add and use pfn/zpdesc seeking funcs
> mm/zsmalloc: convert obj_malloc() to use zpdesc
> mm/zsmalloc: convert obj_allocated() and related helpers to use zpdesc
> mm/zsmalloc: convert init_zspage() to use zpdesc
> mm/zsmalloc: convert obj_to_page() and zs_free() to use zpdesc
> mm/zsmalloc: add zpdesc_is_isolated/zpdesc_zone helper for
> zs_page_migrate
> mm/zsmalloc: convert __free_zspage() to use zdsesc
> mm/zsmalloc: convert location_to_obj() to take zpdesc
> mm/zsmalloc: convert migrate_zspage() to use zpdesc
> mm/zsmalloc: convert get_zspage() to take zpdesc
> mm/zsmalloc: convert get/set_first_obj_offset() to take zpdesc
>
> mm/zpdesc.h | 134 +++++++++++++++
> mm/zsmalloc.c | 454 +++++++++++++++++++++++++++-----------------------
> 2 files changed, 384 insertions(+), 204 deletions(-)
> create mode 100644 mm/zpdesc.h
>
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool
2024-06-28 7:26 ` [PATCH 00/20] mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool Alex Shi
@ 2024-06-28 7:30 ` Alex Shi
0 siblings, 0 replies; 28+ messages in thread
From: Alex Shi @ 2024-06-28 7:30 UTC (permalink / raw)
To: alexs, Vitaly Wool, Miaohe Lin, Andrew Morton, linux-kernel,
linux-mm, minchan, willy, senozhatsky, david, 42.hyeyoo
On 6/28/24 3:26 PM, Alex Shi wrote:
>
> On 6/28/24 11:11 AM, alexs@kernel.org wrote:
>> From: Alex Shi <alexs@kernel.org>
>>
>> According to Metthew's plan, the page descriptor will be replace by a 8
>> bytes mem_desc on destination purpose.
>> https://lore.kernel.org/lkml/YvV1KTyzZ+Jrtj9x@casper.infradead.org/
>>
>> Here is a implement on zsmalloc to replace page descriptor by 'zpdesc',
>> which is still overlay on struct page now. but it's a step move forward
>> above destination.
>>
>> To name the struct zpdesc instead of zsdesc, since there are still 3
>> zpools under zswap: zbud, z3fold, zsmalloc for now(z3fold maybe removed
>> soon), and we could easyly extend it to other zswap.zpool in needs.
>>
>> For all zswap.zpools, they are all using single page since often used
>> under memory pressure. So the conversion via folio series helper is
>> better than page's for compound_head check saving.
>>
>> For now, all zpools are using some page struct members, like page.flags
>> for PG_private/PG_locked. and list_head lru, page.mapping for page migration.
>>
>> This patachset could save 123Kbyetes zsmalloc.o size.
>
> This patchset is based on next/mm-unstable.
Sorry, just double checked, this patchset based on git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm mm-unstable branch. "4b17ce353e02 mm: optimization on page allocation when CMA enabled"
Thanks
Alex
>
>>
>> Thanks
>> Alex
>>
>> Alex Shi (8):
>> mm/zsmalloc: add zpdesc memory descriptor for zswap.zpool
>> mm/zsmalloc: use zpdesc in trylock_zspage/lock_zspage
>> mm/zsmalloc: convert create_page_chain() and its users to use zpdesc
>> mm/zsmalloc: rename reset_page to reset_zpdesc and use zpdesc in it
>> mm/zsmalloc: convert SetZsPageMovable and remove unused funcs
>> mm/zsmalloc: introduce __zpdesc_clear_movable
>> mm/zsmalloc: introduce __zpdesc_clear_zsmalloc
>> mm/zsmalloc: introduce __zpdesc_set_zsmalloc()
>>
>> Hyeonggon Yoo (12):
>> mm/zsmalloc: convert __zs_map_object/__zs_unmap_object to use zpdesc
>> mm/zsmalloc: add and use pfn/zpdesc seeking funcs
>> mm/zsmalloc: convert obj_malloc() to use zpdesc
>> mm/zsmalloc: convert obj_allocated() and related helpers to use zpdesc
>> mm/zsmalloc: convert init_zspage() to use zpdesc
>> mm/zsmalloc: convert obj_to_page() and zs_free() to use zpdesc
>> mm/zsmalloc: add zpdesc_is_isolated/zpdesc_zone helper for
>> zs_page_migrate
>> mm/zsmalloc: convert __free_zspage() to use zdsesc
>> mm/zsmalloc: convert location_to_obj() to take zpdesc
>> mm/zsmalloc: convert migrate_zspage() to use zpdesc
>> mm/zsmalloc: convert get_zspage() to take zpdesc
>> mm/zsmalloc: convert get/set_first_obj_offset() to take zpdesc
>>
>> mm/zpdesc.h | 134 +++++++++++++++
>> mm/zsmalloc.c | 454 +++++++++++++++++++++++++++-----------------------
>> 2 files changed, 384 insertions(+), 204 deletions(-)
>> create mode 100644 mm/zpdesc.h
>>
^ permalink raw reply [flat|nested] 28+ messages in thread