kunit_iov_iter.c 25 KB

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