一. tnode的分配
1.结构体及初始化过程说明
-
struct yaffs_allocator {
-
int n_tnodes_created;
-
struct yaffs_tnode *free_tnodes; //指向空闲的tnode结点;如果不存在空闲的tnode则为空;可以把free_tnodes理解为空闲链表的头
-
int n_free_tnodes; //空闲的tnode数目
-
struct yaffs_tnode_list *alloc_tnode_list;
-
-
int n_obj_created;
-
struct list_head free_objs;
-
int n_free_objects;
-
-
struct yaffs_obj_list *allocated_obj_list;
-
};
在初始化时将free_tnodes设为NULL
-
static void yaffs_init_raw_tnodes(struct yaffs_dev *dev)
-
{
-
struct yaffs_allocator *allocator = dev->allocator;
-
allocator->alloc_tnode_list = NULL;
-
allocator->free_tnodes = NULL; //指向空闲的tnode结点;如果不存在空闲的tnode则为空
-
allocator->n_free_tnodes = 0; //空闲的tnodes数目为0
-
allocator->n_tnodes_created = 0; //己创建的tnodes数止为0
-
}
刚开始时free_node=NULL
就调用yaffs_create_tnodes分配100个新的tnode, 此时free_node指向刚分配的tnode
1.0 获取一个tnode,并初始化
-
struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev)
-
{
-
struct yaffs_tnode *tn = yaffs_alloc_raw_tnode(dev); //从tnode_tree中分配一个tnode
-
if (tn) {
-
memset(tn, 0, dev->tnode_size); //将tnode中的内容初始化为0
-
dev->n_tnodes++; //dev中己分配的tnodes顺次加1
-
}
-
dev->checkpoint_blocks_required = 0; /* force recalculation */
-
return tn;
-
}
1.1 分配或者取出一个空闲的tnode
yaffs_get_tnode
-->
yaffs_alloc_raw_tnode
-
struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev)
-
{
-
struct yaffs_allocator *allocator = (struct yaffs_allocator *)dev->allocator;
-
struct yaffs_tnode *tn = NULL;
-
if (!allocator->free_tnodes) //如果allocator->free_tnodes为空,说明没有空闲的tnode了,就重新分配100个tnode
-
yaffs_create_tnodes(dev, YAFFS_ALLOCATION_NTNODES); // YAFFS_ALLOCATION_NTNODES=100
-
-
if (allocator->free_tnodes) { //如果allocator->free_tnodes为空存在空闲的tnode
-
tn = allocator->free_tnodes; //把当前空闲的tnode返回
-
allocator->free_tnodes = allocator->free_tnodes->internal[0]; //allocator->free_tnodes指向下一个空闲的tnode
-
allocator->n_free_tnodes--; //空闲的tnode计数减少1
-
}
-
-
return tn;
-
}
1.2 分配n_tnodes个tnodes
yaffs_get_tnode
-->
yaffs_alloc_raw_tnode
-->
yaffs_create_tnodes
-
static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes)
-
{
-
struct yaffs_allocator *allocator = (struct yaffs_allocator *)dev->allocator;
-
int i;
-
struct yaffs_tnode *new_tnodes;
-
u8 *mem;
-
struct yaffs_tnode *curr;
-
struct yaffs_tnode *next;
-
struct yaffs_tnode_list *tnl;
-
if (n_tnodes < 1)
-
return YAFFS_OK;
-
-
/* make these things */
-
new_tnodes = kmalloc(n_tnodes * dev->tnode_size, GFP_NOFS); //申请n_tnodes个tnode的内存空间
-
mem = (u8 *) new_tnodes;
-
-
/* New hookup for wide tnodes */
-
for (i = 0; i < n_tnodes - 1; i++) { //初始化tnodes链表
-
curr = (struct yaffs_tnode *)&mem[i * dev->tnode_size]; //其中internal[0]指向下一个tnodes
-
next = (struct yaffs_tnode *)&mem[(i + 1) * dev->tnode_size]; //最后一个tnodes的internal[0]指向空
-
curr->internal[0] = next;
-
}
-
-
curr = (struct yaffs_tnode *)&mem[(n_tnodes - 1) * dev->tnode_size];
-
curr->internal[0] = allocator->free_tnodes; //因为此时free_tnodes=NULL(不为NULL,不会调用此分配函数),所以该链表以NULL结尾
-
allocator->free_tnodes = (struct yaffs_tnode *)mem; //allocator->free_tnodes指向刚分配的100个tnode的首地址
-
-
allocator->n_free_tnodes += n_tnodes;
-
allocator->n_tnodes_created += n_tnodes;
-
-
/* Now add this bunch of tnodes to a list for freeing up.
-
* NB If we can't add this to the management list it isn't fatal
-
* but it just means we can't free this bunch of tnodes later.
-
*/
-
tnl = kmalloc(sizeof(struct yaffs_tnode_list), GFP_NOFS);
-
if (!tnl) {
-
yaffs_trace();
-
return YAFFS_FAIL;
-
} else {
-
tnl->tnodes = new_tnodes;
-
tnl->next = allocator->alloc_tnode_list;
-
allocator->alloc_tnode_list = tnl;
-
}
-
return YAFFS_OK;
-
}
特别注意: 上述在初始化tnodes链表时, 并不是
dev->tnode_size=40,而sizeof(sturct yaffs_tnode)=32,所以kmalloc(n_tnodes * dev->tnode_size, GFP_NOFS)中分配的内存的使用并不是连续的.
所以,以后会看到tnode在level1时是8个,而到了level0时却变成了16个
二. tnode的释放
2.
-
static void yaffs_free_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
-
{
-
yaffs_free_raw_tnode(dev, tn);
-
dev->n_tnodes--; //dev中己分配的tnodes减1
-
dev->checkpoint_blocks_required = 0; /* force recalculation */
-
}
2.1
yaffs_free_tnode
--> yaffs_free_raw_tnode
-
void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
-
{
-
struct yaffs_allocator *allocator = dev->allocator;
-
if (tn) {
-
tn->internal[0] = allocator->free_tnodes; //链表操作:将这个tnode插入到free_tnodes中
-
allocator->free_tnodes = tn;
-
allocator->n_free_tnodes++;
-
}
-
dev->checkpoint_blocks_required = 0; /* force recalculation */
-
}
三. tnode的使用
3. yaffs_dev结构体中几个变量说明一下:
-
struct yaffs_dev {
-
u16 chunk_grp_bits;
-
u16 chunk_grp_size;
-
u32 tnode_width; //总的chunk需要多少位才能表示出来(20位)
-
u32 tnode_mask; //
-
u32 tnode_size; //一个tnode占的字节数(40B)
-
}
tnode_width=20,
tnode_size=40,
chunk_grp_bits=0,
chunk_grp_size=1;
tnode_mask = (1 << 20) - 1;
3.1 tnode_width的由来
要想理解tnode是如何使用的,需要首先弄清楚tnod_width是个什么东东.
yaffs文件系统在初始化时会调用yaffs_guts_initialise.
-
int yaffs_guts_initialise(struct yaffs_dev *dev)
-
{
-
// chunks_per_block=128, internal_end_block=4084, x=0x7fa80, bits=19
-
x = dev->param.chunks_per_block * (dev->internal_end_block + 1); //计算整个nand_flash上的chunk数=0x7FA80: 每个block有128个chunk:
-
-
bits = calc_shifts_ceiling(x); //总chunk需要多少位才能表示0x7FA80(19bit)
-
/* Set up tnode width if wide tnodes are enabled. */
-
if (!dev->param.wide_tnodes_disabled) {
-
/* bits must be even so that we end up with 32-bit words */
-
if (bits & 1) //为了能扩展成32bits,需要变成偶数,现在bits=20
-
bits++;
-
if (bits < 16)
-
dev->tnode_width = 16;
-
else
-
dev->tnode_width = bits; //所以dev->tnode_width=20
-
} else {
-
dev->tnode_width = 16;
-
}
-
-
dev->tnode_mask = (1 << dev->tnode_width) - 1;
-
-
if (bits <= dev->tnode_width) // tnode还可以分组?不过这里没有用到
-
dev->chunk_grp_bits = 0; // dev->chunk_grp_bits = 0;
-
else
-
dev->chunk_grp_bits = bits - dev->tnode_width;
-
-
dev->tnode_size = (dev->tnode_width * YAFFS_NTNODES_LEVEL0) / 8; //表示一个chunk要占20位, LEVEL0有16个tnode,所以需要的字节数为tnode_size=40B
-
if (dev->tnode_size < sizeof(struct yaffs_tnode)) //dev->tnode_size=40, sizeof(struct yaffs_tnode)=32
-
dev->tnode_size = sizeof(struct yaffs_tnode);
-
-
dev->chunk_grp_size = 1 << dev->chunk_grp_bits; //chunk_grp_size=1
-
}
3.2 tnode赋值
对level0的tnode进行赋值: 一个tnode可以表示16个chunk, pos是在tnode中的第几项,val是在tnode的第pos项上的值
-
void yaffs_load_tnode_0(struct yaffs_dev *dev, struct yaffs_tnode *tn, unsigned pos, unsigned val)
-
{
-
u32 *map = (u32 *) tn;
-
u32 bit_in_map;
-
u32 bit_in_word;
-
u32 word_in_map;
-
u32 mask;
-
-
pos &= YAFFS_TNODES_LEVEL0_MASK; //pos不能超过16
-
val >>= dev->chunk_grp_bits;
-
-
bit_in_map = pos * dev->tnode_width; //当前要写的位置(单位bit)
-
word_in_map = bit_in_map / 32; //当前要写的位置在u32上的偏移(单位bit)
-
bit_in_word = bit_in_map & (32 - 1); //当前要写的位置在第几个u32上
-
-
mask = dev->tnode_mask << bit_in_word;
-
-
map[word_in_map] &= ~mask;
-
map[word_in_map] |= (mask & (val << bit_in_word));
-
-
//如果当前位置再写20位超出了一个u32的表示范围,就要写在下一个u32上
-
if (dev->tnode_width > (32 - bit_in_word)) { //这个地方改成: (bit_in_word+dev->tnode_width>32)会好理解一些
-
bit_in_word = (32 - bit_in_word);
-
word_in_map++;
-
mask =
-
dev->tnode_mask >> bit_in_word;
-
map[word_in_map] &= ~mask;
-
map[word_in_map] |= (mask & (val >> bit_in_word));
-
}
-
}
举例说明一下:
tnode是40Byte,用u32表示是: u32[0-9]
假设pos=0,直接把val写在tnode的u32_0的[0-19]位上
假设pos=1,把val写在tnode的u32_0的[20-32]位上,还剩8位怎么办?写在u32_1的[0-7]位上.
假设pos=2,把val写在tnode的u32_1的[8-27]位上.
假设pos=3,把val写在tnode的u32_1的[28-32]位上,还剩16位怎么办?写在u32t_2的[0-15]位上.
以此类推.
假设pos=3,把val写在u32_9的[12-31]位上,至此40个Byte全部用尽.
3.3 level[1-5]与level0的tnode对比
level[1-5]与level0的tnode使用情况是不一样的
如下图所示:
对于level[1-5] : 只用了32个Byte,剩余的8个Byte未使用
对于level0: 每一位都要用,如果这个tnode的40个Byte连续且可按位访问的话,每22个bit代表了nand_flash上的一个chunk,一个tnode有可表示16个chunk
阅读(3019) | 评论(0) | 转发(2) |