aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Farman <farman@linux.ibm.com>2018-06-29 13:54:01 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2018-07-02 05:25:39 -0400
commitdfa758638fd2d1184760deb2693abf76e982c53a (patch)
treeb9fa7cdab4e365e8de3253f91bff6727a10c7578
parent3284da34a87ab7a527a593f89bbdaf6debe9e713 (diff)
s390/mm: fix refcount usage for 4K pgste
s390 no longer uses the _mapcount field in struct page to identify the page table format being used. While the code was diligent in handling the different mappings, it neglected to turn "off" the map bits when alloc_pgste was being used. This resulted in bits remaining "on" in the _refcount field, and thus an artifically huge "in use" count that prevents the pages from actually being released by __free_page. There's opportunity for improvement in the "1 vs 3" vs "1U vs 3U" vs "0x1 vs 0x11" etc. variations for all these calls, I am just keeping things simple compared to neighboring code. Fixes: 620b4e903179 ("s390: use _refcount for pgtables") Reported-by: Halil Pasic <pasic@linux.ibm.com> Bisected-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Eric Farman <farman@linux.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/mm/pgalloc.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
index 84bd6329a88d..e3bd5627afef 100644
--- a/arch/s390/mm/pgalloc.c
+++ b/arch/s390/mm/pgalloc.c
@@ -252,6 +252,8 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
252 spin_unlock_bh(&mm->context.lock); 252 spin_unlock_bh(&mm->context.lock);
253 if (mask != 0) 253 if (mask != 0)
254 return; 254 return;
255 } else {
256 atomic_xor_bits(&page->_refcount, 3U << 24);
255 } 257 }
256 258
257 pgtable_page_dtor(page); 259 pgtable_page_dtor(page);
@@ -304,6 +306,8 @@ static void __tlb_remove_table(void *_table)
304 break; 306 break;
305 /* fallthrough */ 307 /* fallthrough */
306 case 3: /* 4K page table with pgstes */ 308 case 3: /* 4K page table with pgstes */
309 if (mask & 3)
310 atomic_xor_bits(&page->_refcount, 3 << 24);
307 pgtable_page_dtor(page); 311 pgtable_page_dtor(page);
308 __free_page(page); 312 __free_page(page);
309 break; 313 break;