forked from latrelstack/px-fuse
-
Notifications
You must be signed in to change notification settings - Fork 0
/
iov_iter.h
143 lines (125 loc) · 4.77 KB
/
iov_iter.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
* Berkeley style UIO structures - Alan Cox 1994.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef ____iov_iter_H
#define ____iov_iter_H
#include <linux/kernel.h>
#include <linux/uio.h>
#include <linux/version.h>
struct page;
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0) || \
LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0)
/* Linux 3.16.x and 3.17.x already have this declaration. */
enum {
ITER_IOVEC = 0,
ITER_KVEC = 2,
ITER_BVEC = 4,
};
#endif
struct __iov_iter {
int type;
size_t iov_offset;
size_t count;
union {
const struct iovec *iov;
const struct kvec *kvec;
const struct bio_vec *bvec;
};
unsigned long nr_segs;
};
static inline struct iovec __iov_iter_iovec(const struct __iov_iter *iter)
{
return (struct iovec) {
.iov_base = iter->iov->iov_base + iter->iov_offset,
.iov_len = min(iter->count,
iter->iov->iov_len - iter->iov_offset),
};
}
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);
int __iov_iter_fault_in_readable(struct __iov_iter *i, size_t bytes);
int __iov_iter_fault_in_multipages_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,
struct __iov_iter *i);
size_t __copy_page_from_iter(struct page *page, size_t offset, size_t bytes,
struct __iov_iter *i);
size_t copy_to_iter(const void *addr, size_t bytes, struct __iov_iter *i);
size_t copy_from_iter(void *addr, size_t bytes, struct __iov_iter *i);
size_t copy_from_iter_nocache(void *addr, size_t bytes, struct __iov_iter *i);
size_t __iov_iter_zero(size_t bytes, struct __iov_iter *);
unsigned long __iov_iter_alignment(const struct __iov_iter *i);
unsigned long __iov_iter_gap_alignment(const struct __iov_iter *i);
void __iov_iter_init(struct __iov_iter *i, int direction, const struct iovec *iov,
unsigned long nr_segs, size_t count);
void __iov_iter_kvec(struct __iov_iter *i, int direction, const struct kvec *kvec,
unsigned long nr_segs, size_t count);
void __iov_iter_bvec(struct __iov_iter *i, int direction, const struct bio_vec *bvec,
unsigned long nr_segs, size_t count);
ssize_t __iov_iter_get_pages(struct __iov_iter *i, struct page **pages,
size_t maxsize, unsigned maxpages, size_t *start);
ssize_t __iov_iter_get_pages_alloc(struct __iov_iter *i, struct page ***pages,
size_t maxsize, size_t *start);
int __iov_iter_npages(const struct __iov_iter *i, int maxpages);
const void *dup_iter(struct __iov_iter *new, struct __iov_iter *old, gfp_t flags);
static inline size_t __iov_iter_count(struct __iov_iter *i)
{
return i->count;
}
static inline bool iter_is_iovec(struct __iov_iter *i)
{
return !(i->type & (ITER_BVEC | ITER_KVEC));
}
/*
* Get one of READ or WRITE out of iter->type without any other flags OR'd in
* with it.
*
* The ?: is just for type safety.
*/
#define __iov_iter_rw(i) ((0 ? (struct __iov_iter *)0 : (i))->type & RW_MASK)
/*
* Cap the __iov_iter by given limit; note that the second argument is
* *not* the new size - it's upper limit for such. Passing it a value
* greater than the amount of data in __iov_iter is fine - it'll just do
* nothing in that case.
*/
static inline void __iov_iter_truncate(struct __iov_iter *i, u64 count)
{
/*
* count doesn't have to fit in size_t - comparison extends both
* operands to u64 here and any value that would be truncated by
* conversion in assignement is by definition greater than all
* values of size_t, including old i->count.
*/
if (i->count > count)
i->count = count;
}
/*
* reexpand a previously truncated iterator; count must be no more than how much
* we had shrunk it.
*/
static inline void __iov_iter_reexpand(struct __iov_iter *i, size_t count)
{
i->count = count;
}
size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, struct __iov_iter *i);
size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct __iov_iter *i);
int import_iovec(int type, const struct iovec __user * uvector,
unsigned nr_segs, unsigned fast_segs,
struct iovec **iov, struct __iov_iter *i);
#ifdef CONFIG_COMPAT
struct compat_iovec;
int compat_import_iovec(int type, const struct compat_iovec __user * uvector,
unsigned nr_segs, unsigned fast_segs,
struct iovec **iov, struct __iov_iter *i);
#endif
int import_single_range(int type, void __user *buf, size_t len,
struct iovec *iov, struct __iov_iter *i);
#endif