YAFFS Development Notes (read notes)
时间:2009-04-03 来源:hylpro
2009.3.26YAFFS Development Notes
Yaffs可以编译成内核模块,开发过程可以用RAM模拟NAND, 或者编译成应用程序测试yaffs_guts.YAFFS对MTD的接口叫 yaffs, 到RAM的接口叫yaffsram. 编译使用步骤如下:
YAFFS Data structures都在yaffs_guts.h, 主要结构:
Tnodes , Objects 会批量分配然后存储于有一个free list以便高效率重用. 下图是YAFFs在文件系统所处地位.
yaffs_Objectstruct yaffs_ObjectStruct { __u8 fake:1; // A fake object has no presence on NAND. __u8 renameAllowed:1; // Are we allowed to rename it? __u8 unlinkAllowed:1; // Are we allowed to unlink it? __u8 dirty:1; // the object needs to be written to flash __u8 valid:1; // When the file system is being loaded up, this object might be created before the data is available (ie. file data records appear before the header). __u8 serial; // serial number of chunk in NAND. Store here so we don't have to read back the old one to update. __u16 sum; // sum of the name to speed searching struct yaffs_DeviceStruct *myDev; // The device I'm on struct list_head hashLink; // list of objects in this hash bucket
struct list_head hardLinks; // all the equivalent hard linked objects live on this list
// directory structure stuff struct yaffs_ObjectStruct *parent; //my parent directory struct list_head siblings; // siblings in a directory also used for linking up the free list
// Where's my data in NAND? int chunkId; // where it lives __u32 objectId; // the object id value __u32 st_mode; // protection __u32 st_uid; // user ID of owner __u32 st_gid; // group ID of owner __u32 st_atime; // time of last access __u32 st_mtime; // time of last modification __u32 st_ctime; // time of last change
yaffs_ObjectType variantType; yaffs_ObjectVariant variant; };
fake, renameAllowed, unlinkAllowed 是处理"fake"类型的objects 使用的: fake的是指不在NAND上实际存在的obj, YAFFS只有root 和lost+found 是这种fake类型, 都不能重命名或者unlinked.
有四个变种yaffs_Object: Files : 文件大小和tnode tree. Directories: 一个children obj的列表. Symlinks: 指向一个路径字符串. Hardlinks: hold information to identify the equivalent object.
File structure (tnodes)
一个分层索引,用于track所有属于此文件的chunkID. (图遗失,但不难理解..)
文件创建时, 只有一个最低层的tnode, 随着文件扩张, 超过一个tnode容量时,就分配另一个tnode,同时一个internal node 也加入进来指向这两个tnodes. 遍历tnode树也很简单: 每个中间层的tnode使用3bit的page id索引(page id为文件内偏移). 最低层, 即level 0, 用4bits. 比如找文件偏移为page 0x235的chunkID: 0x235 就是0000001000110101, 分割: 000.000.100.011.0101, 参考下表: Level Bits Selected value
tnode 的消耗量: 16M的文件系统约要: 16M/512/16=2000个level 0,和一些内部tnode. 至少64k了. NAND data数据是存在NAND的"chunks"内. yaffs(不是yaffs2)采用512byte+16byte spare大小的chunk. Chunks 数据类型有:
16 byte spare area包含:
typedef struct { unsigned chunkId:20; //chunk number in file, 0代表是yaffs_ObjectHeader,非零是文件数据 unsigned serialNumber:2; //serial number for chunk unsigned byteCount:10; //number of bytes of data used in this chunk,仅对数据有效 unsigned objectId:18; //the object id that this chunk belongs to. unsigned ecc:12; //ECC on tags unsigned unusedStuff:2; //unused } yaffs_Tags;
非零chunkID代表是文件数据, ID是其在文件内的以chunk为单位的偏移. offset 0的chunkID 是1.参考yaffs_guts.c -> yaffs_Scan.
当一个chunk内数据要被替换时, (如,文件信息改变,或者文件数据被覆盖), 采用写一个新chunk的方式,写完新的chunk才会删除老的.这样照顾到断电/crash.为了区分同时存在两个相同chunkID的情况,需要serialNumber.
yaffs_ObjectHeadertypedef struct { yaffs_ObjectType type; //file,directory,hardlink or symlink
// Apply to everything int parentObjectId;
__u16 sum; // checksum of name, speed up name lookup char name[YAFFS_MAX_NAME_LENGTH + 1];
// Thes following apply to directories, files, symlinks - not hard links __u32 st_mode; // protection __u32 st_uid; // user ID of owner __u32 st_gid; // group ID of owner __u32 st_atime; // time of last access __u32 st_mtime; // time of last modification __u32 st_ctime; // time of last change // File size applies to files only int fileSize; // Equivalent object id applies to hard links only. int equivalentObjectId; // alias only applies to symlinks
char alias[YAFFS_MAX_ALIAS_LENGTH + 1]; /*长度有点小*/ } yaffs_ObjectHeader;
每个NAND内的yaffs_Object都对应存储一个yaffs_ObjectHeader.
equivalentObjectId : 用于hardlinks. hardlink 使用这个域指定链接到的objectID. 这和linux有所不同,比如ext2是用dir entry来制作hard link的, 而yaffs用他自己的inode来hard link.
NAND Interface所有访问 NAND 的操作都是通过yaffs_Device内的四个函数指针实现的.此时的 chunk 就是一个 page.
当data 或者 spare 指针为NULL是, 对应RW被忽略. NAND的相关知识:
mkyaffsmkyaffs 的操作就是擦除所有非坏块. YAFFS 定义擦除的块就是free的. |