| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Berkeley style UIO structures - Alan Cox 1994. |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or |
|---|
| 5 | | - * modify it under the terms of the GNU General Public License |
|---|
| 6 | | - * as published by the Free Software Foundation; either version |
|---|
| 7 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 8 | 4 | */ |
|---|
| 9 | 5 | #ifndef __LINUX_UIO_H |
|---|
| 10 | 6 | #define __LINUX_UIO_H |
|---|
| .. | .. |
|---|
| 21 | 17 | size_t iov_len; |
|---|
| 22 | 18 | }; |
|---|
| 23 | 19 | |
|---|
| 24 | | -enum { |
|---|
| 25 | | - ITER_IOVEC = 0, |
|---|
| 26 | | - ITER_KVEC = 2, |
|---|
| 27 | | - ITER_BVEC = 4, |
|---|
| 28 | | - ITER_PIPE = 8, |
|---|
| 20 | +enum iter_type { |
|---|
| 21 | + /* iter types */ |
|---|
| 22 | + ITER_IOVEC = 4, |
|---|
| 23 | + ITER_KVEC = 8, |
|---|
| 24 | + ITER_BVEC = 16, |
|---|
| 25 | + ITER_PIPE = 32, |
|---|
| 26 | + ITER_DISCARD = 64, |
|---|
| 27 | +}; |
|---|
| 28 | + |
|---|
| 29 | +struct iov_iter_state { |
|---|
| 30 | + size_t iov_offset; |
|---|
| 31 | + size_t count; |
|---|
| 32 | + unsigned long nr_segs; |
|---|
| 29 | 33 | }; |
|---|
| 30 | 34 | |
|---|
| 31 | 35 | struct iov_iter { |
|---|
| 32 | | - int type; |
|---|
| 36 | + /* |
|---|
| 37 | + * Bit 0 is the read/write bit, set if we're writing. |
|---|
| 38 | + * Bit 1 is the BVEC_FLAG_NO_REF bit, set if type is a bvec and |
|---|
| 39 | + * the caller isn't expecting to drop a page reference when done. |
|---|
| 40 | + */ |
|---|
| 41 | + unsigned int type; |
|---|
| 33 | 42 | size_t iov_offset; |
|---|
| 34 | 43 | size_t count; |
|---|
| 35 | 44 | union { |
|---|
| .. | .. |
|---|
| 41 | 50 | union { |
|---|
| 42 | 51 | unsigned long nr_segs; |
|---|
| 43 | 52 | struct { |
|---|
| 44 | | - int idx; |
|---|
| 45 | | - int start_idx; |
|---|
| 53 | + unsigned int head; |
|---|
| 54 | + unsigned int start_head; |
|---|
| 46 | 55 | }; |
|---|
| 47 | 56 | }; |
|---|
| 48 | 57 | }; |
|---|
| 58 | + |
|---|
| 59 | +static inline enum iter_type iov_iter_type(const struct iov_iter *i) |
|---|
| 60 | +{ |
|---|
| 61 | + return i->type & ~(READ | WRITE); |
|---|
| 62 | +} |
|---|
| 63 | + |
|---|
| 64 | +static inline void iov_iter_save_state(struct iov_iter *iter, |
|---|
| 65 | + struct iov_iter_state *state) |
|---|
| 66 | +{ |
|---|
| 67 | + state->iov_offset = iter->iov_offset; |
|---|
| 68 | + state->count = iter->count; |
|---|
| 69 | + state->nr_segs = iter->nr_segs; |
|---|
| 70 | +} |
|---|
| 71 | + |
|---|
| 72 | +static inline bool iter_is_iovec(const struct iov_iter *i) |
|---|
| 73 | +{ |
|---|
| 74 | + return iov_iter_type(i) == ITER_IOVEC; |
|---|
| 75 | +} |
|---|
| 76 | + |
|---|
| 77 | +static inline bool iov_iter_is_kvec(const struct iov_iter *i) |
|---|
| 78 | +{ |
|---|
| 79 | + return iov_iter_type(i) == ITER_KVEC; |
|---|
| 80 | +} |
|---|
| 81 | + |
|---|
| 82 | +static inline bool iov_iter_is_bvec(const struct iov_iter *i) |
|---|
| 83 | +{ |
|---|
| 84 | + return iov_iter_type(i) == ITER_BVEC; |
|---|
| 85 | +} |
|---|
| 86 | + |
|---|
| 87 | +static inline bool iov_iter_is_pipe(const struct iov_iter *i) |
|---|
| 88 | +{ |
|---|
| 89 | + return iov_iter_type(i) == ITER_PIPE; |
|---|
| 90 | +} |
|---|
| 91 | + |
|---|
| 92 | +static inline bool iov_iter_is_discard(const struct iov_iter *i) |
|---|
| 93 | +{ |
|---|
| 94 | + return iov_iter_type(i) == ITER_DISCARD; |
|---|
| 95 | +} |
|---|
| 96 | + |
|---|
| 97 | +static inline unsigned char iov_iter_rw(const struct iov_iter *i) |
|---|
| 98 | +{ |
|---|
| 99 | + return i->type & (READ | WRITE); |
|---|
| 100 | +} |
|---|
| 49 | 101 | |
|---|
| 50 | 102 | /* |
|---|
| 51 | 103 | * Total number of bytes covered by an iovec. |
|---|
| .. | .. |
|---|
| 72 | 124 | iter->iov->iov_len - iter->iov_offset), |
|---|
| 73 | 125 | }; |
|---|
| 74 | 126 | } |
|---|
| 75 | | - |
|---|
| 76 | | -#define iov_for_each(iov, iter, start) \ |
|---|
| 77 | | - if (!((start).type & (ITER_BVEC | ITER_PIPE))) \ |
|---|
| 78 | | - for (iter = (start); \ |
|---|
| 79 | | - (iter).count && \ |
|---|
| 80 | | - ((iov = iov_iter_iovec(&(iter))), 1); \ |
|---|
| 81 | | - iov_iter_advance(&(iter), (iov).iov_len)) |
|---|
| 82 | 127 | |
|---|
| 83 | 128 | size_t iov_iter_copy_from_user_atomic(struct page *page, |
|---|
| 84 | 129 | struct iov_iter *i, unsigned long offset, size_t bytes); |
|---|
| .. | .. |
|---|
| 154 | 199 | #define _copy_from_iter_flushcache _copy_from_iter_nocache |
|---|
| 155 | 200 | #endif |
|---|
| 156 | 201 | |
|---|
| 157 | | -#ifdef CONFIG_ARCH_HAS_UACCESS_MCSAFE |
|---|
| 158 | | -size_t _copy_to_iter_mcsafe(const void *addr, size_t bytes, struct iov_iter *i); |
|---|
| 202 | +#ifdef CONFIG_ARCH_HAS_COPY_MC |
|---|
| 203 | +size_t _copy_mc_to_iter(const void *addr, size_t bytes, struct iov_iter *i); |
|---|
| 159 | 204 | #else |
|---|
| 160 | | -#define _copy_to_iter_mcsafe _copy_to_iter |
|---|
| 205 | +#define _copy_mc_to_iter _copy_to_iter |
|---|
| 161 | 206 | #endif |
|---|
| 162 | 207 | |
|---|
| 163 | 208 | static __always_inline __must_check |
|---|
| .. | .. |
|---|
| 170 | 215 | } |
|---|
| 171 | 216 | |
|---|
| 172 | 217 | static __always_inline __must_check |
|---|
| 173 | | -size_t copy_to_iter_mcsafe(void *addr, size_t bytes, struct iov_iter *i) |
|---|
| 218 | +size_t copy_mc_to_iter(void *addr, size_t bytes, struct iov_iter *i) |
|---|
| 174 | 219 | { |
|---|
| 175 | 220 | if (unlikely(!check_copy_size(addr, bytes, true))) |
|---|
| 176 | 221 | return 0; |
|---|
| 177 | 222 | else |
|---|
| 178 | | - return _copy_to_iter_mcsafe(addr, bytes, i); |
|---|
| 223 | + return _copy_mc_to_iter(addr, bytes, i); |
|---|
| 179 | 224 | } |
|---|
| 180 | 225 | |
|---|
| 181 | 226 | size_t iov_iter_zero(size_t bytes, struct iov_iter *); |
|---|
| 182 | 227 | unsigned long iov_iter_alignment(const struct iov_iter *i); |
|---|
| 183 | 228 | unsigned long iov_iter_gap_alignment(const struct iov_iter *i); |
|---|
| 184 | | -void iov_iter_init(struct iov_iter *i, int direction, const struct iovec *iov, |
|---|
| 229 | +void iov_iter_init(struct iov_iter *i, unsigned int direction, const struct iovec *iov, |
|---|
| 185 | 230 | unsigned long nr_segs, size_t count); |
|---|
| 186 | | -void iov_iter_kvec(struct iov_iter *i, int direction, const struct kvec *kvec, |
|---|
| 231 | +void iov_iter_kvec(struct iov_iter *i, unsigned int direction, const struct kvec *kvec, |
|---|
| 187 | 232 | unsigned long nr_segs, size_t count); |
|---|
| 188 | | -void iov_iter_bvec(struct iov_iter *i, int direction, const struct bio_vec *bvec, |
|---|
| 233 | +void iov_iter_bvec(struct iov_iter *i, unsigned int direction, const struct bio_vec *bvec, |
|---|
| 189 | 234 | unsigned long nr_segs, size_t count); |
|---|
| 190 | | -void iov_iter_pipe(struct iov_iter *i, int direction, struct pipe_inode_info *pipe, |
|---|
| 235 | +void iov_iter_pipe(struct iov_iter *i, unsigned int direction, struct pipe_inode_info *pipe, |
|---|
| 191 | 236 | size_t count); |
|---|
| 237 | +void iov_iter_discard(struct iov_iter *i, unsigned int direction, size_t count); |
|---|
| 192 | 238 | ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages, |
|---|
| 193 | 239 | size_t maxsize, unsigned maxpages, size_t *start); |
|---|
| 194 | 240 | ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, struct page ***pages, |
|---|
| 195 | 241 | size_t maxsize, size_t *start); |
|---|
| 196 | 242 | int iov_iter_npages(const struct iov_iter *i, int maxpages); |
|---|
| 243 | +void iov_iter_restore(struct iov_iter *i, struct iov_iter_state *state); |
|---|
| 197 | 244 | |
|---|
| 198 | 245 | const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags); |
|---|
| 199 | 246 | |
|---|
| .. | .. |
|---|
| 201 | 248 | { |
|---|
| 202 | 249 | return i->count; |
|---|
| 203 | 250 | } |
|---|
| 204 | | - |
|---|
| 205 | | -static inline bool iter_is_iovec(const struct iov_iter *i) |
|---|
| 206 | | -{ |
|---|
| 207 | | - return !(i->type & (ITER_BVEC | ITER_KVEC | ITER_PIPE)); |
|---|
| 208 | | -} |
|---|
| 209 | | - |
|---|
| 210 | | -/* |
|---|
| 211 | | - * Get one of READ or WRITE out of iter->type without any other flags OR'd in |
|---|
| 212 | | - * with it. |
|---|
| 213 | | - * |
|---|
| 214 | | - * The ?: is just for type safety. |
|---|
| 215 | | - */ |
|---|
| 216 | | -#define iov_iter_rw(i) ((0 ? (struct iov_iter *)0 : (i))->type & (READ | WRITE)) |
|---|
| 217 | 251 | |
|---|
| 218 | 252 | /* |
|---|
| 219 | 253 | * Cap the iov_iter by given limit; note that the second argument is |
|---|
| .. | .. |
|---|
| 241 | 275 | { |
|---|
| 242 | 276 | i->count = count; |
|---|
| 243 | 277 | } |
|---|
| 244 | | -size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); |
|---|
| 278 | + |
|---|
| 279 | +struct csum_state { |
|---|
| 280 | + __wsum csum; |
|---|
| 281 | + size_t off; |
|---|
| 282 | +}; |
|---|
| 283 | + |
|---|
| 284 | +size_t csum_and_copy_to_iter(const void *addr, size_t bytes, void *csstate, struct iov_iter *i); |
|---|
| 245 | 285 | size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); |
|---|
| 246 | 286 | bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); |
|---|
| 287 | +size_t hash_and_copy_to_iter(const void *addr, size_t bytes, void *hashp, |
|---|
| 288 | + struct iov_iter *i); |
|---|
| 247 | 289 | |
|---|
| 248 | | -int import_iovec(int type, const struct iovec __user * uvector, |
|---|
| 249 | | - unsigned nr_segs, unsigned fast_segs, |
|---|
| 250 | | - struct iovec **iov, struct iov_iter *i); |
|---|
| 251 | | - |
|---|
| 252 | | -#ifdef CONFIG_COMPAT |
|---|
| 253 | | -struct compat_iovec; |
|---|
| 254 | | -int compat_import_iovec(int type, const struct compat_iovec __user * uvector, |
|---|
| 255 | | - unsigned nr_segs, unsigned fast_segs, |
|---|
| 256 | | - struct iovec **iov, struct iov_iter *i); |
|---|
| 257 | | -#endif |
|---|
| 258 | | - |
|---|
| 290 | +struct iovec *iovec_from_user(const struct iovec __user *uvector, |
|---|
| 291 | + unsigned long nr_segs, unsigned long fast_segs, |
|---|
| 292 | + struct iovec *fast_iov, bool compat); |
|---|
| 293 | +ssize_t import_iovec(int type, const struct iovec __user *uvec, |
|---|
| 294 | + unsigned nr_segs, unsigned fast_segs, struct iovec **iovp, |
|---|
| 295 | + struct iov_iter *i); |
|---|
| 296 | +ssize_t __import_iovec(int type, const struct iovec __user *uvec, |
|---|
| 297 | + unsigned nr_segs, unsigned fast_segs, struct iovec **iovp, |
|---|
| 298 | + struct iov_iter *i, bool compat); |
|---|
| 259 | 299 | int import_single_range(int type, void __user *buf, size_t len, |
|---|
| 260 | 300 | struct iovec *iov, struct iov_iter *i); |
|---|
| 261 | 301 | |
|---|