link-timeout.c 24 KB

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