分类: LINUX
2013-12-25 18:07:47
原文地址:inode对象的建立 作者:tq08g2z
前面sysfs_get_inode()中调用iget_locked(sb,
sd->s_ino)来建立inode对象,这个iget_locked()也是VFS的一个非常重要的函数。其定义为:
---------------------------------------------------------------------
fs/inode.c
592
static unsigned long hash(struct super_block *sb, unsigned long hashval)
593
{
594 unsigned long tmp;
595
596 tmp = (hashval * (unsigned long)sb) ^
(GOLDEN_RATIO_PRIME + hashval) /
598 tmp = tmp ^ ((tmp ^
GOLDEN_RATIO_PRIME) >> I_HASHBITS);
599 return tmp & I_HASHMASK;
600
}
1047
/**
1048 * iget_locked - obtain an inode from a
mounted file system
1049 * @sb:
super block of file system
1050 * @ino:
inode number to get
1051 *
1052 * iget_locked() uses ifind_fast() to search
for the inode specified by @ino in
1053 * the inode cache and if present it is
returned with an increased reference
1054 * count. This is for file systems where the
inode number is sufficient for
1055 * unique identification of an inode.
1056 *
1057 * If the inode is not in cache,
get_new_inode_fast() is called to allocate a
1058 * new inode and this is returned locked,
hashed, and with the I_NEW flag set.
1059 * The file system gets to fill it in before
unlocking it via
1060 * unlock_new_inode().
1061 */
1062
struct inode *iget_locked(struct super_block *sb, unsigned long ino)
1063
{
1064 struct hlist_head *head =
inode_hashtable + hash(sb, ino);
1065 struct inode *inode;
1066
1067
inode = ifind_fast(sb, head,
ino);
1068 if (inode)
1069 return inode;
1070 /*
1071 * get_new_inode_fast() will do the
right thing, re-trying the search
1072 * in case it had to block at any
point.
1073 */
1074 return get_new_inode_fast(sb, head,
ino);
1075
}
1076
EXPORT_SYMBOL(iget_locked);
---------------------------------------------------------------------
1、获得inode可能存在的哈希链表的头,并有局部变量head指向它。
2、调用ifind_fast(sb,
head, ino)来在inode缓存中超找有ino指定的inode。如果找到则增加其引用计数并返回该inode对象地址。
---------------------------------------------------------------------
fs/inode.c
567
/*
568 * find_inode_fast is the fast path version of
find_inode, see the comment at
569 * iget_locked for details.
570 */
571
static struct inode *find_inode_fast(struct super_block *sb,
572 struct
hlist_head *head, unsigned long ino)
573
{
574 struct hlist_node *node;
575 struct inode *inode = NULL;
576
577
repeat:
578 hlist_for_each_entry(inode, node,
head, i_hash) {
579 if (inode->i_ino != ino)
580 continue;
581 if (inode->i_sb != sb)
582 continue;
583 if (inode->i_state &
(I_FREEING|I_CLEAR|I_WILL_FREE)) {
584
__wait_on_freeing_inode(inode);
585 goto repeat;
586 }
587 break;
588 }
589 return node ? inode : NULL;
590
}
897
/**
898 * ifind_fast - internal function, you want
ilookup() or iget().
899 * @sb:
super block of file system to search
900 * @head:
head of the list to search
901 * @ino:
inode number to search for
902 *
903 * ifind_fast() searches for the inode @ino in
the inode cache. This is for
904 * file systems where the inode number is
sufficient for unique identification
905 * of an inode.
906 *
907 * If the inode is in the cache, the inode is
returned with an incremented
908 * reference count.
909 *
910 * Otherwise NULL is returned.
911 */
912
static struct inode *ifind_fast(struct super_block *sb,
913 struct hlist_head *head,
unsigned long ino)
914
{
915 struct inode *inode;
916
917 spin_lock(&inode_lock);
918 inode = find_inode_fast(sb, head,
ino);
919 if (inode) {
920 __iget(inode);
921 spin_unlock(&inode_lock);
922 wait_on_inode(inode);
923 return inode;
924 }
925 spin_unlock(&inode_lock);
926 return NULL;
927
}
---------------------------------------------------------------------
3、在inode缓存中没有找到所要的inode对象,则调用get_new_inode_fast(sb, head, ino)分配、初始化inode对象并返回该inode对象。这个函数定义为:
---------------------------------------------------------------------
fs/inode.c
760
/*
761 * get_new_inode_fast is the fast path version
of get_new_inode, see the
762 * comment at iget_locked for details.
763 */
764
static struct inode *get_new_inode_fast(struct super_block *sb,
765 struct
hlist_head *head, unsigned long ino)
766
{
767 struct inode *inode;
768
769 inode = alloc_inode(sb);
770 if (inode) {
771 struct inode *old;
772
773 spin_lock(&inode_lock);
774 /* We released the lock, so..
*/
775 old = find_inode_fast(sb,
head, ino);
776
if (!old) {
777 inode->i_ino = ino;
778
__inode_add_to_lists(sb, head, inode);
779 inode->i_state =
I_NEW;
780
spin_unlock(&inode_lock);
781
782 /* Return the locked
inode with I_NEW set, the
783 * caller is
responsible for filling in the contents
784 */
785 return inode;
786 }
787
788 /*
789 * Uhhuh, somebody else
created the same inode under
790 * us. Use the old inode
instead of the one we just
791 * allocated.
792 */
793 __iget(old);
794 spin_unlock(&inode_lock);
795 destroy_inode(inode);
796 inode = old;
797 wait_on_inode(inode);
798 }
799 return inode;
800
}
---------------------------------------------------------------------
get_new_inode_fast()接受三个参数,分别位inode所在文件系统的超级块对象地址,inode可能存在的哈希表的表头以及inode节点号。
这个函数执行如下操作:
a.调用alloc_inode(sb)来分配一个inode对象:
---------------------------------------------------------------------
fs/inode.c
202
static struct inode *alloc_inode(struct super_block *sb)
203
{
204 struct inode *inode;
205
206 if (sb->s_op->alloc_inode)
207 inode =
sb->s_op->alloc_inode(sb);
208 else
209 inode =
kmem_cache_alloc(inode_cachep, GFP_KERNEL);
210
211 if (!inode)
212 return NULL;
213
214 if (unlikely(inode_init_always(sb,
inode))) {
215 if
(inode->i_sb->s_op->destroy_inode)
216
inode->i_sb->s_op->destroy_inode(inode);
217 else
218
kmem_cache_free(inode_cachep, inode);
219 return NULL;
220 }
221
222 return inode;
223
}
---------------------------------------------------------------------
sysfs的super_operations操作集sysfs_ops是没有alloc_inode()方法的。
inode_init_always(sb,
inode)函数完成对于inode的基本的初始化:
---------------------------------------------------------------------
fs/inode.c
118
/**
119 * inode_init_always - perform inode structure
intialisation
120 * @sb: superblock inode belongs to
121 * @inode: inode to initialise
122 *
123 * These are initializations that need to be
done on every inode
124 * allocation as the fields are not
initialised by slab allocation.
125 */
126
int inode_init_always(struct super_block *sb, struct inode *inode)
127
{
128 static const struct
address_space_operations empty_aops;
129 static const struct inode_operations
empty_iops;
130 static const struct file_operations
empty_fops;
131 struct address_space *const mapping =
&inode->i_data;
132
133 inode->i_sb = sb;
134 inode->i_blkbits =
sb->s_blocksize_bits;
135 inode->i_flags = 0;
136 atomic_set(&inode->i_count, 1);
137 inode->i_op = &empty_iops;
138 inode->i_fop = &empty_fops;
139 inode->i_nlink = 1;
140 inode->i_uid = 0;
141 inode->i_gid = 0;
142
atomic_set(&inode->i_writecount, 0);
143 inode->i_size = 0;
144 inode->i_blocks = 0;
145 inode->i_bytes = 0;
146 inode->i_generation = 0;
147
#ifdef CONFIG_QUOTA
148 memset(&inode->i_dquot, 0,
sizeof(inode->i_dquot));
149
#endif
150 inode->i_pipe = NULL;
151 inode->i_bdev = NULL;
152 inode->i_cdev = NULL;
153 inode->i_rdev = 0;
154 inode->dirtied_when = 0;
155
156 if (security_inode_alloc(inode))
157 goto out;
158 spin_lock_init(&inode->i_lock);
159
lockdep_set_class(&inode->i_lock,
&sb->s_type->i_lock_key);
160
161 mutex_init(&inode->i_mutex);
162
lockdep_set_class(&inode->i_mutex,
&sb->s_type->i_mutex_key);
163
164
init_rwsem(&inode->i_alloc_sem);
165
lockdep_set_class(&inode->i_alloc_sem,
&sb->s_type->i_alloc_sem_key);
166
167 mapping->a_ops = &empty_aops;
168 mapping->host = inode;
169 mapping->flags = 0;
170 mapping_set_gfp_mask(mapping,
GFP_HIGHUSER_MOVABLE);
171 mapping->assoc_mapping = NULL;
172 mapping->backing_dev_info =
&default_backing_dev_info;
173 mapping->writeback_index = 0;
174
175 /*
176 * If the block_device provides a
backing_dev_info for client
177 * inodes then use that. Otherwise the inode share the bdev's
178 * backing_dev_info.
179 */
180 if (sb->s_bdev) {
181 struct backing_dev_info *bdi;
182
183 bdi =
sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
184 mapping->backing_dev_info =
bdi;
185 }
186 inode->i_private = NULL;
187 inode->i_mapping = mapping;
188
#ifdef CONFIG_FS_POSIX_ACL
189 inode->i_acl =
inode->i_default_acl = ACL_NOT_CACHED;
190
#endif
191
192
#ifdef CONFIG_FSNOTIFY
193 inode->i_fsnotify_mask = 0;
194
#endif
195
196 return 0;
197
out:
198 return -ENOMEM;
199
}
200
EXPORT_SYMBOL(inode_init_always);
---------------------------------------------------------------------
然后返回刚刚创建并初始化的inode对象地址。
b.获得inode锁node_lock。
c.再次在inode缓存中查找对应于inode号的inode对象。若这次找到了,则增加它的引用计数,销毁新分配的inode对象。并返回inode对象地址。
d.依然没有找到。则将inode对象的i_ino设置为inode号ino,调用__inode_add_to_lists(sb, head, inode)函数将inode对象添加进对应的inode哈希表中(inode->i_hash),添加进inode_in_use链表中(inode->i_list)添加进super_block的所有inode链表中(inode->i_sb_list、sb->s_inodes)。
e.设置inode的i_state字段为I_NEW。
f.释放inode锁inode_lock
g.返回新创建的inode对象地址。