Skip to content

Commit be39f19

Browse files
Dominik DingelMartin Schwidefsky
authored andcommitted
s390/mm: page_table_realloc returns failure
There is a possible race between setting has_pgste and reallocation of the page_table, change the order to fix this. Also page_table_alloc_pgste can fail, in that case we need to backpropagte this as -ENOMEM to the caller of page_table_realloc. Based on a patch by Christian Borntraeger <borntraeger@de.ibm.com>. Reviewed-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Dominik Dingel <dingel@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
1 parent 1db9e05 commit be39f19

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

arch/s390/mm/pgtable.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,10 +1087,9 @@ static unsigned long page_table_realloc_pmd(struct mmu_gather *tlb,
10871087
continue;
10881088
/* Allocate new page table with pgstes */
10891089
new = page_table_alloc_pgste(mm, addr);
1090-
if (!new) {
1091-
mm->context.has_pgste = 0;
1092-
continue;
1093-
}
1090+
if (!new)
1091+
return -ENOMEM;
1092+
10941093
spin_lock(&mm->page_table_lock);
10951094
if (likely((unsigned long *) pmd_deref(*pmd) == table)) {
10961095
/* Nuke pmd entry pointing to the "short" page table */
@@ -1128,13 +1127,15 @@ static unsigned long page_table_realloc_pud(struct mmu_gather *tlb,
11281127
if (pud_none_or_clear_bad(pud))
11291128
continue;
11301129
next = page_table_realloc_pmd(tlb, mm, pud, addr, next);
1130+
if (unlikely(IS_ERR_VALUE(next)))
1131+
return next;
11311132
} while (pud++, addr = next, addr != end);
11321133

11331134
return addr;
11341135
}
11351136

1136-
static void page_table_realloc(struct mmu_gather *tlb, struct mm_struct *mm,
1137-
unsigned long addr, unsigned long end)
1137+
static unsigned long page_table_realloc(struct mmu_gather *tlb, struct mm_struct *mm,
1138+
unsigned long addr, unsigned long end)
11381139
{
11391140
unsigned long next;
11401141
pgd_t *pgd;
@@ -1145,7 +1146,11 @@ static void page_table_realloc(struct mmu_gather *tlb, struct mm_struct *mm,
11451146
if (pgd_none_or_clear_bad(pgd))
11461147
continue;
11471148
next = page_table_realloc_pud(tlb, mm, pgd, addr, next);
1149+
if (unlikely(IS_ERR_VALUE(next)))
1150+
return next;
11481151
} while (pgd++, addr = next, addr != end);
1152+
1153+
return 0;
11491154
}
11501155

11511156
/*
@@ -1165,9 +1170,9 @@ int s390_enable_sie(void)
11651170
/* split thp mappings and disable thp for future mappings */
11661171
thp_split_mm(mm);
11671172
/* Reallocate the page tables with pgstes */
1168-
mm->context.has_pgste = 1;
11691173
tlb_gather_mmu(&tlb, mm, 0, TASK_SIZE);
1170-
page_table_realloc(&tlb, mm, 0, TASK_SIZE);
1174+
if (!page_table_realloc(&tlb, mm, 0, TASK_SIZE))
1175+
mm->context.has_pgste = 1;
11711176
tlb_finish_mmu(&tlb, 0, TASK_SIZE);
11721177
up_write(&mm->mmap_sem);
11731178
return mm->context.has_pgste ? 0 : -ENOMEM;

0 commit comments

Comments
 (0)