linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] swap writepages swizzled
@ 2002-11-11 19:02 Hugh Dickins
  2002-11-11 19:14 ` Andrew Morton
  0 siblings, 1 reply; 2+ messages in thread
From: Hugh Dickins @ 2002-11-11 19:02 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

tmpfs failed fsx+swapout tests after many hours, a page found zeroed.
Not a truncate problem, but mirror image of earlier truncate problems:
swap goes through mpage_writepages, which must therefore allow for a
sudden swizzle back to file identity.

Second time this caught us, so I've audited the tree for other places
which might be surprised by such swizzling.  The only others I found
were (perhaps) in the parisc and sparc64 flush_dcache_page called
from do_generic_mapping_read on a looped tmpfs file which is also
mmapped; but that's a very marginal case, I wanted to understand it
better before making any edit, and now realize that hch's sendfile
in loop eliminates it (now go through do_shmem_file_read instead:
similar but crucially this locks the page when raising its count,
which is enough to keep vmscan from interfering).

Patch applies to 2.5.47, or 2.5.47-mm1 with offsets and fuzz.
Only the patch to mpage.c is required: I think it's worth adding
BUG_ON checks in __set_page_dirty_nobuffers and get_swap_bio,
just leave those out if you disagree; similarly, optional patch
to try_to_free_buffers, once upon a time swap came that way,
happily ever after it doesn't, so the test seems misleading.

Hugh

--- 2.5.47/fs/mpage.c	Mon Nov 11 08:26:55 2002
+++ linux/fs/mpage.c	Mon Nov 11 17:01:27 2002
@@ -587,12 +587,19 @@
 		page_cache_get(page);
 		write_unlock(&mapping->page_lock);
 
+		/*
+		 * At this point we hold neither mapping->page_lock nor
+		 * lock on the page itself: the page may be truncated or
+		 * invalidated (changing page->mapping to NULL), or even
+		 * swizzled back from swapper_space to tmpfs file mapping.
+		 */
+
 		lock_page(page);
 
 		if (sync)
 			wait_on_page_writeback(page);
 
-		if (page->mapping && !PageWriteback(page) &&
+		if (page->mapping == mapping && !PageWriteback(page) &&
 					test_clear_page_dirty(page)) {
 			if (writepage) {
 				ret = (*writepage)(page);
--- 2.5.47/mm/page-writeback.c	Thu Oct 31 05:40:06 2002
+++ linux/mm/page-writeback.c	Mon Nov 11 17:01:27 2002
@@ -613,6 +613,7 @@
 		if (mapping) {
 			write_lock(&mapping->page_lock);
 			if (page->mapping) {	/* Race with truncate? */
+				BUG_ON(page->mapping != mapping);
 				if (!mapping->backing_dev_info->memory_backed)
 					inc_page_state(nr_dirty);
 				list_del(&page->list);
--- 2.5.47/mm/page_io.c	Mon Oct  7 20:37:50 2002
+++ linux/mm/page_io.c	Mon Nov 11 17:01:27 2002
@@ -30,6 +30,7 @@
 		struct swap_info_struct *sis;
 		swp_entry_t entry;
 
+		BUG_ON(!PageSwapCache(page));
 		entry.val = page->index;
 		sis = get_swap_info_struct(swp_type(entry));
 
--- 2.5.47/fs/buffer.c	Mon Nov 11 08:26:55 2002
+++ linux/fs/buffer.c	Mon Nov 11 17:01:27 2002
@@ -2496,7 +2496,7 @@
 
 	spin_lock(&mapping->private_lock);
 	ret = drop_buffers(page, &buffers_to_free);
-	if (ret && !PageSwapCache(page)) {
+	if (ret) {
 		/*
 		 * If the filesystem writes its buffers by hand (eg ext3)
 		 * then we can have clean buffers against a dirty page.  We


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] swap writepages swizzled
  2002-11-11 19:02 [PATCH] swap writepages swizzled Hugh Dickins
@ 2002-11-11 19:14 ` Andrew Morton
  0 siblings, 0 replies; 2+ messages in thread
From: Andrew Morton @ 2002-11-11 19:14 UTC (permalink / raw)
  To: Hugh Dickins; +Cc: linux-kernel

Hugh Dickins wrote:
> 
> ...
> optional patch
> to try_to_free_buffers, once upon a time swap came that way,
> happily ever after it doesn't, so the test seems misleading.
> 

Alas, swapcache pages can still have buffers attached.

It's pretty rare.  Suppose an application has paged in a page from
an ext3 file.  It is sleeping on the completion of the read. Now,
the file is ftruncated.  Pagetables are torn down and truncate_inode_pages
tries to throw away the pagecache.  But the particular page which is
being faulted in has an elevated refcount, so it is not succesfully
freed by truncate.  It _is_ removed from pagecache.

The page is instantiated in the faulter's pagetables as an anonymous
page just floating out there somewhere.

It doesn't have its buffers removed either, because it was attached
to an ext3 transaction at the time of the truncate, and try_to_release_page()
failed.

We end up with an anonymous, swappable page which has buffers.

So we need to keep that test.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2002-11-11 19:08 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-11-11 19:02 [PATCH] swap writepages swizzled Hugh Dickins
2002-11-11 19:14 ` Andrew Morton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).