populate_pud tries to return the number of pages mapped so far if populate_pmd fails. This is of dubious utility, since if populate_pmd did any work before failing, the returned number of pages will be inconsistent with cpa->pfn, and the loop in __change_page_attr_set_clr will retry with that inconsistent state. Further, if the number of pages mapped before failure is zero, that will trigger the BUG_ON in __change_page_attr_set_clr. Just return all errors up the stack and let the original caller deal with it. Signed-off-by: Arvind Sankar <nivedita@xxxxxxxxxxxx> --- arch/x86/mm/pat/set_memory.c | 43 ++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index a1003bc9fdf6..2f98423ef69a 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -1247,9 +1247,9 @@ static void populate_pte(struct cpa_data *cpa, } } -static long populate_pmd(struct cpa_data *cpa, - unsigned long start, unsigned long end, - unsigned num_pages, pud_t *pud, pgprot_t pgprot) +static int populate_pmd(struct cpa_data *cpa, + unsigned long start, unsigned long end, + unsigned num_pages, pud_t *pud, pgprot_t pgprot) { long cur_pages = 0; pmd_t *pmd; @@ -1283,7 +1283,7 @@ static long populate_pmd(struct cpa_data *cpa, * We mapped them all? */ if (num_pages == cur_pages) - return cur_pages; + return 0; pmd_pgprot = pgprot_4k_2_large(pgprot); @@ -1318,7 +1318,7 @@ static long populate_pmd(struct cpa_data *cpa, populate_pte(cpa, start, end, num_pages - cur_pages, pmd, pgprot); } - return num_pages; + return 0; } static int populate_pud(struct cpa_data *cpa, unsigned long start, p4d_t *p4d, @@ -1328,6 +1328,7 @@ static int populate_pud(struct cpa_data *cpa, unsigned long start, p4d_t *p4d, unsigned long end; long cur_pages = 0; pgprot_t pud_pgprot; + int ret; end = start + (cpa->numpages << PAGE_SHIFT); @@ -1352,17 +1353,16 @@ static int populate_pud(struct cpa_data *cpa, unsigned long start, p4d_t *p4d, if (alloc_pmd_page(pud)) return -1; - cur_pages = populate_pmd(cpa, start, pre_end, cur_pages, - pud, pgprot); - if (cur_pages < 0) - return cur_pages; + ret = populate_pmd(cpa, start, pre_end, cur_pages, pud, pgprot); + if (ret < 0) + return ret; start = pre_end; } /* We mapped them all? */ if (cpa->numpages == cur_pages) - return cur_pages; + return 0; pud = pud_offset(p4d, start); pud_pgprot = pgprot_4k_2_large(pgprot); @@ -1379,10 +1379,10 @@ static int populate_pud(struct cpa_data *cpa, unsigned long start, p4d_t *p4d, if (pud_none(*pud)) if (alloc_pmd_page(pud)) return -1; - if (populate_pmd(cpa, start, start + PUD_SIZE, - PUD_SIZE >> PAGE_SHIFT, - pud, pgprot) < 0) - return cur_pages; + ret = populate_pmd(cpa, start, start + PUD_SIZE, + PUD_SIZE >> PAGE_SHIFT, pud, pgprot); + if (ret < 0) + return ret; } start += PUD_SIZE; @@ -1392,21 +1392,17 @@ static int populate_pud(struct cpa_data *cpa, unsigned long start, p4d_t *p4d, /* Map trailing leftover */ if (start < end) { - long tmp; - pud = pud_offset(p4d, start); if (pud_none(*pud)) if (alloc_pmd_page(pud)) return -1; - tmp = populate_pmd(cpa, start, end, cpa->numpages - cur_pages, + ret = populate_pmd(cpa, start, end, cpa->numpages - cur_pages, pud, pgprot); - if (tmp < 0) - return cur_pages; - - cur_pages += tmp; + if (ret < 0) + return ret; } - return cur_pages; + return 0; } /* @@ -1419,7 +1415,7 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr) pud_t *pud = NULL; /* shut up gcc */ p4d_t *p4d; pgd_t *pgd_entry; - long ret; + int ret; unsigned long end, end_p4d; pgd_entry = cpa->pgd + pgd_index(addr); @@ -1468,7 +1464,6 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr) return ret; } - cpa->numpages = ret; return 0; } -- 2.24.1