lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri, 25 Nov 2016 16:25:12 +0800
From:   Hui Zhu <zhuhui@...omi.com>
To:     <minchan@...nel.org>, <ngupta@...are.org>,
        <sergey.senozhatsky.work@...il.com>, <dan.j.williams@...el.com>,
        <jthumshirn@...e.de>, <akpm@...ux-foundation.org>,
        <zhuhui@...omi.com>, <re.emese@...il.com>,
        <andriy.shevchenko@...ux.intel.com>, <vishal.l.verma@...el.com>,
        <hannes@...xchg.org>, <mhocko@...e.com>,
        <mgorman@...hsingularity.net>, <vbabka@...e.cz>,
        <vdavydov.dev@...il.com>, <kirill.shutemov@...ux.intel.com>,
        <ying.huang@...el.com>, <yang.shi@...aro.org>,
        <dave.hansen@...ux.intel.com>, <willy@...ux.intel.com>,
        <vkuznets@...hat.com>, <vitalywool@...il.com>,
        <jmarchan@...hat.com>, <lstoakes@...il.com>, <geliangtang@....com>,
        <viro@...iv.linux.org.uk>, <hughd@...gle.com>, <riel@...hat.com>,
        <linux-kernel@...r.kernel.org>, <linux-mm@...ck.org>
CC:     <teawater@...il.com>
Subject: [RFC 1/2] SWAP: add interface to let disk close swap cache

This patch add a interface to gendisk that SWAP device can use it to
control the swap cache rule.

Signed-off-by: Hui Zhu <zhuhui@...omi.com>
---
 include/linux/genhd.h |  3 +++
 include/linux/swap.h  |  8 ++++++
 mm/Kconfig            | 10 +++++++
 mm/memory.c           |  2 +-
 mm/swapfile.c         | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 mm/vmscan.c           |  2 +-
 6 files changed, 96 insertions(+), 3 deletions(-)

diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index e0341af..6baec46 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -215,6 +215,9 @@ struct gendisk {
 #endif	/* CONFIG_BLK_DEV_INTEGRITY */
 	int node_id;
 	struct badblocks *bb;
+#ifdef CONFIG_SWAP_CACHE_RULE
+	bool swap_cache_not_keep;
+#endif
 };
 
 static inline struct gendisk *part_to_disk(struct hd_struct *part)
diff --git a/include/linux/swap.h b/include/linux/swap.h
index a56523c..6fa11ca 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -582,5 +582,13 @@ static inline bool mem_cgroup_swap_full(struct page *page)
 }
 #endif
 
+#ifdef CONFIG_SWAP_CACHE_RULE
+extern bool swap_not_keep_cache(struct page *page);
+extern void swap_cache_rule_update(void);
+#else
+#define swap_not_keep_cache(p)		mem_cgroup_swap_full(p)
+#define swap_cache_rule_update()
+#endif
+
 #endif /* __KERNEL__*/
 #endif /* _LINUX_SWAP_H */
diff --git a/mm/Kconfig b/mm/Kconfig
index 86e3e0e..6623e87 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -711,3 +711,13 @@ config ARCH_USES_HIGH_VMA_FLAGS
 	bool
 config ARCH_HAS_PKEYS
 	bool
+
+config SWAP_CACHE_RULE
+	bool "Swap cache rule support"
+	depends on SWAP
+	default n
+	help
+	  add a interface to gendisk that SWAP device can use it to
+	  control the swap cache rule.
+
+	  If unsure, say "n".
diff --git a/mm/memory.c b/mm/memory.c
index e18c57b..099cb5b 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2654,7 +2654,7 @@ int do_swap_page(struct fault_env *fe, pte_t orig_pte)
 	}
 
 	swap_free(entry);
-	if (mem_cgroup_swap_full(page) ||
+	if (swap_not_keep_cache(page) ||
 	    (vma->vm_flags & VM_LOCKED) || PageMlocked(page))
 		try_to_free_swap(page);
 	unlock_page(page);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index f304389..9837261 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1019,7 +1019,7 @@ int free_swap_and_cache(swp_entry_t entry)
 		 * Also recheck PageSwapCache now page is locked (above).
 		 */
 		if (PageSwapCache(page) && !PageWriteback(page) &&
-		    (!page_mapped(page) || mem_cgroup_swap_full(page))) {
+		    (!page_mapped(page) || swap_not_keep_cache(page))) {
 			delete_from_swap_cache(page);
 			SetPageDirty(page);
 		}
@@ -1992,6 +1992,8 @@ static void reinsert_swap_info(struct swap_info_struct *p)
 	filp_close(victim, NULL);
 out:
 	putname(pathname);
+	if (!err)
+		swap_cache_rule_update();
 	return err;
 }
 
@@ -2576,6 +2578,8 @@ static bool swap_discardable(struct swap_info_struct *si)
 		putname(name);
 	if (inode && S_ISREG(inode->i_mode))
 		inode_unlock(inode);
+	if (!error)
+		swap_cache_rule_update();
 	return error;
 }
 
@@ -2954,3 +2958,71 @@ static void free_swap_count_continuations(struct swap_info_struct *si)
 		}
 	}
 }
+
+#ifdef CONFIG_SWAP_CACHE_RULE
+enum swap_cache_rule_type {
+	SWAP_CACHE_UNKNOWN = 0,
+	SWAP_CACHE_SPECIAL_RULE,
+	SWAP_CACHE_NOT_KEEP,
+	SWAP_CACHE_NEED_CHECK,
+};
+
+static enum swap_cache_rule_type swap_cache_rule __read_mostly;
+
+bool swap_not_keep_cache(struct page *page)
+{
+	enum swap_cache_rule_type rule = READ_ONCE(swap_cache_rule);
+
+	if (rule == SWAP_CACHE_NOT_KEEP)
+		return true;
+
+	if (unlikely(rule == SWAP_CACHE_SPECIAL_RULE)) {
+		struct swap_info_struct *sis;
+
+		BUG_ON(!PageSwapCache(page));
+
+		sis = page_swap_info(page);
+		if (sis->flags & SWP_BLKDEV) {
+			struct gendisk *disk = sis->bdev->bd_disk;
+
+			if (READ_ONCE(disk->swap_cache_not_keep))
+				return true;
+		}
+	}
+
+	return mem_cgroup_swap_full(page);
+}
+
+void swap_cache_rule_update(void)
+{
+	enum swap_cache_rule_type rule = SWAP_CACHE_UNKNOWN;
+	int type;
+
+	spin_lock(&swap_lock);
+	for (type = 0; type < nr_swapfiles; type++) {
+		struct swap_info_struct *sis = swap_info[type];
+		enum swap_cache_rule_type current_rule = SWAP_CACHE_NEED_CHECK;
+
+		if (!(sis->flags & SWP_USED))
+			continue;
+
+		if (sis->flags & SWP_BLKDEV) {
+			struct gendisk *disk = sis->bdev->bd_disk;
+
+			if (READ_ONCE(disk->swap_cache_not_keep))
+				current_rule = SWAP_CACHE_NOT_KEEP;
+		}
+
+		if (rule == SWAP_CACHE_UNKNOWN)
+			rule = current_rule;
+		else if (rule != current_rule) {
+			rule = SWAP_CACHE_SPECIAL_RULE;
+			break;
+		}
+	}
+	spin_unlock(&swap_lock);
+
+	WRITE_ONCE(swap_cache_rule, rule);
+}
+EXPORT_SYMBOL(swap_cache_rule_update);
+#endif
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 76fda22..52c67fe 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1239,7 +1239,7 @@ static unsigned long shrink_page_list(struct list_head *page_list,
 
 activate_locked:
 		/* Not a candidate for swapping, so reclaim swap space. */
-		if (PageSwapCache(page) && mem_cgroup_swap_full(page))
+		if (PageSwapCache(page) && swap_not_keep_cache(page))
 			try_to_free_swap(page);
 		VM_BUG_ON_PAGE(PageActive(page), page);
 		SetPageActive(page);
-- 
1.9.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ