diff options
| author | Mark Brown <broonie@kernel.org> | 2020-12-11 17:49:01 +0000 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2020-12-11 17:49:01 +0000 |
| commit | 3e98a021cc85e7d52acdd1eae8a988e975ec5bf9 (patch) | |
| tree | cecfac58b9550a602555a02a9d583ed0f3378b38 /mm/filemap.c | |
| parent | 58f7553fa424fd0fd74e8b796d50c66014cebebe (diff) | |
| parent | 2fee9583198eb97b5351feda7bd825e0f778385c (diff) | |
Merge remote-tracking branch 'spi/for-5.11' into spi-next
Diffstat (limited to 'mm/filemap.c')
| -rw-r--r-- | mm/filemap.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index d5e7c2029d16..0b2067b3c328 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1484,11 +1484,19 @@ void end_page_writeback(struct page *page) rotate_reclaimable_page(page); } + /* + * Writeback does not hold a page reference of its own, relying + * on truncation to wait for the clearing of PG_writeback. + * But here we must make sure that the page is not freed and + * reused before the wake_up_page(). + */ + get_page(page); if (!test_clear_page_writeback(page)) BUG(); smp_mb__after_atomic(); wake_up_page(page, PG_writeback); + put_page(page); } EXPORT_SYMBOL(end_page_writeback); @@ -2347,10 +2355,15 @@ page_ok: page_not_up_to_date: /* Get exclusive access to the page ... */ - if (iocb->ki_flags & IOCB_WAITQ) + if (iocb->ki_flags & IOCB_WAITQ) { + if (written) { + put_page(page); + goto out; + } error = lock_page_async(page, iocb->ki_waitq); - else + } else { error = lock_page_killable(page); + } if (unlikely(error)) goto readpage_error; @@ -2393,10 +2406,15 @@ readpage: } if (!PageUptodate(page)) { - if (iocb->ki_flags & IOCB_WAITQ) + if (iocb->ki_flags & IOCB_WAITQ) { + if (written) { + put_page(page); + goto out; + } error = lock_page_async(page, iocb->ki_waitq); - else + } else { error = lock_page_killable(page); + } if (unlikely(error)) goto readpage_error; |
