diff options
Diffstat (limited to 'lib/iovec.c')
-rw-r--r-- | lib/iovec.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/lib/iovec.c b/lib/iovec.c index 454baa88bf27..fa2c050dc137 100644 --- a/lib/iovec.c +++ b/lib/iovec.c @@ -1,5 +1,7 @@ #include <linux/uaccess.h> #include <linux/export.h> +#include <linux/fs.h> +#include <linux/mm.h> #include <linux/uio.h> /* @@ -51,3 +53,31 @@ int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len) return 0; } EXPORT_SYMBOL(memcpy_toiovec); + +int iov_count_pages(const struct iov_iter *iter, unsigned align) +{ + struct iov_iter i = *iter; + int nr_pages = 0; + + while (iov_iter_count(&i)) { + unsigned long uaddr = (unsigned long) i.iov->iov_base + + i.iov_offset; + unsigned long len = i.iov->iov_len - i.iov_offset; + + if ((uaddr & align) || (len & align)) + return -EINVAL; + + /* + * Overflow, abort + */ + if (uaddr + len < uaddr) + return -EINVAL; + + nr_pages += DIV_ROUND_UP(len + offset_in_page(uaddr), + PAGE_SIZE); + iov_iter_advance(&i, len); + } + + return nr_pages; +} +EXPORT_SYMBOL(iov_count_pages); |