プロフィール

kosaki

Author:kosaki
連絡先はコチラ

ブログ検索
最近の記事
最近のコメント
最近のトラックバック
リンク
カテゴリー
月別アーカイブ
RSSフィード
FC2ブログランキング

スポンサーサイト このエントリーをはてなブックマークに追加

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。


スポンサー広告 | 【--------(--) --:--:--】 | Trackback(-) | Comments(-)

seqcountが preempt_disableしてない件について このエントリーをはてなブックマークに追加

カーネル読書会で、シーケンスロックのスピンロックをとらない軽量版が(関数名では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なんて見てないでちゃんと最新をおっかけろ?
おっしゃるとおり。ごめんなさい。
ちょっと、手間隙かかるのよね。最新をウォッチし続けるのって(^^ゞ

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




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

関連記事


linux | 【2006-06-15(Thu) 22:26:43】 | Trackback:(1) | Comments:(6)
コメント

うーむ、全然問題ないと思うなぁ。
write_seqcount_beginやwrite_seqcount_endとかは同時に複数の更新処理が動作しないと保証された場合のみ使える関数だよ。
ちなみにinode->i_sizeの更新はinode->i_semで保護されてるはず。
2006-06-15 木 10:18:18 | URL | ひら #G3vcSUbA [ 編集]

write_seqcount_begin~write_seqcount_endはread_seqcount_beginしたとき値の更新を通知するために存在するわけで、(更新の為の)排他目的のものではない、と認識すればよいかと。
2006-06-15 木 10:51:38 | URL | ひら #G3vcSUbA [ 編集]

おおお、なるほど。
たしかに2と3は撤回したほうがいいかも。
あとで調べてから、返事書きまする。

ご指摘ありがとうございまする。
2006-06-16 金 09:54:31 | URL | 革命の日々 #- [ 編集]

529~532行は不要ですね。
530行でpreempt_disable();する以前にpreempt_countは1以上なのでプリエンプションは発生しません。というのもinode->i_semのロックを取得する際にpreempt_disable()しますので。

1.に関してはwrite_seqcount_begin()の後にプリエンプションが発生しますと、デッドロックが発生する可能性があります。何らかのロックを保持した状態で、他のロックを保持するのは問題ありません(ただしロックする順序に気をつけなければならない)が、プリエンプションはまずいです。
2006-06-16 金 23:55:45 | URL | ひら #G3vcSUbA [ 編集]
このコメントは管理人のみ閲覧できます
2007-09-02 日 03:01:25 | | # [ 編集]
このコメントは管理人のみ閲覧できます
2007-12-20 木 12:44:29 | | # [ 編集]
seqcountが preempt_disableしてない件について というエントリで、seqcountってプリエンプションをなーんも考えてないんだけど、呼び出し側のi_size_write() もなーんも考えてないように見える。これって大丈夫なの?
【2006-06-25 Sun 02:00:49】 | 革命の日々!
  1. 無料アクセス解析
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。