iget (4)
とりあえず hlist_entry マクロというか container_of マクロの謎はある程度解けたので元に戻ります。その前に hlist_for_each マクロも確認必要。
#define hlist_for_each(pos, head) \ for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ pos = pos->next)
ええと、include/linux/list.h にて定義。
あと struct hlist_head 型とか struct hlist_node 型などの定義は include/linux/list.h で以下
struct hlist_head { struct hlist_node *first; }; struct hlist_node { struct hlist_node *next, **pprev; };
む pprev な属性の意図が不明。とりあえず hlist_for_each マクロでは使っていないのでスルー。あと謎なのが prefetch という手続き。
で、掘ってみたのですが i386 なソレだと include/asm-i386/processor.h で以下
static inline void prefetch(const void *x) { alternative_input(ASM_NOP4, "prefetchnta (%1)", X86_FEATURE_XMM, "r" (x)); }
で、alternative_input マクロは include/asm-i386/alternative.h にて定義されてて以下
#define alternative_input(oldinstr, newinstr, feature, input...) \ asm volatile ("661:\n\t" oldinstr "\n662:\n" \ ".section .altinstructions,\"a\"\n" \ " .align 4\n" \ " .long 661b\n" /* label */ \ " .long 663f\n" /* new instruction */ \ " .byte %c0\n" /* feature bit */ \ " .byte 662b-661b\n" /* sourcelen */ \ " .byte 664f-663f\n" /* replacementlen */ \ ".previous\n" \ ".section .altinstr_replacement,\"ax\"\n" \ "663:\n\t" newinstr "\n664:\n" /* replacement */\ ".previous" :: "i" (feature), ##input)
ぎゃー。とりあえず hlist_for_each マクロは pos が NULL になったら終わるはずなので、意図としては
- node を持ってる inode オブジェクトの
- inode 番号が同一
- super block オブジェクトも同じ
- i_state が I_FREEING でも I_CLEAR でも I_WILL_FREE でもない
のであれば inode オブジェクトのポインタを戻す、という理解でええんかな。
戻って
fs/inode.c の ifind_fast 手続き。上記の find_inode_fast 手続きが NULL を戻したら spin_unlock して NULL を戻します。そうでなかった場合は以下
if (inode) { __iget(inode); spin_unlock(&inode_lock); wait_on_inode(inode); return inode; }
__iget 手続きは何なんだろ。fs/inode.c で定義されてて以下
/* * inode_lock must be held */ void __iget(struct inode * inode) { if (atomic_read(&inode->i_count)) { atomic_inc(&inode->i_count); return; } atomic_inc(&inode->i_count); if (!(inode->i_state & (I_DIRTY|I_LOCK))) list_move(&inode->i_list, &inode_in_use); inodes_stat.nr_unused--; }
i_count を云々してますがこの属性は_参照カウント_とある。ざっくり的に理解するとしたらば cache 見に行ってあれば参照カウント上げとく、という事なのかなぁ。
iget_locked
再掲。
struct inode *iget_locked(struct super_block *sb, unsigned long ino) { struct hlist_head *head = inode_hashtable + hash(sb, ino); struct inode *inode; inode = ifind_fast(sb, head, ino); if (inode) return inode; /* * get_new_inode_fast() will do the right thing, re-trying the search * in case it had to block at any point. */ return get_new_inode_fast(sb, head, ino); }
inode cache 見に行ってあったら戻す。参照カウントも上げとく。無かった場合どうなるか。
get_new_inode_fast 手続き
これと get_new_inode 手続きのナニが不明ですが、以下なコメントがある。
/* * get_new_inode_fast is the fast path version of get_new_inode, see the * comment at iget_locked for details. */
うーん。ちょっと fast とそうでない違いが理解できてない。
体調微妙なので今日はこれで終了。