Commit 225311a4 authored by Huang Ying's avatar Huang Ying Committed by Linus Torvalds

mm: test code to write THP to swap device as a whole

To support delay splitting THP (Transparent Huge Page) after swapped
out, we need to enhance swap writing code to support to write a THP as a
whole.  This will improve swap write IO performance.

As Ming Lei <ming.lei@redhat.com> pointed out, this should be based on
multipage bvec support, which hasn't been merged yet.  So this patch is
only for testing the functionality of the other patches in the series.
And will be reimplemented after multipage bvec support is merged.

Link: http://lkml.kernel.org/r/20170724051840.2309-7-ying.huang@intel.comSigned-off-by: default avatar"Huang, Ying" <ying.huang@intel.com>
Cc: "Kirill A . Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: Ross Zwisler <ross.zwisler@intel.com> [for brd.c, zram_drv.c, pmem.c]
Cc: Shaohua Li <shli@kernel.org>
Cc: Vishal L Verma <vishal.l.verma@intel.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 98cc093c
...@@ -38,7 +38,15 @@ ...@@ -38,7 +38,15 @@
#define BIO_BUG_ON #define BIO_BUG_ON
#endif #endif
#ifdef CONFIG_THP_SWAP
#if HPAGE_PMD_NR > 256
#define BIO_MAX_PAGES HPAGE_PMD_NR
#else
#define BIO_MAX_PAGES 256 #define BIO_MAX_PAGES 256
#endif
#else
#define BIO_MAX_PAGES 256
#endif
#define bio_prio(bio) (bio)->bi_ioprio #define bio_prio(bio) (bio)->bi_ioprio
#define bio_set_prio(bio, prio) ((bio)->bi_ioprio = prio) #define bio_set_prio(bio, prio) ((bio)->bi_ioprio = prio)
......
...@@ -303,8 +303,8 @@ PAGEFLAG(OwnerPriv1, owner_priv_1, PF_ANY) ...@@ -303,8 +303,8 @@ PAGEFLAG(OwnerPriv1, owner_priv_1, PF_ANY)
* Only test-and-set exist for PG_writeback. The unconditional operators are * Only test-and-set exist for PG_writeback. The unconditional operators are
* risky: they bypass page accounting. * risky: they bypass page accounting.
*/ */
TESTPAGEFLAG(Writeback, writeback, PF_NO_COMPOUND) TESTPAGEFLAG(Writeback, writeback, PF_NO_TAIL)
TESTSCFLAG(Writeback, writeback, PF_NO_COMPOUND) TESTSCFLAG(Writeback, writeback, PF_NO_TAIL)
PAGEFLAG(MappedToDisk, mappedtodisk, PF_NO_TAIL) PAGEFLAG(MappedToDisk, mappedtodisk, PF_NO_TAIL)
/* PG_readahead is only used for reads; PG_reclaim is only for writes */ /* PG_readahead is only used for reads; PG_reclaim is only for writes */
......
...@@ -85,6 +85,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT, ...@@ -85,6 +85,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
#endif #endif
THP_ZERO_PAGE_ALLOC, THP_ZERO_PAGE_ALLOC,
THP_ZERO_PAGE_ALLOC_FAILED, THP_ZERO_PAGE_ALLOC_FAILED,
THP_SWPOUT,
#endif #endif
#ifdef CONFIG_MEMORY_BALLOON #ifdef CONFIG_MEMORY_BALLOON
BALLOON_INFLATE, BALLOON_INFLATE,
......
...@@ -28,16 +28,18 @@ ...@@ -28,16 +28,18 @@
static struct bio *get_swap_bio(gfp_t gfp_flags, static struct bio *get_swap_bio(gfp_t gfp_flags,
struct page *page, bio_end_io_t end_io) struct page *page, bio_end_io_t end_io)
{ {
int i, nr = hpage_nr_pages(page);
struct bio *bio; struct bio *bio;
bio = bio_alloc(gfp_flags, 1); bio = bio_alloc(gfp_flags, nr);
if (bio) { if (bio) {
bio->bi_iter.bi_sector = map_swap_page(page, &bio->bi_bdev); bio->bi_iter.bi_sector = map_swap_page(page, &bio->bi_bdev);
bio->bi_iter.bi_sector <<= PAGE_SHIFT - 9; bio->bi_iter.bi_sector <<= PAGE_SHIFT - 9;
bio->bi_end_io = end_io; bio->bi_end_io = end_io;
bio_add_page(bio, page, PAGE_SIZE, 0); for (i = 0; i < nr; i++)
BUG_ON(bio->bi_iter.bi_size != PAGE_SIZE); bio_add_page(bio, page + i, PAGE_SIZE, 0);
VM_BUG_ON(bio->bi_iter.bi_size != PAGE_SIZE * nr);
} }
return bio; return bio;
} }
...@@ -262,6 +264,15 @@ static sector_t swap_page_sector(struct page *page) ...@@ -262,6 +264,15 @@ static sector_t swap_page_sector(struct page *page)
return (sector_t)__page_file_index(page) << (PAGE_SHIFT - 9); return (sector_t)__page_file_index(page) << (PAGE_SHIFT - 9);
} }
static inline void count_swpout_vm_event(struct page *page)
{
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
if (unlikely(PageTransHuge(page)))
count_vm_event(THP_SWPOUT);
#endif
count_vm_events(PSWPOUT, hpage_nr_pages(page));
}
int __swap_writepage(struct page *page, struct writeback_control *wbc, int __swap_writepage(struct page *page, struct writeback_control *wbc,
bio_end_io_t end_write_func) bio_end_io_t end_write_func)
{ {
...@@ -313,7 +324,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc, ...@@ -313,7 +324,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
ret = bdev_write_page(sis->bdev, swap_page_sector(page), page, wbc); ret = bdev_write_page(sis->bdev, swap_page_sector(page), page, wbc);
if (!ret) { if (!ret) {
count_vm_event(PSWPOUT); count_swpout_vm_event(page);
return 0; return 0;
} }
...@@ -326,7 +337,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc, ...@@ -326,7 +337,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
goto out; goto out;
} }
bio->bi_opf = REQ_OP_WRITE | wbc_to_write_flags(wbc); bio->bi_opf = REQ_OP_WRITE | wbc_to_write_flags(wbc);
count_vm_event(PSWPOUT); count_swpout_vm_event(page);
set_page_writeback(page); set_page_writeback(page);
unlock_page(page); unlock_page(page);
submit_bio(bio); submit_bio(bio);
......
...@@ -1071,6 +1071,7 @@ const char * const vmstat_text[] = { ...@@ -1071,6 +1071,7 @@ const char * const vmstat_text[] = {
#endif #endif
"thp_zero_page_alloc", "thp_zero_page_alloc",
"thp_zero_page_alloc_failed", "thp_zero_page_alloc_failed",
"thp_swpout",
#endif #endif
#ifdef CONFIG_MEMORY_BALLOON #ifdef CONFIG_MEMORY_BALLOON
"balloon_inflate", "balloon_inflate",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment