[PATCH 3/4] x86/mm/pat: Propagate all errors out of populate_pud

From: Arvind Sankar
Date: Tue Mar 03 2020 - 15:54:52 EST


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