summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <koverstreet@google.com>2013-03-22 13:24:17 -0700
committerKent Overstreet <koverstreet@google.com>2013-03-22 13:24:17 -0700
commit46b21eec593b4042577c5fcdc6c2238d3913d51d (patch)
treeee4c8a27a438971025dfc659029e14dba3088018
parentcda4afa7accbcacb76ad3773b3cd01747b791fa6 (diff)
add offset to iov_iteriov
-rw-r--r--fs/iov-iter.c46
-rw-r--r--include/linux/fs.h4
2 files changed, 21 insertions, 29 deletions
diff --git a/fs/iov-iter.c b/fs/iov-iter.c
index 6cecab49b7ca..edc5d1ce535f 100644
--- a/fs/iov-iter.c
+++ b/fs/iov-iter.c
@@ -180,35 +180,25 @@ void iov_iter_advance(struct iov_iter *i, size_t bytes)
{
BUG_ON(i->count < bytes);
- if (likely(i->nr_segs == 1)) {
- i->iov_offset += bytes;
- i->count -= bytes;
- } else {
- const struct iovec *iov = i->iov;
- size_t base = i->iov_offset;
- unsigned long nr_segs = i->nr_segs;
-
- /*
- * The !iov->iov_len check ensures we skip over unlikely
- * zero-length segments (without overruning the iovec).
- */
- while (bytes || unlikely(i->count && !iov->iov_len)) {
- int copy;
-
- copy = min(bytes, iov->iov_len - base);
- BUG_ON(!i->count || i->count < copy);
- i->count -= copy;
- bytes -= copy;
- base += copy;
- if (iov->iov_len == base) {
- iov++;
- nr_segs--;
- base = 0;
- }
+ i->count -= bytes;
+ i->offset += bytes;
+
+ while (bytes) {
+ size_t len;
+
+ BUG_ON(!i->nr_segs);
+
+ len = i->iov->iov_len - i->iov_offset;
+
+ if (bytes < len) {
+ i->iov_offset += bytes;
+ bytes = 0;
+ } else {
+ bytes -= len;
+ i->iov++;
+ i->nr_segs--;
+ i->iov_offset = 0;
}
- i->iov = iov;
- i->iov_offset = base;
- i->nr_segs = nr_segs;
}
}
EXPORT_SYMBOL(iov_iter_advance);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e5ea8b38da14..3fc25679467e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -293,6 +293,7 @@ struct iov_iter {
unsigned long nr_segs;
size_t iov_offset;
size_t count;
+ loff_t offset;
};
size_t __iov_iter_copy_to_user_atomic(struct page *page,
@@ -311,12 +312,13 @@ size_t iov_iter_single_seg_count(const struct iov_iter *i);
static inline void iov_iter_init(struct iov_iter *i,
const struct iovec *iov, unsigned long nr_segs,
- size_t count)
+ size_t count, loff_t offset)
{
i->iov = iov;
i->nr_segs = nr_segs;
i->iov_offset = 0;
i->count = count;
+ i->offset = offset;
}
static inline size_t iov_iter_count(struct iov_iter *i)