Q:块设备层保序功能的作用?
A:通用块层可以提交一个带保序标签(BIO_RW_BARRIER)的BIO到IO请求队列,块设备层可以保证在保序BIO之前提交的BIO都先于BIO执行且抵达存储介质;保序BIO执行完毕后,它需要写入的数据必定已经抵达存储介质;在保序IO之后提交的BIO都晚于保序BIO执行,确保BIO不饥饿.
Q:块设备层保序功能的应用?
A:保序功能最典型的应用场景是文件系统的日志,日志文件系统做文件操作时的日志操作可以简化为:1.开始事务->2.将修改的元数据写入到日志空间->3.向日志空间写入事务提交块->4.事务结束,这个过程中,IO调度器可能重排2,3步的BIO,导致第3步先于第2步执行完毕,掉电后一个不完整的事务被恢复,文件系统数据被破坏.
Q:块设备保序功能的实现?
A:BIO从提交到抵达存储介质需要经过的IO路径有:IO调度器缓存队列->IO分发队列->驱动缓存队列->磁盘缓存->磁盘介质,保序的真正实现需要借助磁盘提供支持,2.6.27的保序实现会根据磁盘提供的功能做不同的操作.其原理是在收到保序请求后,清空IO调度器中缓存的request,同时在保序请求前后插入刷硬盘缓存指令的request,确保保序请求执行完毕后它和它以前请求写入的数据都已抵达存储介质,具体步骤如下:
1.当块设备层收到保序BIO时,独立创建一个带REQ_HARDBARRIER标志的request,调用add_request()向request_queue添加request,插入的位置是ELEVATOR_INSERT_BACK.
2.elv_insert()收到ELEVATOR_INSERT_BACK位置的请求后,将IO调度器中缓冲的request都转移到分发队列,同时将保序request插入到分发队列的最后.
3.底层驱动提供的q->request_fn()函数被调用,elv_next_request()->blk_do_ordered()处理到保序request时,如果q->ordseq=0且硬盘支持冲刷缓存指令,调用start_ordered()开始保序流程.