lkml.org 
[lkml]   [2013]   [Jan]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH V6 03/30] iov_iter: add copy_to_user support
    Date
    From: Zach Brown <zab@zabbo.net>

    This adds iov_iter wrappers around copy_to_user() to match the existing
    wrappers around copy_from_user().

    This will be used by the generic file system buffered read path.

    Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
    Cc: Zach Brown <zab@zabbo.net>
    ---
    fs/iov-iter.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
    include/linux/fs.h | 4 +++
    2 files changed, 84 insertions(+)

    diff --git a/fs/iov-iter.c b/fs/iov-iter.c
    index 5c4f3a5..d68b67f 100644
    --- a/fs/iov-iter.c
    +++ b/fs/iov-iter.c
    @@ -6,6 +6,86 @@
    #include <linux/highmem.h>
    #include <linux/pagemap.h>

    +static size_t __iovec_copy_to_user(char *vaddr, const struct iovec *iov,
    + size_t base, size_t bytes, int atomic)
    +{
    + size_t copied = 0, left = 0;
    +
    + while (bytes) {
    + char __user *buf = iov->iov_base + base;
    + int copy = min(bytes, iov->iov_len - base);
    +
    + base = 0;
    + if (atomic)
    + left = __copy_to_user_inatomic(buf, vaddr, copy);
    + else
    + left = copy_to_user(buf, vaddr, copy);
    + copied += copy;
    + bytes -= copy;
    + vaddr += copy;
    + iov++;
    +
    + if (unlikely(left))
    + break;
    + }
    + return copied - left;
    +}
    +
    +/*
    + * Copy as much as we can into the page and return the number of bytes which
    + * were sucessfully copied. If a fault is encountered then return the number of
    + * bytes which were copied.
    + */
    +size_t iov_iter_copy_to_user_atomic(struct page *page,
    + struct iov_iter *i, unsigned long offset, size_t bytes)
    +{
    + char *kaddr;
    + size_t copied;
    +
    + BUG_ON(!in_atomic());
    + kaddr = kmap_atomic(page);
    + if (likely(i->nr_segs == 1)) {
    + int left;
    + char __user *buf = i->iov->iov_base + i->iov_offset;
    + left = __copy_to_user_inatomic(buf, kaddr + offset, bytes);
    + copied = bytes - left;
    + } else {
    + copied = __iovec_copy_to_user(kaddr + offset, i->iov,
    + i->iov_offset, bytes, 1);
    + }
    + kunmap_atomic(kaddr);
    +
    + return copied;
    +}
    +EXPORT_SYMBOL(iov_iter_copy_to_user_atomic);
    +
    +/*
    + * This has the same sideeffects and return value as
    + * iov_iter_copy_to_user_atomic().
    + * The difference is that it attempts to resolve faults.
    + * Page must not be locked.
    + */
    +size_t iov_iter_copy_to_user(struct page *page,
    + struct iov_iter *i, unsigned long offset, size_t bytes)
    +{
    + char *kaddr;
    + size_t copied;
    +
    + kaddr = kmap(page);
    + if (likely(i->nr_segs == 1)) {
    + int left;
    + char __user *buf = i->iov->iov_base + i->iov_offset;
    + left = copy_to_user(buf, kaddr + offset, bytes);
    + copied = bytes - left;
    + } else {
    + copied = __iovec_copy_to_user(kaddr + offset, i->iov,
    + i->iov_offset, bytes, 0);
    + }
    + kunmap(page);
    + return copied;
    +}
    +EXPORT_SYMBOL(iov_iter_copy_to_user);
    +
    static size_t __iovec_copy_from_user(char *vaddr, const struct iovec *iov,
    size_t base, size_t bytes, int atomic)
    {
    diff --git a/include/linux/fs.h b/include/linux/fs.h
    index 7617ee0..640f2cd 100644
    --- a/include/linux/fs.h
    +++ b/include/linux/fs.h
    @@ -295,6 +295,10 @@ struct iov_iter {
    size_t count;
    };

    +size_t iov_iter_copy_to_user_atomic(struct page *page,
    + struct iov_iter *i, unsigned long offset, size_t bytes);
    +size_t iov_iter_copy_to_user(struct page *page,
    + struct iov_iter *i, unsigned long offset, size_t bytes);
    size_t iov_iter_copy_from_user_atomic(struct page *page,
    struct iov_iter *i, unsigned long offset, size_t bytes);
    size_t iov_iter_copy_from_user(struct page *page,
    --
    1.8.1.1


    \
     
     \ /
      Last update: 2013-01-29 21:41    [W:6.725 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site