阻塞在io_schedule里

来源:互联网 发布:深入浅出node.js微盘 编辑:程序博客网 时间:2024/04/28 05:48

最近碰到一个问题,android平台,在执行fsck_msdos时拔卡,出现fsck_msdos进程状态为D。因为卡驱动插拔部分(非MMC那一套)我已经改成如果没有umount就不再进行新一轮的插卡检测,所以这里就不能正常跑了

 

1. 查看该进程堆栈 cat /proc/pid/stack

    看到停在sync_page里的io_schedule。单独看到io_schedule我以为和schedule差不多,往里看并没有设置进程状态为非RUNNING, 所以以为与schedule一样会得到再次调度,实际上io_schedule是需要唤醒的。wait_on_page_bit有将进程状态设置为TASK_UNINTERRUPTIBLE,再调用sync_page。

2. 阻塞在sync_page的io_schedule是因为page状态为lock。每个page操作期间都会上锁,如果此时状态为lock,就是同样的page被另一个进程正在访问,但ps查看所有进程并没有什么进程被阻塞,连底层card_queue_thread也是sleep状态。

3. 结果我花时间把ULK 相关3章看了一遍,还是没头绪,总认为是kernel本身的问题,认为可能是插拔这种非正常状态下导致某些路径未执行unlock_page解锁。花了好长时间在这个上面,加了无数打印看流程

4. 我的打印集中在block_read_full_page,

如果uptodate的就直接end_buffer_async_read,否则submit_bh->sumbit_bio到底层

对于page都是uptodate马上unlock。end_buffer_async_read会调用4次,前3次都是still_busy,最后一次才是unlock,说是因为到block_read_full_page后因为存在file hole,所以一个一个的读,一个page分4次,4个bh完了才能unlock一个page

5. 实际上打印显示插拔如果处于4次循环之间,容易出现某1,2个bh未正常走完submit_bh,未能走到bio_endio,也就不能unlock page。打印走到了__make_request,已经是块设备驱动的上一层函数了

6. 在__make_request中并未走到块设备驱动注册的request_fn,也就是blk_init_queue注册的card_request,因为未unplug,虽然我们的card_queue_thread并未依据queue plug状态决定是否取request,但__make_request不调用card_request,card_queue_thread就一直sleep,不唤醒,不issue_rq。

7. 在card_blk_remove中将queue状态设置为QUEUE_FLAG_STOPPED,就更走不到__make_request。__generic_make_request就不会调用make_request_fn而直接end_io。

8. 问题应该是当卡拔出后因为queue plug的原因,queue里的request未empty,所以一些page处于lock状态,如果有别的进程同样访问该page就会锁住,且无法kill。应该像mmc driver一样在card remove时empty queue

 

 

原创粉丝点击