jffs2的目录项查找调用的函数是jffs2_lookup,下面一起看一下这个函数。
/* We keep the dirent list sorted in increasing order of name hash,
and we use the same hash function as the dentries. Makes this
nice and simple
*/
//上面的函数介绍中已经说明了,jffs2将文件夹的目录项按照目录项名的哈希值升序排序,以便于查找
static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
unsigned int flags)
{
struct jffs2_inode_info *dir_f;
struct jffs2_full_dirent *fd = NULL, *fd_list;
uint32_t ino = 0;
struct inode *inode = NULL;
jffs2_dbg(1, "jffs2_lookup()\n");
if (target->d_name.len > JFFS2_MAX_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);
dir_f = JFFS2_INODE_INFO(dir_i); //获取jffs2_inode_info
mutex_lock(&dir_f->sem);//获取锁
/* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
//遍历dents链表
for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) {
if (fd_list->nhash == target->d_name.hash &&
(!fd || fd_list->version > fd->version) &&
strlen(fd_list->name) == target->d_name.len &&
!strncmp(fd_list->name, target->d_name.name, target->d_name.len)) {
fd = fd_list;
}
}
if (fd)//若果找到了相应的jffs2_full_dirent结构体
ino = fd->ino;
mutex_unlock(&dir_f->sem);
if (ino) {
inode = jffs2_iget(dir_i->i_sb, ino);//获取相应inode节点
if (IS_ERR(inode))
pr_warn("iget() failed for ino #%u\n", ino);
}
return d_splice_alias(inode, target);//splice a disconnected dentry into the tree if one exists
}
一开始看这个函数有个疑问,在jffs2的mount过程中,最后不是把相应的full_dirent结构体释放了吗?为什么这里可以直接读呢?
原来,对于ino!=1的目录节点,在jffs2_do_read_inode_internel函数中,jffs2_do_read_inode_internal->jffs2_get_inode_nodes->read_direntry函数已经根据读取到的flash数据,建立了目录文件的目录项的jffs2_full_dirent结构体,并调用函数jffs2_add_fd_to_list把该full_dirent添加进入dents链表里,所以这里jffs2_lookup函数直接查询dents链表即可。
而对于ino==1的节点,在mount过程的最后,jffs2_do_fill_super->jffs2_iget(sb, 1)->jffs2_fo_read_inode函数最终还是会调用read_direntry函数完成full_dirent节点的创建。