继续接着上一篇博客分析jffs2文件系统的挂载过程。
上一篇博客分析了jffs2_scan_eraseblock函数的扫描过程,函数很长,我们主要抓住扫描的逻辑就好。
对于扫描到的inode节点,jffs2调用函数jffs2_scan_inode_node进行处理,对于扫描到的dirent节点,jffs2调用函数jffs2_scan_dirent_node进行处理。下面主要分析这两个函数。
jffs2_scan_dirent_node函数的任务是校验dirent节点的CRC,然后分配为dirent节点的内核描述符jffs2_full_dirent,在jffs2_full_dirent结构体后面写上该dirent代表的文件的文件名并初始化dirent,并为该dirent的pino创建jffs2_inode_cache描述符,并将jffs2_full_dirent结构实例连接到jffs2_inode_cache的scan_dents链表
static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s)
{
struct jffs2_full_dirent *fd;
struct jffs2_inode_cache *ic;
uint32_t checkedlen;
uint32_t crc;
int err;
jffs2_dbg(1, "%s(): Node at 0x%08x\n", __func__, ofs);
/* We don't get here unless the node is still valid, so we don't have to
mask in the ACCURATE bit any more. */
crc = crc32(0, rd, sizeof(*rd)-8);
if (crc != je32_to_cpu(rd->node_crc)) { //校验节点的crc值
pr_notice("%s(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
__func__, ofs, je32_to_cpu(rd->node_crc), crc);
/* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
return err;
return 0;
}
pseudo_random += je32_to_cpu(rd->version);
/* Should never happen. Did. (OLPC trac #4184)*/
checkedlen = strnlen(rd->name, rd->nsize);
if (checkedlen < rd->nsize) {
pr_err("Dirent at %08x has zeroes in name. Truncating to %d chars\n",
ofs, checkedlen);
}
fd = jffs2_alloc_full_dirent(checkedlen+1);分配dirent加文件名那么大的内存空间
if (!fd) {
return -ENOMEM;
}
memcpy(&fd->name, rd->name, checkedlen);//拷贝文件名
fd->name[checkedlen] = 0;
crc = crc32(0, fd->name, rd->nsize); //校验包括文件名的CRC值
if (crc != je32_to_cpu(rd->name_crc)) {
pr_notice("%s(): Name CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
__func__, ofs, je32_to_cpu(rd->name_crc), crc);
jffs2_dbg(1, "Name for which CRC failed is (now) '%s', ino #%d\n",
fd->name, je32_to_cpu(rd->ino));
jffs2_free_full_dirent(fd);
/* FIXME: Why do we believe totlen? */
/* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */
if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
return err;
return 0;
}
ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino));//为该dirent的pino创建jffs2_inode_cache结构体
if (!ic) {
jffs2_free_full_dirent(fd);
return -ENOMEM;
}
fd->raw = jffs2_link_node_ref(c, jeb, ofs | dirent_node_state(rd),
PAD(je32_to_cpu(rd->totlen)), ic);
//jffs2_full_dirent结构相关成员的赋值操作
fd->next = NULL;
fd->version = je32_to_cpu(rd->version);
fd->ino = je32_to_cpu(rd->ino);
fd->nhash = full_name_hash(fd->name, checkedlen);
fd->type = rd->type;
jffs2_add_fd_to_list(c, fd, &ic->scan_dents);//将jffs2_full_dirent结构实例连接到jffs2_inode_cache的scan_dents链表
if (jffs2_sum_active()) {
jffs2_sum_add_dirent_mem(s, rd, ofs - jeb->offset);
}
return 0;
}
函数jffs2_scan_inode_node的任务是校验节点的crc值,创建jffs2_inode_cache描述符,如果开启了summary功能,则要将相关结构体加入summary节点的链表中
static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s)
{
struct jffs2_inode_cache *ic;
uint32_t crc, ino = je32_to_cpu(ri->ino);
jffs2_dbg(1, "%s(): Node at 0x%08x\n", __func__, ofs);
/* We do very little here now. Just check the ino# to which we should attribute
this node; we can do all the CRC checking etc. later. There's a tradeoff here --
we used to scan the flash once only, reading everything we want from it into
memory, then building all our in-core data structures and freeing the extra
information. Now we allow the first part of the mount to complete a lot quicker,
but we have to go _back_ to the flash in order to finish the CRC checking, etc.
Which means that the _full_ amount of time to get to proper write mode with GC
operational may actually be _longer_ than before. Sucks to be me. */
/* Check the node CRC in any case. */
crc = crc32(0, ri, sizeof(*ri)-8);
if (crc != je32_to_cpu(ri->node_crc)) { //进行crc校验
pr_notice("%s(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
__func__, ofs, je32_to_cpu(ri->node_crc), crc);
/*
* We believe totlen because the CRC on the node
* _header_ was OK, just the node itself failed.
*/
return jffs2_scan_dirty_space(c, jeb,
PAD(je32_to_cpu(ri->totlen)));
}
ic = jffs2_get_ino_cache(c, ino); //获取对应的jffs2_inode_cache,如果为NULL则创建之
if (!ic) {
ic = jffs2_scan_make_ino_cache(c, ino);
if (!ic)
return -ENOMEM;
}
/* Wheee. It worked */
jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic);
jffs2_dbg(1, "Node is ino #%u, version %d. Range 0x%x-0x%x\n",
je32_to_cpu(ri->ino), je32_to_cpu(ri->version),
je32_to_cpu(ri->offset),
je32_to_cpu(ri->offset)+je32_to_cpu(ri->dsize));
pseudo_random += je32_to_cpu(ri->version);
if (jffs2_sum_active()) { //summary相关处理
jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset);
}
return 0;
}