aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-04-07 10:22:53 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-04-11 22:29:47 -0400
commit0b8def9d6dfa6b2a9a2740cf81d8d2c134688d39 (patch)
treeb9f8769682257d9a8ec4ccb0a3253d021fd68ce8 /mm
parente9d1593d4e9311bca040ecf6ec7599e6f235140c (diff)
__generic_file_write_iter: keep ->ki_pos and return value consistent
A side effect worth noting: in O_APPEND case we set ->ki_pos early, so if it turns out to be an error or a zero-length write, we'll end up with ->ki_pos modified. Safe, since all callers never look at the ->ki_pos after the call of __generic_file_write_iter() returning non-positive, all the way to caller of ->write_iter() and those discard ->ki_pos when getting that. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'mm')
-rw-r--r--mm/filemap.c24
1 files changed, 10 insertions, 14 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 9920db455f05..353f82e09e63 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2557,7 +2557,6 @@ ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
2557 struct file *file = iocb->ki_filp; 2557 struct file *file = iocb->ki_filp;
2558 struct address_space * mapping = file->f_mapping; 2558 struct address_space * mapping = file->f_mapping;
2559 struct inode *inode = mapping->host; 2559 struct inode *inode = mapping->host;
2560 loff_t pos = iocb->ki_pos;
2561 ssize_t written = 0; 2560 ssize_t written = 0;
2562 ssize_t err; 2561 ssize_t err;
2563 ssize_t status; 2562 ssize_t status;
@@ -2565,7 +2564,7 @@ ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
2565 2564
2566 /* We can write back this queue in page reclaim */ 2565 /* We can write back this queue in page reclaim */
2567 current->backing_dev_info = inode_to_bdi(inode); 2566 current->backing_dev_info = inode_to_bdi(inode);
2568 err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); 2567 err = generic_write_checks(file, &iocb->ki_pos, &count, S_ISBLK(inode->i_mode));
2569 if (err) 2568 if (err)
2570 goto out; 2569 goto out;
2571 2570
@@ -2583,9 +2582,9 @@ ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
2583 goto out; 2582 goto out;
2584 2583
2585 if (io_is_direct(file)) { 2584 if (io_is_direct(file)) {
2586 loff_t endbyte; 2585 loff_t pos, endbyte;
2587 2586
2588 written = generic_file_direct_write(iocb, from, pos); 2587 written = generic_file_direct_write(iocb, from, iocb->ki_pos);
2589 /* 2588 /*
2590 * If the write stopped short of completing, fall back to 2589 * If the write stopped short of completing, fall back to
2591 * buffered writes. Some filesystems do this for writes to 2590 * buffered writes. Some filesystems do this for writes to
@@ -2593,13 +2592,10 @@ ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
2593 * not succeed (even if it did, DAX does not handle dirty 2592 * not succeed (even if it did, DAX does not handle dirty
2594 * page-cache pages correctly). 2593 * page-cache pages correctly).
2595 */ 2594 */
2596 if (written < 0 || written == count || IS_DAX(inode)) 2595 if (written < 0 || !iov_iter_count(from) || IS_DAX(inode))
2597 goto out; 2596 goto out;
2598 2597
2599 pos += written; 2598 status = generic_perform_write(file, from, pos = iocb->ki_pos);
2600 count -= written;
2601
2602 status = generic_perform_write(file, from, pos);
2603 /* 2599 /*
2604 * If generic_perform_write() returned a synchronous error 2600 * If generic_perform_write() returned a synchronous error
2605 * then we want to return the number of bytes which were 2601 * then we want to return the number of bytes which were
@@ -2611,15 +2607,15 @@ ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
2611 err = status; 2607 err = status;
2612 goto out; 2608 goto out;
2613 } 2609 }
2614 iocb->ki_pos = pos + status;
2615 /* 2610 /*
2616 * We need to ensure that the page cache pages are written to 2611 * We need to ensure that the page cache pages are written to
2617 * disk and invalidated to preserve the expected O_DIRECT 2612 * disk and invalidated to preserve the expected O_DIRECT
2618 * semantics. 2613 * semantics.
2619 */ 2614 */
2620 endbyte = pos + status - 1; 2615 endbyte = pos + status - 1;
2621 err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte); 2616 err = filemap_write_and_wait_range(mapping, pos, endbyte);
2622 if (err == 0) { 2617 if (err == 0) {
2618 iocb->ki_pos = endbyte + 1;
2623 written += status; 2619 written += status;
2624 invalidate_mapping_pages(mapping, 2620 invalidate_mapping_pages(mapping,
2625 pos >> PAGE_CACHE_SHIFT, 2621 pos >> PAGE_CACHE_SHIFT,
@@ -2631,9 +2627,9 @@ ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
2631 */ 2627 */
2632 } 2628 }
2633 } else { 2629 } else {
2634 written = generic_perform_write(file, from, pos); 2630 written = generic_perform_write(file, from, iocb->ki_pos);
2635 if (likely(written >= 0)) 2631 if (likely(written > 0))
2636 iocb->ki_pos = pos + written; 2632 iocb->ki_pos += written;
2637 } 2633 }
2638out: 2634out:
2639 current->backing_dev_info = NULL; 2635 current->backing_dev_info = NULL;