Commit daf70db8 authored by Zach Brown's avatar Zach Brown Committed by Linus Torvalds

[PATCH] write and wait on range before direct io read

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: default avatarZach Brown <zach.brown@oracle.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 7afadfdc
...@@ -1206,7 +1206,8 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, ...@@ -1206,7 +1206,8 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
*/ */
dio->lock_type = dio_lock_type; dio->lock_type = dio_lock_type;
if (dio_lock_type != DIO_NO_LOCKING) { 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; struct address_space *mapping;
mapping = iocb->ki_filp->f_mapping; mapping = iocb->ki_filp->f_mapping;
...@@ -1214,7 +1215,9 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, ...@@ -1214,7 +1215,9 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
down(&inode->i_sem); down(&inode->i_sem);
reader_with_isem = 1; reader_with_isem = 1;
} }
retval = filemap_write_and_wait(mapping);
retval = filemap_write_and_wait_range(mapping, offset,
end - 1);
if (retval) { if (retval) {
kfree(dio); kfree(dio);
goto out; goto out;
......
...@@ -1360,6 +1360,8 @@ extern int filemap_fdatawrite(struct address_space *); ...@@ -1360,6 +1360,8 @@ extern int filemap_fdatawrite(struct address_space *);
extern int filemap_flush(struct address_space *); extern int filemap_flush(struct address_space *);
extern int filemap_fdatawait(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(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_supers(void);
extern void sync_filesystems(int wait); extern void sync_filesystems(int wait);
extern void emergency_sync(void); extern void emergency_sync(void);
......
...@@ -336,6 +336,22 @@ int filemap_write_and_wait(struct address_space *mapping) ...@@ -336,6 +336,22 @@ int filemap_write_and_wait(struct address_space *mapping)
return retval; 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: * This function is used to add newly allocated pagecache pages:
* the page is new, so we can just run SetPageLocked() against it. * the page is new, so we can just run SetPageLocked() against it.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment