JFFS2 uses jffs2_lookup() to determinate the inode number of the file by its name. If the jffs2_lookup() finds the inode then iget() it. iget() calls jffs2_read_inode() to read the inode. jffs2_read_inode() gets the inode info and the sb info from the inode parameter. Then initializes the inode info and calls jffs2_do_read_inode() to fill up the structures. jffs2_do_read_inode() asks for the inodecache of the inode by jffs2_get_ino_cache() If it has inode cache then it can do three different cases depending on the status of the inode cache.
The state of the inode cache is:
- INO_STATE_UNCHECKED, INO_STATE_CHECKEDABSENT: modifies the state of the node to INO_STATE_READING and continues the operating.
- INO_STATE_CHECKING, INO_STATE_GC: it must wait (sleep_on_spinunlock) because somebody holds the ic lock and uses this inode.
- INO_STATE_READING, INO_STATE_PRESENT: error occurred because this shouldn't happen. In inode info the inocache pointer is setted to NULL.
If it hasn't got inode cache and the inode number is 1 which is the root node then it allocates a new one for it and sets the parameters (ino, nodes, state). Then adds the inode cache to the inode cache list.
If it hasn't got inocache yet then returns with error otherwise it returns with the return value of the called jffs2_do_read_inode_internal().
jffs2_do_read_inode_internal() gets all the relevant nodes of this inode by calling
jffs2_get_inode_nodes(). jffs2_get_inode_nodes() allocates a buffer where the nodes can be loaded. It walks through the inode's next_in_ino list and if the current raw reference is valid then it reads it.
If the type of the read node is:
- JFFS2_NODETYPE_DIRENT then read_direntry() is called. read_direntry() allocates a new full_dirent and fills in its parameters (raw, version, ino, type, nhash, next, name). It adds the new full_dirent to the fd list, if necessary, it sets the mctime_ver and latest_mctime function parameters and returns.
- JFFS2_NODETYPE_INODE then read_dnode() is called. read_dnode() allocates a new tmp_dnode_info (tn) for the node and checks the nodes data CRC on case of NAND flash. Then it allocates a full_dnode (fd) pointed by the
tn->fd
pointer and fills the fields of both structures and adds the tn to the red-black tree pointed by the incoming pointer parameter tnp.
- everything else then read_unknown() is called. read_unknown() checks the header CRC of the node. If it's wrong then JFFS2 drops a notice about it and returns. If the CRC is good then checks the nodetype in the view of COMPAT mask.
- JFFS2_FEATURE_INCOMPAT: drops a notice about it and calls BUG().
- JFFS2_FEATURE_ROCOMPAT: drops a notice about it and if the fs is mounted as rw then BUG() id called.
- JFFS2_FEATURE_RWCOMPAT_COPY: drops a notice about it.
- JFFS2_FEATURE_RWCOMPAT_DELETE: drops a notice about it and returns with 1. It means that this node will be marked as obsolete.
jffs2_get_inode_nodes() returns. If the node is a data node then it builds up the fragtree of the inode in inode info and frees the jffs2_tmp_dnode_info structures during the fragtree building. It sets the inode info dents pointer equal to fd_list (fd_list is a pointer parameter of jffs2_get_inode_nodes() and if the node was a directory inode then its children are listed in fd_list.
Then it reads the latest node, checks its CRC and does some modification on structures depending on the type of the node (truncate fragtree, modify mctime, ...). If the state field of the inode cache of the inode is INO_STATE_READING then it sets the status to INO_STATE_PRESENT. And finally it returns.
If jffs2_do_read_inode() returns with error then marks the inode bad and returns, otherwise the inode structure are actualized by the values of the latest_node (mode, uid, gid, etc.). The operations of the inode (inode, file, mapping) are set dependings on the mode of the inode.
Havasi Ferenc
2005-12-22