]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - mm/filemap.c
fix braino in generic_file_read_iter()
[karo-tx-linux.git] / mm / filemap.c
index 1944c631e3e660d6d06d72e8b23096d44d0183ea..d6e67be1802ef5290a3d49ebbc8464eaf0353a90 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/compiler.h>
 #include <linux/dax.h>
 #include <linux/fs.h>
+#include <linux/sched/signal.h>
 #include <linux/uaccess.h>
 #include <linux/capability.h>
 #include <linux/kernel_stat.h>
@@ -2032,7 +2033,6 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
        if (iocb->ki_flags & IOCB_DIRECT) {
                struct address_space *mapping = file->f_mapping;
                struct inode *inode = mapping->host;
-               struct iov_iter data = *iter;
                loff_t size;
 
                size = i_size_read(inode);
@@ -2043,11 +2043,12 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
 
                file_accessed(file);
 
-               retval = mapping->a_ops->direct_IO(iocb, &data);
+               retval = mapping->a_ops->direct_IO(iocb, iter);
                if (retval >= 0) {
                        iocb->ki_pos += retval;
-                       iov_iter_advance(iter, retval);
+                       count -= retval;
                }
+               iov_iter_revert(iter, count - iov_iter_count(iter));
 
                /*
                 * Btrfs can have a short DIO read if we encounter
@@ -2058,7 +2059,7 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
                 * the rest of the read.  Buffered reads will not work for
                 * DAX files, so don't bother trying.
                 */
-               if (retval < 0 || !iov_iter_count(iter) || iocb->ki_pos >= size ||
+               if (retval < 0 || !count || iocb->ki_pos >= size ||
                    IS_DAX(inode))
                        goto out;
        }
@@ -2703,7 +2704,6 @@ generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from)
        ssize_t         written;
        size_t          write_len;
        pgoff_t         end;
-       struct iov_iter data;
 
        write_len = iov_iter_count(from);
        end = (pos + write_len - 1) >> PAGE_SHIFT;
@@ -2732,8 +2732,7 @@ generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from)
                }
        }
 
-       data = *from;
-       written = mapping->a_ops->direct_IO(iocb, &data);
+       written = mapping->a_ops->direct_IO(iocb, from);
 
        /*
         * Finally, try again to invalidate clean pages which might have been
@@ -2750,13 +2749,14 @@ generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from)
 
        if (written > 0) {
                pos += written;
-               iov_iter_advance(from, written);
+               write_len -= written;
                if (pos > i_size_read(inode) && !S_ISBLK(inode->i_mode)) {
                        i_size_write(inode, pos);
                        mark_inode_dirty(inode);
                }
                iocb->ki_pos = pos;
        }
+       iov_iter_revert(from, write_len - iov_iter_count(from));
 out:
        return written;
 }