Skip to content

Commit 0cdc444

Browse files
Mel Gormantorvalds
authored andcommitted
mm: swap: mark swap pages writeback before queueing for direct IO
As pointed out by Andrew Morton, the swap-over-NFS writeback is not setting PageWriteback before it is queued for direct IO. While swap pages do not participate in BDI or process dirty accounting and the IO is synchronous, the writeback bit is still required and not setting it in this case was an oversight. swapoff depends on the page writeback to synchronoise all pending writes on a swap page before it is reused. Swapcache freeing and reuse depend on checking the PageWriteback under lock to ensure the page is safe to reuse. Direct IO handlers and the direct IO handler for NFS do not deal with PageWriteback as they are synchronous writes. In the case of NFS, it schedules pages (or a page in the case of swap) for IO and then waits synchronously for IO to complete in nfs_direct_write(). It is recognised that this is a slowdown from normal swap handling which is asynchronous and uses a completion handler. Shoving PageWriteback handling down into direct IO handlers looks like a bad fit to handle the swap case although it may have to be dealt with some day if swap is converted to use direct IO in general and bmap is finally done away with. At that point it will be necessary to refit asynchronous direct IO with completion handlers onto the swap subsystem. As swapcache currently depends on PageWriteback to protect against races, this patch sets PageWriteback under the page lock before queueing it for direct IO. It is cleared when the direct IO handler returns. IO errors are treated similarly to the direct-to-bio case except PageError is not set as in the case of swap-over-NFS, it is likely to be a transient error. It was asked what prevents such a page being reclaimed in parallel. With this patch applied, such a page will now be skipped (most of the time) or blocked until the writeback completes. Reclaim checks PageWriteback under the page lock before calling try_to_free_swap and the page lock should prevent the page being requeued for IO before it is freed. This and Jerome's related patch should considered for -stable as far back as 3.6 when swap-over-NFS was introduced. [[email protected]: use pr_err_ratelimited()] [[email protected]: remove hopefully-unneeded cast in printk] Signed-off-by: Mel Gorman <[email protected]> Cc: Jerome Marchand <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: <[email protected]> [3.6+] Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 2d30d31 commit 0cdc444

File tree

1 file changed

+15
-0
lines changed

1 file changed

+15
-0
lines changed

mm/page_io.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
223223
kiocb.ki_left = PAGE_SIZE;
224224
kiocb.ki_nbytes = PAGE_SIZE;
225225

226+
set_page_writeback(page);
226227
unlock_page(page);
227228
ret = mapping->a_ops->direct_IO(KERNEL_WRITE,
228229
&kiocb, &iov,
@@ -232,8 +233,22 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
232233
count_vm_event(PSWPOUT);
233234
ret = 0;
234235
} else {
236+
/*
237+
* In the case of swap-over-nfs, this can be a
238+
* temporary failure if the system has limited
239+
* memory for allocating transmit buffers.
240+
* Mark the page dirty and avoid
241+
* rotate_reclaimable_page but rate-limit the
242+
* messages but do not flag PageError like
243+
* the normal direct-to-bio case as it could
244+
* be temporary.
245+
*/
235246
set_page_dirty(page);
247+
ClearPageReclaim(page);
248+
pr_err_ratelimited("Write error on dio swapfile (%Lu)\n",
249+
page_file_offset(page));
236250
}
251+
end_page_writeback(page);
237252
return ret;
238253
}
239254

0 commit comments

Comments
 (0)