diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-07-16 17:10:07 +0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-07-16 17:10:07 +0400 |
commit | d26fad5b38e1c4667d4f2604936e59c837caa54d (patch) | |
tree | 04b524a69a0129c181567445bff18847a1b44721 /lib/iovec.c | |
parent | e720fff6341fe4b95e5a93c939bd3c77fa55ced4 (diff) | |
parent | 1795cd9b3a91d4b5473c97f491d63892442212ab (diff) | |
download | linux-d26fad5b38e1c4667d4f2604936e59c837caa54d.tar.xz |
Merge tag 'v3.16-rc5' into sched/core, to refresh the branch before applying bigger tree-wide changes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'lib/iovec.c')
-rw-r--r-- | lib/iovec.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/lib/iovec.c b/lib/iovec.c index 454baa88bf27..7a7c2da4cddf 100644 --- a/lib/iovec.c +++ b/lib/iovec.c @@ -51,3 +51,58 @@ int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len) return 0; } EXPORT_SYMBOL(memcpy_toiovec); + +/* + * Copy kernel to iovec. Returns -EFAULT on error. + */ + +int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata, + int offset, int len) +{ + int copy; + for (; len > 0; ++iov) { + /* Skip over the finished iovecs */ + if (unlikely(offset >= iov->iov_len)) { + offset -= iov->iov_len; + continue; + } + copy = min_t(unsigned int, iov->iov_len - offset, len); + if (copy_to_user(iov->iov_base + offset, kdata, copy)) + return -EFAULT; + offset = 0; + kdata += copy; + len -= copy; + } + + return 0; +} +EXPORT_SYMBOL(memcpy_toiovecend); + +/* + * Copy iovec to kernel. Returns -EFAULT on error. + */ + +int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, + int offset, int len) +{ + /* Skip over the finished iovecs */ + while (offset >= iov->iov_len) { + offset -= iov->iov_len; + iov++; + } + + while (len > 0) { + u8 __user *base = iov->iov_base + offset; + int copy = min_t(unsigned int, len, iov->iov_len - offset); + + offset = 0; + if (copy_from_user(kdata, base, copy)) + return -EFAULT; + len -= copy; + kdata += copy; + iov++; + } + + return 0; +} +EXPORT_SYMBOL(memcpy_fromiovecend); |