Skip to content

Commit

Permalink
hugetlb: simplify migrate_huge_page()
Browse files Browse the repository at this point in the history
Since we migrate only one hugepage, don't use linked list for passing the
page around.  Directly pass the page that need to be migrated as argument.
This also removes the usage of page->lru in the migrate path.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Hillf Danton <dhillf@gmail.com>
Reviewed-by: Michal Hocko <mhocko@suse.cz>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
kvaneesh authored and torvalds committed Aug 1, 2012
1 parent 24669e5 commit 189ebff
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 57 deletions.
4 changes: 2 additions & 2 deletions include/linux/migrate.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ extern int migrate_page(struct address_space *,
extern int migrate_pages(struct list_head *l, new_page_t x,
unsigned long private, bool offlining,
enum migrate_mode mode);
extern int migrate_huge_pages(struct list_head *l, new_page_t x,
extern int migrate_huge_page(struct page *, new_page_t x,
unsigned long private, bool offlining,
enum migrate_mode mode);

Expand All @@ -36,7 +36,7 @@ static inline void putback_lru_pages(struct list_head *l) {}
static inline int migrate_pages(struct list_head *l, new_page_t x,
unsigned long private, bool offlining,
enum migrate_mode mode) { return -ENOSYS; }
static inline int migrate_huge_pages(struct list_head *l, new_page_t x,
static inline int migrate_huge_page(struct page *page, new_page_t x,
unsigned long private, bool offlining,
enum migrate_mode mode) { return -ENOSYS; }

Expand Down
15 changes: 4 additions & 11 deletions mm/memory-failure.c
Original file line number Diff line number Diff line change
Expand Up @@ -1416,7 +1416,6 @@ static int soft_offline_huge_page(struct page *page, int flags)
int ret;
unsigned long pfn = page_to_pfn(page);
struct page *hpage = compound_head(page);
LIST_HEAD(pagelist);

ret = get_any_page(page, pfn, flags);
if (ret < 0)
Expand All @@ -1431,24 +1430,18 @@ static int soft_offline_huge_page(struct page *page, int flags)
}

/* Keep page count to indicate a given hugepage is isolated. */

list_add(&hpage->lru, &pagelist);
ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, false,
ret = migrate_huge_page(hpage, new_page, MPOL_MF_MOVE_ALL, false,
MIGRATE_SYNC);
put_page(hpage);
if (ret) {
struct page *page1, *page2;
list_for_each_entry_safe(page1, page2, &pagelist, lru)
put_page(page1);

pr_info("soft offline: %#lx: migration failed %d, type %lx\n",
pfn, ret, page->flags);
if (ret > 0)
ret = -EIO;
return ret;
}
done:
if (!PageHWPoison(hpage))
atomic_long_add(1 << compound_trans_order(hpage), &mce_bad_pages);
atomic_long_add(1 << compound_trans_order(hpage),
&mce_bad_pages);
set_page_hwpoison_huge_page(hpage);
dequeue_hwpoisoned_huge_page(hpage);
/* keep elevated page count for bad page */
Expand Down
65 changes: 21 additions & 44 deletions mm/migrate.c
Original file line number Diff line number Diff line change
Expand Up @@ -932,15 +932,8 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
if (anon_vma)
put_anon_vma(anon_vma);
unlock_page(hpage);

out:
if (rc != -EAGAIN) {
list_del(&hpage->lru);
put_page(hpage);
}

put_page(new_hpage);

if (result) {
if (rc)
*result = rc;
Expand Down Expand Up @@ -1016,48 +1009,32 @@ int migrate_pages(struct list_head *from,
return nr_failed + retry;
}

int migrate_huge_pages(struct list_head *from,
new_page_t get_new_page, unsigned long private, bool offlining,
enum migrate_mode mode)
int migrate_huge_page(struct page *hpage, new_page_t get_new_page,
unsigned long private, bool offlining,
enum migrate_mode mode)
{
int retry = 1;
int nr_failed = 0;
int pass = 0;
struct page *page;
struct page *page2;
int rc;

for (pass = 0; pass < 10 && retry; pass++) {
retry = 0;

list_for_each_entry_safe(page, page2, from, lru) {
int pass, rc;

for (pass = 0; pass < 10; pass++) {
rc = unmap_and_move_huge_page(get_new_page,
private, hpage, pass > 2, offlining,
mode);
switch (rc) {
case -ENOMEM:
goto out;
case -EAGAIN:
/* try again */
cond_resched();

rc = unmap_and_move_huge_page(get_new_page,
private, page, pass > 2, offlining,
mode);

switch(rc) {
case -ENOMEM:
goto out;
case -EAGAIN:
retry++;
break;
case 0:
break;
default:
/* Permanent failure */
nr_failed++;
break;
}
break;
case 0:
goto out;
default:
rc = -EIO;
goto out;
}
}
rc = 0;
out:
if (rc)
return rc;

return nr_failed + retry;
return rc;
}

#ifdef CONFIG_NUMA
Expand Down

0 comments on commit 189ebff

Please sign in to comment.