aboutsummaryrefslogtreecommitdiffstats
path: root/mm/filemap.c
diff options
context:
space:
mode:
authorJeff Moyer <jmoyer@redhat.com>2006-10-20 02:28:13 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-20 13:26:35 -0400
commitfb5527e68d495650a7658fec9a7246bf922db212 (patch)
treedc0c993c3f07ddf1d1cf02a725ac3348f638d7bc /mm/filemap.c
parente8e82b76e0312827f5ae04b573a05b02854a447e (diff)
[PATCH] direct-io: sync and invalidate file region when falling back to buffered write
When direct-io falls back to buffered write, it will just leave the dirty data floating about in pagecache, pending regular writeback. But normal direct-io semantics are that IO is synchronous, and that it leaves no pagecache behind. So change the fallback-to-buffered-write code to sync the file region and to then strip away the pagecache, just as a regular direct-io write would do. Acked-by: Jeff Moyer <jmoyer@redhat.com> Cc: Zach Brown <zach.brown@oracle.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm/filemap.c')
-rw-r--r--mm/filemap.c51
1 files changed, 45 insertions, 6 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 3464b681f844..57faa8d12099 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2222,7 +2222,7 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
2222 unsigned long nr_segs, loff_t *ppos) 2222 unsigned long nr_segs, loff_t *ppos)
2223{ 2223{
2224 struct file *file = iocb->ki_filp; 2224 struct file *file = iocb->ki_filp;
2225 const struct address_space * mapping = file->f_mapping; 2225 struct address_space * mapping = file->f_mapping;
2226 size_t ocount; /* original count */ 2226 size_t ocount; /* original count */
2227 size_t count; /* after file limit checks */ 2227 size_t count; /* after file limit checks */
2228 struct inode *inode = mapping->host; 2228 struct inode *inode = mapping->host;
@@ -2275,8 +2275,11 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
2275 2275
2276 /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ 2276 /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
2277 if (unlikely(file->f_flags & O_DIRECT)) { 2277 if (unlikely(file->f_flags & O_DIRECT)) {
2278 written = generic_file_direct_write(iocb, iov, 2278 loff_t endbyte;
2279 &nr_segs, pos, ppos, count, ocount); 2279 ssize_t written_buffered;
2280
2281 written = generic_file_direct_write(iocb, iov, &nr_segs, pos,
2282 ppos, count, ocount);
2280 if (written < 0 || written == count) 2283 if (written < 0 || written == count)
2281 goto out; 2284 goto out;
2282 /* 2285 /*
@@ -2285,10 +2288,46 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
2285 */ 2288 */
2286 pos += written; 2289 pos += written;
2287 count -= written; 2290 count -= written;
2288 } 2291 written_buffered = generic_file_buffered_write(iocb, iov,
2292 nr_segs, pos, ppos, count,
2293 written);
2294 /*
2295 * If generic_file_buffered_write() retuned a synchronous error
2296 * then we want to return the number of bytes which were
2297 * direct-written, or the error code if that was zero. Note
2298 * that this differs from normal direct-io semantics, which
2299 * will return -EFOO even if some bytes were written.
2300 */
2301 if (written_buffered < 0) {
2302 err = written_buffered;
2303 goto out;
2304 }
2289 2305
2290 written = generic_file_buffered_write(iocb, iov, nr_segs, 2306 /*
2291 pos, ppos, count, written); 2307 * We need to ensure that the page cache pages are written to
2308 * disk and invalidated to preserve the expected O_DIRECT
2309 * semantics.
2310 */
2311 endbyte = pos + written_buffered - written - 1;
2312 err = do_sync_file_range(file, pos, endbyte,
2313 SYNC_FILE_RANGE_WAIT_BEFORE|
2314 SYNC_FILE_RANGE_WRITE|
2315 SYNC_FILE_RANGE_WAIT_AFTER);
2316 if (err == 0) {
2317 written = written_buffered;
2318 invalidate_mapping_pages(mapping,
2319 pos >> PAGE_CACHE_SHIFT,
2320 endbyte >> PAGE_CACHE_SHIFT);
2321 } else {
2322 /*
2323 * We don't know how much we wrote, so just return
2324 * the number of bytes which were direct-written
2325 */
2326 }
2327 } else {
2328 written = generic_file_buffered_write(iocb, iov, nr_segs,
2329 pos, ppos, count, written);
2330 }
2292out: 2331out:
2293 current->backing_dev_info = NULL; 2332 current->backing_dev_info = NULL;
2294 return written ? written : err; 2333 return written ? written : err;