diff options
Diffstat (limited to 'include/linux/uio.h')
| -rw-r--r-- | include/linux/uio.h | 75 | 
1 files changed, 58 insertions, 17 deletions
diff --git a/include/linux/uio.h b/include/linux/uio.h index 27e3fd942960..044c1d8c230c 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -42,6 +42,7 @@ struct iov_iter_state {  struct iov_iter {  	u8 iter_type; +	bool copy_mc;  	bool nofault;  	bool data_source;  	bool user_backed; @@ -49,14 +50,35 @@ struct iov_iter {  		size_t iov_offset;  		int last_offset;  	}; -	size_t count; +	/* +	 * Hack alert: overlay ubuf_iovec with iovec + count, so +	 * that the members resolve correctly regardless of the type +	 * of iterator used. This means that you can use: +	 * +	 * &iter->__ubuf_iovec or iter->__iov +	 * +	 * interchangably for the user_backed cases, hence simplifying +	 * some of the cases that need to deal with both. +	 */  	union { -		const struct iovec *iov; -		const struct kvec *kvec; -		const struct bio_vec *bvec; -		struct xarray *xarray; -		struct pipe_inode_info *pipe; -		void __user *ubuf; +		/* +		 * This really should be a const, but we cannot do that without +		 * also modifying any of the zero-filling iter init functions. +		 * Leave it non-const for now, but it should be treated as such. +		 */ +		struct iovec __ubuf_iovec; +		struct { +			union { +				/* use iter_iov() to get the current vec */ +				const struct iovec *__iov; +				const struct kvec *kvec; +				const struct bio_vec *bvec; +				struct xarray *xarray; +				struct pipe_inode_info *pipe; +				void __user *ubuf; +			}; +			size_t count; +		};  	};  	union {  		unsigned long nr_segs; @@ -68,6 +90,16 @@ struct iov_iter {  	};  }; +static inline const struct iovec *iter_iov(const struct iov_iter *iter) +{ +	if (iter->iter_type == ITER_UBUF) +		return (const struct iovec *) &iter->__ubuf_iovec; +	return iter->__iov; +} + +#define iter_iov_addr(iter)	(iter_iov(iter)->iov_base + (iter)->iov_offset) +#define iter_iov_len(iter)	(iter_iov(iter)->iov_len - (iter)->iov_offset) +  static inline enum iter_type iov_iter_type(const struct iov_iter *i)  {  	return i->iter_type; @@ -143,15 +175,6 @@ static inline size_t iov_length(const struct iovec *iov, unsigned long nr_segs)  	return ret;  } -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), -	}; -} -  size_t copy_page_from_iter_atomic(struct page *page, unsigned offset,  				  size_t bytes, struct iov_iter *i);  void iov_iter_advance(struct iov_iter *i, size_t bytes); @@ -173,6 +196,8 @@ static inline size_t copy_folio_to_iter(struct folio *folio, size_t offset,  {  	return copy_page_to_iter(&folio->page, offset, bytes, i);  } +size_t copy_page_to_iter_nofault(struct page *page, unsigned offset, +				 size_t bytes, struct iov_iter *i);  static __always_inline __must_check  size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i) @@ -232,8 +257,22 @@ size_t _copy_from_iter_flushcache(void *addr, size_t bytes, struct iov_iter *i);  #ifdef CONFIG_ARCH_HAS_COPY_MC  size_t _copy_mc_to_iter(const void *addr, size_t bytes, struct iov_iter *i); +static inline void iov_iter_set_copy_mc(struct iov_iter *i) +{ +	i->copy_mc = true; +} + +static inline bool iov_iter_is_copy_mc(const struct iov_iter *i) +{ +	return i->copy_mc; +}  #else  #define _copy_mc_to_iter _copy_to_iter +static inline void iov_iter_set_copy_mc(struct iov_iter *i) { } +static inline bool iov_iter_is_copy_mc(const struct iov_iter *i) +{ +	return false; +}  #endif  size_t iov_iter_zero(size_t bytes, struct iov_iter *); @@ -356,10 +395,12 @@ static inline void iov_iter_ubuf(struct iov_iter *i, unsigned int direction,  	WARN_ON(direction & ~(READ | WRITE));  	*i = (struct iov_iter) {  		.iter_type = ITER_UBUF, +		.copy_mc = false,  		.user_backed = true,  		.data_source = direction,  		.ubuf = buf, -		.count = count +		.count = count, +		.nr_segs = 1  	};  }  /* Flags for iov_iter_get/extract_pages*() */  |