现象

在本人的系统软件中调用io_submit提交IO请求,长时间运行后会返回不为1,而且还伴随着 Bad File descripotr 错误。检查了提交前后文件描述符的值,都是对的;检查了文件是否存在,文件打开前后都是存在的。那到底什么原因呢?

分析

首先的找到问题的直接原因,这就需要理解io submit 的错误码。

错误码的含义

通过 man io_submit 很容易看到:

  io_submit returns the number of iocbs submitted and 0 if nr is zero.

ERRORS EINVAL The aio_context specified by ctx_id is invalid. nr is less than 0. The iocb at *iocbpp[0] is not properly initialized, or the operation specified is invalid for the file descriptor in the iocb.

   EFAULT One of the data structures points to invalid data.

   EBADF  The file descriptor specified in the first iocb is invalid.

   EAGAIN Insufficient resources are available to queue any iocbs.</code></pre> 

几种可能导致的原因

针对io submit 返回的EBADF, 常见的错误包括:

  • 传入的IOCB 中的文件描述符没有对应一个文件;
  • 传入的IOCB中的文件描述符对应的文件后来被删去了;
  • 传入的IOCB 中的文件描述符没有读写权限;
  • 传入的IOCB中的文件描述符对应的文件后来被关闭了。

为此,笔者进行了下面的工作来检查是否是上面的错误:

  • 检查提交前后IOCB中的文件描述符字段是否变化:没有变化,排除这个问题;
  • 检查传入的IOCB中的文件描述符对应的文件是否存在:提交前后一直存在;
  • 检查对应的文件在IO请求提交前后是否可读可写:可读可写,排除这个问题;
  • 检查传入的IOCB中的文件描述符对应的文件在提交过程中是否会被关闭:通过深入阅读相关模块代码发现在当前系统上,为了避免重复打开相同文件,有一个文件描述符 cache 管理文件描述符,这个cache 容量有限,每新打开一个文件的时候,cache size就会加1;当达到容量上限的时候,会把最近不使用的文件关掉。如果这个时候,有在飞的io submit 请求,那么就出现io submit 的文件描述符中间被关闭的情况。

验证

基于上面的分析,把上述 cache 容量上限调整到所在磁盘的文件数量的上限,进行了同样的测试,长时间运行仍然稳定。因此,可以认为根因就是提交请求的文件描述符被fd cache中途关掉了。

总结

通过分析上面的问题可以看到,针对一般的错误,我们首先需要知道直接原因,比如io submit 错误,需要知道错误码的含义、可能导致的原因;然后据此结合时间系统上下文进行分析排查,才能彻底定位、解决问题。