Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1467478 > unrolled thread

[RFC 0/4] ZRAM: make it just store the high compression rate page

Started byHui Zhu <zhuhui@xiaomi.com>
First post2016-08-22 10:50 +0200
Last post2016-08-25 10:30 +0200
Articles 6 — 4 participants

Back to article view | Back to linux.kernel


Contents

  [RFC 0/4] ZRAM: make it just store the high compression rate page Hui Zhu <zhuhui@xiaomi.com> - 2016-08-22 10:50 +0200
    [RFC 4/4] vmscan.c: zram: add non swap support for shmem file pages Hui Zhu <zhuhui@xiaomi.com> - 2016-08-22 10:50 +0200
    Re: [RFC 0/4] ZRAM: make it just store the high compression rate page Minchan Kim <minchan@kernel.org> - 2016-08-24 03:10 +0200
      Re: [RFC 0/4] ZRAM: make it just store the high compression rate page Hui Zhu <teawater@gmail.com> - 2016-08-24 04:00 +0200
    Re: [RFC 0/4] ZRAM: make it just store the high compression rate page Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com> - 2016-08-25 08:20 +0200
      Re: [RFC 0/4] ZRAM: make it just store the high compression rate page Hui Zhu <teawater@gmail.com> - 2016-08-25 10:30 +0200

#1467478 — [RFC 0/4] ZRAM: make it just store the high compression rate page

FromHui Zhu <zhuhui@xiaomi.com>
Date2016-08-22 10:50 +0200
Subject[RFC 0/4] ZRAM: make it just store the high compression rate page
Message-ID<s8T5D-3Zg-11@gated-at.bofh.it>
Current ZRAM just can store all pages even if the compression rate
of a page is really low.  So the compression rate of ZRAM is out of
control when it is running.
In my part, I did some test and record with ZRAM.  The compression rate
is about 40%.

This series of patches make ZRAM can just store the page that the
compressed size is smaller than a value.
With these patches, I set the value to 2048 and did the same test with
before.  The compression rate is about 20%.  The times of lowmemorykiller
also decreased.

Hui Zhu (4):
vmscan.c: shrink_page_list: unmap anon pages after pageout
Add non-swap page flag to mark a page will not swap
ZRAM: do not swap the pages that compressed size bigger than non_swap
vmscan.c: zram: add non swap support for shmem file pages

 drivers/block/zram/Kconfig     |   11 +++
 drivers/block/zram/zram_drv.c  |   38 +++++++++++
 drivers/block/zram/zram_drv.h  |    4 +
 fs/proc/meminfo.c              |    6 +
 include/linux/mm_inline.h      |   20 +++++
 include/linux/mmzone.h         |    3 
 include/linux/page-flags.h     |    8 ++
 include/linux/rmap.h           |    5 +
 include/linux/shmem_fs.h       |    6 +
 include/trace/events/mmflags.h |    9 ++
 kernel/events/uprobes.c        |   16 ++++
 mm/Kconfig                     |    9 ++
 mm/memory.c                    |   34 ++++++++++
 mm/migrate.c                   |    4 +
 mm/mprotect.c                  |    8 ++
 mm/page_io.c                   |   11 ++-
 mm/rmap.c                      |   23 ++++++
 mm/shmem.c                     |   77 +++++++++++++++++-----
 mm/vmscan.c                    |  139 +++++++++++++++++++++++++++++++++++------
 19 files changed, 387 insertions(+), 44 deletions(-)

[toc] | [next] | [standalone]


#1467480 — [RFC 4/4] vmscan.c: zram: add non swap support for shmem file pages

FromHui Zhu <zhuhui@xiaomi.com>
Date2016-08-22 10:50 +0200
Subject[RFC 4/4] vmscan.c: zram: add non swap support for shmem file pages
Message-ID<s8T5E-3Zg-37@gated-at.bofh.it>
In reply to#1467478
This patch add the whole support for shmem file pages non swap.
To make sure a page is shmem file page, check mapping->a_ops == &shmem_aops.
I think it is really a hack way.

There are not a lot of shmem file pages will be swapped out.

Signed-off-by: Hui Zhu <zhuhui@xiaomi.com>
---
 drivers/block/zram/zram_drv.c |  3 +-
 include/linux/shmem_fs.h      |  6 ++++
 mm/page_io.c                  |  2 +-
 mm/rmap.c                     |  5 ---
 mm/shmem.c                    | 77 ++++++++++++++++++++++++++++++++++---------
 mm/vmscan.c                   | 27 +++++++++++----
 6 files changed, 89 insertions(+), 31 deletions(-)

diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 8f7f1ec..914c096 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -715,8 +715,7 @@ compress_again:
 	}
 
 #ifdef CONFIG_ZRAM_NON_SWAP
-	if (!is_partial_io(bvec) && PageAnon(page) &&
-	    zram->non_swap && clen > zram->non_swap) {
+	if (!is_partial_io(bvec) && zram->non_swap && clen > zram->non_swap) {
 		ret = 0;
 		SetPageNonSwap(page);
 		goto out;
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index ff078e7..fd44473 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -124,4 +124,10 @@ static inline bool shmem_huge_enabled(struct vm_area_struct *vma)
 }
 #endif
 
+extern const struct address_space_operations shmem_aops;
+
+#ifdef CONFIG_LATE_UNMAP
+extern void shmem_page_unmap(struct page *page);
+#endif
+
 #endif
diff --git a/mm/page_io.c b/mm/page_io.c
index adaf801..5fd3069 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -238,7 +238,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc)
 	int ret = 0;
 
 #ifdef CONFIG_LATE_UNMAP
-	if (!(PageAnon(page) && page_mapped(page)))
+	if (!page_mapped(page))
 #endif
 		if (try_to_free_swap(page)) {
 			unlock_page(page);
diff --git a/mm/rmap.c b/mm/rmap.c
index d484f95..418f731 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1490,13 +1490,8 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
 
 #ifdef CONFIG_LATE_UNMAP
 	if ((flags & TTU_CHECK_DIRTY) || (flags & TTU_READONLY)) {
-		BUG_ON(!PageAnon(page));
-
 		pteval = *pte;
 
-		BUG_ON(pte_write(pteval) &&
-		       page_mapcount(page) + page_swapcount(page) > 1);
-
 		if ((flags & TTU_CHECK_DIRTY) && pte_dirty(pteval)) {
 			set_page_dirty(page);
 			pteval = pte_mkclean(pteval);
diff --git a/mm/shmem.c b/mm/shmem.c
index fd8b2b5..556d853 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -182,7 +182,6 @@ static inline void shmem_unacct_blocks(unsigned long flags, long pages)
 }
 
 static const struct super_operations shmem_ops;
-static const struct address_space_operations shmem_aops;
 static const struct file_operations shmem_file_operations;
 static const struct inode_operations shmem_inode_operations;
 static const struct inode_operations shmem_dir_inode_operations;
@@ -1178,6 +1177,55 @@ out:
 	return error;
 }
 
+#define SHMEM_WRITEPAGE_LOCK				\
+	do {						\
+		mutex_lock(&shmem_swaplist_mutex);	\
+		if (list_empty(&info->swaplist))	\
+			list_add_tail(&info->swaplist,	\
+				      &shmem_swaplist);	\
+	} while (0)
+
+#define SHMEM_WRITEPAGE_SWAP						\
+	do {								\
+		spin_lock(&info->lock);					\
+		shmem_recalc_inode(inode);				\
+		info->swapped++;					\
+		spin_unlock(&info->lock);				\
+		swap_shmem_alloc(swap);					\
+		shmem_delete_from_page_cache(page,			\
+					     swp_to_radix_entry(swap));	\
+	} while (0)
+
+#define SHMEM_WRITEPAGE_UNLOCK				\
+	do {						\
+		mutex_unlock(&shmem_swaplist_mutex);	\
+	} while (0)
+
+#define SHMEM_WRITEPAGE_BUG_ON				\
+	do {						\
+		BUG_ON(page_mapped(page));		\
+	} while (0)
+
+#ifdef CONFIG_LATE_UNMAP
+void
+shmem_page_unmap(struct page *page)
+{
+	struct shmem_inode_info *info;
+	struct address_space *mapping;
+	struct inode *inode;
+	swp_entry_t swap = { .val = page_private(page) };
+
+	mapping = page->mapping;
+	inode = mapping->host;
+	info = SHMEM_I(inode);
+
+	SHMEM_WRITEPAGE_LOCK;
+	SHMEM_WRITEPAGE_SWAP;
+	SHMEM_WRITEPAGE_UNLOCK;
+	SHMEM_WRITEPAGE_BUG_ON;
+}
+#endif
+
 /*
  * Move the page from the page cache to the swap cache.
  */
@@ -1259,26 +1307,23 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
 	 * we've incremented swapped, because shmem_unuse_inode() will
 	 * prune a !swapped inode from the swaplist under this mutex.
 	 */
-	mutex_lock(&shmem_swaplist_mutex);
-	if (list_empty(&info->swaplist))
-		list_add_tail(&info->swaplist, &shmem_swaplist);
+#ifndef CONFIG_LATE_UNMAP
+	SHMEM_WRITEPAGE_LOCK;
+#endif
 
 	if (add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) {
-		spin_lock_irq(&info->lock);
-		shmem_recalc_inode(inode);
-		info->swapped++;
-		spin_unlock_irq(&info->lock);
-
-		swap_shmem_alloc(swap);
-		shmem_delete_from_page_cache(page, swp_to_radix_entry(swap));
-
-		mutex_unlock(&shmem_swaplist_mutex);
-		BUG_ON(page_mapped(page));
+#ifndef CONFIG_LATE_UNMAP
+		SHMEM_WRITEPAGE_SWAP;
+		SHMEM_WRITEPAGE_UNLOCK;
+		SHMEM_WRITEPAGE_BUG_ON;
+#endif
 		swap_writepage(page, wbc);
 		return 0;
 	}
 
-	mutex_unlock(&shmem_swaplist_mutex);
+#ifndef CONFIG_LATE_UNMAP
+	SHMEM_WRITEPAGE_UNLOCK;
+#endif
 free_swap:
 	swapcache_free(swap);
 redirty:
@@ -3764,7 +3809,7 @@ static void shmem_destroy_inodecache(void)
 	kmem_cache_destroy(shmem_inode_cachep);
 }
 
-static const struct address_space_operations shmem_aops = {
+const struct address_space_operations shmem_aops = {
 	.writepage	= shmem_writepage,
 	.set_page_dirty	= __set_page_dirty_no_writeback,
 #ifdef CONFIG_TMPFS
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 14d49cd..effb6c4 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -54,6 +54,8 @@
 #include <linux/swapops.h>
 #include <linux/balloon_compaction.h>
 
+#include <linux/shmem_fs.h>
+
 #include "internal.h"
 
 #define CREATE_TRACE_POINTS
@@ -492,12 +494,13 @@ void drop_slab(void)
 		drop_slab_node(nid);
 }
 
-static inline int is_page_cache_freeable(struct page *page)
+static inline int is_page_cache_freeable(struct page *page,
+					 struct address_space *mapping)
 {
 	int count = page_count(page) - page_has_private(page);
 
 #ifdef CONFIG_LATE_UNMAP
-	if (PageAnon(page))
+	if (PageAnon(page) || (mapping && mapping->a_ops == &shmem_aops))
 		count -= page_mapcount(page);
 #endif
 
@@ -576,7 +579,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping,
 	 * swap_backing_dev_info is bust: it doesn't reflect the
 	 * congestion state of the swapdevs.  Easy to fix, if needed.
 	 */
-	if (!is_page_cache_freeable(page))
+	if (!is_page_cache_freeable(page, mapping))
 		return PAGE_KEEP;
 	if (!mapping) {
 		/*
@@ -972,7 +975,7 @@ static unsigned long shrink_page_list(struct list_head *page_list,
 		struct page *page;
 		int may_enter_fs;
 		enum page_references references = PAGEREF_RECLAIM_CLEAN;
-		bool dirty, writeback, anon;
+		bool dirty, writeback, anon, late_unmap;
 		bool lazyfree = false;
 		int ret = SWAP_SUCCESS;
 
@@ -1109,6 +1112,10 @@ static unsigned long shrink_page_list(struct list_head *page_list,
 		}
 
 		anon = PageAnon(page);
+		if (anon)
+			late_unmap = true;
+		else
+			late_unmap = false;
 
 		/*
 		 * Anonymous process memory has backing store?
@@ -1144,13 +1151,16 @@ static unsigned long shrink_page_list(struct list_head *page_list,
 			enum ttu_flags l_ttu_flags = ttu_flags;
 
 #ifdef CONFIG_LATE_UNMAP
+			if (mapping->a_ops == &shmem_aops)
+				late_unmap = true;
+
 			/* Hanle the pte_dirty
 			   and change pte to readonly.
 			   Write behavior before unmap will make
 			   pte dirty again.  Then we can check
 			   pte_dirty before unmap to make sure
 			   the page was written or not.  */
-			if (anon)
+			if (late_unmap)
 				l_ttu_flags |= TTU_CHECK_DIRTY | TTU_READONLY;
 #endif
 			TRY_TO_UNMAP(page, l_ttu_flags);
@@ -1211,7 +1221,7 @@ static unsigned long shrink_page_list(struct list_head *page_list,
 					goto keep_locked;
 
 #ifdef CONFIG_LATE_UNMAP
-				if (anon) {
+				if (late_unmap) {
 					if (!PageSwapCache(page))
 						goto keep_locked;
 
@@ -1231,8 +1241,11 @@ static unsigned long shrink_page_list(struct list_head *page_list,
 					}
 #endif
 
-					if (page_mapped(page) && mapping)
+					if (page_mapped(page) && mapping) {
 						TRY_TO_UNMAP(page, ttu_flags);
+						if (!anon)
+							shmem_page_unmap(page);
+					}
 				}
 #endif
 
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1469002

FromMinchan Kim <minchan@kernel.org>
Date2016-08-24 03:10 +0200
Message-ID<s9uRz-3sv-7@gated-at.bofh.it>
In reply to#1467478
Hi Hui,

On Mon, Aug 22, 2016 at 04:25:05PM +0800, Hui Zhu wrote:
> Current ZRAM just can store all pages even if the compression rate
> of a page is really low.  So the compression rate of ZRAM is out of
> control when it is running.
> In my part, I did some test and record with ZRAM.  The compression rate
> is about 40%.
> 
> This series of patches make ZRAM can just store the page that the
> compressed size is smaller than a value.
> With these patches, I set the value to 2048 and did the same test with
> before.  The compression rate is about 20%.  The times of lowmemorykiller
> also decreased.

I have an interest about the feature for a long time but didn't work on it
because I didn't have a good idea to implment it with generic approach
without layer violation. I will look into this after handling urgent works.

Thanks.

[toc] | [prev] | [next] | [standalone]


#1469021

FromHui Zhu <teawater@gmail.com>
Date2016-08-24 04:00 +0200
Message-ID<s9vDX-3Ld-1@gated-at.bofh.it>
In reply to#1469002
Hi Minchan,

On Wed, Aug 24, 2016 at 9:04 AM, Minchan Kim <minchan@kernel.org> wrote:
> Hi Hui,
>
> On Mon, Aug 22, 2016 at 04:25:05PM +0800, Hui Zhu wrote:
>> Current ZRAM just can store all pages even if the compression rate
>> of a page is really low.  So the compression rate of ZRAM is out of
>> control when it is running.
>> In my part, I did some test and record with ZRAM.  The compression rate
>> is about 40%.
>>
>> This series of patches make ZRAM can just store the page that the
>> compressed size is smaller than a value.
>> With these patches, I set the value to 2048 and did the same test with
>> before.  The compression rate is about 20%.  The times of lowmemorykiller
>> also decreased.
>
> I have an interest about the feature for a long time but didn't work on it
> because I didn't have a good idea to implment it with generic approach
> without layer violation. I will look into this after handling urgent works.
>
> Thanks.

That will be great.  Thanks.

Best,
Hui

[toc] | [prev] | [next] | [standalone]


#1469861

FromSergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
Date2016-08-25 08:20 +0200
Message-ID<s9Wb7-5Ex-5@gated-at.bofh.it>
In reply to#1467478
Hello,

On (08/22/16 16:25), Hui Zhu wrote:
> 
> Current ZRAM just can store all pages even if the compression rate
> of a page is really low.  So the compression rate of ZRAM is out of
> control when it is running.
> In my part, I did some test and record with ZRAM.  The compression rate
> is about 40%.
> 
> This series of patches make ZRAM can just store the page that the
> compressed size is smaller than a value.
> With these patches, I set the value to 2048 and did the same test with
> before.  The compression rate is about 20%.  The times of lowmemorykiller
> also decreased.

I haven't looked at the patches in details yet. can you educate me a bit?
is your test stable? why the number of lowmemorykill-s has decreased?
... or am reading "The times of lowmemorykiller also decreased" wrong?

suppose you have X pages that result in bad compression size (from zram
point of view). zram stores such pages uncompressed, IOW we have no memory
savings - swapped out page lands in zsmalloc PAGE_SIZE class. now you
don't try to store those pages in zsmalloc, but keep them as unevictable.
so the page still occupies PAGE_SIZE; no memory saving again. why did it
improve LMK?

	-ss

[toc] | [prev] | [next] | [standalone]


#1469958

FromHui Zhu <teawater@gmail.com>
Date2016-08-25 10:30 +0200
Message-ID<s9YcW-6Yd-7@gated-at.bofh.it>
In reply to#1469861
On Thu, Aug 25, 2016 at 2:09 PM, Sergey Senozhatsky
<sergey.senozhatsky.work@gmail.com> wrote:
> Hello,
>
> On (08/22/16 16:25), Hui Zhu wrote:
>>
>> Current ZRAM just can store all pages even if the compression rate
>> of a page is really low.  So the compression rate of ZRAM is out of
>> control when it is running.
>> In my part, I did some test and record with ZRAM.  The compression rate
>> is about 40%.
>>
>> This series of patches make ZRAM can just store the page that the
>> compressed size is smaller than a value.
>> With these patches, I set the value to 2048 and did the same test with
>> before.  The compression rate is about 20%.  The times of lowmemorykiller
>> also decreased.
>
> I haven't looked at the patches in details yet. can you educate me a bit?
> is your test stable? why the number of lowmemorykill-s has decreased?
> ... or am reading "The times of lowmemorykiller also decreased" wrong?
>
> suppose you have X pages that result in bad compression size (from zram
> point of view). zram stores such pages uncompressed, IOW we have no memory
> savings - swapped out page lands in zsmalloc PAGE_SIZE class. now you
> don't try to store those pages in zsmalloc, but keep them as unevictable.
> so the page still occupies PAGE_SIZE; no memory saving again. why did it
> improve LMK?

No, zram will not save this page uncompressed with these patches.  It
will set it as non-swap and kick back to shrink_page_list.
Shrink_page_list will remove this page from swapcache and kick it to
unevictable list.
Then this page will not be swaped before it get write.
That is why most of code are around vmscan.c.

Thanks,
Hui

>
>         -ss

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web