カーネル読書会で、シーケンスロックのスピンロックをとらない軽量版が(関数名ではseqcount_hogehoge) あるんだけど、preempt_disable()してないから使うべきではない。と発言したら

いやいや、呼び出し側でIRQ disable()してるかもしれないから、一概にそうとは言えない。

と諭されてしまった。
おっしゃるとおり。


ちなみに、以下に seqcountのwrite lock関数を引用しておく。ご参考までに

136 static inline void write_seqcount_begin(seqcount_t *s)
137 {
138 s->sequence++;
139 smp_wmb();
140 }
141
142 static inline void write_seqcount_end(seqcount_t *s)
143 {
144 smp_wmb();
145 s->sequence++;
146 }




で、おっしゃるとおり。で終わっていると寂しいので使っている場所を見てみた。

ソースは例によって lxr.linux.no の 2.6.11 カーネルね。


まず、使っている場所は一箇所のみ。
以下に示すように、inode->i_size いじってる場所。

http://lxr.linux.no/source/include/linux/fs.h#L526
523 static inline void i_size_write(struct inode *inode, loff_t i_size)
524 {
525 #if BITS_PER_LONG==32 && defined(CONFIG_SMP)
526 write_seqcount_begin(&inode->i_size_seqcount);
527 inode->i_size = i_size;
528 write_seqcount_end(&inode->i_size_seqcount);
529 #elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
530 preempt_disable();
531 inode->i_size = i_size;
532 preempt_enable();
533 #else
534 inode->i_size = i_size;
535 #endif
536 }



あ、あららー
やっぱり、preempt_disable()しないとまずそうですよ。
IRQ disableしてないってのもあるが、それより何より、
シングルCPUのときは preempt_disable(); してるってのが、
いかにもわざとそうしてるんじゃないんだよー
という雰囲気をかもし出している。

いや、それ以前に、ここseqcountじゃなく、seqlock使わないとまずい場所に見えるんですが・・・(n'ω'`)


カーネル読書会に来ていなかった人のために補足すると問題点は以下

1.SMP環境においてwrite_seqcount_begin() したあとで、preemptすると、ロック保持期間が滅茶苦茶長くなる
2.seqcount()は書き手が複数いたときの排他をまったくしないので、設計上1人になることを保障しなければならないが、i_size_write()がそんな事をしているようには見えない。かつi_sizeは64bit変数なので、32bitアーキでは1命令では書けない
3.seqcount使うなら読み手もread lock取らないといけないが、そんな事をしてな場所が腐るほどある。

3は問題じゃないかもしれないけどね。i_sizeが絶対32bitで収まるfsだと単純に=演算子で代入しちゃってもうまくいくから。
そこはちゃんと見てない。

なに?
2.6.11なんて見てないでちゃんと最新をおっかけろ?
おっしゃるとおり。ごめんなさい。
ちょっと、手間隙かかるのよね。最新をウォッチし続けるのって(^^ゞ

気になっているので誰かコメントくれると嬉しいっす。




しょせんカスか
ちゃんと見切れていません! ランキング!