inotify はどうやってディレクトリ監視を実現しているのか。実装の制限、というか罠について

22
AoiMoe a.k.aしお兄P @AoiMoe

inotifyのIN_MODIFYみたいに、親に何かを通知したい場合に dentry の d_parent 使ってるけど、これってハードリンクされてたらどうなんの?

2013-06-26 20:03:26
AoiMoe a.k.aしお兄P @AoiMoe

Linuxのinotifyは最初からdentry(BSDのnamecacheに相当)のd_parentを頼りにしてるので、何も考えてない感じ。ハードリンク何ソレ、よねこれ

2013-06-27 17:10:19
AoiMoe a.k.aしお兄P @AoiMoe

inotifyで変更を監視する、みたいな話があるけど、ハードリンクがあると容易に検出漏れするわけだが、本当にそんなんでいいのか。

2013-06-28 15:17:09
AoiMoe a.k.aしお兄P @AoiMoe

リンクカウントが足されたのは検出可能だし、FSまるごと監視対象にすれば漏れないけど。

2013-06-28 15:17:52
AoiMoe a.k.aしお兄P @AoiMoe

うん、 mkdir a b touch a/foo ln a/foo b/ して inotifywait -m -e modify a した状態で echo foo >> a/foo は検出するが echo foo >> b/foo は検出しない、という結果になりました

2013-06-28 15:56:03
AoiMoe a.k.aしお兄P @AoiMoe

inotify(7)のどこにも「dentryベースの追跡なのでハードリンクしてると漏れる」みたいな注意がされてないけど、それでいいんかねえ

2013-06-28 15:59:20
AoiMoe a.k.aしお兄P @AoiMoe

あ、リンクカウントの変更は追跡してないな

2013-06-28 16:03:30
AoiMoe a.k.aしお兄P @AoiMoe

ってこれはカーネルが古いんだな

2013-06-28 16:04:15
AoiMoe a.k.aしお兄P @AoiMoe

2.6.25より前ではたぶん忘れてたんだろうwwww

2013-06-28 16:04:54
AoiMoe a.k.aしお兄P @AoiMoe

まあ、inode/vnodeベースの追跡ってのは、たとえばNFSなんかではstatdあたりにそのための機能を入れないといけなかったりするけど。

2013-06-28 16:06:21
AoiMoe a.k.aしお兄P @AoiMoe

と、ここまで検討した結果は「こんなad hocなもんを実装するのかよ」という話である

2013-06-28 16:09:22
AoiMoe a.k.aしお兄P @AoiMoe

kqueueでNFSの監視とかどうしてるんだ、と思って nfs/nfs_kq.c を見たら nfs_kqpoll で「NFS_MINATTRTIMO/2秒(=2.5秒)ごとにポーリングするよ」とか書いてあって頭を抱えた

2013-06-28 16:13:50
小崎 資広 (KOSAKI Motohiro) @kosaki55tea

@AoiMoe CentOS6でも同じ結果だた。ソースを見ると inotifyはinodeで追跡してるように見えるので、さて原因はなんだろう

2013-06-28 16:17:06
AoiMoe a.k.aしお兄P @AoiMoe

a/foo に対する書き込みがあると、 (1)writeシステムコールからfooのfileに対してfsnotify_modifyが呼ばる (2)fooのdentryにdget_parentしてaのdentryを取ってきて、こいつに通知する ってコードに見える

2013-06-28 16:27:10
小崎 資広 (KOSAKI Motohiro) @kosaki55tea

@AoiMoe あれ、fsnotify()のほうが本体だという認識だったのですが。勘違いだったかな

2013-06-28 16:38:15
AoiMoe a.k.aしお兄P @AoiMoe

@kosaki55tea そっちは、さっきの例でいえば a/foo 自体のフックに通知する関数ですね。a/foo に対するイベントを a のフックに通知するところで、dentry 使ってヒエラルキーをさかのぼってる

2013-06-28 16:41:33
小崎 資広 (KOSAKI Motohiro) @kosaki55tea

@AoiMoe ああ、inotifywaitの引数が a/foo じゃなくて a/ だった。見落としてた。すいません

2013-06-28 16:43:41
AoiMoe a.k.aしお兄P @AoiMoe

んー、というわけなので、kqueue的には、EVFILT_VNODEの「identがfdなので以下略」問題だけを解決して、変更の監視をしたいなら全部のファイルを明示的に見るようにしろ、でいいような気がしてきたがどうでしょう

2013-06-28 16:52:27
AoiMoe a.k.aしお兄P @AoiMoe

BSD的には、真面目にやるなら新しいVOP追加して、ディレクトリにフックかけたときにdirentなめてinoテーブル見て以下略とかすることになるぜよ。

2013-06-28 16:57:41
AoiMoe a.k.aしお兄P @AoiMoe

新しいVOP追加するまでもなくVOP_KQFILTERで頑張ればいいのか。いずれにしても頑張る羽目になるわけだが。

2013-06-28 17:02:11
AoiMoe a.k.aしお兄P @AoiMoe

VFS_VGETするといちいちvnode生成して効率悪いので、FSの中でやるしかない

2013-06-28 17:02:59
SODA Noriyuki @n_soda

@AoiMoe inotify(7)エミュレーションは諦めるってことですね。ちょっと影響でかすぎるので、それかなあ。ディスクリプタのリミットも「広げろ!」でもいいのかも。Linuxでも fs.inotify.max_user_watches (8192)の制限はあるわけで

2013-06-28 17:03:17