On 5/20/20 7:24 AM, Xiaoguang Wang wrote: > In io_sq_thread(), currently if we get an -EBUSY error and go to sleep, > we will won't clear it again, which will result in io_sq_thread() will > never have a chance to submit sqes again. Below test program test.c > can reveal this bug: > > int main(int argc, char *argv[]) > { > struct io_uring ring; > int i, fd, ret; > struct io_uring_sqe *sqe; > struct io_uring_cqe *cqe; > struct iovec *iovecs; > void *buf; > struct io_uring_params p; > > if (argc < 2) { > printf("%s: file\n", argv[0]); > return 1; > } > > memset(&p, 0, sizeof(p)); > p.flags = IORING_SETUP_SQPOLL; > ret = io_uring_queue_init_params(4, &ring, &p); > if (ret < 0) { > fprintf(stderr, "queue_init: %s\n", strerror(-ret)); > return 1; > } > > fd = open(argv[1], O_RDONLY | O_DIRECT); > if (fd < 0) { > perror("open"); > return 1; > } > > iovecs = calloc(10, sizeof(struct iovec)); > for (i = 0; i < 10; i++) { > if (posix_memalign(&buf, 4096, 4096)) > return 1; > iovecs[i].iov_base = buf; > iovecs[i].iov_len = 4096; > } > > ret = io_uring_register_files(&ring, &fd, 1); > if (ret < 0) { > fprintf(stderr, "%s: register %d\n", __FUNCTION__, ret); > return ret; > } > > for (i = 0; i < 10; i++) { > sqe = io_uring_get_sqe(&ring); > if (!sqe) > break; > > io_uring_prep_readv(sqe, 0, &iovecs[i], 1, 0); > sqe->flags |= IOSQE_FIXED_FILE; > > ret = io_uring_submit(&ring); > sleep(1); > printf("submit %d\n", i); > } > > for (i = 0; i < 10; i++) { > io_uring_wait_cqe(&ring, &cqe); > printf("receive: %d\n", i); > if (cqe->res != 4096) { > fprintf(stderr, "ret=%d, wanted 4096\n", cqe->res); > ret = 1; > } > io_uring_cqe_seen(&ring, cqe); > } > > close(fd); > io_uring_queue_exit(&ring); > return 0; > } > sudo ./test testfile > above command will hang on the tenth request, to fix this bug, when io > sq_thread is waken up, we reset the variable 'ret' to be zero. Applied, thanks. -- Jens Axboe