|
@@ -1085,11 +1085,90 @@ static void shrink_readahead_size_eio(struct file *filp,
|
|
|
ra->ra_pages /= 4;
|
|
|
}
|
|
|
|
|
|
+size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
|
|
|
+ struct iov_iter *i)
|
|
|
+{
|
|
|
+ size_t skip, copy, left, wanted;
|
|
|
+ const struct iovec *iov;
|
|
|
+ char __user *buf;
|
|
|
+ void *kaddr, *from;
|
|
|
+
|
|
|
+ if (unlikely(bytes > i->count))
|
|
|
+ bytes = i->count;
|
|
|
+
|
|
|
+ if (unlikely(!bytes))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ wanted = bytes;
|
|
|
+ iov = i->iov;
|
|
|
+ skip = i->iov_offset;
|
|
|
+ buf = iov->iov_base + skip;
|
|
|
+ copy = min(bytes, iov->iov_len - skip);
|
|
|
+
|
|
|
+ if (!fault_in_pages_writeable(buf, copy)) {
|
|
|
+ kaddr = kmap_atomic(page);
|
|
|
+ from = kaddr + offset;
|
|
|
+
|
|
|
+ /* first chunk, usually the only one */
|
|
|
+ left = __copy_to_user_inatomic(buf, from, copy);
|
|
|
+ copy -= left;
|
|
|
+ skip += copy;
|
|
|
+ from += copy;
|
|
|
+ bytes -= copy;
|
|
|
+
|
|
|
+ while (unlikely(!left && bytes)) {
|
|
|
+ iov++;
|
|
|
+ buf = iov->iov_base;
|
|
|
+ copy = min(bytes, iov->iov_len);
|
|
|
+ left = __copy_to_user_inatomic(buf, from, copy);
|
|
|
+ copy -= left;
|
|
|
+ skip = copy;
|
|
|
+ from += copy;
|
|
|
+ bytes -= copy;
|
|
|
+ }
|
|
|
+ if (likely(!bytes)) {
|
|
|
+ kunmap_atomic(kaddr);
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ offset = from - kaddr;
|
|
|
+ buf += copy;
|
|
|
+ kunmap_atomic(kaddr);
|
|
|
+ copy = min(bytes, iov->iov_len - skip);
|
|
|
+ }
|
|
|
+ /* Too bad - revert to non-atomic kmap */
|
|
|
+ kaddr = kmap(page);
|
|
|
+ from = kaddr + offset;
|
|
|
+ left = __copy_to_user(buf, from, copy);
|
|
|
+ copy -= left;
|
|
|
+ skip += copy;
|
|
|
+ from += copy;
|
|
|
+ bytes -= copy;
|
|
|
+ while (unlikely(!left && bytes)) {
|
|
|
+ iov++;
|
|
|
+ buf = iov->iov_base;
|
|
|
+ copy = min(bytes, iov->iov_len);
|
|
|
+ left = __copy_to_user(buf, from, copy);
|
|
|
+ copy -= left;
|
|
|
+ skip = copy;
|
|
|
+ from += copy;
|
|
|
+ bytes -= copy;
|
|
|
+ }
|
|
|
+ kunmap(page);
|
|
|
+done:
|
|
|
+ i->count -= wanted - bytes;
|
|
|
+ i->nr_segs -= iov - i->iov;
|
|
|
+ i->iov = iov;
|
|
|
+ i->iov_offset = skip;
|
|
|
+ return wanted - bytes;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(copy_page_to_iter);
|
|
|
+
|
|
|
/**
|
|
|
* do_generic_file_read - generic file read routine
|
|
|
* @filp: the file to read
|
|
|
* @ppos: current file position
|
|
|
- * @desc: read_descriptor
|
|
|
+ * @iter: data destination
|
|
|
+ * @written: already copied
|
|
|
*
|
|
|
* This is a generic file read routine, and uses the
|
|
|
* mapping->a_ops->readpage() function for the actual low-level stuff.
|
|
@@ -1097,8 +1176,8 @@ static void shrink_readahead_size_eio(struct file *filp,
|
|
|
* This is really ugly. But the goto's actually try to clarify some
|
|
|
* of the logic when it comes to error handling etc.
|
|
|
*/
|
|
|
-static void do_generic_file_read(struct file *filp, loff_t *ppos,
|
|
|
- read_descriptor_t *desc)
|
|
|
+static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos,
|
|
|
+ struct iov_iter *iter, ssize_t written)
|
|
|
{
|
|
|
struct address_space *mapping = filp->f_mapping;
|
|
|
struct inode *inode = mapping->host;
|
|
@@ -1108,12 +1187,12 @@ static void do_generic_file_read(struct file *filp, loff_t *ppos,
|
|
|
pgoff_t prev_index;
|
|
|
unsigned long offset; /* offset into pagecache page */
|
|
|
unsigned int prev_offset;
|
|
|
- int error;
|
|
|
+ int error = 0;
|
|
|
|
|
|
index = *ppos >> PAGE_CACHE_SHIFT;
|
|
|
prev_index = ra->prev_pos >> PAGE_CACHE_SHIFT;
|
|
|
prev_offset = ra->prev_pos & (PAGE_CACHE_SIZE-1);
|
|
|
- last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
|
|
|
+ last_index = (*ppos + iter->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
|
|
|
offset = *ppos & ~PAGE_CACHE_MASK;
|
|
|
|
|
|
for (;;) {
|
|
@@ -1148,7 +1227,7 @@ find_page:
|
|
|
if (!page->mapping)
|
|
|
goto page_not_up_to_date_locked;
|
|
|
if (!mapping->a_ops->is_partially_uptodate(page,
|
|
|
- offset, desc->count))
|
|
|
+ offset, iter->count))
|
|
|
goto page_not_up_to_date_locked;
|
|
|
unlock_page(page);
|
|
|
}
|
|
@@ -1198,24 +1277,23 @@ page_ok:
|
|
|
/*
|
|
|
* Ok, we have the page, and it's up-to-date, so
|
|
|
* now we can copy it to user space...
|
|
|
- *
|
|
|
- * The file_read_actor routine returns how many bytes were
|
|
|
- * actually used..
|
|
|
- * NOTE! This may not be the same as how much of a user buffer
|
|
|
- * we filled up (we may be padding etc), so we can only update
|
|
|
- * "pos" here (the actor routine has to update the user buffer
|
|
|
- * pointers and the remaining count).
|
|
|
*/
|
|
|
- ret = file_read_actor(desc, page, offset, nr);
|
|
|
+
|
|
|
+ ret = copy_page_to_iter(page, offset, nr, iter);
|
|
|
offset += ret;
|
|
|
index += offset >> PAGE_CACHE_SHIFT;
|
|
|
offset &= ~PAGE_CACHE_MASK;
|
|
|
prev_offset = offset;
|
|
|
|
|
|
page_cache_release(page);
|
|
|
- if (ret == nr && desc->count)
|
|
|
- continue;
|
|
|
- goto out;
|
|
|
+ written += ret;
|
|
|
+ if (!iov_iter_count(iter))
|
|
|
+ goto out;
|
|
|
+ if (ret < nr) {
|
|
|
+ error = -EFAULT;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ continue;
|
|
|
|
|
|
page_not_up_to_date:
|
|
|
/* Get exclusive access to the page ... */
|
|
@@ -1250,6 +1328,7 @@ readpage:
|
|
|
if (unlikely(error)) {
|
|
|
if (error == AOP_TRUNCATED_PAGE) {
|
|
|
page_cache_release(page);
|
|
|
+ error = 0;
|
|
|
goto find_page;
|
|
|
}
|
|
|
goto readpage_error;
|
|
@@ -1280,7 +1359,6 @@ readpage:
|
|
|
|
|
|
readpage_error:
|
|
|
/* UHHUH! A synchronous read error occurred. Report it */
|
|
|
- desc->error = error;
|
|
|
page_cache_release(page);
|
|
|
goto out;
|
|
|
|
|
@@ -1291,16 +1369,17 @@ no_cached_page:
|
|
|
*/
|
|
|
page = page_cache_alloc_cold(mapping);
|
|
|
if (!page) {
|
|
|
- desc->error = -ENOMEM;
|
|
|
+ error = -ENOMEM;
|
|
|
goto out;
|
|
|
}
|
|
|
error = add_to_page_cache_lru(page, mapping,
|
|
|
index, GFP_KERNEL);
|
|
|
if (error) {
|
|
|
page_cache_release(page);
|
|
|
- if (error == -EEXIST)
|
|
|
+ if (error == -EEXIST) {
|
|
|
+ error = 0;
|
|
|
goto find_page;
|
|
|
- desc->error = error;
|
|
|
+ }
|
|
|
goto out;
|
|
|
}
|
|
|
goto readpage;
|
|
@@ -1313,44 +1392,7 @@ out:
|
|
|
|
|
|
*ppos = ((loff_t)index << PAGE_CACHE_SHIFT) + offset;
|
|
|
file_accessed(filp);
|
|
|
-}
|
|
|
-
|
|
|
-int file_read_actor(read_descriptor_t *desc, struct page *page,
|
|
|
- unsigned long offset, unsigned long size)
|
|
|
-{
|
|
|
- char *kaddr;
|
|
|
- unsigned long left, count = desc->count;
|
|
|
-
|
|
|
- if (size > count)
|
|
|
- size = count;
|
|
|
-
|
|
|
- /*
|
|
|
- * Faults on the destination of a read are common, so do it before
|
|
|
- * taking the kmap.
|
|
|
- */
|
|
|
- if (!fault_in_pages_writeable(desc->arg.buf, size)) {
|
|
|
- kaddr = kmap_atomic(page);
|
|
|
- left = __copy_to_user_inatomic(desc->arg.buf,
|
|
|
- kaddr + offset, size);
|
|
|
- kunmap_atomic(kaddr);
|
|
|
- if (left == 0)
|
|
|
- goto success;
|
|
|
- }
|
|
|
-
|
|
|
- /* Do it the slow way */
|
|
|
- kaddr = kmap(page);
|
|
|
- left = __copy_to_user(desc->arg.buf, kaddr + offset, size);
|
|
|
- kunmap(page);
|
|
|
-
|
|
|
- if (left) {
|
|
|
- size -= left;
|
|
|
- desc->error = -EFAULT;
|
|
|
- }
|
|
|
-success:
|
|
|
- desc->count = count - size;
|
|
|
- desc->written += size;
|
|
|
- desc->arg.buf += size;
|
|
|
- return size;
|
|
|
+ return written ? written : error;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -1408,14 +1450,15 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
|
|
{
|
|
|
struct file *filp = iocb->ki_filp;
|
|
|
ssize_t retval;
|
|
|
- unsigned long seg = 0;
|
|
|
size_t count;
|
|
|
loff_t *ppos = &iocb->ki_pos;
|
|
|
+ struct iov_iter i;
|
|
|
|
|
|
count = 0;
|
|
|
retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
|
|
|
if (retval)
|
|
|
return retval;
|
|
|
+ iov_iter_init(&i, iov, nr_segs, count, 0);
|
|
|
|
|
|
/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
|
|
|
if (filp->f_flags & O_DIRECT) {
|
|
@@ -1437,6 +1480,11 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
|
|
if (retval > 0) {
|
|
|
*ppos = pos + retval;
|
|
|
count -= retval;
|
|
|
+ /*
|
|
|
+ * If we did a short DIO read we need to skip the
|
|
|
+ * section of the iov that we've already read data into.
|
|
|
+ */
|
|
|
+ iov_iter_advance(&i, retval);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -1453,39 +1501,7 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- count = retval;
|
|
|
- for (seg = 0; seg < nr_segs; seg++) {
|
|
|
- read_descriptor_t desc;
|
|
|
- loff_t offset = 0;
|
|
|
-
|
|
|
- /*
|
|
|
- * If we did a short DIO read we need to skip the section of the
|
|
|
- * iov that we've already read data into.
|
|
|
- */
|
|
|
- if (count) {
|
|
|
- if (count > iov[seg].iov_len) {
|
|
|
- count -= iov[seg].iov_len;
|
|
|
- continue;
|
|
|
- }
|
|
|
- offset = count;
|
|
|
- count = 0;
|
|
|
- }
|
|
|
-
|
|
|
- desc.written = 0;
|
|
|
- desc.arg.buf = iov[seg].iov_base + offset;
|
|
|
- desc.count = iov[seg].iov_len - offset;
|
|
|
- if (desc.count == 0)
|
|
|
- continue;
|
|
|
- desc.error = 0;
|
|
|
- do_generic_file_read(filp, ppos, &desc);
|
|
|
- retval += desc.written;
|
|
|
- if (desc.error) {
|
|
|
- retval = retval ?: desc.error;
|
|
|
- break;
|
|
|
- }
|
|
|
- if (desc.count > 0)
|
|
|
- break;
|
|
|
- }
|
|
|
+ retval = do_generic_file_read(filp, ppos, &i, retval);
|
|
|
out:
|
|
|
return retval;
|
|
|
}
|