mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
Merge branch 'work.afs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull AFS updates from Al Viro: "AFS series, with some iov_iter bits included" * 'work.afs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (26 commits) missing bits of "iov_iter: Separate type from direction and use accessor functions" afs: Probe multiple fileservers simultaneously afs: Fix callback handling afs: Eliminate the address pointer from the address list cursor afs: Allow dumping of server cursor on operation failure afs: Implement YFS support in the fs client afs: Expand data structure fields to support YFS afs: Get the target vnode in afs_rmdir() and get a callback on it afs: Calc callback expiry in op reply delivery afs: Fix FS.FetchStatus delivery from updating wrong vnode afs: Implement the YFS cache manager service afs: Remove callback details from afs_callback_break struct afs: Commit the status on a new file/dir/symlink afs: Increase to 64-bit volume ID and 96-bit vnode ID for YFS afs: Don't invoke the server to read data beyond EOF afs: Add a couple of tracepoints to log I/O errors afs: Handle EIO from delivery function afs: Fix TTL on VL server and address lists afs: Implement VL server rotation afs: Improve FS server rotation error handling ...
This commit is contained in:
commit
9931a07d51
85 changed files with 5632 additions and 1239 deletions
125
lib/iov_iter.c
125
lib/iov_iter.c
|
|
@ -83,6 +83,7 @@
|
|||
const struct kvec *kvec; \
|
||||
struct kvec v; \
|
||||
iterate_kvec(i, n, v, kvec, skip, (K)) \
|
||||
} else if (unlikely(i->type & ITER_DISCARD)) { \
|
||||
} else { \
|
||||
const struct iovec *iov; \
|
||||
struct iovec v; \
|
||||
|
|
@ -114,6 +115,8 @@
|
|||
} \
|
||||
i->nr_segs -= kvec - i->kvec; \
|
||||
i->kvec = kvec; \
|
||||
} else if (unlikely(i->type & ITER_DISCARD)) { \
|
||||
skip += n; \
|
||||
} else { \
|
||||
const struct iovec *iov; \
|
||||
struct iovec v; \
|
||||
|
|
@ -428,17 +431,19 @@ int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes)
|
|||
}
|
||||
EXPORT_SYMBOL(iov_iter_fault_in_readable);
|
||||
|
||||
void iov_iter_init(struct iov_iter *i, int direction,
|
||||
void iov_iter_init(struct iov_iter *i, unsigned int direction,
|
||||
const struct iovec *iov, unsigned long nr_segs,
|
||||
size_t count)
|
||||
{
|
||||
WARN_ON(direction & ~(READ | WRITE));
|
||||
direction &= READ | WRITE;
|
||||
|
||||
/* It will get better. Eventually... */
|
||||
if (uaccess_kernel()) {
|
||||
direction |= ITER_KVEC;
|
||||
i->type = direction;
|
||||
i->type = ITER_KVEC | direction;
|
||||
i->kvec = (struct kvec *)iov;
|
||||
} else {
|
||||
i->type = direction;
|
||||
i->type = ITER_IOVEC | direction;
|
||||
i->iov = iov;
|
||||
}
|
||||
i->nr_segs = nr_segs;
|
||||
|
|
@ -558,7 +563,7 @@ static size_t copy_pipe_to_iter(const void *addr, size_t bytes,
|
|||
size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i)
|
||||
{
|
||||
const char *from = addr;
|
||||
if (unlikely(i->type & ITER_PIPE))
|
||||
if (unlikely(iov_iter_is_pipe(i)))
|
||||
return copy_pipe_to_iter(addr, bytes, i);
|
||||
if (iter_is_iovec(i))
|
||||
might_fault();
|
||||
|
|
@ -658,7 +663,7 @@ size_t _copy_to_iter_mcsafe(const void *addr, size_t bytes, struct iov_iter *i)
|
|||
const char *from = addr;
|
||||
unsigned long rem, curr_addr, s_addr = (unsigned long) addr;
|
||||
|
||||
if (unlikely(i->type & ITER_PIPE))
|
||||
if (unlikely(iov_iter_is_pipe(i)))
|
||||
return copy_pipe_to_iter_mcsafe(addr, bytes, i);
|
||||
if (iter_is_iovec(i))
|
||||
might_fault();
|
||||
|
|
@ -692,7 +697,7 @@ EXPORT_SYMBOL_GPL(_copy_to_iter_mcsafe);
|
|||
size_t _copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
|
||||
{
|
||||
char *to = addr;
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i))) {
|
||||
WARN_ON(1);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -712,7 +717,7 @@ EXPORT_SYMBOL(_copy_from_iter);
|
|||
bool _copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i)
|
||||
{
|
||||
char *to = addr;
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i))) {
|
||||
WARN_ON(1);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -739,7 +744,7 @@ EXPORT_SYMBOL(_copy_from_iter_full);
|
|||
size_t _copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i)
|
||||
{
|
||||
char *to = addr;
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i))) {
|
||||
WARN_ON(1);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -773,7 +778,7 @@ EXPORT_SYMBOL(_copy_from_iter_nocache);
|
|||
size_t _copy_from_iter_flushcache(void *addr, size_t bytes, struct iov_iter *i)
|
||||
{
|
||||
char *to = addr;
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i))) {
|
||||
WARN_ON(1);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -794,7 +799,7 @@ EXPORT_SYMBOL_GPL(_copy_from_iter_flushcache);
|
|||
bool _copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i)
|
||||
{
|
||||
char *to = addr;
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i))) {
|
||||
WARN_ON(1);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -836,7 +841,9 @@ size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
|
|||
size_t wanted = copy_to_iter(kaddr + offset, bytes, i);
|
||||
kunmap_atomic(kaddr);
|
||||
return wanted;
|
||||
} else if (likely(!(i->type & ITER_PIPE)))
|
||||
} else if (unlikely(iov_iter_is_discard(i)))
|
||||
return bytes;
|
||||
else if (likely(!iov_iter_is_pipe(i)))
|
||||
return copy_page_to_iter_iovec(page, offset, bytes, i);
|
||||
else
|
||||
return copy_page_to_iter_pipe(page, offset, bytes, i);
|
||||
|
|
@ -848,7 +855,7 @@ size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes,
|
|||
{
|
||||
if (unlikely(!page_copy_sane(page, offset, bytes)))
|
||||
return 0;
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) {
|
||||
WARN_ON(1);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -888,7 +895,7 @@ static size_t pipe_zero(size_t bytes, struct iov_iter *i)
|
|||
|
||||
size_t iov_iter_zero(size_t bytes, struct iov_iter *i)
|
||||
{
|
||||
if (unlikely(i->type & ITER_PIPE))
|
||||
if (unlikely(iov_iter_is_pipe(i)))
|
||||
return pipe_zero(bytes, i);
|
||||
iterate_and_advance(i, bytes, v,
|
||||
clear_user(v.iov_base, v.iov_len),
|
||||
|
|
@ -908,7 +915,7 @@ size_t iov_iter_copy_from_user_atomic(struct page *page,
|
|||
kunmap_atomic(kaddr);
|
||||
return 0;
|
||||
}
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) {
|
||||
kunmap_atomic(kaddr);
|
||||
WARN_ON(1);
|
||||
return 0;
|
||||
|
|
@ -972,10 +979,14 @@ static void pipe_advance(struct iov_iter *i, size_t size)
|
|||
|
||||
void iov_iter_advance(struct iov_iter *i, size_t size)
|
||||
{
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i))) {
|
||||
pipe_advance(i, size);
|
||||
return;
|
||||
}
|
||||
if (unlikely(iov_iter_is_discard(i))) {
|
||||
i->count -= size;
|
||||
return;
|
||||
}
|
||||
iterate_and_advance(i, size, v, 0, 0, 0)
|
||||
}
|
||||
EXPORT_SYMBOL(iov_iter_advance);
|
||||
|
|
@ -987,7 +998,7 @@ void iov_iter_revert(struct iov_iter *i, size_t unroll)
|
|||
if (WARN_ON(unroll > MAX_RW_COUNT))
|
||||
return;
|
||||
i->count += unroll;
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i))) {
|
||||
struct pipe_inode_info *pipe = i->pipe;
|
||||
int idx = i->idx;
|
||||
size_t off = i->iov_offset;
|
||||
|
|
@ -1011,12 +1022,14 @@ void iov_iter_revert(struct iov_iter *i, size_t unroll)
|
|||
pipe_truncate(i);
|
||||
return;
|
||||
}
|
||||
if (unlikely(iov_iter_is_discard(i)))
|
||||
return;
|
||||
if (unroll <= i->iov_offset) {
|
||||
i->iov_offset -= unroll;
|
||||
return;
|
||||
}
|
||||
unroll -= i->iov_offset;
|
||||
if (i->type & ITER_BVEC) {
|
||||
if (iov_iter_is_bvec(i)) {
|
||||
const struct bio_vec *bvec = i->bvec;
|
||||
while (1) {
|
||||
size_t n = (--bvec)->bv_len;
|
||||
|
|
@ -1049,23 +1062,25 @@ EXPORT_SYMBOL(iov_iter_revert);
|
|||
*/
|
||||
size_t iov_iter_single_seg_count(const struct iov_iter *i)
|
||||
{
|
||||
if (unlikely(i->type & ITER_PIPE))
|
||||
if (unlikely(iov_iter_is_pipe(i)))
|
||||
return i->count; // it is a silly place, anyway
|
||||
if (i->nr_segs == 1)
|
||||
return i->count;
|
||||
else if (i->type & ITER_BVEC)
|
||||
if (unlikely(iov_iter_is_discard(i)))
|
||||
return i->count;
|
||||
else if (iov_iter_is_bvec(i))
|
||||
return min(i->count, i->bvec->bv_len - i->iov_offset);
|
||||
else
|
||||
return min(i->count, i->iov->iov_len - i->iov_offset);
|
||||
}
|
||||
EXPORT_SYMBOL(iov_iter_single_seg_count);
|
||||
|
||||
void iov_iter_kvec(struct iov_iter *i, int direction,
|
||||
void iov_iter_kvec(struct iov_iter *i, unsigned int direction,
|
||||
const struct kvec *kvec, unsigned long nr_segs,
|
||||
size_t count)
|
||||
{
|
||||
BUG_ON(!(direction & ITER_KVEC));
|
||||
i->type = direction;
|
||||
WARN_ON(direction & ~(READ | WRITE));
|
||||
i->type = ITER_KVEC | (direction & (READ | WRITE));
|
||||
i->kvec = kvec;
|
||||
i->nr_segs = nr_segs;
|
||||
i->iov_offset = 0;
|
||||
|
|
@ -1073,12 +1088,12 @@ void iov_iter_kvec(struct iov_iter *i, int direction,
|
|||
}
|
||||
EXPORT_SYMBOL(iov_iter_kvec);
|
||||
|
||||
void iov_iter_bvec(struct iov_iter *i, int direction,
|
||||
void iov_iter_bvec(struct iov_iter *i, unsigned int direction,
|
||||
const struct bio_vec *bvec, unsigned long nr_segs,
|
||||
size_t count)
|
||||
{
|
||||
BUG_ON(!(direction & ITER_BVEC));
|
||||
i->type = direction;
|
||||
WARN_ON(direction & ~(READ | WRITE));
|
||||
i->type = ITER_BVEC | (direction & (READ | WRITE));
|
||||
i->bvec = bvec;
|
||||
i->nr_segs = nr_segs;
|
||||
i->iov_offset = 0;
|
||||
|
|
@ -1086,13 +1101,13 @@ void iov_iter_bvec(struct iov_iter *i, int direction,
|
|||
}
|
||||
EXPORT_SYMBOL(iov_iter_bvec);
|
||||
|
||||
void iov_iter_pipe(struct iov_iter *i, int direction,
|
||||
void iov_iter_pipe(struct iov_iter *i, unsigned int direction,
|
||||
struct pipe_inode_info *pipe,
|
||||
size_t count)
|
||||
{
|
||||
BUG_ON(direction != ITER_PIPE);
|
||||
BUG_ON(direction != READ);
|
||||
WARN_ON(pipe->nrbufs == pipe->buffers);
|
||||
i->type = direction;
|
||||
i->type = ITER_PIPE | READ;
|
||||
i->pipe = pipe;
|
||||
i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
|
||||
i->iov_offset = 0;
|
||||
|
|
@ -1101,12 +1116,30 @@ void iov_iter_pipe(struct iov_iter *i, int direction,
|
|||
}
|
||||
EXPORT_SYMBOL(iov_iter_pipe);
|
||||
|
||||
/**
|
||||
* iov_iter_discard - Initialise an I/O iterator that discards data
|
||||
* @i: The iterator to initialise.
|
||||
* @direction: The direction of the transfer.
|
||||
* @count: The size of the I/O buffer in bytes.
|
||||
*
|
||||
* Set up an I/O iterator that just discards everything that's written to it.
|
||||
* It's only available as a READ iterator.
|
||||
*/
|
||||
void iov_iter_discard(struct iov_iter *i, unsigned int direction, size_t count)
|
||||
{
|
||||
BUG_ON(direction != READ);
|
||||
i->type = ITER_DISCARD | READ;
|
||||
i->count = count;
|
||||
i->iov_offset = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iov_iter_discard);
|
||||
|
||||
unsigned long iov_iter_alignment(const struct iov_iter *i)
|
||||
{
|
||||
unsigned long res = 0;
|
||||
size_t size = i->count;
|
||||
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i))) {
|
||||
if (size && i->iov_offset && allocated(&i->pipe->bufs[i->idx]))
|
||||
return size | i->iov_offset;
|
||||
return size;
|
||||
|
|
@ -1125,7 +1158,7 @@ unsigned long iov_iter_gap_alignment(const struct iov_iter *i)
|
|||
unsigned long res = 0;
|
||||
size_t size = i->count;
|
||||
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) {
|
||||
WARN_ON(1);
|
||||
return ~0U;
|
||||
}
|
||||
|
|
@ -1193,8 +1226,11 @@ ssize_t iov_iter_get_pages(struct iov_iter *i,
|
|||
if (maxsize > i->count)
|
||||
maxsize = i->count;
|
||||
|
||||
if (unlikely(i->type & ITER_PIPE))
|
||||
if (unlikely(iov_iter_is_pipe(i)))
|
||||
return pipe_get_pages(i, pages, maxsize, maxpages, start);
|
||||
if (unlikely(iov_iter_is_discard(i)))
|
||||
return -EFAULT;
|
||||
|
||||
iterate_all_kinds(i, maxsize, v, ({
|
||||
unsigned long addr = (unsigned long)v.iov_base;
|
||||
size_t len = v.iov_len + (*start = addr & (PAGE_SIZE - 1));
|
||||
|
|
@ -1205,7 +1241,7 @@ ssize_t iov_iter_get_pages(struct iov_iter *i,
|
|||
len = maxpages * PAGE_SIZE;
|
||||
addr &= ~(PAGE_SIZE - 1);
|
||||
n = DIV_ROUND_UP(len, PAGE_SIZE);
|
||||
res = get_user_pages_fast(addr, n, (i->type & WRITE) != WRITE, pages);
|
||||
res = get_user_pages_fast(addr, n, iov_iter_rw(i) != WRITE, pages);
|
||||
if (unlikely(res < 0))
|
||||
return res;
|
||||
return (res == n ? len : res * PAGE_SIZE) - *start;
|
||||
|
|
@ -1270,8 +1306,11 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
|
|||
if (maxsize > i->count)
|
||||
maxsize = i->count;
|
||||
|
||||
if (unlikely(i->type & ITER_PIPE))
|
||||
if (unlikely(iov_iter_is_pipe(i)))
|
||||
return pipe_get_pages_alloc(i, pages, maxsize, start);
|
||||
if (unlikely(iov_iter_is_discard(i)))
|
||||
return -EFAULT;
|
||||
|
||||
iterate_all_kinds(i, maxsize, v, ({
|
||||
unsigned long addr = (unsigned long)v.iov_base;
|
||||
size_t len = v.iov_len + (*start = addr & (PAGE_SIZE - 1));
|
||||
|
|
@ -1283,7 +1322,7 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,
|
|||
p = get_pages_array(n);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
res = get_user_pages_fast(addr, n, (i->type & WRITE) != WRITE, p);
|
||||
res = get_user_pages_fast(addr, n, iov_iter_rw(i) != WRITE, p);
|
||||
if (unlikely(res < 0)) {
|
||||
kvfree(p);
|
||||
return res;
|
||||
|
|
@ -1313,7 +1352,7 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum,
|
|||
__wsum sum, next;
|
||||
size_t off = 0;
|
||||
sum = *csum;
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) {
|
||||
WARN_ON(1);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1355,7 +1394,7 @@ bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum,
|
|||
__wsum sum, next;
|
||||
size_t off = 0;
|
||||
sum = *csum;
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) {
|
||||
WARN_ON(1);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1400,7 +1439,7 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum,
|
|||
__wsum sum, next;
|
||||
size_t off = 0;
|
||||
sum = *csum;
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) {
|
||||
WARN_ON(1); /* for now */
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1442,8 +1481,10 @@ int iov_iter_npages(const struct iov_iter *i, int maxpages)
|
|||
|
||||
if (!size)
|
||||
return 0;
|
||||
if (unlikely(iov_iter_is_discard(i)))
|
||||
return 0;
|
||||
|
||||
if (unlikely(i->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(i))) {
|
||||
struct pipe_inode_info *pipe = i->pipe;
|
||||
size_t off;
|
||||
int idx;
|
||||
|
|
@ -1481,11 +1522,13 @@ EXPORT_SYMBOL(iov_iter_npages);
|
|||
const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags)
|
||||
{
|
||||
*new = *old;
|
||||
if (unlikely(new->type & ITER_PIPE)) {
|
||||
if (unlikely(iov_iter_is_pipe(new))) {
|
||||
WARN_ON(1);
|
||||
return NULL;
|
||||
}
|
||||
if (new->type & ITER_BVEC)
|
||||
if (unlikely(iov_iter_is_discard(new)))
|
||||
return NULL;
|
||||
if (iov_iter_is_bvec(new))
|
||||
return new->bvec = kmemdup(new->bvec,
|
||||
new->nr_segs * sizeof(struct bio_vec),
|
||||
flags);
|
||||
|
|
|
|||
Loading…
Reference in a new issue