From: Vivek Goyal
翻译:王鑫
Hi,
我一直在尝试寻找关于 blog IO controller cgroups 的以下两个问题的解决办法:IO controller 的当前 throttling 逻辑无法限制buffered WRITES。它的实现是在设备上限制所有的 WRITEs,但到那时,buffered WRITE 已经丢失了提交者的上下文,并且大多数的IO进入到设备上的 flusher 线程的上下文中。因此当前并不支持对buffered write的限制。
所有的WRITEs都在设备级上进行限制,这就很容易导致文件系统的串行。
举一个简单的例子,如果一个进程往cache中写入一些页面,然后运行fsync(),这个时候进程才开始被 throttled ,于是它会锁定整个文件系统。在ext4中,我注意到甚至一个简单的“ls”都不会再继续进行了。这个原因可以归结为文件系统并不关注cgroups和以顺序模式的文件系统日志这件导致串行这件事。
因此即使我们获得提交者的cgroup信息到设备并且在设备那里做限制,它仍然会导致文件系统的串行,这并不是一个好主意。
因此怎样去修正这个问题呢?貌似有以下两种办法:仍然在设备级上去做限制。让文件系统关注cgroups使得多个事务可以以并行的方式(每一个cgroup)同时前进,并且在cgroups之间并不存在那些导致文件系统串行的共享资源。
当WRITEs进入cache时进行限制而不是直到设备才开始 throttle。比如类似balance_dirty_pages()这样的函数。直接IO仍然是在设备级上进行限制的。按照这种方式,关于限制,我们可以避免文件系统日志导致串行
但是这个方法的很重要的一点就是我们控制进入cache的IO速率而不是设备上的IO速率。按照那样的方法则可能会发生flusher过后会提交许多WRITEs到设备,并且我们将会在终端节点上看到许多周期性的IO spike。
因此这个方法可能会有一点帮助,但远远不是一个完整的解决方案。它主要能够帮助那些拥有许多IO资源和有效IO带宽但是希望控制资源分配给低优先级的客户。
方法1看起来很难去修正。在往文件系统写东西的时候,文件系统从不关注cgroups。因此我很怀疑我能够说服文件系统的设计者来改动基础的文件系统和日志记录部分的代码来使得文件系统关注cgroup。
因此我在本系列补丁中仅实现了方法2。方法2并不是一个最好的解决方案,但是它至少给了我们一些在buffered write上的控制能力,这总比一点都不给要好。Andrea Righi也曾经做过一个类似的补丁:https://lkml.org/lkml/2011/2/28/115
这个补丁是关于bio和任务限制之间的交互的,因此我重做了它。
设计
IO控制器已经有跟踪一个group的IO速率的能力,并且当group超过一定速率时会把bio插入内部队列,并在随后将这些bio分发出去。
本补丁也引入了balance_dirty_pages_ratelimited_nr()中限制dirtying task的能力。现在所有除直接WRITES外的所有WRITEs在设备级上都不会受限制。如果一个dirtying task超过其配置的速率,它将被放入等待队列,当它可以dirty更多页面的时候才被唤醒。
没有新的接口被引入,直接IO和buffered IO都是使用通用IO速率限制。
How To
- Create a cgroup and limit it to 1MB/s for writes.
echo "8:16 1024000" > /cgroup/blk/test1/blkio.throttle.write_bps_device
- Launch dd thread in the cgroup
dd if=/dev/zero of=zerofile bs=4K count=1K
1024+0 records in
1024+0 records out
4194304 bytes (4.2 MB) copied, 4.00428 s, 1.0 MB/s
Any feedback is welcome.
ThanksVivek
最新评论