summaryrefslogtreecommitdiffstats
path: root/mm/page_io.c
diff options
context:
space:
mode:
authorMinchan Kim <minchan@kernel.org>2016-03-22 17:24:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-22 18:36:02 -0400
commit3f2b1a04f44933f2d6fe0a9bf9a9c1c452df23f7 (patch)
tree611d0d78edba650d2f56764d69b2924300e004d7 /mm/page_io.c
parentd750c42ac265c00df3f0963a240a4440fa073603 (diff)
zram: revive swap_slot_free_notify
Commit b430e9d1c6d4 ("remove compressed copy from zram in-memory") applied swap_slot_free_notify call in *end_swap_bio_read* to remove duplicated memory between zram and memory. However, with the introduction of rw_page in zram: 8c7f01025f7b ("zram: implement rw_page operation of zram"), it became void because rw_page doesn't need bio. Memory footprint is really important in embedded platforms which have small memory, for example, 512M) recently because it could start to kill processes if memory footprint exceeds some threshold by LMK or some similar memory management modules. This patch restores the function for rw_page, thereby eliminating this duplication. Signed-off-by: Minchan Kim <minchan@kernel.org> Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Cc: karam.lee <karam.lee@lge.com> Cc: <sangseok.lee@lge.com> Cc: Chan Jeong <chan.jeong@lge.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_io.c')
-rw-r--r--mm/page_io.c93
1 files changed, 50 insertions, 43 deletions
diff --git a/mm/page_io.c b/mm/page_io.c
index ff74e512f029..18aac7819cc9 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -66,6 +66,54 @@ void end_swap_bio_write(struct bio *bio)
66 bio_put(bio); 66 bio_put(bio);
67} 67}
68 68
69static void swap_slot_free_notify(struct page *page)
70{
71 struct swap_info_struct *sis;
72 struct gendisk *disk;
73
74 /*
75 * There is no guarantee that the page is in swap cache - the software
76 * suspend code (at least) uses end_swap_bio_read() against a non-
77 * swapcache page. So we must check PG_swapcache before proceeding with
78 * this optimization.
79 */
80 if (unlikely(!PageSwapCache(page)))
81 return;
82
83 sis = page_swap_info(page);
84 if (!(sis->flags & SWP_BLKDEV))
85 return;
86
87 /*
88 * The swap subsystem performs lazy swap slot freeing,
89 * expecting that the page will be swapped out again.
90 * So we can avoid an unnecessary write if the page
91 * isn't redirtied.
92 * This is good for real swap storage because we can
93 * reduce unnecessary I/O and enhance wear-leveling
94 * if an SSD is used as the as swap device.
95 * But if in-memory swap device (eg zram) is used,
96 * this causes a duplicated copy between uncompressed
97 * data in VM-owned memory and compressed data in
98 * zram-owned memory. So let's free zram-owned memory
99 * and make the VM-owned decompressed page *dirty*,
100 * so the page should be swapped out somewhere again if
101 * we again wish to reclaim it.
102 */
103 disk = sis->bdev->bd_disk;
104 if (disk->fops->swap_slot_free_notify) {
105 swp_entry_t entry;
106 unsigned long offset;
107
108 entry.val = page_private(page);
109 offset = swp_offset(entry);
110
111 SetPageDirty(page);
112 disk->fops->swap_slot_free_notify(sis->bdev,
113 offset);
114 }
115}
116
69static void end_swap_bio_read(struct bio *bio) 117static void end_swap_bio_read(struct bio *bio)
70{ 118{
71 struct page *page = bio->bi_io_vec[0].bv_page; 119 struct page *page = bio->bi_io_vec[0].bv_page;
@@ -81,49 +129,7 @@ static void end_swap_bio_read(struct bio *bio)
81 } 129 }
82 130
83 SetPageUptodate(page); 131 SetPageUptodate(page);
84 132 swap_slot_free_notify(page);
85 /*
86 * There is no guarantee that the page is in swap cache - the software
87 * suspend code (at least) uses end_swap_bio_read() against a non-
88 * swapcache page. So we must check PG_swapcache before proceeding with
89 * this optimization.
90 */
91 if (likely(PageSwapCache(page))) {
92 struct swap_info_struct *sis;
93
94 sis = page_swap_info(page);
95 if (sis->flags & SWP_BLKDEV) {
96 /*
97 * The swap subsystem performs lazy swap slot freeing,
98 * expecting that the page will be swapped out again.
99 * So we can avoid an unnecessary write if the page
100 * isn't redirtied.
101 * This is good for real swap storage because we can
102 * reduce unnecessary I/O and enhance wear-leveling
103 * if an SSD is used as the as swap device.
104 * But if in-memory swap device (eg zram) is used,
105 * this causes a duplicated copy between uncompressed
106 * data in VM-owned memory and compressed data in
107 * zram-owned memory. So let's free zram-owned memory
108 * and make the VM-owned decompressed page *dirty*,
109 * so the page should be swapped out somewhere again if
110 * we again wish to reclaim it.
111 */
112 struct gendisk *disk = sis->bdev->bd_disk;
113 if (disk->fops->swap_slot_free_notify) {
114 swp_entry_t entry;
115 unsigned long offset;
116
117 entry.val = page_private(page);
118 offset = swp_offset(entry);
119
120 SetPageDirty(page);
121 disk->fops->swap_slot_free_notify(sis->bdev,
122 offset);
123 }
124 }
125 }
126
127out: 133out:
128 unlock_page(page); 134 unlock_page(page);
129 bio_put(bio); 135 bio_put(bio);
@@ -347,6 +353,7 @@ int swap_readpage(struct page *page)
347 353
348 ret = bdev_read_page(sis->bdev, swap_page_sector(page), page); 354 ret = bdev_read_page(sis->bdev, swap_page_sector(page), page);
349 if (!ret) { 355 if (!ret) {
356 swap_slot_free_notify(page);
350 count_vm_event(PSWPIN); 357 count_vm_event(PSWPIN);
351 return 0; 358 return 0;
352 } 359 }