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