summaryrefslogtreecommitdiffstats
path: root/lib/iov_iter.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2017-05-03 21:41:35 +0200
committerDaniel Vetter <daniel.vetter@ffwll.ch>2017-05-03 21:41:35 +0200
commitad15f74ac6c7ed1c7c252a760b017da042ec83fb (patch)
tree0b8643ae709d8f413f9b58b544d65aeaf48a0c7a /lib/iov_iter.c
parent8a2d6ae1f737fd22eaeadd0dc32b85c92f239025 (diff)
parent8b03d1ed2c43a2ba5ef3381322ee4515b97381bf (diff)
downloadop-kernel-dev-ad15f74ac6c7ed1c7c252a760b017da042ec83fb.zip
op-kernel-dev-ad15f74ac6c7ed1c7c252a760b017da042ec83fb.tar.gz
Merge tag 'tags/drm-for-v4.12' into drm-intel-next-queued
Backmerge the main drm-next pull to sync up. Chris also pointed out that commit ade0b0c965f59176daddbef9c4717354034f9bce Author: Chris Wilson <chris@chris-wilson.co.uk> Date: Sat Apr 22 09:15:37 2017 +0100 drm/i915: Confirm the request is still active before adding it to the await is double-applied in the git merge, so make sure we get this right. Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'lib/iov_iter.c')
-rw-r--r--lib/iov_iter.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index e68604a..60abc44 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -786,6 +786,68 @@ void iov_iter_advance(struct iov_iter *i, size_t size)
}
EXPORT_SYMBOL(iov_iter_advance);
+void iov_iter_revert(struct iov_iter *i, size_t unroll)
+{
+ if (!unroll)
+ return;
+ i->count += unroll;
+ if (unlikely(i->type & ITER_PIPE)) {
+ struct pipe_inode_info *pipe = i->pipe;
+ int idx = i->idx;
+ size_t off = i->iov_offset;
+ while (1) {
+ size_t n = off - pipe->bufs[idx].offset;
+ if (unroll < n) {
+ off -= (n - unroll);
+ break;
+ }
+ unroll -= n;
+ if (!unroll && idx == i->start_idx) {
+ off = 0;
+ break;
+ }
+ if (!idx--)
+ idx = pipe->buffers - 1;
+ off = pipe->bufs[idx].offset + pipe->bufs[idx].len;
+ }
+ i->iov_offset = off;
+ i->idx = idx;
+ pipe_truncate(i);
+ return;
+ }
+ if (unroll <= i->iov_offset) {
+ i->iov_offset -= unroll;
+ return;
+ }
+ unroll -= i->iov_offset;
+ if (i->type & ITER_BVEC) {
+ const struct bio_vec *bvec = i->bvec;
+ while (1) {
+ size_t n = (--bvec)->bv_len;
+ i->nr_segs++;
+ if (unroll <= n) {
+ i->bvec = bvec;
+ i->iov_offset = n - unroll;
+ return;
+ }
+ unroll -= n;
+ }
+ } else { /* same logics for iovec and kvec */
+ const struct iovec *iov = i->iov;
+ while (1) {
+ size_t n = (--iov)->iov_len;
+ i->nr_segs++;
+ if (unroll <= n) {
+ i->iov = iov;
+ i->iov_offset = n - unroll;
+ return;
+ }
+ unroll -= n;
+ }
+ }
+}
+EXPORT_SYMBOL(iov_iter_revert);
+
/*
* Return the count of just the current iov_iter segment.
*/
@@ -839,6 +901,7 @@ void iov_iter_pipe(struct iov_iter *i, int direction,
i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
i->iov_offset = 0;
i->count = count;
+ i->start_idx = i->idx;
}
EXPORT_SYMBOL(iov_iter_pipe);
OpenPOWER on IntegriCloud