| From foo@baz Mon Dec 18 15:03:25 CET 2017 |
| From: David Howells <dhowells@redhat.com> |
| Date: Thu, 16 Mar 2017 16:27:48 +0000 |
| Subject: afs: Fix afs_kill_pages() |
| |
| From: David Howells <dhowells@redhat.com> |
| |
| |
| [ Upstream commit 7286a35e893176169b09715096a4aca557e2ccd2 ] |
| |
| Fix afs_kill_pages() in two ways: |
| |
| (1) If a writeback has been partially flushed, then if we try and kill the |
| pages it contains, some of them may no longer be undergoing writeback |
| and end_page_writeback() will assert. |
| |
| Fix this by checking to see whether the page in question is actually |
| undergoing writeback before ending that writeback. |
| |
| (2) The loop that scans for pages to kill doesn't increase the first page |
| index, and so the loop may not terminate, but it will try to process |
| the same pages over and over again. |
| |
| Fix this by increasing the first page index to one after the last page |
| we processed. |
| |
| Signed-off-by: David Howells <dhowells@redhat.com> |
| Signed-off-by: Sasha Levin <alexander.levin@verizon.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/afs/write.c | 10 +++++++--- |
| 1 file changed, 7 insertions(+), 3 deletions(-) |
| |
| --- a/fs/afs/write.c |
| +++ b/fs/afs/write.c |
| @@ -300,10 +300,14 @@ static void afs_kill_pages(struct afs_vn |
| ASSERTCMP(pv.nr, ==, count); |
| |
| for (loop = 0; loop < count; loop++) { |
| - ClearPageUptodate(pv.pages[loop]); |
| + struct page *page = pv.pages[loop]; |
| + ClearPageUptodate(page); |
| if (error) |
| - SetPageError(pv.pages[loop]); |
| - end_page_writeback(pv.pages[loop]); |
| + SetPageError(page); |
| + if (PageWriteback(page)) |
| + end_page_writeback(page); |
| + if (page->index >= first) |
| + first = page->index + 1; |
| } |
| |
| __pagevec_release(&pv); |