Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 217447
b: refs/heads/master
c: 49ac825
h: refs/heads/master
i:
  217445: b92a4b5
  217443: 4e86de6
  217439: a1befe0
v: v3
  • Loading branch information
KAMEZAWA Hiroyuki authored and Linus Torvalds committed Oct 26, 2010
1 parent 1b6e517 commit 4f9518e
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 37 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4b20477f588055fbe87e69435d3c2344d250f0d7
refs/heads/master: 49ac825587f33afec8841b7fab2eb4db775014e6
4 changes: 4 additions & 0 deletions trunk/include/linux/memory_hotplug.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ extern void online_page(struct page *page);
extern int online_pages(unsigned long, unsigned long);
extern void __offline_isolated_pages(unsigned long, unsigned long);

#ifdef CONFIG_MEMORY_HOTREMOVE
extern bool is_pageblock_removable_nolock(struct page *page);
#endif /* CONFIG_MEMORY_HOTREMOVE */

/* reasonably generic interface to expand the physical pages in a zone */
extern int __add_pages(int nid, struct zone *zone, unsigned long start_pfn,
unsigned long nr_pages);
Expand Down
17 changes: 2 additions & 15 deletions trunk/mm/memory_hotplug.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,27 +602,14 @@ static struct page *next_active_pageblock(struct page *page)
/* Checks if this range of memory is likely to be hot-removable. */
int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
{
int type;
struct page *page = pfn_to_page(start_pfn);
struct page *end_page = page + nr_pages;

/* Check the starting page of each pageblock within the range */
for (; page < end_page; page = next_active_pageblock(page)) {
type = get_pageblock_migratetype(page);

/*
* A pageblock containing MOVABLE or free pages is considered
* removable
*/
if (type != MIGRATE_MOVABLE && !pageblock_free(page))
return 0;

/*
* A pageblock starting with a PageReserved page is not
* considered removable.
*/
if (PageReserved(page))
if (!is_pageblock_removable_nolock(page))
return 0;
cond_resched();
}

/* All pageblocks in the memory block are likely to be hot-removable */
Expand Down
87 changes: 66 additions & 21 deletions trunk/mm/page_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -5297,12 +5297,65 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
* page allocater never alloc memory from ISOLATE block.
*/

static int
__count_immobile_pages(struct zone *zone, struct page *page, int count)
{
unsigned long pfn, iter, found;
/*
* For avoiding noise data, lru_add_drain_all() should be called
* If ZONE_MOVABLE, the zone never contains immobile pages
*/
if (zone_idx(zone) == ZONE_MOVABLE)
return true;

if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE)
return true;

pfn = page_to_pfn(page);
for (found = 0, iter = 0; iter < pageblock_nr_pages; iter++) {
unsigned long check = pfn + iter;

if (!pfn_valid_within(check)) {
iter++;
continue;
}
page = pfn_to_page(check);
if (!page_count(page)) {
if (PageBuddy(page))
iter += (1 << page_order(page)) - 1;
continue;
}
if (!PageLRU(page))
found++;
/*
* If there are RECLAIMABLE pages, we need to check it.
* But now, memory offline itself doesn't call shrink_slab()
* and it still to be fixed.
*/
/*
* If the page is not RAM, page_count()should be 0.
* we don't need more check. This is an _used_ not-movable page.
*
* The problematic thing here is PG_reserved pages. PG_reserved
* is set to both of a memory hole page and a _used_ kernel
* page at boot.
*/
if (found > count)
return false;
}
return true;
}

bool is_pageblock_removable_nolock(struct page *page)
{
struct zone *zone = page_zone(page);
return __count_immobile_pages(zone, page, 0);
}

int set_migratetype_isolate(struct page *page)
{
struct zone *zone;
struct page *curr_page;
unsigned long flags, pfn, iter;
unsigned long immobile = 0;
unsigned long flags, pfn;
struct memory_isolate_notify arg;
int notifier_ret;
int ret = -EBUSY;
Expand All @@ -5312,11 +5365,6 @@ int set_migratetype_isolate(struct page *page)
zone_idx = zone_idx(zone);

spin_lock_irqsave(&zone->lock, flags);
if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE ||
zone_idx == ZONE_MOVABLE) {
ret = 0;
goto out;
}

pfn = page_to_pfn(page);
arg.start_pfn = pfn;
Expand All @@ -5338,21 +5386,18 @@ int set_migratetype_isolate(struct page *page)
notifier_ret = notifier_to_errno(notifier_ret);
if (notifier_ret)
goto out;

for (iter = pfn; iter < (pfn + pageblock_nr_pages); iter++) {
if (!pfn_valid_within(pfn))
continue;

curr_page = pfn_to_page(iter);
if (!page_count(curr_page) || PageLRU(curr_page))
continue;

immobile++;
}

if (arg.pages_found == immobile)
/*
* FIXME: Now, memory hotplug doesn't call shrink_slab() by itself.
* We just check MOVABLE pages.
*/
if (__count_immobile_pages(zone, page, arg.pages_found))
ret = 0;

/*
* immobile means "not-on-lru" paes. If immobile is larger than
* removable-by-driver pages reported by notifier, we'll fail.
*/

out:
if (!ret) {
set_pageblock_migratetype(page, MIGRATE_ISOLATE);
Expand Down

0 comments on commit 4f9518e

Please sign in to comment.