From: Zach Brown This adds filemap_write_and_wait_range(mapping, lstart, lend) which starts writeback and waits on a range of pages. We call this from __blkdev_direct_IO with just the range that is going to be read by the direct_IO read. It was lightly tested with fsx and ext3 and passed. Signed-off-by: Zach Brown Signed-off-by: Andrew Morton --- 25-akpm/fs/direct-io.c | 7 +++++-- 25-akpm/include/linux/fs.h | 2 ++ 25-akpm/mm/filemap.c | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff -puN fs/direct-io.c~write-and-wait-on-range-before-direct-io-read fs/direct-io.c --- 25/fs/direct-io.c~write-and-wait-on-range-before-direct-io-read 2005-02-22 18:16:10.000000000 -0800 +++ 25-akpm/fs/direct-io.c 2005-02-22 18:16:10.000000000 -0800 @@ -1206,7 +1206,8 @@ __blockdev_direct_IO(int rw, struct kioc */ dio->lock_type = dio_lock_type; if (dio_lock_type != DIO_NO_LOCKING) { - if (rw == READ) { + /* watch out for a 0 len io from a tricksy fs */ + if (rw == READ && end > offset) { struct address_space *mapping; mapping = iocb->ki_filp->f_mapping; @@ -1214,7 +1215,9 @@ __blockdev_direct_IO(int rw, struct kioc down(&inode->i_sem); reader_with_isem = 1; } - retval = filemap_write_and_wait(mapping); + + retval = filemap_write_and_wait_range(mapping, offset, + end - 1); if (retval) { kfree(dio); goto out; diff -puN include/linux/fs.h~write-and-wait-on-range-before-direct-io-read include/linux/fs.h --- 25/include/linux/fs.h~write-and-wait-on-range-before-direct-io-read 2005-02-22 18:16:10.000000000 -0800 +++ 25-akpm/include/linux/fs.h 2005-02-22 18:16:10.000000000 -0800 @@ -1360,6 +1360,8 @@ extern int filemap_fdatawrite(struct add extern int filemap_flush(struct address_space *); extern int filemap_fdatawait(struct address_space *); extern int filemap_write_and_wait(struct address_space *mapping); +extern int filemap_write_and_wait_range(struct address_space *mapping, + loff_t lstart, loff_t lend); extern void sync_supers(void); extern void sync_filesystems(int wait); extern void emergency_sync(void); diff -puN mm/filemap.c~write-and-wait-on-range-before-direct-io-read mm/filemap.c --- 25/mm/filemap.c~write-and-wait-on-range-before-direct-io-read 2005-02-22 18:16:10.000000000 -0800 +++ 25-akpm/mm/filemap.c 2005-02-22 18:16:10.000000000 -0800 @@ -336,6 +336,22 @@ int filemap_write_and_wait(struct addres return retval; } +int filemap_write_and_wait_range(struct address_space *mapping, + loff_t lstart, loff_t lend) +{ + int retval = 0; + + if (mapping->nrpages) { + retval = __filemap_fdatawrite_range(mapping, lstart, lend, + WB_SYNC_ALL); + if (retval == 0) + retval = wait_on_page_writeback_range(mapping, + lstart >> PAGE_CACHE_SHIFT, + lend >> PAGE_CACHE_SHIFT); + } + return retval; +} + /* * This function is used to add newly allocated pagecache pages: * the page is new, so we can just run SetPageLocked() against it. _