该分析sys_io_submit函数了,这个函数有点复杂,但是条理很清晰,先说一句就是提交异步io,具体怎么提交呢?我们知道,对于异步io,一次 性可以提交多个请求,那么可以想象的就是在sys_io_submit中会把我们用户程序的多个请求分解成一个一个的请求,依次提交,这是很合理的假设, 内核实际上也是这么做的,刚才的建立异步io的阶段只是建立了一个可以让异步io表演的大的环境,现在的提交请求和将来的读取数据便是大戏了,准备好了 吗?马上开演!
1562 asmlinkage long sys_io_submit(aio_context_t ctx_id, long nr,
1563 struct iocb __user * __user *iocbpp)
1564 {
1565 struct kioctx *ctx;
1566 long ret = 0;
1567 int i;
1568
1569 if (unlikely(nr < 0))
1570 return -EINVAL;
1571
1572 if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp)))))
1573 return -EFAULT;
1574
1575 ctx = lookup_ioctx(ctx_id);//这里查找我们刚才建立的kioctx
1576 if (unlikely(!ctx)) {
1577 pr_debug("EINVAL: io_submit: invalid context id/n");
1578 return -EINVAL;
1579 }
1580
1581 /*
1582 * AKPM: should this return a partial result if some of the IOs were
1583 * successfully submitted?
1584 */
1585 for (i=0; i<nr; i++) {//这个循环实质上分解了用户请求
1586 struct iocb __user *user_iocb;
1587 struct iocb tmp;
1588
1589 if (unlikely(__get_user(user_iocb, iocbpp + i))) {
1590 ret = -EFAULT;
1591 break;
1592 }
1593
1594 if (unlikely(copy_from_user(&tmp, user_iocb, sizeof(tmp)))) {
1595 ret = -EFAULT;
1596 break;
1597 }
1598
1599 ret = io_submit_one(ctx, user_iocb, &tmp);//一次提交一个,直到全部提交完毕
1600 if (ret)
1601 break;
1602 }
1603
1604 put_ioctx(ctx);
1605 return