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; } _