mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
This commit is contained in:
commit
0e4c0ee580
@ -39,7 +39,10 @@ struct iov_iter {
|
||||
};
|
||||
union {
|
||||
unsigned long nr_segs;
|
||||
int idx;
|
||||
struct {
|
||||
int idx;
|
||||
int start_idx;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@ -81,6 +84,7 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to);
|
||||
size_t iov_iter_copy_from_user_atomic(struct page *page,
|
||||
struct iov_iter *i, unsigned long offset, size_t bytes);
|
||||
void iov_iter_advance(struct iov_iter *i, size_t bytes);
|
||||
void iov_iter_revert(struct iov_iter *i, size_t bytes);
|
||||
int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes);
|
||||
size_t iov_iter_single_seg_count(const struct iov_iter *i);
|
||||
size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -398,7 +398,7 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
|
||||
struct iov_iter *to, int len)
|
||||
{
|
||||
int start = skb_headlen(skb);
|
||||
int i, copy = start - offset;
|
||||
int i, copy = start - offset, start_off = offset, n;
|
||||
struct sk_buff *frag_iter;
|
||||
|
||||
trace_skb_copy_datagram_iovec(skb, len);
|
||||
@ -407,11 +407,12 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
|
||||
if (copy > 0) {
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
if (copy_to_iter(skb->data + offset, copy, to) != copy)
|
||||
n = copy_to_iter(skb->data + offset, copy, to);
|
||||
offset += n;
|
||||
if (n != copy)
|
||||
goto short_copy;
|
||||
if ((len -= copy) == 0)
|
||||
return 0;
|
||||
offset += copy;
|
||||
}
|
||||
|
||||
/* Copy paged appendix. Hmm... why does this look so complicated? */
|
||||
@ -425,13 +426,14 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
|
||||
if ((copy = end - offset) > 0) {
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
if (copy_page_to_iter(skb_frag_page(frag),
|
||||
n = copy_page_to_iter(skb_frag_page(frag),
|
||||
frag->page_offset + offset -
|
||||
start, copy, to) != copy)
|
||||
start, copy, to);
|
||||
offset += n;
|
||||
if (n != copy)
|
||||
goto short_copy;
|
||||
if (!(len -= copy))
|
||||
return 0;
|
||||
offset += copy;
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
@ -463,6 +465,7 @@ int skb_copy_datagram_iter(const struct sk_buff *skb, int offset,
|
||||
*/
|
||||
|
||||
fault:
|
||||
iov_iter_revert(to, offset - start_off);
|
||||
return -EFAULT;
|
||||
|
||||
short_copy:
|
||||
@ -613,7 +616,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
|
||||
__wsum *csump)
|
||||
{
|
||||
int start = skb_headlen(skb);
|
||||
int i, copy = start - offset;
|
||||
int i, copy = start - offset, start_off = offset;
|
||||
struct sk_buff *frag_iter;
|
||||
int pos = 0;
|
||||
int n;
|
||||
@ -623,11 +626,11 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
n = csum_and_copy_to_iter(skb->data + offset, copy, csump, to);
|
||||
offset += n;
|
||||
if (n != copy)
|
||||
goto fault;
|
||||
if ((len -= copy) == 0)
|
||||
return 0;
|
||||
offset += copy;
|
||||
pos = copy;
|
||||
}
|
||||
|
||||
@ -649,12 +652,12 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
|
||||
offset - start, copy,
|
||||
&csum2, to);
|
||||
kunmap(page);
|
||||
offset += n;
|
||||
if (n != copy)
|
||||
goto fault;
|
||||
*csump = csum_block_add(*csump, csum2, pos);
|
||||
if (!(len -= copy))
|
||||
return 0;
|
||||
offset += copy;
|
||||
pos += copy;
|
||||
}
|
||||
start = end;
|
||||
@ -687,6 +690,7 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
|
||||
return 0;
|
||||
|
||||
fault:
|
||||
iov_iter_revert(to, offset - start_off);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
@ -771,6 +775,7 @@ int skb_copy_and_csum_datagram_msg(struct sk_buff *skb,
|
||||
}
|
||||
return 0;
|
||||
csum_error:
|
||||
iov_iter_revert(&msg->msg_iter, chunk);
|
||||
return -EINVAL;
|
||||
fault:
|
||||
return -EFAULT;
|
||||
|
Loading…
Reference in New Issue
Block a user