2014-08-31 48 views
3

任何人都可以解释为什么Linux内核的ext2的功能 int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)内存屏障()

问题smp_rmb()else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) { 情况下smp_wmb()

这是在上游内核提交2235219b7721b8e74de6841e79240936561a2b63中添加的,它省略了对.statfs的不必要计算,但无法理解为什么添加了内存屏障。

+0

谢谢,添加到kernel.org的链接。 – qwerty 2014-08-31 09:52:25

回答

4

由于函数通过做用spin_lock开始(和结束时解锁),

spin_lock(&sbi->s_lock); 

它被保护,以防止并发访问。那么,为什么smp_wmbsmp_rmb的需要...

至于写操作,

sbi->s_overhead_last = overhead; 
    smp_wmb(); 
    sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count); 

看来该smp_wmb将防止任何编译器或处理器的优化(因为在内存访问方面,两个写入之间没有依赖关系),这会改变两个分配的顺序。由于在ext2_statfs中没有并发访问,所以在可能具有类似行为的另一个函数中可能会发生问题,并检查是否存在块计数更改,如果不存在,则使用sbi->s_overhead_last的开销 - 如果另一个函数在这个时候,线程将在另一个函数中,在两个写入操作的中间以错误的顺序。

这可能是一种预防措施作为对SBI性质会用spin_lock它(具有相同的自旋锁)预先任何类似的写访问。而且它增强了这两个操作必须按此顺序完成的事实。

至于读访问需要的是不太明显的,需要进一步分析SBIES块之间的依赖关系。

+0

很有意义。谢谢你的回答。 – qwerty 2014-08-31 12:05:22

+0

由于自旋锁确实没有并发性。然而,前一次执行相同函数(或修改相关数据的其他任何内容)的结果可能对当前的cpu尚不可见。障碍确保此函数始终能够看到当前状态(因锁定而不能更改),并且在释放锁定之前结果已提交。 – Jester 2014-08-31 12:14:01

+0

对,你的答案/评论对我来说都很有意义,但是因为自旋锁(我相信)对MB有很大影响,所以不应该写一个类似功能的人(如果检查和更新)可能在未来只使用相同的原始自旋锁(超级块 - >锁),而不是关心可能已被编译器优化的排序? – qwerty 2014-08-31 12:43:53