Re: [PATCH] hibernation should work ok with memory hotplug

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2008-11-04 at 17:34 +0100, Rafael J. Wysocki wrote:
> Now, I need to do one more thing, which is to check how much memory has to be
> freed before creating the image.  For this purpose I need to lock memory
> hotplug temporarily, count pages to free and unlock it.  What interface should
> I use for this purpose? 
> 
> [I'll also need to lock memory hotplug temporarily during resume.]

We currently don't have any big switch to disable memory hotplug, like
lock_memory_hotplug() or something. :)

If you are simply scanning and counting pages, I think the best thing to
use would be the zone_span_seq*() seqlock stuff.  Do your count inside
the seqlock's while loop.  That covers detecting a zone changing while
it is being scanned.

The other case to detect is when a new zone gets added.  These are
really rare.  Rare enough that we actually use a stop_machine() call in
build_all_zonelists() to do it.  All you would have to do is detect when
one of these calls gets made.  I think that's a good application for a
new seq_lock.

I've attached an utterly untested patch that should do the trick.
Yasunori and KAME should probably take a look at it since the node
addition code is theirs.

-- Dave

---

 linux-2.6.git-dave/mm/page_alloc.c |   26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff -puN mm/page_alloc.c~zone-list-seqlock mm/page_alloc.c
--- linux-2.6.git/mm/page_alloc.c~zone-list-seqlock	2008-11-04 08:53:38.000000000 -0800
+++ linux-2.6.git-dave/mm/page_alloc.c	2008-11-04 08:57:04.000000000 -0800
@@ -2378,17 +2378,43 @@ static void build_zonelist_cache(pg_data
 
 #endif	/* CONFIG_NUMA */
 
+/*
+ * This provides a way for other parts of the
+ * system to detect when the list of zones
+ * might have changed underneath them.
+ *
+ * Use this if you are doing a for_each_zone()
+ * or for_each_node() and really, really care
+ * if you miss some memory.
+ */
+static seqlock_t zonelist_seqlock = SEQLOCK_UNLOCKED;
+
+/*
+ * We could #ifdef these under MEMORY_HOTPLUG, but they
+ * are tiny.
+ */
+unsigned zonelist_seqbegin(void)
+{
+        return read_seqbegin(&zonelist_seqlock);
+}
+int zonelist_seqretry(void)
+{
+        return read_seqretry(&zonelist_seqlock, iv);
+}
+
 /* return values int ....just for stop_machine() */
 static int __build_all_zonelists(void *dummy)
 {
 	int nid;
 
+	write_seqlock(&zonelist_seqlock);
 	for_each_online_node(nid) {
 		pg_data_t *pgdat = NODE_DATA(nid);
 
 		build_zonelists(pgdat);
 		build_zonelist_cache(pgdat);
 	}
+	write_sequnlock(&zonelist_seqlock);
 	return 0;
 }
 
_
_______________________________________________
linux-pm mailing list
linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux