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