diff options
| author | David Woodhouse <dwmw2@infradead.org> | 2007-04-26 04:31:28 -0400 |
|---|---|---|
| committer | David Woodhouse <dwmw2@infradead.org> | 2007-04-26 04:31:28 -0400 |
| commit | ef2e58ea6b9931c3a4816c66593da49bb20e3b24 (patch) | |
| tree | ce7432add3becbe78de4ea06425cd2d9e91f4ada /mm/filemap.c | |
| parent | 06d63cc51d47f572009138a7f3ac34d95773405d (diff) | |
| parent | de46c33745f5e2ad594c72f2cf5f490861b16ce1 (diff) | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'mm/filemap.c')
| -rw-r--r-- | mm/filemap.c | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index d1060b8d3cd6..5dfc093ceb3d 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -2379,7 +2379,8 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | |||
| 2379 | struct file *file = iocb->ki_filp; | 2379 | struct file *file = iocb->ki_filp; |
| 2380 | struct address_space *mapping = file->f_mapping; | 2380 | struct address_space *mapping = file->f_mapping; |
| 2381 | ssize_t retval; | 2381 | ssize_t retval; |
| 2382 | size_t write_len = 0; | 2382 | size_t write_len; |
| 2383 | pgoff_t end = 0; /* silence gcc */ | ||
| 2383 | 2384 | ||
| 2384 | /* | 2385 | /* |
| 2385 | * If it's a write, unmap all mmappings of the file up-front. This | 2386 | * If it's a write, unmap all mmappings of the file up-front. This |
| @@ -2388,23 +2389,46 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | |||
| 2388 | */ | 2389 | */ |
| 2389 | if (rw == WRITE) { | 2390 | if (rw == WRITE) { |
| 2390 | write_len = iov_length(iov, nr_segs); | 2391 | write_len = iov_length(iov, nr_segs); |
| 2392 | end = (offset + write_len - 1) >> PAGE_CACHE_SHIFT; | ||
| 2391 | if (mapping_mapped(mapping)) | 2393 | if (mapping_mapped(mapping)) |
| 2392 | unmap_mapping_range(mapping, offset, write_len, 0); | 2394 | unmap_mapping_range(mapping, offset, write_len, 0); |
| 2393 | } | 2395 | } |
| 2394 | 2396 | ||
| 2395 | retval = filemap_write_and_wait(mapping); | 2397 | retval = filemap_write_and_wait(mapping); |
| 2396 | if (retval == 0) { | 2398 | if (retval) |
| 2397 | retval = mapping->a_ops->direct_IO(rw, iocb, iov, | 2399 | goto out; |
| 2398 | offset, nr_segs); | 2400 | |
| 2399 | if (rw == WRITE && mapping->nrpages) { | 2401 | /* |
| 2400 | pgoff_t end = (offset + write_len - 1) | 2402 | * After a write we want buffered reads to be sure to go to disk to get |
| 2401 | >> PAGE_CACHE_SHIFT; | 2403 | * the new data. We invalidate clean cached page from the region we're |
| 2402 | int err = invalidate_inode_pages2_range(mapping, | 2404 | * about to write. We do this *before* the write so that we can return |
| 2405 | * -EIO without clobbering -EIOCBQUEUED from ->direct_IO(). | ||
| 2406 | */ | ||
| 2407 | if (rw == WRITE && mapping->nrpages) { | ||
| 2408 | retval = invalidate_inode_pages2_range(mapping, | ||
| 2403 | offset >> PAGE_CACHE_SHIFT, end); | 2409 | offset >> PAGE_CACHE_SHIFT, end); |
| 2404 | if (err) | 2410 | if (retval) |
| 2405 | retval = err; | 2411 | goto out; |
| 2406 | } | ||
| 2407 | } | 2412 | } |
| 2413 | |||
| 2414 | retval = mapping->a_ops->direct_IO(rw, iocb, iov, offset, nr_segs); | ||
| 2415 | if (retval) | ||
| 2416 | goto out; | ||
| 2417 | |||
| 2418 | /* | ||
| 2419 | * Finally, try again to invalidate clean pages which might have been | ||
| 2420 | * faulted in by get_user_pages() if the source of the write was an | ||
| 2421 | * mmap()ed region of the file we're writing. That's a pretty crazy | ||
| 2422 | * thing to do, so we don't support it 100%. If this invalidation | ||
| 2423 | * fails and we have -EIOCBQUEUED we ignore the failure. | ||
| 2424 | */ | ||
| 2425 | if (rw == WRITE && mapping->nrpages) { | ||
| 2426 | int err = invalidate_inode_pages2_range(mapping, | ||
| 2427 | offset >> PAGE_CACHE_SHIFT, end); | ||
| 2428 | if (err && retval >= 0) | ||
| 2429 | retval = err; | ||
| 2430 | } | ||
| 2431 | out: | ||
| 2408 | return retval; | 2432 | return retval; |
| 2409 | } | 2433 | } |
| 2410 | 2434 | ||
