xref: /linux/lib/tests/kunit_iov_iter.c (revision 7278aa840b69e5a31826329ef893230d67cae811)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* I/O iterator tests.  This can only test kernel-backed iterator types.
3  *
4  * Copyright (C) 2023 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  */
7 
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9 
10 #include <linux/module.h>
11 #include <linux/vmalloc.h>
12 #include <linux/mm.h>
13 #include <linux/uio.h>
14 #include <linux/bvec.h>
15 #include <linux/folio_queue.h>
16 #include <linux/minmax.h>
17 #include <kunit/test.h>
18 
19 MODULE_DESCRIPTION("iov_iter testing");
20 MODULE_AUTHOR("David Howells <dhowells@redhat.com>");
21 MODULE_LICENSE("GPL");
22 
23 struct kvec_test_range {
24 	int	from, to;
25 };
26 
27 static const struct kvec_test_range kvec_test_ranges[] = {
28 	{ 0x00002, 0x00002 },
29 	{ 0x00027, 0x03000 },
30 	{ 0x05193, 0x18794 },
31 	{ 0x20000, 0x20000 },
32 	{ 0x20000, 0x24000 },
33 	{ 0x24000, 0x27001 },
34 	{ 0x29000, 0xffffb },
35 	{ 0xffffd, 0xffffe },
36 	{ -1 }
37 };
38 
39 static inline u8 pattern(unsigned long x)
40 {
41 	return (u8)x + (u8)(x >> 8) + (u8)(x >> 16);
42 }
43 
44 static void iov_kunit_unmap(void *data)
45 {
46 	vfree(data);
47 }
48 
49 static void *__init iov_kunit_create_buffer(struct kunit *test,
50 					    struct page ***ppages,
51 					    size_t npages)
52 {
53 	struct page **pages;
54 	unsigned long got;
55 	void *buffer;
56 	unsigned int i;
57 
58 	pages = kzalloc_objs(struct page *, npages, GFP_KERNEL);
59 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pages);
60 	*ppages = pages;
61 
62 	got = alloc_pages_bulk(GFP_KERNEL, npages, pages);
63 	if (got != npages) {
64 		release_pages(pages, got);
65 		kvfree(pages);
66 		KUNIT_ASSERT_EQ(test, got, npages);
67 	}
68 	/* Make sure that we don't get a physically contiguous buffer. */
69 	for (i = 0; i < npages / 4; ++i)
70 		swap(pages[i], pages[i + npages / 2]);
71 
72 	buffer = vmap(pages, npages, VM_MAP | VM_MAP_PUT_PAGES, PAGE_KERNEL);
73 	if (buffer == NULL) {
74 		release_pages(pages, got);
75 		kvfree(pages);
76 	}
77         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buffer);
78 
79 	kunit_add_action_or_reset(test, iov_kunit_unmap, buffer);
80 	return buffer;
81 }
82 
83 static void __init iov_kunit_load_kvec(struct kunit *test,
84 				       struct iov_iter *iter, int dir,
85 				       struct kvec *kvec, unsigned int kvmax,
86 				       void *buffer, size_t bufsize,
87 				       const struct kvec_test_range *pr)
88 {
89 	size_t size = 0;
90 	int i;
91 
92 	for (i = 0; i < kvmax; i++, pr++) {
93 		if (pr->from < 0)
94 			break;
95 		KUNIT_ASSERT_GE(test, pr->to, pr->from);
96 		KUNIT_ASSERT_LE(test, pr->to, bufsize);
97 		kvec[i].iov_base = buffer + pr->from;
98 		kvec[i].iov_len = pr->to - pr->from;
99 		size += pr->to - pr->from;
100 	}
101 	KUNIT_ASSERT_LE(test, size, bufsize);
102 
103 	iov_iter_kvec(iter, dir, kvec, i, size);
104 }
105 
106 /*
107  * Test copying to a ITER_KVEC-type iterator.
108  */
109 static void __init iov_kunit_copy_to_kvec(struct kunit *test)
110 {
111 	const struct kvec_test_range *pr;
112 	struct iov_iter iter;
113 	struct page **spages, **bpages;
114 	struct kvec kvec[8];
115 	u8 *scratch, *buffer;
116 	size_t bufsize, npages, size, copied;
117 	int i, patt;
118 
119 	bufsize = 0x100000;
120 	npages = bufsize / PAGE_SIZE;
121 
122 	scratch = iov_kunit_create_buffer(test, &spages, npages);
123 	for (i = 0; i < bufsize; i++)
124 		scratch[i] = pattern(i);
125 
126 	buffer = iov_kunit_create_buffer(test, &bpages, npages);
127 	memset(buffer, 0, bufsize);
128 
129 	iov_kunit_load_kvec(test, &iter, READ, kvec, ARRAY_SIZE(kvec),
130 			    buffer, bufsize, kvec_test_ranges);
131 	size = iter.count;
132 
133 	copied = copy_to_iter(scratch, size, &iter);
134 
135 	KUNIT_EXPECT_EQ(test, copied, size);
136 	KUNIT_EXPECT_EQ(test, iter.count, 0);
137 	KUNIT_EXPECT_EQ(test, iter.nr_segs, 0);
138 
139 	/* Build the expected image in the scratch buffer. */
140 	patt = 0;
141 	memset(scratch, 0, bufsize);
142 	for (pr = kvec_test_ranges; pr->from >= 0; pr++)
143 		for (i = pr->from; i < pr->to; i++)
144 			scratch[i] = pattern(patt++);
145 
146 	/* Compare the images */
147 	for (i = 0; i < bufsize; i++) {
148 		KUNIT_EXPECT_EQ_MSG(test, buffer[i], scratch[i], "at i=%x", i);
149 		if (buffer[i] != scratch[i])
150 			return;
151 	}
152 
153 	KUNIT_SUCCEED(test);
154 }
155 
156 /*
157  * Test copying from a ITER_KVEC-type iterator.
158  */
159 static void __init iov_kunit_copy_from_kvec(struct kunit *test)
160 {
161 	const struct kvec_test_range *pr;
162 	struct iov_iter iter;
163 	struct page **spages, **bpages;
164 	struct kvec kvec[8];
165 	u8 *scratch, *buffer;
166 	size_t bufsize, npages, size, copied;
167 	int i, j;
168 
169 	bufsize = 0x100000;
170 	npages = bufsize / PAGE_SIZE;
171 
172 	buffer = iov_kunit_create_buffer(test, &bpages, npages);
173 	for (i = 0; i < bufsize; i++)
174 		buffer[i] = pattern(i);
175 
176 	scratch = iov_kunit_create_buffer(test, &spages, npages);
177 	memset(scratch, 0, bufsize);
178 
179 	iov_kunit_load_kvec(test, &iter, WRITE, kvec, ARRAY_SIZE(kvec),
180 			    buffer, bufsize, kvec_test_ranges);
181 	size = min(iter.count, bufsize);
182 
183 	copied = copy_from_iter(scratch, size, &iter);
184 
185 	KUNIT_EXPECT_EQ(test, copied, size);
186 	KUNIT_EXPECT_EQ(test, iter.count, 0);
187 	KUNIT_EXPECT_EQ(test, iter.nr_segs, 0);
188 
189 	/* Build the expected image in the main buffer. */
190 	i = 0;
191 	memset(buffer, 0, bufsize);
192 	for (pr = kvec_test_ranges; pr->from >= 0; pr++) {
193 		for (j = pr->from; j < pr->to; j++) {
194 			buffer[i++] = pattern(j);
195 			if (i >= bufsize)
196 				goto stop;
197 		}
198 	}
199 stop:
200 
201 	/* Compare the images */
202 	for (i = 0; i < bufsize; i++) {
203 		KUNIT_EXPECT_EQ_MSG(test, scratch[i], buffer[i], "at i=%x", i);
204 		if (scratch[i] != buffer[i])
205 			return;
206 	}
207 
208 	KUNIT_SUCCEED(test);
209 }
210 
211 struct bvec_test_range {
212 	int	page, from, to;
213 };
214 
215 static const struct bvec_test_range bvec_test_ranges[] = {
216 	{ 0, 0x0002, 0x0002 },
217 	{ 1, 0x0027, 0x0893 },
218 	{ 2, 0x0193, 0x0794 },
219 	{ 3, 0x0000, 0x1000 },
220 	{ 4, 0x0000, 0x1000 },
221 	{ 5, 0x0000, 0x1000 },
222 	{ 6, 0x0000, 0x0ffb },
223 	{ 6, 0x0ffd, 0x0ffe },
224 	{ -1, -1, -1 }
225 };
226 
227 static void __init iov_kunit_load_bvec(struct kunit *test,
228 				       struct iov_iter *iter, int dir,
229 				       struct bio_vec *bvec, unsigned int bvmax,
230 				       struct page **pages, size_t npages,
231 				       size_t bufsize,
232 				       const struct bvec_test_range *pr)
233 {
234 	struct page *can_merge = NULL, *page;
235 	size_t size = 0;
236 	int i;
237 
238 	for (i = 0; i < bvmax; i++, pr++) {
239 		if (pr->from < 0)
240 			break;
241 		KUNIT_ASSERT_LT(test, pr->page, npages);
242 		KUNIT_ASSERT_LT(test, pr->page * PAGE_SIZE, bufsize);
243 		KUNIT_ASSERT_GE(test, pr->from, 0);
244 		KUNIT_ASSERT_GE(test, pr->to, pr->from);
245 		KUNIT_ASSERT_LE(test, pr->to, PAGE_SIZE);
246 
247 		page = pages[pr->page];
248 		if (pr->from == 0 && pr->from != pr->to && page == can_merge) {
249 			i--;
250 			bvec[i].bv_len += pr->to;
251 		} else {
252 			bvec_set_page(&bvec[i], page, pr->to - pr->from, pr->from);
253 		}
254 
255 		size += pr->to - pr->from;
256 		if ((pr->to & ~PAGE_MASK) == 0)
257 			can_merge = page + pr->to / PAGE_SIZE;
258 		else
259 			can_merge = NULL;
260 	}
261 
262 	iov_iter_bvec(iter, dir, bvec, i, size);
263 }
264 
265 /*
266  * Test copying to a ITER_BVEC-type iterator.
267  */
268 static void __init iov_kunit_copy_to_bvec(struct kunit *test)
269 {
270 	const struct bvec_test_range *pr;
271 	struct iov_iter iter;
272 	struct bio_vec bvec[8];
273 	struct page **spages, **bpages;
274 	u8 *scratch, *buffer;
275 	size_t bufsize, npages, size, copied;
276 	int i, b, patt;
277 
278 	bufsize = 0x100000;
279 	npages = bufsize / PAGE_SIZE;
280 
281 	scratch = iov_kunit_create_buffer(test, &spages, npages);
282 	for (i = 0; i < bufsize; i++)
283 		scratch[i] = pattern(i);
284 
285 	buffer = iov_kunit_create_buffer(test, &bpages, npages);
286 	memset(buffer, 0, bufsize);
287 
288 	iov_kunit_load_bvec(test, &iter, READ, bvec, ARRAY_SIZE(bvec),
289 			    bpages, npages, bufsize, bvec_test_ranges);
290 	size = iter.count;
291 
292 	copied = copy_to_iter(scratch, size, &iter);
293 
294 	KUNIT_EXPECT_EQ(test, copied, size);
295 	KUNIT_EXPECT_EQ(test, iter.count, 0);
296 	KUNIT_EXPECT_EQ(test, iter.nr_segs, 0);
297 
298 	/* Build the expected image in the scratch buffer. */
299 	b = 0;
300 	patt = 0;
301 	memset(scratch, 0, bufsize);
302 	for (pr = bvec_test_ranges; pr->from >= 0; pr++, b++) {
303 		u8 *p = scratch + pr->page * PAGE_SIZE;
304 
305 		for (i = pr->from; i < pr->to; i++)
306 			p[i] = pattern(patt++);
307 	}
308 
309 	/* Compare the images */
310 	for (i = 0; i < bufsize; i++) {
311 		KUNIT_EXPECT_EQ_MSG(test, buffer[i], scratch[i], "at i=%x", i);
312 		if (buffer[i] != scratch[i])
313 			return;
314 	}
315 
316 	KUNIT_SUCCEED(test);
317 }
318 
319 /*
320  * Test copying from a ITER_BVEC-type iterator.
321  */
322 static void __init iov_kunit_copy_from_bvec(struct kunit *test)
323 {
324 	const struct bvec_test_range *pr;
325 	struct iov_iter iter;
326 	struct bio_vec bvec[8];
327 	struct page **spages, **bpages;
328 	u8 *scratch, *buffer;
329 	size_t bufsize, npages, size, copied;
330 	int i, j;
331 
332 	bufsize = 0x100000;
333 	npages = bufsize / PAGE_SIZE;
334 
335 	buffer = iov_kunit_create_buffer(test, &bpages, npages);
336 	for (i = 0; i < bufsize; i++)
337 		buffer[i] = pattern(i);
338 
339 	scratch = iov_kunit_create_buffer(test, &spages, npages);
340 	memset(scratch, 0, bufsize);
341 
342 	iov_kunit_load_bvec(test, &iter, WRITE, bvec, ARRAY_SIZE(bvec),
343 			    bpages, npages, bufsize, bvec_test_ranges);
344 	size = iter.count;
345 
346 	copied = copy_from_iter(scratch, size, &iter);
347 
348 	KUNIT_EXPECT_EQ(test, copied, size);
349 	KUNIT_EXPECT_EQ(test, iter.count, 0);
350 	KUNIT_EXPECT_EQ(test, iter.nr_segs, 0);
351 
352 	/* Build the expected image in the main buffer. */
353 	i = 0;
354 	memset(buffer, 0, bufsize);
355 	for (pr = bvec_test_ranges; pr->from >= 0; pr++) {
356 		size_t patt = pr->page * PAGE_SIZE;
357 
358 		for (j = pr->from; j < pr->to; j++) {
359 			buffer[i++] = pattern(patt + j);
360 			if (i >= bufsize)
361 				goto stop;
362 		}
363 	}
364 stop:
365 
366 	/* Compare the images */
367 	for (i = 0; i < bufsize; i++) {
368 		KUNIT_EXPECT_EQ_MSG(test, scratch[i], buffer[i], "at i=%x", i);
369 		if (scratch[i] != buffer[i])
370 			return;
371 	}
372 
373 	KUNIT_SUCCEED(test);
374 }
375 
376 static void iov_kunit_destroy_folioq(void *data)
377 {
378 	struct folio_queue *folioq, *next;
379 
380 	for (folioq = data; folioq; folioq = next) {
381 		next = folioq->next;
382 		kfree(folioq);
383 	}
384 }
385 
386 static void __init iov_kunit_load_folioq(struct kunit *test,
387 					struct iov_iter *iter, int dir,
388 					struct folio_queue *folioq,
389 					struct page **pages, size_t npages)
390 {
391 	struct folio_queue *p = folioq;
392 	size_t size = 0;
393 	int i;
394 
395 	for (i = 0; i < npages; i++) {
396 		if (folioq_full(p)) {
397 			p->next = kzalloc_obj(struct folio_queue);
398 			KUNIT_ASSERT_NOT_ERR_OR_NULL(test, p->next);
399 			folioq_init(p->next, 0);
400 			p->next->prev = p;
401 			p = p->next;
402 		}
403 		folioq_append(p, page_folio(pages[i]));
404 		size += PAGE_SIZE;
405 	}
406 	iov_iter_folio_queue(iter, dir, folioq, 0, 0, size);
407 }
408 
409 static struct folio_queue *iov_kunit_create_folioq(struct kunit *test)
410 {
411 	struct folio_queue *folioq;
412 
413 	folioq = kzalloc_obj(struct folio_queue);
414 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, folioq);
415 	kunit_add_action_or_reset(test, iov_kunit_destroy_folioq, folioq);
416 	folioq_init(folioq, 0);
417 	return folioq;
418 }
419 
420 /*
421  * Test copying to a ITER_FOLIOQ-type iterator.
422  */
423 static void __init iov_kunit_copy_to_folioq(struct kunit *test)
424 {
425 	const struct kvec_test_range *pr;
426 	struct iov_iter iter;
427 	struct folio_queue *folioq;
428 	struct page **spages, **bpages;
429 	u8 *scratch, *buffer;
430 	size_t bufsize, npages, size, copied;
431 	int i, patt;
432 
433 	bufsize = 0x100000;
434 	npages = bufsize / PAGE_SIZE;
435 
436 	folioq = iov_kunit_create_folioq(test);
437 
438 	scratch = iov_kunit_create_buffer(test, &spages, npages);
439 	for (i = 0; i < bufsize; i++)
440 		scratch[i] = pattern(i);
441 
442 	buffer = iov_kunit_create_buffer(test, &bpages, npages);
443 	memset(buffer, 0, bufsize);
444 
445 	iov_kunit_load_folioq(test, &iter, READ, folioq, bpages, npages);
446 
447 	i = 0;
448 	for (pr = kvec_test_ranges; pr->from >= 0; pr++) {
449 		size = pr->to - pr->from;
450 		KUNIT_ASSERT_LE(test, pr->to, bufsize);
451 
452 		iov_iter_folio_queue(&iter, READ, folioq, 0, 0, pr->to);
453 		iov_iter_advance(&iter, pr->from);
454 		copied = copy_to_iter(scratch + i, size, &iter);
455 
456 		KUNIT_EXPECT_EQ(test, copied, size);
457 		KUNIT_EXPECT_EQ(test, iter.count, 0);
458 		KUNIT_EXPECT_EQ(test, iter.iov_offset, pr->to % PAGE_SIZE);
459 		i += size;
460 		if (test->status == KUNIT_FAILURE)
461 			goto stop;
462 	}
463 
464 	/* Build the expected image in the scratch buffer. */
465 	patt = 0;
466 	memset(scratch, 0, bufsize);
467 	for (pr = kvec_test_ranges; pr->from >= 0; pr++)
468 		for (i = pr->from; i < pr->to; i++)
469 			scratch[i] = pattern(patt++);
470 
471 	/* Compare the images */
472 	for (i = 0; i < bufsize; i++) {
473 		KUNIT_EXPECT_EQ_MSG(test, buffer[i], scratch[i], "at i=%x", i);
474 		if (buffer[i] != scratch[i])
475 			return;
476 	}
477 
478 stop:
479 	KUNIT_SUCCEED(test);
480 }
481 
482 /*
483  * Test copying from a ITER_FOLIOQ-type iterator.
484  */
485 static void __init iov_kunit_copy_from_folioq(struct kunit *test)
486 {
487 	const struct kvec_test_range *pr;
488 	struct iov_iter iter;
489 	struct folio_queue *folioq;
490 	struct page **spages, **bpages;
491 	u8 *scratch, *buffer;
492 	size_t bufsize, npages, size, copied;
493 	int i, j;
494 
495 	bufsize = 0x100000;
496 	npages = bufsize / PAGE_SIZE;
497 
498 	folioq = iov_kunit_create_folioq(test);
499 
500 	buffer = iov_kunit_create_buffer(test, &bpages, npages);
501 	for (i = 0; i < bufsize; i++)
502 		buffer[i] = pattern(i);
503 
504 	scratch = iov_kunit_create_buffer(test, &spages, npages);
505 	memset(scratch, 0, bufsize);
506 
507 	iov_kunit_load_folioq(test, &iter, READ, folioq, bpages, npages);
508 
509 	i = 0;
510 	for (pr = kvec_test_ranges; pr->from >= 0; pr++) {
511 		size = pr->to - pr->from;
512 		KUNIT_ASSERT_LE(test, pr->to, bufsize);
513 
514 		iov_iter_folio_queue(&iter, WRITE, folioq, 0, 0, pr->to);
515 		iov_iter_advance(&iter, pr->from);
516 		copied = copy_from_iter(scratch + i, size, &iter);
517 
518 		KUNIT_EXPECT_EQ(test, copied, size);
519 		KUNIT_EXPECT_EQ(test, iter.count, 0);
520 		KUNIT_EXPECT_EQ(test, iter.iov_offset, pr->to % PAGE_SIZE);
521 		i += size;
522 	}
523 
524 	/* Build the expected image in the main buffer. */
525 	i = 0;
526 	memset(buffer, 0, bufsize);
527 	for (pr = kvec_test_ranges; pr->from >= 0; pr++) {
528 		for (j = pr->from; j < pr->to; j++) {
529 			buffer[i++] = pattern(j);
530 			if (i >= bufsize)
531 				goto stop;
532 		}
533 	}
534 stop:
535 
536 	/* Compare the images */
537 	for (i = 0; i < bufsize; i++) {
538 		KUNIT_EXPECT_EQ_MSG(test, scratch[i], buffer[i], "at i=%x", i);
539 		if (scratch[i] != buffer[i])
540 			return;
541 	}
542 
543 	KUNIT_SUCCEED(test);
544 }
545 
546 static void iov_kunit_destroy_xarray(void *data)
547 {
548 	struct xarray *xarray = data;
549 
550 	xa_destroy(xarray);
551 	kfree(xarray);
552 }
553 
554 static void __init iov_kunit_load_xarray(struct kunit *test,
555 					 struct iov_iter *iter, int dir,
556 					 struct xarray *xarray,
557 					 struct page **pages, size_t npages)
558 {
559 	size_t size = 0;
560 	int i;
561 
562 	for (i = 0; i < npages; i++) {
563 		void *x = xa_store(xarray, i, pages[i], GFP_KERNEL);
564 
565 		KUNIT_ASSERT_FALSE(test, xa_is_err(x));
566 		size += PAGE_SIZE;
567 	}
568 	iov_iter_xarray(iter, dir, xarray, 0, size);
569 }
570 
571 static struct xarray *iov_kunit_create_xarray(struct kunit *test)
572 {
573 	struct xarray *xarray;
574 
575 	xarray = kzalloc_obj(struct xarray);
576 	xa_init(xarray);
577 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xarray);
578 	kunit_add_action_or_reset(test, iov_kunit_destroy_xarray, xarray);
579 	return xarray;
580 }
581 
582 /*
583  * Test copying to a ITER_XARRAY-type iterator.
584  */
585 static void __init iov_kunit_copy_to_xarray(struct kunit *test)
586 {
587 	const struct kvec_test_range *pr;
588 	struct iov_iter iter;
589 	struct xarray *xarray;
590 	struct page **spages, **bpages;
591 	u8 *scratch, *buffer;
592 	size_t bufsize, npages, size, copied;
593 	int i, patt;
594 
595 	bufsize = 0x100000;
596 	npages = bufsize / PAGE_SIZE;
597 
598 	xarray = iov_kunit_create_xarray(test);
599 
600 	scratch = iov_kunit_create_buffer(test, &spages, npages);
601 	for (i = 0; i < bufsize; i++)
602 		scratch[i] = pattern(i);
603 
604 	buffer = iov_kunit_create_buffer(test, &bpages, npages);
605 	memset(buffer, 0, bufsize);
606 
607 	iov_kunit_load_xarray(test, &iter, READ, xarray, bpages, npages);
608 
609 	i = 0;
610 	for (pr = kvec_test_ranges; pr->from >= 0; pr++) {
611 		size = pr->to - pr->from;
612 		KUNIT_ASSERT_LE(test, pr->to, bufsize);
613 
614 		iov_iter_xarray(&iter, READ, xarray, pr->from, size);
615 		copied = copy_to_iter(scratch + i, size, &iter);
616 
617 		KUNIT_EXPECT_EQ(test, copied, size);
618 		KUNIT_EXPECT_EQ(test, iter.count, 0);
619 		KUNIT_EXPECT_EQ(test, iter.iov_offset, size);
620 		i += size;
621 	}
622 
623 	/* Build the expected image in the scratch buffer. */
624 	patt = 0;
625 	memset(scratch, 0, bufsize);
626 	for (pr = kvec_test_ranges; pr->from >= 0; pr++)
627 		for (i = pr->from; i < pr->to; i++)
628 			scratch[i] = pattern(patt++);
629 
630 	/* Compare the images */
631 	for (i = 0; i < bufsize; i++) {
632 		KUNIT_EXPECT_EQ_MSG(test, buffer[i], scratch[i], "at i=%x", i);
633 		if (buffer[i] != scratch[i])
634 			return;
635 	}
636 
637 	KUNIT_SUCCEED(test);
638 }
639 
640 /*
641  * Test copying from a ITER_XARRAY-type iterator.
642  */
643 static void __init iov_kunit_copy_from_xarray(struct kunit *test)
644 {
645 	const struct kvec_test_range *pr;
646 	struct iov_iter iter;
647 	struct xarray *xarray;
648 	struct page **spages, **bpages;
649 	u8 *scratch, *buffer;
650 	size_t bufsize, npages, size, copied;
651 	int i, j;
652 
653 	bufsize = 0x100000;
654 	npages = bufsize / PAGE_SIZE;
655 
656 	xarray = iov_kunit_create_xarray(test);
657 
658 	buffer = iov_kunit_create_buffer(test, &bpages, npages);
659 	for (i = 0; i < bufsize; i++)
660 		buffer[i] = pattern(i);
661 
662 	scratch = iov_kunit_create_buffer(test, &spages, npages);
663 	memset(scratch, 0, bufsize);
664 
665 	iov_kunit_load_xarray(test, &iter, READ, xarray, bpages, npages);
666 
667 	i = 0;
668 	for (pr = kvec_test_ranges; pr->from >= 0; pr++) {
669 		size = pr->to - pr->from;
670 		KUNIT_ASSERT_LE(test, pr->to, bufsize);
671 
672 		iov_iter_xarray(&iter, WRITE, xarray, pr->from, size);
673 		copied = copy_from_iter(scratch + i, size, &iter);
674 
675 		KUNIT_EXPECT_EQ(test, copied, size);
676 		KUNIT_EXPECT_EQ(test, iter.count, 0);
677 		KUNIT_EXPECT_EQ(test, iter.iov_offset, size);
678 		i += size;
679 	}
680 
681 	/* Build the expected image in the main buffer. */
682 	i = 0;
683 	memset(buffer, 0, bufsize);
684 	for (pr = kvec_test_ranges; pr->from >= 0; pr++) {
685 		for (j = pr->from; j < pr->to; j++) {
686 			buffer[i++] = pattern(j);
687 			if (i >= bufsize)
688 				goto stop;
689 		}
690 	}
691 stop:
692 
693 	/* Compare the images */
694 	for (i = 0; i < bufsize; i++) {
695 		KUNIT_EXPECT_EQ_MSG(test, scratch[i], buffer[i], "at i=%x", i);
696 		if (scratch[i] != buffer[i])
697 			return;
698 	}
699 
700 	KUNIT_SUCCEED(test);
701 }
702 
703 /*
704  * Test the extraction of ITER_KVEC-type iterators.
705  */
706 static void __init iov_kunit_extract_pages_kvec(struct kunit *test)
707 {
708 	const struct kvec_test_range *pr;
709 	struct iov_iter iter;
710 	struct page **bpages, *pagelist[8], **pages = pagelist;
711 	struct kvec kvec[8];
712 	u8 *buffer;
713 	ssize_t len;
714 	size_t bufsize, size = 0, npages;
715 	int i, from;
716 
717 	bufsize = 0x100000;
718 	npages = bufsize / PAGE_SIZE;
719 
720 	buffer = iov_kunit_create_buffer(test, &bpages, npages);
721 
722 	iov_kunit_load_kvec(test, &iter, READ, kvec, ARRAY_SIZE(kvec),
723 			    buffer, bufsize, kvec_test_ranges);
724 	size = iter.count;
725 
726 	pr = kvec_test_ranges;
727 	from = pr->from;
728 	do {
729 		size_t offset0 = LONG_MAX;
730 
731 		for (i = 0; i < ARRAY_SIZE(pagelist); i++)
732 			pagelist[i] = (void *)(unsigned long)0xaa55aa55aa55aa55ULL;
733 
734 		len = iov_iter_extract_pages(&iter, &pages, 100 * 1024,
735 					     ARRAY_SIZE(pagelist), 0, &offset0);
736 		KUNIT_EXPECT_GE(test, len, 0);
737 		if (len < 0)
738 			break;
739 		KUNIT_EXPECT_GE(test, (ssize_t)offset0, 0);
740 		KUNIT_EXPECT_LT(test, offset0, PAGE_SIZE);
741 		KUNIT_EXPECT_LE(test, len, size);
742 		KUNIT_EXPECT_EQ(test, iter.count, size - len);
743 		size -= len;
744 
745 		if (len == 0)
746 			break;
747 
748 		for (i = 0; i < ARRAY_SIZE(pagelist); i++) {
749 			struct page *p;
750 			ssize_t part = min_t(ssize_t, len, PAGE_SIZE - offset0);
751 			int ix;
752 
753 			KUNIT_ASSERT_GE(test, part, 0);
754 			while (from == pr->to) {
755 				pr++;
756 				from = pr->from;
757 				if (from < 0)
758 					goto stop;
759 			}
760 			ix = from / PAGE_SIZE;
761 			KUNIT_ASSERT_LT(test, ix, npages);
762 			p = bpages[ix];
763 			KUNIT_EXPECT_PTR_EQ(test, pagelist[i], p);
764 			KUNIT_EXPECT_EQ(test, offset0, from % PAGE_SIZE);
765 			from += part;
766 			len -= part;
767 			KUNIT_ASSERT_GE(test, len, 0);
768 			if (len == 0)
769 				break;
770 			offset0 = 0;
771 		}
772 
773 		if (test->status == KUNIT_FAILURE)
774 			break;
775 	} while (iov_iter_count(&iter) > 0);
776 
777 stop:
778 	KUNIT_EXPECT_EQ(test, size, 0);
779 	KUNIT_EXPECT_EQ(test, iter.count, 0);
780 	KUNIT_SUCCEED(test);
781 }
782 
783 /*
784  * Test the extraction of ITER_BVEC-type iterators.
785  */
786 static void __init iov_kunit_extract_pages_bvec(struct kunit *test)
787 {
788 	const struct bvec_test_range *pr;
789 	struct iov_iter iter;
790 	struct page **bpages, *pagelist[8], **pages = pagelist;
791 	struct bio_vec bvec[8];
792 	ssize_t len;
793 	size_t bufsize, size = 0, npages;
794 	int i, from;
795 
796 	bufsize = 0x100000;
797 	npages = bufsize / PAGE_SIZE;
798 
799 	iov_kunit_create_buffer(test, &bpages, npages);
800 	iov_kunit_load_bvec(test, &iter, READ, bvec, ARRAY_SIZE(bvec),
801 			    bpages, npages, bufsize, bvec_test_ranges);
802 	size = iter.count;
803 
804 	pr = bvec_test_ranges;
805 	from = pr->from;
806 	do {
807 		size_t offset0 = LONG_MAX;
808 
809 		for (i = 0; i < ARRAY_SIZE(pagelist); i++)
810 			pagelist[i] = (void *)(unsigned long)0xaa55aa55aa55aa55ULL;
811 
812 		len = iov_iter_extract_pages(&iter, &pages, 100 * 1024,
813 					     ARRAY_SIZE(pagelist), 0, &offset0);
814 		KUNIT_EXPECT_GE(test, len, 0);
815 		if (len < 0)
816 			break;
817 		KUNIT_EXPECT_GE(test, (ssize_t)offset0, 0);
818 		KUNIT_EXPECT_LT(test, offset0, PAGE_SIZE);
819 		KUNIT_EXPECT_LE(test, len, size);
820 		KUNIT_EXPECT_EQ(test, iter.count, size - len);
821 		size -= len;
822 
823 		if (len == 0)
824 			break;
825 
826 		for (i = 0; i < ARRAY_SIZE(pagelist); i++) {
827 			struct page *p;
828 			ssize_t part = min_t(ssize_t, len, PAGE_SIZE - offset0);
829 			int ix;
830 
831 			KUNIT_ASSERT_GE(test, part, 0);
832 			while (from == pr->to) {
833 				pr++;
834 				from = pr->from;
835 				if (from < 0)
836 					goto stop;
837 			}
838 			ix = pr->page + from / PAGE_SIZE;
839 			KUNIT_ASSERT_LT(test, ix, npages);
840 			p = bpages[ix];
841 			KUNIT_EXPECT_PTR_EQ(test, pagelist[i], p);
842 			KUNIT_EXPECT_EQ(test, offset0, from % PAGE_SIZE);
843 			from += part;
844 			len -= part;
845 			KUNIT_ASSERT_GE(test, len, 0);
846 			if (len == 0)
847 				break;
848 			offset0 = 0;
849 		}
850 
851 		if (test->status == KUNIT_FAILURE)
852 			break;
853 	} while (iov_iter_count(&iter) > 0);
854 
855 stop:
856 	KUNIT_EXPECT_EQ(test, size, 0);
857 	KUNIT_EXPECT_EQ(test, iter.count, 0);
858 	KUNIT_SUCCEED(test);
859 }
860 
861 /*
862  * Test the extraction of ITER_FOLIOQ-type iterators.
863  */
864 static void __init iov_kunit_extract_pages_folioq(struct kunit *test)
865 {
866 	const struct kvec_test_range *pr;
867 	struct folio_queue *folioq;
868 	struct iov_iter iter;
869 	struct page **bpages, *pagelist[8], **pages = pagelist;
870 	ssize_t len;
871 	size_t bufsize, size = 0, npages;
872 	int i, from;
873 
874 	bufsize = 0x100000;
875 	npages = bufsize / PAGE_SIZE;
876 
877 	folioq = iov_kunit_create_folioq(test);
878 
879 	iov_kunit_create_buffer(test, &bpages, npages);
880 	iov_kunit_load_folioq(test, &iter, READ, folioq, bpages, npages);
881 
882 	for (pr = kvec_test_ranges; pr->from >= 0; pr++) {
883 		from = pr->from;
884 		size = pr->to - from;
885 		KUNIT_ASSERT_LE(test, pr->to, bufsize);
886 
887 		iov_iter_folio_queue(&iter, WRITE, folioq, 0, 0, pr->to);
888 		iov_iter_advance(&iter, from);
889 
890 		do {
891 			size_t offset0 = LONG_MAX;
892 
893 			for (i = 0; i < ARRAY_SIZE(pagelist); i++)
894 				pagelist[i] = (void *)(unsigned long)0xaa55aa55aa55aa55ULL;
895 
896 			len = iov_iter_extract_pages(&iter, &pages, 100 * 1024,
897 						     ARRAY_SIZE(pagelist), 0, &offset0);
898 			KUNIT_EXPECT_GE(test, len, 0);
899 			if (len < 0)
900 				break;
901 			KUNIT_EXPECT_LE(test, len, size);
902 			KUNIT_EXPECT_EQ(test, iter.count, size - len);
903 			if (len == 0)
904 				break;
905 			size -= len;
906 			KUNIT_EXPECT_GE(test, (ssize_t)offset0, 0);
907 			KUNIT_EXPECT_LT(test, offset0, PAGE_SIZE);
908 
909 			for (i = 0; i < ARRAY_SIZE(pagelist); i++) {
910 				struct page *p;
911 				ssize_t part = min_t(ssize_t, len, PAGE_SIZE - offset0);
912 				int ix;
913 
914 				KUNIT_ASSERT_GE(test, part, 0);
915 				ix = from / PAGE_SIZE;
916 				KUNIT_ASSERT_LT(test, ix, npages);
917 				p = bpages[ix];
918 				KUNIT_EXPECT_PTR_EQ(test, pagelist[i], p);
919 				KUNIT_EXPECT_EQ(test, offset0, from % PAGE_SIZE);
920 				from += part;
921 				len -= part;
922 				KUNIT_ASSERT_GE(test, len, 0);
923 				if (len == 0)
924 					break;
925 				offset0 = 0;
926 			}
927 
928 			if (test->status == KUNIT_FAILURE)
929 				goto stop;
930 		} while (iov_iter_count(&iter) > 0);
931 
932 		KUNIT_EXPECT_EQ(test, size, 0);
933 		KUNIT_EXPECT_EQ(test, iter.count, 0);
934 	}
935 
936 stop:
937 	KUNIT_SUCCEED(test);
938 }
939 
940 /*
941  * Test the extraction of ITER_XARRAY-type iterators.
942  */
943 static void __init iov_kunit_extract_pages_xarray(struct kunit *test)
944 {
945 	const struct kvec_test_range *pr;
946 	struct iov_iter iter;
947 	struct xarray *xarray;
948 	struct page **bpages, *pagelist[8], **pages = pagelist;
949 	ssize_t len;
950 	size_t bufsize, size = 0, npages;
951 	int i, from;
952 
953 	bufsize = 0x100000;
954 	npages = bufsize / PAGE_SIZE;
955 
956 	xarray = iov_kunit_create_xarray(test);
957 
958 	iov_kunit_create_buffer(test, &bpages, npages);
959 	iov_kunit_load_xarray(test, &iter, READ, xarray, bpages, npages);
960 
961 	for (pr = kvec_test_ranges; pr->from >= 0; pr++) {
962 		from = pr->from;
963 		size = pr->to - from;
964 		KUNIT_ASSERT_LE(test, pr->to, bufsize);
965 
966 		iov_iter_xarray(&iter, WRITE, xarray, from, size);
967 
968 		do {
969 			size_t offset0 = LONG_MAX;
970 
971 			for (i = 0; i < ARRAY_SIZE(pagelist); i++)
972 				pagelist[i] = (void *)(unsigned long)0xaa55aa55aa55aa55ULL;
973 
974 			len = iov_iter_extract_pages(&iter, &pages, 100 * 1024,
975 						     ARRAY_SIZE(pagelist), 0, &offset0);
976 			KUNIT_EXPECT_GE(test, len, 0);
977 			if (len < 0)
978 				break;
979 			KUNIT_EXPECT_LE(test, len, size);
980 			KUNIT_EXPECT_EQ(test, iter.count, size - len);
981 			if (len == 0)
982 				break;
983 			size -= len;
984 			KUNIT_EXPECT_GE(test, (ssize_t)offset0, 0);
985 			KUNIT_EXPECT_LT(test, offset0, PAGE_SIZE);
986 
987 			for (i = 0; i < ARRAY_SIZE(pagelist); i++) {
988 				struct page *p;
989 				ssize_t part = min_t(ssize_t, len, PAGE_SIZE - offset0);
990 				int ix;
991 
992 				KUNIT_ASSERT_GE(test, part, 0);
993 				ix = from / PAGE_SIZE;
994 				KUNIT_ASSERT_LT(test, ix, npages);
995 				p = bpages[ix];
996 				KUNIT_EXPECT_PTR_EQ(test, pagelist[i], p);
997 				KUNIT_EXPECT_EQ(test, offset0, from % PAGE_SIZE);
998 				from += part;
999 				len -= part;
1000 				KUNIT_ASSERT_GE(test, len, 0);
1001 				if (len == 0)
1002 					break;
1003 				offset0 = 0;
1004 			}
1005 
1006 			if (test->status == KUNIT_FAILURE)
1007 				goto stop;
1008 		} while (iov_iter_count(&iter) > 0);
1009 
1010 		KUNIT_EXPECT_EQ(test, size, 0);
1011 		KUNIT_EXPECT_EQ(test, iter.count, 0);
1012 		KUNIT_EXPECT_EQ(test, iter.iov_offset, pr->to - pr->from);
1013 	}
1014 
1015 stop:
1016 	KUNIT_SUCCEED(test);
1017 }
1018 
1019 static struct kunit_case __refdata iov_kunit_cases[] = {
1020 	KUNIT_CASE(iov_kunit_copy_to_kvec),
1021 	KUNIT_CASE(iov_kunit_copy_from_kvec),
1022 	KUNIT_CASE(iov_kunit_copy_to_bvec),
1023 	KUNIT_CASE(iov_kunit_copy_from_bvec),
1024 	KUNIT_CASE(iov_kunit_copy_to_folioq),
1025 	KUNIT_CASE(iov_kunit_copy_from_folioq),
1026 	KUNIT_CASE(iov_kunit_copy_to_xarray),
1027 	KUNIT_CASE(iov_kunit_copy_from_xarray),
1028 	KUNIT_CASE(iov_kunit_extract_pages_kvec),
1029 	KUNIT_CASE(iov_kunit_extract_pages_bvec),
1030 	KUNIT_CASE(iov_kunit_extract_pages_folioq),
1031 	KUNIT_CASE(iov_kunit_extract_pages_xarray),
1032 	{}
1033 };
1034 
1035 static struct kunit_suite iov_kunit_suite = {
1036 	.name = "iov_iter",
1037 	.test_cases = iov_kunit_cases,
1038 };
1039 
1040 kunit_test_suites(&iov_kunit_suite);
1041