从虚拟化前端Bug学习分析Kernel Dump( 十 )

至此 , 我只是分析了这几个数据结构中相关的变量内容 , 还没有解释这些变量或者函数的含义 , 现在我们已经验证了触发 BUG 的条件 total_sg > vq->vring.num , 但是为什么会出现这种情况呢?要分析这几个变量的值需要回溯到调用这个函数的函数 , 最终可能需要一直回溯到发起 IO 请求的应用层程序 , 这显然是一件非常麻烦的事情 。 换一个角度来想 , total_sg 是 vm 需要的 scatterlist 的总数 , scatterlist 是一个跟物理内存有关的结构 , 这里可以简单理解为 vm 所需要的物理内存 , 而 vring 是 virtio 前后端数据传输的载体 , 这里可以简单理解前后端数据传输的能力 。 直观的感觉是 total_sg 确实不应该比 vring.num 大 , 但实际上 total_sg 只比 vring.num 大 1 , 而且这里 total_sg 的值与我刚开始的想法不一样 , 由于 total_sg 是 unsigned int 类型的 , 而这里的比较是 total_sg > vq->vring.num , 因此我开始的想法是 total_sg 下溢出了 。 分析到这里 , 我抱着试一试的态度把 BUG_ON(total_sg > vq->vring.num); 丢到 Google 上搜了一把 , 发现这行代码已经在某个版本中 patch 掉了 , 最新的 kernel 里把 BUG_ON 改成了低一级的 WARN_ON_ONCE , 同时把条件改成了 total_sg > vq->vring.num && !vq->indirect 。 也就是说 , 在使用了 indirect descriptors 的情况下 , 是允许 total_sg > vq->vring.num 这中情况出现的 , 那如何验证 vm 有没有使用 indirect descriptors 呢?实际上在 vring_virtqueue 中的成员 indirect 标示了是否使用 indirect descriptors , 在上面执行 

推荐阅读