blk_run_page() is incorrectly using page->mapping, which makes it racy against
addition to swapcache.

Make block_sync_page() use page_mapping(), and remove bkl_run_page(), which
only had one caller.


---

 /dev/null                      |    0 
 25-akpm/fs/buffer.c            |    7 ++++++-
 25-akpm/include/linux/blkdev.h |   10 ----------
 3 files changed, 6 insertions(+), 11 deletions(-)

diff -puN include/linux/blkdev.h~blk_run_page-race-fix include/linux/blkdev.h
--- 25/include/linux/blkdev.h~blk_run_page-race-fix	Tue May 18 16:10:32 2004
+++ 25-akpm/include/linux/blkdev.h	Tue May 18 16:10:58 2004
@@ -545,16 +545,6 @@ static inline void blk_run_address_space
 		blk_run_backing_dev(mapping->backing_dev_info, NULL);
 }
 
-static inline void blk_run_page(struct page *page)
-{
-	struct address_space *mapping;
-
-	smp_mb();
-	mapping = page->mapping;
-	if (mapping)
-		blk_run_backing_dev(mapping->backing_dev_info, page);
-}
-
 /*
  * end_request() and friends. Must be called with the request queue spinlock
  * acquired. All functions called within end_request() _must_be_ atomic.
diff -L fa/buffer.c -puN /dev/null /dev/null
diff -puN fs/buffer.c~blk_run_page-race-fix fs/buffer.c
--- 25/fs/buffer.c~blk_run_page-race-fix	Tue May 18 16:10:38 2004
+++ 25-akpm/fs/buffer.c	Tue May 18 16:11:40 2004
@@ -2960,7 +2960,12 @@ EXPORT_SYMBOL(try_to_free_buffers);
 
 int block_sync_page(struct page *page)
 {
-	blk_run_page(page);
+	struct address_space *mapping;
+
+	smp_mb();
+	mapping = page_mapping(page);
+	if (mapping)
+		blk_run_backing_dev(mapping->backing_dev_info, page);
 	return 0;
 }
 

_