aboutsummaryrefslogtreecommitdiffstats
path: root/mm/filemap.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/filemap.c')
-rw-r--r--mm/filemap.c55
1 files changed, 47 insertions, 8 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 7c7addb9333c..cb26e33fd0ff 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -75,8 +75,8 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
75 * ->mmap_sem 75 * ->mmap_sem
76 * ->lock_page (access_process_vm) 76 * ->lock_page (access_process_vm)
77 * 77 *
78 * ->mmap_sem 78 * ->i_mutex (generic_file_buffered_write)
79 * ->i_mutex (msync) 79 * ->mmap_sem (fault_in_pages_readable->do_page_fault)
80 * 80 *
81 * ->i_mutex 81 * ->i_mutex
82 * ->i_alloc_sem (various) 82 * ->i_alloc_sem (various)
@@ -2236,7 +2236,7 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
2236 unsigned long nr_segs, loff_t *ppos) 2236 unsigned long nr_segs, loff_t *ppos)
2237{ 2237{
2238 struct file *file = iocb->ki_filp; 2238 struct file *file = iocb->ki_filp;
2239 const struct address_space * mapping = file->f_mapping; 2239 struct address_space * mapping = file->f_mapping;
2240 size_t ocount; /* original count */ 2240 size_t ocount; /* original count */
2241 size_t count; /* after file limit checks */ 2241 size_t count; /* after file limit checks */
2242 struct inode *inode = mapping->host; 2242 struct inode *inode = mapping->host;
@@ -2289,8 +2289,11 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
2289 2289
2290 /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ 2290 /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
2291 if (unlikely(file->f_flags & O_DIRECT)) { 2291 if (unlikely(file->f_flags & O_DIRECT)) {
2292 written = generic_file_direct_write(iocb, iov, 2292 loff_t endbyte;
2293 &nr_segs, pos, ppos, count, ocount); 2293 ssize_t written_buffered;
2294
2295 written = generic_file_direct_write(iocb, iov, &nr_segs, pos,
2296 ppos, count, ocount);
2294 if (written < 0 || written == count) 2297 if (written < 0 || written == count)
2295 goto out; 2298 goto out;
2296 /* 2299 /*
@@ -2299,10 +2302,46 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
2299 */ 2302 */
2300 pos += written; 2303 pos += written;
2301 count -= written; 2304 count -= written;
2302 } 2305 written_buffered = generic_file_buffered_write(iocb, iov,
2306 nr_segs, pos, ppos, count,
2307 written);
2308 /*
2309 * If generic_file_buffered_write() retuned a synchronous error
2310 * then we want to return the number of bytes which were
2311 * direct-written, or the error code if that was zero. Note
2312 * that this differs from normal direct-io semantics, which
2313 * will return -EFOO even if some bytes were written.
2314 */
2315 if (written_buffered < 0) {
2316 err = written_buffered;
2317 goto out;
2318 }
2303 2319
2304 written = generic_file_buffered_write(iocb, iov, nr_segs, 2320 /*
2305 pos, ppos, count, written); 2321 * We need to ensure that the page cache pages are written to
2322 * disk and invalidated to preserve the expected O_DIRECT
2323 * semantics.
2324 */
2325 endbyte = pos + written_buffered - written - 1;
2326 err = do_sync_file_range(file, pos, endbyte,
2327 SYNC_FILE_RANGE_WAIT_BEFORE|
2328 SYNC_FILE_RANGE_WRITE|
2329 SYNC_FILE_RANGE_WAIT_AFTER);
2330 if (err == 0) {
2331 written = written_buffered;
2332 invalidate_mapping_pages(mapping,
2333 pos >> PAGE_CACHE_SHIFT,
2334 endbyte >> PAGE_CACHE_SHIFT);
2335 } else {
2336 /*
2337 * We don't know how much we wrote, so just return
2338 * the number of bytes which were direct-written
2339 */
2340 }
2341 } else {
2342 written = generic_file_buffered_write(iocb, iov, nr_segs,
2343 pos, ppos, count, written);
2344 }
2306out: 2345out:
2307 current->backing_dev_info = NULL; 2346 current->backing_dev_info = NULL;
2308 return written ? written : err; 2347 return written ? written : err;