2 new /proc/vmstat fields are added, "thp_swapin" and
"thp_swapin_fallback" to count swapin a THP from swap device in one
piece and fallback to normal page swapin.

Signed-off-by: "Huang, Ying" <ying.hu...@intel.com>
Cc: "Kirill A. Shutemov" <kirill.shute...@linux.intel.com>
Cc: Andrea Arcangeli <aarca...@redhat.com>
Cc: Michal Hocko <mho...@kernel.org>
Cc: Johannes Weiner <han...@cmpxchg.org>
Cc: Shaohua Li <s...@kernel.org>
Cc: Hugh Dickins <hu...@google.com>
Cc: Minchan Kim <minc...@kernel.org>
Cc: Rik van Riel <r...@redhat.com>
Cc: Dave Hansen <dave.han...@linux.intel.com>
Cc: Naoya Horiguchi <n-horigu...@ah.jp.nec.com>
Cc: Zi Yan <zi....@cs.rutgers.edu>
Cc: Daniel Jordan <daniel.m.jor...@oracle.com>
---
 Documentation/admin-guide/mm/transhuge.rst |  8 ++++++++
 include/linux/vm_event_item.h              |  2 ++
 mm/huge_memory.c                           |  4 +++-
 mm/page_io.c                               | 15 ++++++++++++---
 mm/vmstat.c                                |  2 ++
 5 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/Documentation/admin-guide/mm/transhuge.rst 
b/Documentation/admin-guide/mm/transhuge.rst
index 7ab93a8404b9..85e33f785fd7 100644
--- a/Documentation/admin-guide/mm/transhuge.rst
+++ b/Documentation/admin-guide/mm/transhuge.rst
@@ -364,6 +364,14 @@ thp_swpout_fallback
        Usually because failed to allocate some continuous swap space
        for the huge page.
 
+thp_swpin
+       is incremented every time a huge page is swapin in one piece
+       without splitting.
+
+thp_swpin_fallback
+       is incremented if a huge page has to be split during swapin.
+       Usually because failed to allocate a huge page.
+
 As the system ages, allocating huge pages may be expensive as the
 system uses memory compaction to copy data around memory to free a
 huge page for use. There are some counters in ``/proc/vmstat`` to help
diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
index 47a3441cf4c4..c20b655cfdcc 100644
--- a/include/linux/vm_event_item.h
+++ b/include/linux/vm_event_item.h
@@ -88,6 +88,8 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
                THP_ZERO_PAGE_ALLOC_FAILED,
                THP_SWPOUT,
                THP_SWPOUT_FALLBACK,
+               THP_SWPIN,
+               THP_SWPIN_FALLBACK,
 #endif
 #ifdef CONFIG_MEMORY_BALLOON
                BALLOON_INFLATE,
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 561f3fb3d888..d3ee25ffeaaf 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1724,8 +1724,10 @@ int do_huge_pmd_swap_page(struct vm_fault *vmf, pmd_t 
orig_pmd)
                                /* swapoff occurs under us */
                                } else if (ret == -EINVAL)
                                        ret = 0;
-                               else
+                               else {
+                                       count_vm_event(THP_SWPIN_FALLBACK);
                                        goto fallback;
+                               }
                        }
                        delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
                        goto out;
diff --git a/mm/page_io.c b/mm/page_io.c
index d4d1c89bcddd..8fd1f3ef83c4 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -348,6 +348,15 @@ int __swap_writepage(struct page *page, struct 
writeback_control *wbc,
        return ret;
 }
 
+static inline void count_swpin_vm_event(struct page *page)
+{
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+       if (unlikely(PageTransHuge(page)))
+               count_vm_event(THP_SWPIN);
+#endif
+       count_vm_events(PSWPIN, hpage_nr_pages(page));
+}
+
 int swap_readpage(struct page *page, bool synchronous)
 {
        struct bio *bio;
@@ -371,7 +380,7 @@ int swap_readpage(struct page *page, bool synchronous)
 
                ret = mapping->a_ops->readpage(swap_file, page);
                if (!ret)
-                       count_vm_event(PSWPIN);
+                       count_swpin_vm_event(page);
                return ret;
        }
 
@@ -382,7 +391,7 @@ int swap_readpage(struct page *page, bool synchronous)
                        unlock_page(page);
                }
 
-               count_vm_event(PSWPIN);
+               count_swpin_vm_event(page);
                return 0;
        }
 
@@ -401,7 +410,7 @@ int swap_readpage(struct page *page, bool synchronous)
        get_task_struct(current);
        bio->bi_private = current;
        bio_set_op_attrs(bio, REQ_OP_READ, 0);
-       count_vm_event(PSWPIN);
+       count_swpin_vm_event(page);
        bio_get(bio);
        qc = submit_bio(bio);
        while (synchronous) {
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 83b30edc2f7f..80a731e9a5e5 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1265,6 +1265,8 @@ const char * const vmstat_text[] = {
        "thp_zero_page_alloc_failed",
        "thp_swpout",
        "thp_swpout_fallback",
+       "thp_swpin",
+       "thp_swpin_fallback",
 #endif
 #ifdef CONFIG_MEMORY_BALLOON
        "balloon_inflate",
-- 
2.18.1

Reply via email to