~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/lib/kunit_iov_iter.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 <kunit/test.h>
 16 
 17 MODULE_DESCRIPTION("iov_iter testing");
 18 MODULE_AUTHOR("David Howells <dhowells@redhat.com>");
 19 MODULE_LICENSE("GPL");
 20 
 21 struct kvec_test_range {
 22         int     from, to;
 23 };
 24 
 25 static const struct kvec_test_range kvec_test_ranges[] = {
 26         { 0x00002, 0x00002 },
 27         { 0x00027, 0x03000 },
 28         { 0x05193, 0x18794 },
 29         { 0x20000, 0x20000 },
 30         { 0x20000, 0x24000 },
 31         { 0x24000, 0x27001 },
 32         { 0x29000, 0xffffb },
 33         { 0xffffd, 0xffffe },
 34         { -1 }
 35 };
 36 
 37 static inline u8 pattern(unsigned long x)
 38 {
 39         return x & 0xff;
 40 }
 41 
 42 static void iov_kunit_unmap(void *data)
 43 {
 44         vunmap(data);
 45 }
 46 
 47 static void *__init iov_kunit_create_buffer(struct kunit *test,
 48                                             struct page ***ppages,
 49                                             size_t npages)
 50 {
 51         struct page **pages;
 52         unsigned long got;
 53         void *buffer;
 54 
 55         pages = kunit_kcalloc(test, npages, sizeof(struct page *), GFP_KERNEL);
 56         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pages);
 57         *ppages = pages;
 58 
 59         got = alloc_pages_bulk_array(GFP_KERNEL, npages, pages);
 60         if (got != npages) {
 61                 release_pages(pages, got);
 62                 KUNIT_ASSERT_EQ(test, got, npages);
 63         }
 64 
 65         buffer = vmap(pages, npages, VM_MAP | VM_MAP_PUT_PAGES, PAGE_KERNEL);
 66         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buffer);
 67 
 68         kunit_add_action_or_reset(test, iov_kunit_unmap, buffer);
 69         return buffer;
 70 }
 71 
 72 static void __init iov_kunit_load_kvec(struct kunit *test,
 73                                        struct iov_iter *iter, int dir,
 74                                        struct kvec *kvec, unsigned int kvmax,
 75                                        void *buffer, size_t bufsize,
 76                                        const struct kvec_test_range *pr)
 77 {
 78         size_t size = 0;
 79         int i;
 80 
 81         for (i = 0; i < kvmax; i++, pr++) {
 82                 if (pr->from < 0)
 83                         break;
 84                 KUNIT_ASSERT_GE(test, pr->to, pr->from);
 85                 KUNIT_ASSERT_LE(test, pr->to, bufsize);
 86                 kvec[i].iov_base = buffer + pr->from;
 87                 kvec[i].iov_len = pr->to - pr->from;
 88                 size += pr->to - pr->from;
 89         }
 90         KUNIT_ASSERT_LE(test, size, bufsize);
 91 
 92         iov_iter_kvec(iter, dir, kvec, i, size);
 93 }
 94 
 95 /*
 96  * Test copying to a ITER_KVEC-type iterator.
 97  */
 98 static void __init iov_kunit_copy_to_kvec(struct kunit *test)
 99 {
100         const struct kvec_test_range *pr;
101         struct iov_iter iter;
102         struct page **spages, **bpages;
103         struct kvec kvec[8];
104         u8 *scratch, *buffer;
105         size_t bufsize, npages, size, copied;
106         int i, patt;
107 
108         bufsize = 0x100000;
109         npages = bufsize / PAGE_SIZE;
110 
111         scratch = iov_kunit_create_buffer(test, &spages, npages);
112         for (i = 0; i < bufsize; i++)
113                 scratch[i] = pattern(i);
114 
115         buffer = iov_kunit_create_buffer(test, &bpages, npages);
116         memset(buffer, 0, bufsize);
117 
118         iov_kunit_load_kvec(test, &iter, READ, kvec, ARRAY_SIZE(kvec),
119                             buffer, bufsize, kvec_test_ranges);
120         size = iter.count;
121 
122         copied = copy_to_iter(scratch, size, &iter);
123 
124         KUNIT_EXPECT_EQ(test, copied, size);
125         KUNIT_EXPECT_EQ(test, iter.count, 0);
126         KUNIT_EXPECT_EQ(test, iter.nr_segs, 0);
127 
128         /* Build the expected image in the scratch buffer. */
129         patt = 0;
130         memset(scratch, 0, bufsize);
131         for (pr = kvec_test_ranges; pr->from >= 0; pr++)
132                 for (i = pr->from; i < pr->to; i++)
133                         scratch[i] = pattern(patt++);
134 
135         /* Compare the images */
136         for (i = 0; i < bufsize; i++) {
137                 KUNIT_EXPECT_EQ_MSG(test, buffer[i], scratch[i], "at i=%x", i);
138                 if (buffer[i] != scratch[i])
139                         return;
140         }
141 
142         KUNIT_SUCCEED(test);
143 }
144 
145 /*
146  * Test copying from a ITER_KVEC-type iterator.
147  */
148 static void __init iov_kunit_copy_from_kvec(struct kunit *test)
149 {
150         const struct kvec_test_range *pr;
151         struct iov_iter iter;
152         struct page **spages, **bpages;
153         struct kvec kvec[8];
154         u8 *scratch, *buffer;
155         size_t bufsize, npages, size, copied;
156         int i, j;
157 
158         bufsize = 0x100000;
159         npages = bufsize / PAGE_SIZE;
160 
161         buffer = iov_kunit_create_buffer(test, &bpages, npages);
162         for (i = 0; i < bufsize; i++)
163                 buffer[i] = pattern(i);
164 
165         scratch = iov_kunit_create_buffer(test, &spages, npages);
166         memset(scratch, 0, bufsize);
167 
168         iov_kunit_load_kvec(test, &iter, WRITE, kvec, ARRAY_SIZE(kvec),
169                             buffer, bufsize, kvec_test_ranges);
170         size = min(iter.count, bufsize);
171 
172         copied = copy_from_iter(scratch, size, &iter);
173 
174         KUNIT_EXPECT_EQ(test, copied, size);
175         KUNIT_EXPECT_EQ(test, iter.count, 0);
176         KUNIT_EXPECT_EQ(test, iter.nr_segs, 0);
177 
178         /* Build the expected image in the main buffer. */
179         i = 0;
180         memset(buffer, 0, bufsize);
181         for (pr = kvec_test_ranges; pr->from >= 0; pr++) {
182                 for (j = pr->from; j < pr->to; j++) {
183                         buffer[i++] = pattern(j);
184                         if (i >= bufsize)
185                                 goto stop;
186                 }
187         }
188 stop:
189 
190         /* Compare the images */
191         for (i = 0; i < bufsize; i++) {
192                 KUNIT_EXPECT_EQ_MSG(test, scratch[i], buffer[i], "at i=%x", i);
193                 if (scratch[i] != buffer[i])
194                         return;
195         }
196 
197         KUNIT_SUCCEED(test);
198 }
199 
200 struct bvec_test_range {
201         int     page, from, to;
202 };
203 
204 static const struct bvec_test_range bvec_test_ranges[] = {
205         { 0, 0x0002, 0x0002 },
206         { 1, 0x0027, 0x0893 },
207         { 2, 0x0193, 0x0794 },
208         { 3, 0x0000, 0x1000 },
209         { 4, 0x0000, 0x1000 },
210         { 5, 0x0000, 0x1000 },
211         { 6, 0x0000, 0x0ffb },
212         { 6, 0x0ffd, 0x0ffe },
213         { -1, -1, -1 }
214 };
215 
216 static void __init iov_kunit_load_bvec(struct kunit *test,
217                                        struct iov_iter *iter, int dir,
218                                        struct bio_vec *bvec, unsigned int bvmax,
219                                        struct page **pages, size_t npages,
220                                        size_t bufsize,
221                                        const struct bvec_test_range *pr)
222 {
223         struct page *can_merge = NULL, *page;
224         size_t size = 0;
225         int i;
226 
227         for (i = 0; i < bvmax; i++, pr++) {
228                 if (pr->from < 0)
229                         break;
230                 KUNIT_ASSERT_LT(test, pr->page, npages);
231                 KUNIT_ASSERT_LT(test, pr->page * PAGE_SIZE, bufsize);
232                 KUNIT_ASSERT_GE(test, pr->from, 0);
233                 KUNIT_ASSERT_GE(test, pr->to, pr->from);
234                 KUNIT_ASSERT_LE(test, pr->to, PAGE_SIZE);
235 
236                 page = pages[pr->page];
237                 if (pr->from == 0 && pr->from != pr->to && page == can_merge) {
238                         i--;
239                         bvec[i].bv_len += pr->to;
240                 } else {
241                         bvec_set_page(&bvec[i], page, pr->to - pr->from, pr->from);
242                 }
243 
244                 size += pr->to - pr->from;
245                 if ((pr->to & ~PAGE_MASK) == 0)
246                         can_merge = page + pr->to / PAGE_SIZE;
247                 else
248                         can_merge = NULL;
249         }
250 
251         iov_iter_bvec(iter, dir, bvec, i, size);
252 }
253 
254 /*
255  * Test copying to a ITER_BVEC-type iterator.
256  */
257 static void __init iov_kunit_copy_to_bvec(struct kunit *test)
258 {
259         const struct bvec_test_range *pr;
260         struct iov_iter iter;
261         struct bio_vec bvec[8];
262         struct page **spages, **bpages;
263         u8 *scratch, *buffer;
264         size_t bufsize, npages, size, copied;
265         int i, b, patt;
266 
267         bufsize = 0x100000;
268         npages = bufsize / PAGE_SIZE;
269 
270         scratch = iov_kunit_create_buffer(test, &spages, npages);
271         for (i = 0; i < bufsize; i++)
272                 scratch[i] = pattern(i);
273 
274         buffer = iov_kunit_create_buffer(test, &bpages, npages);
275         memset(buffer, 0, bufsize);
276 
277         iov_kunit_load_bvec(test, &iter, READ, bvec, ARRAY_SIZE(bvec),
278                             bpages, npages, bufsize, bvec_test_ranges);
279         size = iter.count;
280 
281         copied = copy_to_iter(scratch, size, &iter);
282 
283         KUNIT_EXPECT_EQ(test, copied, size);
284         KUNIT_EXPECT_EQ(test, iter.count, 0);
285         KUNIT_EXPECT_EQ(test, iter.nr_segs, 0);
286 
287         /* Build the expected image in the scratch buffer. */
288         b = 0;
289         patt = 0;
290         memset(scratch, 0, bufsize);
291         for (pr = bvec_test_ranges; pr->from >= 0; pr++, b++) {
292                 u8 *p = scratch + pr->page * PAGE_SIZE;
293 
294                 for (i = pr->from; i < pr->to; i++)
295                         p[i] = pattern(patt++);
296         }
297 
298         /* Compare the images */
299         for (i = 0; i < bufsize; i++) {
300                 KUNIT_EXPECT_EQ_MSG(test, buffer[i], scratch[i], "at i=%x", i);
301                 if (buffer[i] != scratch[i])
302                         return;
303         }
304 
305         KUNIT_SUCCEED(test);
306 }
307 
308 /*
309  * Test copying from a ITER_BVEC-type iterator.
310  */
311 static void __init iov_kunit_copy_from_bvec(struct kunit *test)
312 {
313         const struct bvec_test_range *pr;
314         struct iov_iter iter;
315         struct bio_vec bvec[8];
316         struct page **spages, **bpages;
317         u8 *scratch, *buffer;
318         size_t bufsize, npages, size, copied;
319         int i, j;
320 
321         bufsize = 0x100000;
322         npages = bufsize / PAGE_SIZE;
323 
324         buffer = iov_kunit_create_buffer(test, &bpages, npages);
325         for (i = 0; i < bufsize; i++)
326                 buffer[i] = pattern(i);
327 
328         scratch = iov_kunit_create_buffer(test, &spages, npages);
329         memset(scratch, 0, bufsize);
330 
331         iov_kunit_load_bvec(test, &iter, WRITE, bvec, ARRAY_SIZE(bvec),
332                             bpages, npages, bufsize, bvec_test_ranges);
333         size = iter.count;
334 
335         copied = copy_from_iter(scratch, size, &iter);
336 
337         KUNIT_EXPECT_EQ(test, copied, size);
338         KUNIT_EXPECT_EQ(test, iter.count, 0);
339         KUNIT_EXPECT_EQ(test, iter.nr_segs, 0);
340 
341         /* Build the expected image in the main buffer. */
342         i = 0;
343         memset(buffer, 0, bufsize);
344         for (pr = bvec_test_ranges; pr->from >= 0; pr++) {
345                 size_t patt = pr->page * PAGE_SIZE;
346 
347                 for (j = pr->from; j < pr->to; j++) {
348                         buffer[i++] = pattern(patt + j);
349                         if (i >= bufsize)
350                                 goto stop;
351                 }
352         }
353 stop:
354 
355         /* Compare the images */
356         for (i = 0; i < bufsize; i++) {
357                 KUNIT_EXPECT_EQ_MSG(test, scratch[i], buffer[i], "at i=%x", i);
358                 if (scratch[i] != buffer[i])
359                         return;
360         }
361 
362         KUNIT_SUCCEED(test);
363 }
364 
365 static void iov_kunit_destroy_xarray(void *data)
366 {
367         struct xarray *xarray = data;
368 
369         xa_destroy(xarray);
370         kfree(xarray);
371 }
372 
373 static void __init iov_kunit_load_xarray(struct kunit *test,
374                                          struct iov_iter *iter, int dir,
375                                          struct xarray *xarray,
376                                          struct page **pages, size_t npages)
377 {
378         size_t size = 0;
379         int i;
380 
381         for (i = 0; i < npages; i++) {
382                 void *x = xa_store(xarray, i, pages[i], GFP_KERNEL);
383 
384                 KUNIT_ASSERT_FALSE(test, xa_is_err(x));
385                 size += PAGE_SIZE;
386         }
387         iov_iter_xarray(iter, dir, xarray, 0, size);
388 }
389 
390 static struct xarray *iov_kunit_create_xarray(struct kunit *test)
391 {
392         struct xarray *xarray;
393 
394         xarray = kzalloc(sizeof(struct xarray), GFP_KERNEL);
395         xa_init(xarray);
396         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xarray);
397         kunit_add_action_or_reset(test, iov_kunit_destroy_xarray, xarray);
398         return xarray;
399 }
400 
401 /*
402  * Test copying to a ITER_XARRAY-type iterator.
403  */
404 static void __init iov_kunit_copy_to_xarray(struct kunit *test)
405 {
406         const struct kvec_test_range *pr;
407         struct iov_iter iter;
408         struct xarray *xarray;
409         struct page **spages, **bpages;
410         u8 *scratch, *buffer;
411         size_t bufsize, npages, size, copied;
412         int i, patt;
413 
414         bufsize = 0x100000;
415         npages = bufsize / PAGE_SIZE;
416 
417         xarray = iov_kunit_create_xarray(test);
418 
419         scratch = iov_kunit_create_buffer(test, &spages, npages);
420         for (i = 0; i < bufsize; i++)
421                 scratch[i] = pattern(i);
422 
423         buffer = iov_kunit_create_buffer(test, &bpages, npages);
424         memset(buffer, 0, bufsize);
425 
426         iov_kunit_load_xarray(test, &iter, READ, xarray, bpages, npages);
427 
428         i = 0;
429         for (pr = kvec_test_ranges; pr->from >= 0; pr++) {
430                 size = pr->to - pr->from;
431                 KUNIT_ASSERT_LE(test, pr->to, bufsize);
432 
433                 iov_iter_xarray(&iter, READ, xarray, pr->from, size);
434                 copied = copy_to_iter(scratch + i, size, &iter);
435 
436                 KUNIT_EXPECT_EQ(test, copied, size);
437                 KUNIT_EXPECT_EQ(test, iter.count, 0);
438                 KUNIT_EXPECT_EQ(test, iter.iov_offset, size);
439                 i += size;
440         }
441 
442         /* Build the expected image in the scratch buffer. */
443         patt = 0;
444         memset(scratch, 0, bufsize);
445         for (pr = kvec_test_ranges; pr->from >= 0; pr++)
446                 for (i = pr->from; i < pr->to; i++)
447                         scratch[i] = pattern(patt++);
448 
449         /* Compare the images */
450         for (i = 0; i < bufsize; i++) {
451                 KUNIT_EXPECT_EQ_MSG(test, buffer[i], scratch[i], "at i=%x", i);
452                 if (buffer[i] != scratch[i])
453                         return;
454         }
455 
456         KUNIT_SUCCEED(test);
457 }
458 
459 /*
460  * Test copying from a ITER_XARRAY-type iterator.
461  */
462 static void __init iov_kunit_copy_from_xarray(struct kunit *test)
463 {
464         const struct kvec_test_range *pr;
465         struct iov_iter iter;
466         struct xarray *xarray;
467         struct page **spages, **bpages;
468         u8 *scratch, *buffer;
469         size_t bufsize, npages, size, copied;
470         int i, j;
471 
472         bufsize = 0x100000;
473         npages = bufsize / PAGE_SIZE;
474 
475         xarray = iov_kunit_create_xarray(test);
476 
477         buffer = iov_kunit_create_buffer(test, &bpages, npages);
478         for (i = 0; i < bufsize; i++)
479                 buffer[i] = pattern(i);
480 
481         scratch = iov_kunit_create_buffer(test, &spages, npages);
482         memset(scratch, 0, bufsize);
483 
484         iov_kunit_load_xarray(test, &iter, READ, xarray, bpages, npages);
485 
486         i = 0;
487         for (pr = kvec_test_ranges; pr->from >= 0; pr++) {
488                 size = pr->to - pr->from;
489                 KUNIT_ASSERT_LE(test, pr->to, bufsize);
490 
491                 iov_iter_xarray(&iter, WRITE, xarray, pr->from, size);
492                 copied = copy_from_iter(scratch + i, size, &iter);
493 
494                 KUNIT_EXPECT_EQ(test, copied, size);
495                 KUNIT_EXPECT_EQ(test, iter.count, 0);
496                 KUNIT_EXPECT_EQ(test, iter.iov_offset, size);
497                 i += size;
498         }
499 
500         /* Build the expected image in the main buffer. */
501         i = 0;
502         memset(buffer, 0, bufsize);
503         for (pr = kvec_test_ranges; pr->from >= 0; pr++) {
504                 for (j = pr->from; j < pr->to; j++) {
505                         buffer[i++] = pattern(j);
506                         if (i >= bufsize)
507                                 goto stop;
508                 }
509         }
510 stop:
511 
512         /* Compare the images */
513         for (i = 0; i < bufsize; i++) {
514                 KUNIT_EXPECT_EQ_MSG(test, scratch[i], buffer[i], "at i=%x", i);
515                 if (scratch[i] != buffer[i])
516                         return;
517         }
518 
519         KUNIT_SUCCEED(test);
520 }
521 
522 /*
523  * Test the extraction of ITER_KVEC-type iterators.
524  */
525 static void __init iov_kunit_extract_pages_kvec(struct kunit *test)
526 {
527         const struct kvec_test_range *pr;
528         struct iov_iter iter;
529         struct page **bpages, *pagelist[8], **pages = pagelist;
530         struct kvec kvec[8];
531         u8 *buffer;
532         ssize_t len;
533         size_t bufsize, size = 0, npages;
534         int i, from;
535 
536         bufsize = 0x100000;
537         npages = bufsize / PAGE_SIZE;
538 
539         buffer = iov_kunit_create_buffer(test, &bpages, npages);
540 
541         iov_kunit_load_kvec(test, &iter, READ, kvec, ARRAY_SIZE(kvec),
542                             buffer, bufsize, kvec_test_ranges);
543         size = iter.count;
544 
545         pr = kvec_test_ranges;
546         from = pr->from;
547         do {
548                 size_t offset0 = LONG_MAX;
549 
550                 for (i = 0; i < ARRAY_SIZE(pagelist); i++)
551                         pagelist[i] = (void *)(unsigned long)0xaa55aa55aa55aa55ULL;
552 
553                 len = iov_iter_extract_pages(&iter, &pages, 100 * 1024,
554                                              ARRAY_SIZE(pagelist), 0, &offset0);
555                 KUNIT_EXPECT_GE(test, len, 0);
556                 if (len < 0)
557                         break;
558                 KUNIT_EXPECT_GE(test, (ssize_t)offset0, 0);
559                 KUNIT_EXPECT_LT(test, offset0, PAGE_SIZE);
560                 KUNIT_EXPECT_LE(test, len, size);
561                 KUNIT_EXPECT_EQ(test, iter.count, size - len);
562                 size -= len;
563 
564                 if (len == 0)
565                         break;
566 
567                 for (i = 0; i < ARRAY_SIZE(pagelist); i++) {
568                         struct page *p;
569                         ssize_t part = min_t(ssize_t, len, PAGE_SIZE - offset0);
570                         int ix;
571 
572                         KUNIT_ASSERT_GE(test, part, 0);
573                         while (from == pr->to) {
574                                 pr++;
575                                 from = pr->from;
576                                 if (from < 0)
577                                         goto stop;
578                         }
579                         ix = from / PAGE_SIZE;
580                         KUNIT_ASSERT_LT(test, ix, npages);
581                         p = bpages[ix];
582                         KUNIT_EXPECT_PTR_EQ(test, pagelist[i], p);
583                         KUNIT_EXPECT_EQ(test, offset0, from % PAGE_SIZE);
584                         from += part;
585                         len -= part;
586                         KUNIT_ASSERT_GE(test, len, 0);
587                         if (len == 0)
588                                 break;
589                         offset0 = 0;
590                 }
591 
592                 if (test->status == KUNIT_FAILURE)
593                         break;
594         } while (iov_iter_count(&iter) > 0);
595 
596 stop:
597         KUNIT_EXPECT_EQ(test, size, 0);
598         KUNIT_EXPECT_EQ(test, iter.count, 0);
599         KUNIT_SUCCEED(test);
600 }
601 
602 /*
603  * Test the extraction of ITER_BVEC-type iterators.
604  */
605 static void __init iov_kunit_extract_pages_bvec(struct kunit *test)
606 {
607         const struct bvec_test_range *pr;
608         struct iov_iter iter;
609         struct page **bpages, *pagelist[8], **pages = pagelist;
610         struct bio_vec bvec[8];
611         ssize_t len;
612         size_t bufsize, size = 0, npages;
613         int i, from;
614 
615         bufsize = 0x100000;
616         npages = bufsize / PAGE_SIZE;
617 
618         iov_kunit_create_buffer(test, &bpages, npages);
619         iov_kunit_load_bvec(test, &iter, READ, bvec, ARRAY_SIZE(bvec),
620                             bpages, npages, bufsize, bvec_test_ranges);
621         size = iter.count;
622 
623         pr = bvec_test_ranges;
624         from = pr->from;
625         do {
626                 size_t offset0 = LONG_MAX;
627 
628                 for (i = 0; i < ARRAY_SIZE(pagelist); i++)
629                         pagelist[i] = (void *)(unsigned long)0xaa55aa55aa55aa55ULL;
630 
631                 len = iov_iter_extract_pages(&iter, &pages, 100 * 1024,
632                                              ARRAY_SIZE(pagelist), 0, &offset0);
633                 KUNIT_EXPECT_GE(test, len, 0);
634                 if (len < 0)
635                         break;
636                 KUNIT_EXPECT_GE(test, (ssize_t)offset0, 0);
637                 KUNIT_EXPECT_LT(test, offset0, PAGE_SIZE);
638                 KUNIT_EXPECT_LE(test, len, size);
639                 KUNIT_EXPECT_EQ(test, iter.count, size - len);
640                 size -= len;
641 
642                 if (len == 0)
643                         break;
644 
645                 for (i = 0; i < ARRAY_SIZE(pagelist); i++) {
646                         struct page *p;
647                         ssize_t part = min_t(ssize_t, len, PAGE_SIZE - offset0);
648                         int ix;
649 
650                         KUNIT_ASSERT_GE(test, part, 0);
651                         while (from == pr->to) {
652                                 pr++;
653                                 from = pr->from;
654                                 if (from < 0)
655                                         goto stop;
656                         }
657                         ix = pr->page + from / PAGE_SIZE;
658                         KUNIT_ASSERT_LT(test, ix, npages);
659                         p = bpages[ix];
660                         KUNIT_EXPECT_PTR_EQ(test, pagelist[i], p);
661                         KUNIT_EXPECT_EQ(test, offset0, from % PAGE_SIZE);
662                         from += part;
663                         len -= part;
664                         KUNIT_ASSERT_GE(test, len, 0);
665                         if (len == 0)
666                                 break;
667                         offset0 = 0;
668                 }
669 
670                 if (test->status == KUNIT_FAILURE)
671                         break;
672         } while (iov_iter_count(&iter) > 0);
673 
674 stop:
675         KUNIT_EXPECT_EQ(test, size, 0);
676         KUNIT_EXPECT_EQ(test, iter.count, 0);
677         KUNIT_SUCCEED(test);
678 }
679 
680 /*
681  * Test the extraction of ITER_XARRAY-type iterators.
682  */
683 static void __init iov_kunit_extract_pages_xarray(struct kunit *test)
684 {
685         const struct kvec_test_range *pr;
686         struct iov_iter iter;
687         struct xarray *xarray;
688         struct page **bpages, *pagelist[8], **pages = pagelist;
689         ssize_t len;
690         size_t bufsize, size = 0, npages;
691         int i, from;
692 
693         bufsize = 0x100000;
694         npages = bufsize / PAGE_SIZE;
695 
696         xarray = iov_kunit_create_xarray(test);
697 
698         iov_kunit_create_buffer(test, &bpages, npages);
699         iov_kunit_load_xarray(test, &iter, READ, xarray, bpages, npages);
700 
701         for (pr = kvec_test_ranges; pr->from >= 0; pr++) {
702                 from = pr->from;
703                 size = pr->to - from;
704                 KUNIT_ASSERT_LE(test, pr->to, bufsize);
705 
706                 iov_iter_xarray(&iter, WRITE, xarray, from, size);
707 
708                 do {
709                         size_t offset0 = LONG_MAX;
710 
711                         for (i = 0; i < ARRAY_SIZE(pagelist); i++)
712                                 pagelist[i] = (void *)(unsigned long)0xaa55aa55aa55aa55ULL;
713 
714                         len = iov_iter_extract_pages(&iter, &pages, 100 * 1024,
715                                                      ARRAY_SIZE(pagelist), 0, &offset0);
716                         KUNIT_EXPECT_GE(test, len, 0);
717                         if (len < 0)
718                                 break;
719                         KUNIT_EXPECT_LE(test, len, size);
720                         KUNIT_EXPECT_EQ(test, iter.count, size - len);
721                         if (len == 0)
722                                 break;
723                         size -= len;
724                         KUNIT_EXPECT_GE(test, (ssize_t)offset0, 0);
725                         KUNIT_EXPECT_LT(test, offset0, PAGE_SIZE);
726 
727                         for (i = 0; i < ARRAY_SIZE(pagelist); i++) {
728                                 struct page *p;
729                                 ssize_t part = min_t(ssize_t, len, PAGE_SIZE - offset0);
730                                 int ix;
731 
732                                 KUNIT_ASSERT_GE(test, part, 0);
733                                 ix = from / PAGE_SIZE;
734                                 KUNIT_ASSERT_LT(test, ix, npages);
735                                 p = bpages[ix];
736                                 KUNIT_EXPECT_PTR_EQ(test, pagelist[i], p);
737                                 KUNIT_EXPECT_EQ(test, offset0, from % PAGE_SIZE);
738                                 from += part;
739                                 len -= part;
740                                 KUNIT_ASSERT_GE(test, len, 0);
741                                 if (len == 0)
742                                         break;
743                                 offset0 = 0;
744                         }
745 
746                         if (test->status == KUNIT_FAILURE)
747                                 goto stop;
748                 } while (iov_iter_count(&iter) > 0);
749 
750                 KUNIT_EXPECT_EQ(test, size, 0);
751                 KUNIT_EXPECT_EQ(test, iter.count, 0);
752                 KUNIT_EXPECT_EQ(test, iter.iov_offset, pr->to - pr->from);
753         }
754 
755 stop:
756         KUNIT_SUCCEED(test);
757 }
758 
759 static struct kunit_case __refdata iov_kunit_cases[] = {
760         KUNIT_CASE(iov_kunit_copy_to_kvec),
761         KUNIT_CASE(iov_kunit_copy_from_kvec),
762         KUNIT_CASE(iov_kunit_copy_to_bvec),
763         KUNIT_CASE(iov_kunit_copy_from_bvec),
764         KUNIT_CASE(iov_kunit_copy_to_xarray),
765         KUNIT_CASE(iov_kunit_copy_from_xarray),
766         KUNIT_CASE(iov_kunit_extract_pages_kvec),
767         KUNIT_CASE(iov_kunit_extract_pages_bvec),
768         KUNIT_CASE(iov_kunit_extract_pages_xarray),
769         {}
770 };
771 
772 static struct kunit_suite iov_kunit_suite = {
773         .name = "iov_iter",
774         .test_cases = iov_kunit_cases,
775 };
776 
777 kunit_test_suites(&iov_kunit_suite);
778 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php