summaryrefslogtreecommitdiff
path: root/lib/iovec.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/iovec.c')
-rw-r--r--lib/iovec.c30
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);