linux 为什么io_submit(...,nr,...)提交的请求比nr少?

eulz3vhy  于 12个月前  发布在  Linux
关注(0)|答案(2)|浏览(95)

我使用io_submit(..., nr, ...),nr高达128,但我通常收到较少的请求提交。
根据手册IO_SUBMIT(2),这是合法的,但我想知道:为什么?还有,有没有一种方法可以知道哪个请求被立即提交-而不需要检查io_getevents()
从手册:
成功时,io_submit()返回提交的iocb数量(可能小于nr,如果nr为零,则返回0)。失败时的返回请参见NOTES。

70gysomp

70gysomp1#

提交的结果较少的一个可能原因是,您已达到128个请求未处理的限制。也许您调用了128个io_submit,然后在所有128个请求完成之前再次调用它?请参阅sysfs中的nr_requests条目,了解设备愿意处理的请求数量限制:

# cat /sys/block/sda/queue/nr_requests
128

字符串
这取决于您的代码来跟踪有多少请求是未完成的,并避免尝试调用io_submit,因为许多请求会使它超过这个限制。
现在,这可能不是您的调用提交的请求比您要求的少的原因。如果您查看the kernel source, in fs/aio.c,您可以看到__io_submit_one中可能触发短响应的所有失败条件。其中一个请求可能存在参数问题,或者可能无法为kiocb分配slab内存等。但最有可能的是,由于nr_requests队列深度限制,aio_get_req失败了。
如果你在同一个文件中查看SYSCALL_DEFINE3(io_submit...,你可以看到它很容易找出哪些请求没有提交。它只是你交给io_submit的数组中的位置。例如,如果io_submit返回5,然后你知道你在数组索引0-4中提交的请求已经提交。5和nr - 1之间的任何请求都没有提交。

x7yiwoj4

x7yiwoj42#

导致io_submit返回1且参数nr > 1的一个可能原因是参数iocbpp不是iocb指针的数组。我犯的一个错误是传递iocb数组的地址:

struct iocb* io_request = (struct iocb *)(malloc((sizeof(struct iocb)) * len));
//... io_prep_pwrite stuff
ret = io_submit(ctx, len, &req.io_request); // return 1

字符串
如果我传递+1地址将得到EFAULT(错误地址):

struct iocb* io_request = (struct iocb *)(malloc((sizeof(struct iocb)) * len));
//... io_prep_pwrite stuff
ret = io_submit(ctx, len, (&req.io_request)+1); // return -14


要修复:

struct iocb* request[len];
struct iocb* io_request = (struct iocb *)(malloc((sizeof(struct iocb)) * len));
//... io_prep_pwrite stuff
for (int i = 0; i < len_; i++) {
    request[i] = &(io_request[i]);
}
ret = io_submit(ctx, len, request); // return len


感谢Mike。正如Mike提到的,其中一个请求的参数问题会导致短响应,但是io_submit没有返回错误值来调试。我们可以在返回位置传递iocbpp,以获得错误值,在他的示例中为iocbpp + 5,在我的示例中为iocbpp + 1

相关问题