aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2009-01-06 17:40:22 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-06 18:59:09 -0500
commit48b47c561e41525061b5bc0cfd67d6367fd11dc4 (patch)
treeae99a8cb55b4d2716847521953db4bddd66b8e8b
parent48aae42556e5ea1ba0d8ddab25352706577af2ed (diff)
mm: direct IO starvation improvement
Direct IO can invalidate and sync a lot of pagecache pages in the mapping. A 4K direct IO will actually try to sync and/or invalidate the pagecache of the entire file, for example (which might be many GB or TB large). Improve this by doing range syncs. Also, memory no longer has to be unmapped to catch the dirty bits for syncing, as dirty bits would remain coherent due to dirty mmap accounting. This fixes the immediate DM deadlocks when doing direct IO reads to block device with a mounted filesystem, if only by papering over the problem somewhat rather than addressing the fsync starvation cases. Signed-off-by: Nick Piggin <npiggin@suse.de> Reviewed-by: Jeff Moyer <jmoyer@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/filemap.c16
1 files changed, 5 insertions, 11 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 9c5e6235cc74..f3555fb806d3 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1317,7 +1317,8 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
1317 goto out; /* skip atime */ 1317 goto out; /* skip atime */
1318 size = i_size_read(inode); 1318 size = i_size_read(inode);
1319 if (pos < size) { 1319 if (pos < size) {
1320 retval = filemap_write_and_wait(mapping); 1320 retval = filemap_write_and_wait_range(mapping, pos,
1321 pos + iov_length(iov, nr_segs) - 1);
1321 if (!retval) { 1322 if (!retval) {
1322 retval = mapping->a_ops->direct_IO(READ, iocb, 1323 retval = mapping->a_ops->direct_IO(READ, iocb,
1323 iov, pos, nr_segs); 1324 iov, pos, nr_segs);
@@ -2059,18 +2060,10 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
2059 if (count != ocount) 2060 if (count != ocount)
2060 *nr_segs = iov_shorten((struct iovec *)iov, *nr_segs, count); 2061 *nr_segs = iov_shorten((struct iovec *)iov, *nr_segs, count);
2061 2062
2062 /*
2063 * Unmap all mmappings of the file up-front.
2064 *
2065 * This will cause any pte dirty bits to be propagated into the
2066 * pageframes for the subsequent filemap_write_and_wait().
2067 */
2068 write_len = iov_length(iov, *nr_segs); 2063 write_len = iov_length(iov, *nr_segs);
2069 end = (pos + write_len - 1) >> PAGE_CACHE_SHIFT; 2064 end = (pos + write_len - 1) >> PAGE_CACHE_SHIFT;
2070 if (mapping_mapped(mapping))
2071 unmap_mapping_range(mapping, pos, write_len, 0);
2072 2065
2073 written = filemap_write_and_wait(mapping); 2066 written = filemap_write_and_wait_range(mapping, pos, pos + write_len - 1);
2074 if (written) 2067 if (written)
2075 goto out; 2068 goto out;
2076 2069
@@ -2290,7 +2283,8 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
2290 * the file data here, to try to honour O_DIRECT expectations. 2283 * the file data here, to try to honour O_DIRECT expectations.
2291 */ 2284 */
2292 if (unlikely(file->f_flags & O_DIRECT) && written) 2285 if (unlikely(file->f_flags & O_DIRECT) && written)
2293 status = filemap_write_and_wait(mapping); 2286 status = filemap_write_and_wait_range(mapping,
2287 pos, pos + written - 1);
2294 2288
2295 return written ? written : status; 2289 return written ? written : status;
2296} 2290}