]> 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 1694623a628902b76e11d6983eebd1ea7d33ddf1..d6e67be1802ef5290a3d49ebbc8464eaf0353a90 100644 (file)
@@ -2033,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);
@@ -2044,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
@@ -2059,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;
        }
@@ -2704,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;
@@ -2733,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
@@ -2751,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;
 }