link-timeout.c 21 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109
  1. #include "../config-host.h"
  2. /* SPDX-License-Identifier: MIT */
  3. /*
  4. * Description: run various linked timeout cases
  5. *
  6. */
  7. #include <errno.h>
  8. #include <stdio.h>
  9. #include <unistd.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <fcntl.h>
  13. #include <poll.h>
  14. #include "liburing.h"
  15. #include "helpers.h"
  16. static int test_fail_lone_link_timeouts(struct io_uring *ring)
  17. {
  18. struct __kernel_timespec ts;
  19. struct io_uring_cqe *cqe;
  20. struct io_uring_sqe *sqe;
  21. int ret;
  22. sqe = io_uring_get_sqe(ring);
  23. if (!sqe) {
  24. printf("get sqe failed\n");
  25. goto err;
  26. }
  27. io_uring_prep_link_timeout(sqe, &ts, 0);
  28. ts.tv_sec = 1;
  29. ts.tv_nsec = 0;
  30. sqe->user_data = 1;
  31. sqe->flags |= IOSQE_IO_LINK;
  32. ret = io_uring_submit(ring);
  33. if (ret != 1) {
  34. printf("sqe submit failed: %d\n", ret);
  35. goto err;
  36. }
  37. ret = io_uring_wait_cqe(ring, &cqe);
  38. if (ret < 0) {
  39. printf("wait completion %d\n", ret);
  40. goto err;
  41. }
  42. if (cqe->user_data != 1) {
  43. fprintf(stderr, "invalid user data %d\n", cqe->res);
  44. goto err;
  45. }
  46. if (cqe->res != -EINVAL) {
  47. fprintf(stderr, "got %d, wanted -EINVAL\n", cqe->res);
  48. goto err;
  49. }
  50. io_uring_cqe_seen(ring, cqe);
  51. return 0;
  52. err:
  53. return 1;
  54. }
  55. static int test_fail_two_link_timeouts(struct io_uring *ring)
  56. {
  57. struct __kernel_timespec ts;
  58. struct io_uring_cqe *cqe;
  59. struct io_uring_sqe *sqe;
  60. int ret, i, nr_wait;
  61. ts.tv_sec = 1;
  62. ts.tv_nsec = 0;
  63. /*
  64. * sqe_1: write destined to fail
  65. * use buf=NULL, to do that during the issuing stage
  66. */
  67. sqe = io_uring_get_sqe(ring);
  68. if (!sqe) {
  69. printf("get sqe failed\n");
  70. goto err;
  71. }
  72. io_uring_prep_writev(sqe, 0, NULL, 1, 0);
  73. sqe->flags |= IOSQE_IO_LINK;
  74. sqe->user_data = 1;
  75. /* sqe_2: valid linked timeout */
  76. sqe = io_uring_get_sqe(ring);
  77. if (!sqe) {
  78. printf("get sqe failed\n");
  79. goto err;
  80. }
  81. io_uring_prep_link_timeout(sqe, &ts, 0);
  82. sqe->user_data = 2;
  83. sqe->flags |= IOSQE_IO_LINK;
  84. /* sqe_3: invalid linked timeout */
  85. sqe = io_uring_get_sqe(ring);
  86. if (!sqe) {
  87. printf("get sqe failed\n");
  88. goto err;
  89. }
  90. io_uring_prep_link_timeout(sqe, &ts, 0);
  91. sqe->flags |= IOSQE_IO_LINK;
  92. sqe->user_data = 3;
  93. /* sqe_4: invalid linked timeout */
  94. sqe = io_uring_get_sqe(ring);
  95. if (!sqe) {
  96. printf("get sqe failed\n");
  97. goto err;
  98. }
  99. io_uring_prep_link_timeout(sqe, &ts, 0);
  100. sqe->flags |= IOSQE_IO_LINK;
  101. sqe->user_data = 4;
  102. ret = io_uring_submit(ring);
  103. if (ret < 3) {
  104. printf("sqe submit failed: %d\n", ret);
  105. goto err;
  106. }
  107. nr_wait = ret;
  108. for (i = 0; i < nr_wait; i++) {
  109. ret = io_uring_wait_cqe(ring, &cqe);
  110. if (ret < 0) {
  111. printf("wait completion %d\n", ret);
  112. goto err;
  113. }
  114. switch (cqe->user_data) {
  115. case 1:
  116. if (cqe->res != -EFAULT && cqe->res != -ECANCELED) {
  117. fprintf(stderr, "write got %d, wanted -EFAULT "
  118. "or -ECANCELED\n", cqe->res);
  119. goto err;
  120. }
  121. break;
  122. case 2:
  123. if (cqe->res != -ECANCELED) {
  124. fprintf(stderr, "Link timeout got %d, wanted -ECACNCELED\n", cqe->res);
  125. goto err;
  126. }
  127. break;
  128. case 3:
  129. /* fall through */
  130. case 4:
  131. if (cqe->res != -ECANCELED && cqe->res != -EINVAL) {
  132. fprintf(stderr, "Invalid link timeout got %d"
  133. ", wanted -ECACNCELED || -EINVAL\n", cqe->res);
  134. goto err;
  135. }
  136. break;
  137. }
  138. io_uring_cqe_seen(ring, cqe);
  139. }
  140. return 0;
  141. err:
  142. return 1;
  143. }
  144. /*
  145. * Test linked timeout with timeout (timeoutception)
  146. */
  147. static int test_single_link_timeout_ception(struct io_uring *ring)
  148. {
  149. struct __kernel_timespec ts1, ts2;
  150. struct io_uring_cqe *cqe;
  151. struct io_uring_sqe *sqe;
  152. int ret, i;
  153. sqe = io_uring_get_sqe(ring);
  154. if (!sqe) {
  155. printf("get sqe failed\n");
  156. goto err;
  157. }
  158. ts1.tv_sec = 1;
  159. ts1.tv_nsec = 0;
  160. io_uring_prep_timeout(sqe, &ts1, -1U, 0);
  161. sqe->flags |= IOSQE_IO_LINK;
  162. sqe->user_data = 1;
  163. sqe = io_uring_get_sqe(ring);
  164. if (!sqe) {
  165. printf("get sqe failed\n");
  166. goto err;
  167. }
  168. ts2.tv_sec = 2;
  169. ts2.tv_nsec = 0;
  170. io_uring_prep_link_timeout(sqe, &ts2, 0);
  171. sqe->user_data = 2;
  172. ret = io_uring_submit(ring);
  173. if (ret != 2) {
  174. printf("sqe submit failed: %d\n", ret);
  175. goto err;
  176. }
  177. for (i = 0; i < 2; i++) {
  178. ret = io_uring_wait_cqe(ring, &cqe);
  179. if (ret < 0) {
  180. printf("wait completion %d\n", ret);
  181. goto err;
  182. }
  183. switch (cqe->user_data) {
  184. case 1:
  185. /* newer kernels allow timeout links */
  186. if (cqe->res != -EINVAL && cqe->res != -ETIME) {
  187. fprintf(stderr, "Timeout got %d, wanted "
  188. "-EINVAL or -ETIME\n", cqe->res);
  189. goto err;
  190. }
  191. break;
  192. case 2:
  193. if (cqe->res != -ECANCELED) {
  194. fprintf(stderr, "Link timeout got %d, wanted -ECANCELED\n", cqe->res);
  195. goto err;
  196. }
  197. break;
  198. }
  199. io_uring_cqe_seen(ring, cqe);
  200. }
  201. return 0;
  202. err:
  203. return 1;
  204. }
  205. /*
  206. * Test linked timeout with NOP
  207. */
  208. static int test_single_link_timeout_nop(struct io_uring *ring)
  209. {
  210. struct __kernel_timespec ts;
  211. struct io_uring_cqe *cqe;
  212. struct io_uring_sqe *sqe;
  213. int ret, i;
  214. sqe = io_uring_get_sqe(ring);
  215. if (!sqe) {
  216. printf("get sqe failed\n");
  217. goto err;
  218. }
  219. io_uring_prep_nop(sqe);
  220. sqe->flags |= IOSQE_IO_LINK;
  221. sqe->user_data = 1;
  222. sqe = io_uring_get_sqe(ring);
  223. if (!sqe) {
  224. printf("get sqe failed\n");
  225. goto err;
  226. }
  227. ts.tv_sec = 1;
  228. ts.tv_nsec = 0;
  229. io_uring_prep_link_timeout(sqe, &ts, 0);
  230. sqe->user_data = 2;
  231. ret = io_uring_submit(ring);
  232. if (ret != 2) {
  233. printf("sqe submit failed: %d\n", ret);
  234. goto err;
  235. }
  236. for (i = 0; i < 2; i++) {
  237. ret = io_uring_wait_cqe(ring, &cqe);
  238. if (ret < 0) {
  239. printf("wait completion %d\n", ret);
  240. goto err;
  241. }
  242. switch (cqe->user_data) {
  243. case 1:
  244. if (cqe->res) {
  245. fprintf(stderr, "NOP got %d, wanted 0\n", cqe->res);
  246. goto err;
  247. }
  248. break;
  249. case 2:
  250. if (cqe->res != -ECANCELED) {
  251. fprintf(stderr, "Link timeout got %d, wanted -ECACNCELED\n", cqe->res);
  252. goto err;
  253. }
  254. break;
  255. }
  256. io_uring_cqe_seen(ring, cqe);
  257. }
  258. return 0;
  259. err:
  260. return 1;
  261. }
  262. /*
  263. * Test read that will not complete, with a linked timeout behind it that
  264. * has errors in the SQE
  265. */
  266. static int test_single_link_timeout_error(struct io_uring *ring)
  267. {
  268. struct __kernel_timespec ts;
  269. struct io_uring_cqe *cqe;
  270. struct io_uring_sqe *sqe;
  271. int fds[2], ret, i;
  272. struct iovec iov;
  273. char buffer[128];
  274. if (pipe(fds)) {
  275. perror("pipe");
  276. return 1;
  277. }
  278. sqe = io_uring_get_sqe(ring);
  279. if (!sqe) {
  280. printf("get sqe failed\n");
  281. goto err;
  282. }
  283. iov.iov_base = buffer;
  284. iov.iov_len = sizeof(buffer);
  285. io_uring_prep_readv(sqe, fds[0], &iov, 1, 0);
  286. sqe->flags |= IOSQE_IO_LINK;
  287. sqe->user_data = 1;
  288. sqe = io_uring_get_sqe(ring);
  289. if (!sqe) {
  290. printf("get sqe failed\n");
  291. goto err;
  292. }
  293. ts.tv_sec = 1;
  294. ts.tv_nsec = 0;
  295. io_uring_prep_link_timeout(sqe, &ts, 0);
  296. /* set invalid field, it'll get failed */
  297. sqe->ioprio = 89;
  298. sqe->user_data = 2;
  299. ret = io_uring_submit(ring);
  300. if (ret != 2) {
  301. printf("sqe submit failed: %d\n", ret);
  302. goto err;
  303. }
  304. for (i = 0; i < 2; i++) {
  305. ret = io_uring_wait_cqe(ring, &cqe);
  306. if (ret < 0) {
  307. printf("wait completion %d\n", ret);
  308. goto err;
  309. }
  310. switch (cqe->user_data) {
  311. case 1:
  312. if (cqe->res != -ECANCELED) {
  313. fprintf(stderr, "Read got %d, wanted -ECANCELED\n",
  314. cqe->res);
  315. goto err;
  316. }
  317. break;
  318. case 2:
  319. if (cqe->res != -EINVAL) {
  320. fprintf(stderr, "Link timeout got %d, wanted -EINVAL\n", cqe->res);
  321. goto err;
  322. }
  323. break;
  324. }
  325. io_uring_cqe_seen(ring, cqe);
  326. }
  327. return 0;
  328. err:
  329. return 1;
  330. }
  331. /*
  332. * Test read that will complete, with a linked timeout behind it
  333. */
  334. static int test_single_link_no_timeout(struct io_uring *ring)
  335. {
  336. struct __kernel_timespec ts;
  337. struct io_uring_cqe *cqe;
  338. struct io_uring_sqe *sqe;
  339. int fds[2], ret, i;
  340. struct iovec iov;
  341. char buffer[128];
  342. if (pipe(fds)) {
  343. perror("pipe");
  344. return 1;
  345. }
  346. sqe = io_uring_get_sqe(ring);
  347. if (!sqe) {
  348. printf("get sqe failed\n");
  349. goto err;
  350. }
  351. iov.iov_base = buffer;
  352. iov.iov_len = sizeof(buffer);
  353. io_uring_prep_readv(sqe, fds[0], &iov, 1, 0);
  354. sqe->flags |= IOSQE_IO_LINK;
  355. sqe->user_data = 1;
  356. sqe = io_uring_get_sqe(ring);
  357. if (!sqe) {
  358. printf("get sqe failed\n");
  359. goto err;
  360. }
  361. ts.tv_sec = 1;
  362. ts.tv_nsec = 0;
  363. io_uring_prep_link_timeout(sqe, &ts, 0);
  364. sqe->user_data = 2;
  365. sqe = io_uring_get_sqe(ring);
  366. if (!sqe) {
  367. printf("get sqe failed\n");
  368. goto err;
  369. }
  370. iov.iov_base = buffer;
  371. iov.iov_len = sizeof(buffer);
  372. io_uring_prep_writev(sqe, fds[1], &iov, 1, 0);
  373. sqe->user_data = 3;
  374. ret = io_uring_submit(ring);
  375. if (ret != 3) {
  376. printf("sqe submit failed: %d\n", ret);
  377. goto err;
  378. }
  379. for (i = 0; i < 3; i++) {
  380. ret = io_uring_wait_cqe(ring, &cqe);
  381. if (ret < 0) {
  382. printf("wait completion %d\n", ret);
  383. goto err;
  384. }
  385. switch (cqe->user_data) {
  386. case 1:
  387. case 3:
  388. if (cqe->res != sizeof(buffer)) {
  389. fprintf(stderr, "R/W got %d, wanted %d\n", cqe->res,
  390. (int) sizeof(buffer));
  391. goto err;
  392. }
  393. break;
  394. case 2:
  395. if (cqe->res != -ECANCELED) {
  396. fprintf(stderr, "Link timeout %d, wanted -ECANCELED\n",
  397. cqe->res);
  398. goto err;
  399. }
  400. break;
  401. }
  402. io_uring_cqe_seen(ring, cqe);
  403. }
  404. return 0;
  405. err:
  406. return 1;
  407. }
  408. /*
  409. * Test read that will not complete, with a linked timeout behind it
  410. */
  411. static int test_single_link_timeout(struct io_uring *ring, unsigned nsec)
  412. {
  413. struct __kernel_timespec ts;
  414. struct io_uring_cqe *cqe;
  415. struct io_uring_sqe *sqe;
  416. int fds[2], ret, i;
  417. struct iovec iov;
  418. char buffer[128];
  419. if (pipe(fds)) {
  420. perror("pipe");
  421. return 1;
  422. }
  423. sqe = io_uring_get_sqe(ring);
  424. if (!sqe) {
  425. printf("get sqe failed\n");
  426. goto err;
  427. }
  428. iov.iov_base = buffer;
  429. iov.iov_len = sizeof(buffer);
  430. io_uring_prep_readv(sqe, fds[0], &iov, 1, 0);
  431. sqe->flags |= IOSQE_IO_LINK;
  432. sqe->user_data = 1;
  433. sqe = io_uring_get_sqe(ring);
  434. if (!sqe) {
  435. printf("get sqe failed\n");
  436. goto err;
  437. }
  438. ts.tv_sec = 0;
  439. ts.tv_nsec = nsec;
  440. io_uring_prep_link_timeout(sqe, &ts, 0);
  441. sqe->user_data = 2;
  442. ret = io_uring_submit(ring);
  443. if (ret != 2) {
  444. printf("sqe submit failed: %d\n", ret);
  445. goto err;
  446. }
  447. for (i = 0; i < 2; i++) {
  448. ret = io_uring_wait_cqe(ring, &cqe);
  449. if (ret < 0) {
  450. printf("wait completion %d\n", ret);
  451. goto err;
  452. }
  453. switch (cqe->user_data) {
  454. case 1:
  455. if (cqe->res != -EINTR && cqe->res != -ECANCELED) {
  456. fprintf(stderr, "Read got %d\n", cqe->res);
  457. goto err;
  458. }
  459. break;
  460. case 2:
  461. if (cqe->res != -EALREADY && cqe->res != -ETIME &&
  462. cqe->res != 0) {
  463. fprintf(stderr, "Link timeout got %d\n", cqe->res);
  464. goto err;
  465. }
  466. break;
  467. }
  468. io_uring_cqe_seen(ring, cqe);
  469. }
  470. close(fds[0]);
  471. close(fds[1]);
  472. return 0;
  473. err:
  474. return 1;
  475. }
  476. static int test_timeout_link_chain1(struct io_uring *ring)
  477. {
  478. struct __kernel_timespec ts;
  479. struct io_uring_cqe *cqe;
  480. struct io_uring_sqe *sqe;
  481. int fds[2], ret, i;
  482. struct iovec iov;
  483. char buffer[128];
  484. if (pipe(fds)) {
  485. perror("pipe");
  486. return 1;
  487. }
  488. sqe = io_uring_get_sqe(ring);
  489. if (!sqe) {
  490. printf("get sqe failed\n");
  491. goto err;
  492. }
  493. iov.iov_base = buffer;
  494. iov.iov_len = sizeof(buffer);
  495. io_uring_prep_readv(sqe, fds[0], &iov, 1, 0);
  496. sqe->flags |= IOSQE_IO_LINK;
  497. sqe->user_data = 1;
  498. sqe = io_uring_get_sqe(ring);
  499. if (!sqe) {
  500. printf("get sqe failed\n");
  501. goto err;
  502. }
  503. ts.tv_sec = 0;
  504. ts.tv_nsec = 1000000;
  505. io_uring_prep_link_timeout(sqe, &ts, 0);
  506. sqe->flags |= IOSQE_IO_LINK;
  507. sqe->user_data = 2;
  508. sqe = io_uring_get_sqe(ring);
  509. if (!sqe) {
  510. printf("get sqe failed\n");
  511. goto err;
  512. }
  513. io_uring_prep_nop(sqe);
  514. sqe->user_data = 3;
  515. ret = io_uring_submit(ring);
  516. if (ret != 3) {
  517. printf("sqe submit failed: %d\n", ret);
  518. goto err;
  519. }
  520. for (i = 0; i < 3; i++) {
  521. ret = io_uring_wait_cqe(ring, &cqe);
  522. if (ret < 0) {
  523. printf("wait completion %d\n", ret);
  524. goto err;
  525. }
  526. switch (cqe->user_data) {
  527. case 1:
  528. if (cqe->res != -EINTR && cqe->res != -ECANCELED) {
  529. fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
  530. cqe->res);
  531. goto err;
  532. }
  533. break;
  534. case 2:
  535. /* FASTPOLL kernels can cancel successfully */
  536. if (cqe->res != -EALREADY && cqe->res != -ETIME) {
  537. fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
  538. cqe->res);
  539. goto err;
  540. }
  541. break;
  542. case 3:
  543. if (cqe->res != -ECANCELED) {
  544. fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
  545. cqe->res);
  546. goto err;
  547. }
  548. break;
  549. }
  550. io_uring_cqe_seen(ring, cqe);
  551. }
  552. close(fds[0]);
  553. close(fds[1]);
  554. return 0;
  555. err:
  556. return 1;
  557. }
  558. static int test_timeout_link_chain2(struct io_uring *ring)
  559. {
  560. struct __kernel_timespec ts;
  561. struct io_uring_cqe *cqe;
  562. struct io_uring_sqe *sqe;
  563. int fds[2], ret, i;
  564. if (pipe(fds)) {
  565. perror("pipe");
  566. return 1;
  567. }
  568. sqe = io_uring_get_sqe(ring);
  569. if (!sqe) {
  570. printf("get sqe failed\n");
  571. goto err;
  572. }
  573. io_uring_prep_poll_add(sqe, fds[0], POLLIN);
  574. sqe->flags |= IOSQE_IO_LINK;
  575. sqe->user_data = 1;
  576. sqe = io_uring_get_sqe(ring);
  577. if (!sqe) {
  578. printf("get sqe failed\n");
  579. goto err;
  580. }
  581. ts.tv_sec = 0;
  582. ts.tv_nsec = 1000000;
  583. io_uring_prep_link_timeout(sqe, &ts, 0);
  584. sqe->flags |= IOSQE_IO_LINK;
  585. sqe->user_data = 2;
  586. sqe = io_uring_get_sqe(ring);
  587. if (!sqe) {
  588. printf("get sqe failed\n");
  589. goto err;
  590. }
  591. io_uring_prep_nop(sqe);
  592. sqe->flags |= IOSQE_IO_LINK;
  593. sqe->user_data = 3;
  594. sqe = io_uring_get_sqe(ring);
  595. if (!sqe) {
  596. printf("get sqe failed\n");
  597. goto err;
  598. }
  599. io_uring_prep_nop(sqe);
  600. sqe->user_data = 4;
  601. ret = io_uring_submit(ring);
  602. if (ret != 4) {
  603. printf("sqe submit failed: %d\n", ret);
  604. goto err;
  605. }
  606. for (i = 0; i < 4; i++) {
  607. ret = io_uring_wait_cqe(ring, &cqe);
  608. if (ret < 0) {
  609. printf("wait completion %d\n", ret);
  610. goto err;
  611. }
  612. switch (cqe->user_data) {
  613. /* poll cancel really should return -ECANCEL... */
  614. case 1:
  615. if (cqe->res != -ECANCELED) {
  616. fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
  617. cqe->res);
  618. goto err;
  619. }
  620. break;
  621. case 2:
  622. if (cqe->res != -ETIME) {
  623. fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
  624. cqe->res);
  625. goto err;
  626. }
  627. break;
  628. case 3:
  629. case 4:
  630. if (cqe->res != -ECANCELED) {
  631. fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
  632. cqe->res);
  633. goto err;
  634. }
  635. break;
  636. }
  637. io_uring_cqe_seen(ring, cqe);
  638. }
  639. close(fds[0]);
  640. close(fds[1]);
  641. return 0;
  642. err:
  643. return 1;
  644. }
  645. static int test_timeout_link_chain3(struct io_uring *ring)
  646. {
  647. struct __kernel_timespec ts;
  648. struct io_uring_cqe *cqe;
  649. struct io_uring_sqe *sqe;
  650. int fds[2], ret, i;
  651. if (pipe(fds)) {
  652. perror("pipe");
  653. return 1;
  654. }
  655. sqe = io_uring_get_sqe(ring);
  656. if (!sqe) {
  657. printf("get sqe failed\n");
  658. goto err;
  659. }
  660. io_uring_prep_poll_add(sqe, fds[0], POLLIN);
  661. sqe->flags |= IOSQE_IO_LINK;
  662. sqe->user_data = 1;
  663. sqe = io_uring_get_sqe(ring);
  664. if (!sqe) {
  665. printf("get sqe failed\n");
  666. goto err;
  667. }
  668. ts.tv_sec = 0;
  669. ts.tv_nsec = 1000000;
  670. io_uring_prep_link_timeout(sqe, &ts, 0);
  671. sqe->flags |= IOSQE_IO_LINK;
  672. sqe->user_data = 2;
  673. sqe = io_uring_get_sqe(ring);
  674. if (!sqe) {
  675. printf("get sqe failed\n");
  676. goto err;
  677. }
  678. io_uring_prep_nop(sqe);
  679. sqe->flags |= IOSQE_IO_LINK;
  680. sqe->user_data = 3;
  681. /* POLL -> TIMEOUT -> NOP */
  682. sqe = io_uring_get_sqe(ring);
  683. if (!sqe) {
  684. printf("get sqe failed\n");
  685. goto err;
  686. }
  687. io_uring_prep_poll_add(sqe, fds[0], POLLIN);
  688. sqe->flags |= IOSQE_IO_LINK;
  689. sqe->user_data = 4;
  690. sqe = io_uring_get_sqe(ring);
  691. if (!sqe) {
  692. printf("get sqe failed\n");
  693. goto err;
  694. }
  695. ts.tv_sec = 0;
  696. ts.tv_nsec = 1000000;
  697. io_uring_prep_link_timeout(sqe, &ts, 0);
  698. sqe->user_data = 5;
  699. /* poll on pipe + timeout */
  700. sqe = io_uring_get_sqe(ring);
  701. if (!sqe) {
  702. printf("get sqe failed\n");
  703. goto err;
  704. }
  705. io_uring_prep_nop(sqe);
  706. sqe->user_data = 6;
  707. /* nop */
  708. ret = io_uring_submit(ring);
  709. if (ret != 6) {
  710. printf("sqe submit failed: %d\n", ret);
  711. goto err;
  712. }
  713. for (i = 0; i < 6; i++) {
  714. ret = io_uring_wait_cqe(ring, &cqe);
  715. if (ret < 0) {
  716. printf("wait completion %d\n", ret);
  717. goto err;
  718. }
  719. switch (cqe->user_data) {
  720. case 2:
  721. if (cqe->res != -ETIME) {
  722. fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
  723. cqe->res);
  724. goto err;
  725. }
  726. break;
  727. case 1:
  728. case 3:
  729. case 4:
  730. case 5:
  731. if (cqe->res != -ECANCELED) {
  732. fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
  733. cqe->res);
  734. goto err;
  735. }
  736. break;
  737. case 6:
  738. if (cqe->res) {
  739. fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
  740. cqe->res);
  741. goto err;
  742. }
  743. break;
  744. }
  745. io_uring_cqe_seen(ring, cqe);
  746. }
  747. close(fds[0]);
  748. close(fds[1]);
  749. return 0;
  750. err:
  751. return 1;
  752. }
  753. static int test_timeout_link_chain4(struct io_uring *ring)
  754. {
  755. struct __kernel_timespec ts;
  756. struct io_uring_cqe *cqe;
  757. struct io_uring_sqe *sqe;
  758. int fds[2], ret, i;
  759. if (pipe(fds)) {
  760. perror("pipe");
  761. return 1;
  762. }
  763. sqe = io_uring_get_sqe(ring);
  764. if (!sqe) {
  765. printf("get sqe failed\n");
  766. goto err;
  767. }
  768. io_uring_prep_nop(sqe);
  769. sqe->flags |= IOSQE_IO_LINK;
  770. sqe->user_data = 1;
  771. sqe = io_uring_get_sqe(ring);
  772. if (!sqe) {
  773. printf("get sqe failed\n");
  774. goto err;
  775. }
  776. io_uring_prep_poll_add(sqe, fds[0], POLLIN);
  777. sqe->flags |= IOSQE_IO_LINK;
  778. sqe->user_data = 2;
  779. sqe = io_uring_get_sqe(ring);
  780. if (!sqe) {
  781. printf("get sqe failed\n");
  782. goto err;
  783. }
  784. ts.tv_sec = 0;
  785. ts.tv_nsec = 1000000;
  786. io_uring_prep_link_timeout(sqe, &ts, 0);
  787. sqe->user_data = 3;
  788. ret = io_uring_submit(ring);
  789. if (ret != 3) {
  790. printf("sqe submit failed: %d\n", ret);
  791. goto err;
  792. }
  793. for (i = 0; i < 3; i++) {
  794. ret = io_uring_wait_cqe(ring, &cqe);
  795. if (ret < 0) {
  796. printf("wait completion %d\n", ret);
  797. goto err;
  798. }
  799. switch (cqe->user_data) {
  800. /* poll cancel really should return -ECANCEL... */
  801. case 1:
  802. if (cqe->res) {
  803. fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
  804. cqe->res);
  805. goto err;
  806. }
  807. break;
  808. case 2:
  809. if (cqe->res != -ECANCELED) {
  810. fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
  811. cqe->res);
  812. goto err;
  813. }
  814. break;
  815. case 3:
  816. if (cqe->res != -ETIME) {
  817. fprintf(stderr, "Req %" PRIu64 " got %d\n", (uint64_t) cqe->user_data,
  818. cqe->res);
  819. goto err;
  820. }
  821. break;
  822. }
  823. io_uring_cqe_seen(ring, cqe);
  824. }
  825. close(fds[0]);
  826. close(fds[1]);
  827. return 0;
  828. err:
  829. return 1;
  830. }
  831. static int test_timeout_link_chain5(struct io_uring *ring)
  832. {
  833. struct __kernel_timespec ts1, ts2;
  834. struct io_uring_cqe *cqe;
  835. struct io_uring_sqe *sqe;
  836. int ret, i;
  837. sqe = io_uring_get_sqe(ring);
  838. if (!sqe) {
  839. printf("get sqe failed\n");
  840. goto err;
  841. }
  842. io_uring_prep_nop(sqe);
  843. sqe->flags |= IOSQE_IO_LINK;
  844. sqe->user_data = 1;
  845. sqe = io_uring_get_sqe(ring);
  846. if (!sqe) {
  847. printf("get sqe failed\n");
  848. goto err;
  849. }
  850. ts1.tv_sec = 1;
  851. ts1.tv_nsec = 0;
  852. io_uring_prep_link_timeout(sqe, &ts1, 0);
  853. sqe->flags |= IOSQE_IO_LINK;
  854. sqe->user_data = 2;
  855. sqe = io_uring_get_sqe(ring);
  856. if (!sqe) {
  857. printf("get sqe failed\n");
  858. goto err;
  859. }
  860. ts2.tv_sec = 2;
  861. ts2.tv_nsec = 0;
  862. io_uring_prep_link_timeout(sqe, &ts2, 0);
  863. sqe->user_data = 3;
  864. ret = io_uring_submit(ring);
  865. if (ret != 3) {
  866. printf("sqe submit failed: %d\n", ret);
  867. goto err;
  868. }
  869. for (i = 0; i < 3; i++) {
  870. ret = io_uring_wait_cqe(ring, &cqe);
  871. if (ret < 0) {
  872. printf("wait completion %d\n", ret);
  873. goto err;
  874. }
  875. switch (cqe->user_data) {
  876. case 1:
  877. case 2:
  878. if (cqe->res && cqe->res != -ECANCELED) {
  879. fprintf(stderr, "Request got %d, wanted -EINVAL "
  880. "or -ECANCELED\n",
  881. cqe->res);
  882. goto err;
  883. }
  884. break;
  885. case 3:
  886. if (cqe->res != -ECANCELED && cqe->res != -EINVAL) {
  887. fprintf(stderr, "Link timeout got %d, wanted -ECANCELED\n", cqe->res);
  888. goto err;
  889. }
  890. break;
  891. }
  892. io_uring_cqe_seen(ring, cqe);
  893. }
  894. return 0;
  895. err:
  896. return 1;
  897. }
  898. int main(int argc, char *argv[])
  899. {
  900. struct io_uring ring;
  901. int ret;
  902. if (argc > 1)
  903. return T_EXIT_SKIP;
  904. ret = io_uring_queue_init(8, &ring, 0);
  905. if (ret) {
  906. printf("ring setup failed\n");
  907. return T_EXIT_FAIL;
  908. }
  909. ret = test_timeout_link_chain1(&ring);
  910. if (ret) {
  911. printf("test_single_link_chain1 failed\n");
  912. return ret;
  913. }
  914. ret = test_timeout_link_chain2(&ring);
  915. if (ret) {
  916. printf("test_single_link_chain2 failed\n");
  917. return ret;
  918. }
  919. ret = test_timeout_link_chain3(&ring);
  920. if (ret) {
  921. printf("test_single_link_chain3 failed\n");
  922. return ret;
  923. }
  924. ret = test_timeout_link_chain4(&ring);
  925. if (ret) {
  926. printf("test_single_link_chain4 failed\n");
  927. return ret;
  928. }
  929. ret = test_timeout_link_chain5(&ring);
  930. if (ret) {
  931. printf("test_single_link_chain5 failed\n");
  932. return ret;
  933. }
  934. ret = test_single_link_timeout(&ring, 10);
  935. if (ret) {
  936. printf("test_single_link_timeout 10 failed\n");
  937. return ret;
  938. }
  939. ret = test_single_link_timeout(&ring, 100000ULL);
  940. if (ret) {
  941. printf("test_single_link_timeout 100000 failed\n");
  942. return ret;
  943. }
  944. ret = test_single_link_timeout(&ring, 500000000ULL);
  945. if (ret) {
  946. printf("test_single_link_timeout 500000000 failed\n");
  947. return ret;
  948. }
  949. ret = test_single_link_no_timeout(&ring);
  950. if (ret) {
  951. printf("test_single_link_no_timeout failed\n");
  952. return ret;
  953. }
  954. ret = test_single_link_timeout_error(&ring);
  955. if (ret) {
  956. printf("test_single_link_timeout_error failed\n");
  957. return ret;
  958. }
  959. ret = test_single_link_timeout_nop(&ring);
  960. if (ret) {
  961. printf("test_single_link_timeout_nop failed\n");
  962. return ret;
  963. }
  964. ret = test_single_link_timeout_ception(&ring);
  965. if (ret) {
  966. printf("test_single_link_timeout_ception failed\n");
  967. return ret;
  968. }
  969. ret = test_fail_lone_link_timeouts(&ring);
  970. if (ret) {
  971. printf("test_fail_lone_link_timeouts failed\n");
  972. return ret;
  973. }
  974. ret = test_fail_two_link_timeouts(&ring);
  975. if (ret) {
  976. printf("test_fail_two_link_timeouts failed\n");
  977. return ret;
  978. }
  979. return T_EXIT_PASS;
  980. }