summaryrefslogtreecommitdiffstats
path: root/mm/swapfile.c
diff options
context:
space:
mode:
authorTim Chen <tim.c.chen@linux.intel.com>2017-02-22 18:45:29 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-22 19:41:30 -0500
commite8c26ab60598558ec3a626e7925b06e7417d7710 (patch)
tree7c4c14cea8fed4f82e56c5e4de89109cd642c0bc /mm/swapfile.c
parent4b3ef9daa4fc0bba742a79faecb17fdaaead083b (diff)
mm/swap: skip readahead for unreferenced swap slots
We can avoid needlessly allocating page for swap slots that are not used by anyone. No pages have to be read in for these slots. Link: http://lkml.kernel.org/r/0784b3f20b9bd3aa5552219624cb78dc4ae710c9.1484082593.git.tim.c.chen@linux.intel.com Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com> Signed-off-by: "Huang, Ying" <ying.huang@intel.com> Cc: Aaron Lu <aaron.lu@intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Christian Borntraeger <borntraeger@de.ibm.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Hillf Danton <hillf.zj@alibaba-inc.com> Cc: Huang Ying <ying.huang@intel.com> Cc: Hugh Dickins <hughd@google.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Jonathan Corbet <corbet@lwn.net> escreveu: Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Michal Hocko <mhocko@kernel.org> Cc: Minchan Kim <minchan@kernel.org> Cc: Rik van Riel <riel@redhat.com> Cc: Shaohua Li <shli@kernel.org> Cc: Vladimir Davydov <vdavydov.dev@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r--mm/swapfile.c47
1 files changed, 41 insertions, 6 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 66e95eb73040..7e888de35c41 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -798,7 +798,7 @@ swp_entry_t get_swap_page_of_type(int type)
798 return (swp_entry_t) {0}; 798 return (swp_entry_t) {0};
799} 799}
800 800
801static struct swap_info_struct *_swap_info_get(swp_entry_t entry) 801static struct swap_info_struct *__swap_info_get(swp_entry_t entry)
802{ 802{
803 struct swap_info_struct *p; 803 struct swap_info_struct *p;
804 unsigned long offset, type; 804 unsigned long offset, type;
@@ -814,13 +814,8 @@ static struct swap_info_struct *_swap_info_get(swp_entry_t entry)
814 offset = swp_offset(entry); 814 offset = swp_offset(entry);
815 if (offset >= p->max) 815 if (offset >= p->max)
816 goto bad_offset; 816 goto bad_offset;
817 if (!p->swap_map[offset])
818 goto bad_free;
819 return p; 817 return p;
820 818
821bad_free:
822 pr_err("swap_info_get: %s%08lx\n", Unused_offset, entry.val);
823 goto out;
824bad_offset: 819bad_offset:
825 pr_err("swap_info_get: %s%08lx\n", Bad_offset, entry.val); 820 pr_err("swap_info_get: %s%08lx\n", Bad_offset, entry.val);
826 goto out; 821 goto out;
@@ -833,6 +828,24 @@ out:
833 return NULL; 828 return NULL;
834} 829}
835 830
831static struct swap_info_struct *_swap_info_get(swp_entry_t entry)
832{
833 struct swap_info_struct *p;
834
835 p = __swap_info_get(entry);
836 if (!p)
837 goto out;
838 if (!p->swap_map[swp_offset(entry)])
839 goto bad_free;
840 return p;
841
842bad_free:
843 pr_err("swap_info_get: %s%08lx\n", Unused_offset, entry.val);
844 goto out;
845out:
846 return NULL;
847}
848
836static struct swap_info_struct *swap_info_get(swp_entry_t entry) 849static struct swap_info_struct *swap_info_get(swp_entry_t entry)
837{ 850{
838 struct swap_info_struct *p; 851 struct swap_info_struct *p;
@@ -988,6 +1001,28 @@ int page_swapcount(struct page *page)
988 1001
989/* 1002/*
990 * How many references to @entry are currently swapped out? 1003 * How many references to @entry are currently swapped out?
1004 * This does not give an exact answer when swap count is continued,
1005 * but does include the high COUNT_CONTINUED flag to allow for that.
1006 */
1007int __swp_swapcount(swp_entry_t entry)
1008{
1009 int count = 0;
1010 pgoff_t offset;
1011 struct swap_info_struct *si;
1012 struct swap_cluster_info *ci;
1013
1014 si = __swap_info_get(entry);
1015 if (si) {
1016 offset = swp_offset(entry);
1017 ci = lock_cluster_or_swap_info(si, offset);
1018 count = swap_count(si->swap_map[offset]);
1019 unlock_cluster_or_swap_info(si, ci);
1020 }
1021 return count;
1022}
1023
1024/*
1025 * How many references to @entry are currently swapped out?
991 * This considers COUNT_CONTINUED so it returns exact answer. 1026 * This considers COUNT_CONTINUED so it returns exact answer.
992 */ 1027 */
993int swp_swapcount(swp_entry_t entry) 1028int swp_swapcount(swp_entry_t entry)