Chinaunix首页 | 论坛 | 博客
  • 博客访问: 118730
  • 博文数量: 27
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 85
  • 用 户 组: 普通用户
  • 注册时间: 2014-08-30 13:49
文章分类
文章存档

2017年(3)

2016年(1)

2015年(3)

2014年(20)

我的朋友

分类: LINUX

2014-08-30 13:52:43

一. tnode的分配
1.结构体及初始化过程说明
  1. struct yaffs_allocator {
  2.     int n_tnodes_created;                        
  3.     struct yaffs_tnode *free_tnodes;               //指向空闲的tnode结点;如果不存在空闲的tnode则为空;可以把free_tnodes理解为空闲链表的头
  4.     int n_free_tnodes;                             //空闲的tnode数目
  5.     struct yaffs_tnode_list *alloc_tnode_list;

  6.     int n_obj_created;
  7.     struct list_head free_objs;
  8.     int n_free_objects;

  9.     struct yaffs_obj_list *allocated_obj_list;
  10. };

在初始化时将free_tnodes设为NULL
  1. static void yaffs_init_raw_tnodes(struct yaffs_dev *dev)
  2. {
  3.     struct yaffs_allocator *allocator = dev->allocator;
  4.     allocator->alloc_tnode_list = NULL;
  5.     allocator->free_tnodes = NULL;            //指向空闲的tnode结点;如果不存在空闲的tnode则为空
  6.     allocator->n_free_tnodes = 0;             //空闲的tnodes数目为0  
  7.     allocator->n_tnodes_created = 0;          //己创建的tnodes数止为0
  8. }
刚开始时free_node=NULL

就调用yaffs_create_tnodes分配100个新的tnode, 此时free_node指向刚分配的tnode




1.0 获取一个tnode,并初始化
  1. struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev)
  2. {
  3.     struct yaffs_tnode *tn = yaffs_alloc_raw_tnode(dev);                //从tnode_tree中分配一个tnode
  4.     if (tn) {
  5.         memset(tn, 0, dev->tnode_size);                                 //将tnode中的内容初始化为0
  6.         dev->n_tnodes++;                                                //dev中己分配的tnodes顺次加1
  7.     }
  8.     dev->checkpoint_blocks_required = 0;    /* force recalculation */
  9.     return tn;
  10. }
1.1 分配或者取出一个空闲的tnode
yaffs_get_tnode
    --> yaffs_alloc_raw_tnode
  1. struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev)
  2. {
  3.     struct yaffs_allocator *allocator = (struct yaffs_allocator *)dev->allocator;
  4.     struct yaffs_tnode *tn = NULL;
  5.     if (!allocator->free_tnodes)                                        //如果allocator->free_tnodes为空,说明没有空闲的tnode了,就重新分配100个tnode
  6.         yaffs_create_tnodes(dev, YAFFS_ALLOCATION_NTNODES);             // YAFFS_ALLOCATION_NTNODES=100  

  7.     if (allocator->free_tnodes) {                                       //如果allocator->free_tnodes为空存在空闲的tnode
  8.         tn = allocator->free_tnodes;                                    //把当前空闲的tnode返回
  9.         allocator->free_tnodes = allocator->free_tnodes->internal[0];   //allocator->free_tnodes指向下一个空闲的tnode
  10.         allocator->n_free_tnodes--;                                     //空闲的tnode计数减少1
  11.     }

  12.     return tn;
  13. }
1.2 分配n_tnodes个tnodes
yaffs_get_tnode
    --> yaffs_alloc_raw_tnode
            --> yaffs_create_tnodes

  1. static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes)
  2. {
  3.     struct yaffs_allocator *allocator = (struct yaffs_allocator *)dev->allocator;
  4.     int i;
  5.     struct yaffs_tnode *new_tnodes;
  6.     u8 *mem;
  7.     struct yaffs_tnode *curr;
  8.     struct yaffs_tnode *next;
  9.     struct yaffs_tnode_list *tnl;
  10.     if (n_tnodes < 1)
  11.         return YAFFS_OK;

  12.     /* make these things */
  13.     new_tnodes = kmalloc(n_tnodes * dev->tnode_size, GFP_NOFS);            //申请n_tnodes个tnode的内存空间
  14.     mem = (u8 *) new_tnodes;

  15.     /* New hookup for wide tnodes */
  16.     for (i = 0; i < n_tnodes - 1; i++) {                                    //初始化tnodes链表        
  17.         curr = (struct yaffs_tnode *)&mem[i * dev->tnode_size];             //其中internal[0]指向下一个tnodes
  18.         next = (struct yaffs_tnode *)&mem[(i + 1) * dev->tnode_size];       //最后一个tnodes的internal[0]指向空
  19.         curr->internal[0] = next;
  20.     }

  21.     curr = (struct yaffs_tnode *)&mem[(n_tnodes - 1) * dev->tnode_size];
  22.     curr->internal[0] = allocator->free_tnodes;                              //因为此时free_tnodes=NULL(不为NULL,不会调用此分配函数),所以该链表以NULL结尾
  23.     allocator->free_tnodes = (struct yaffs_tnode *)mem;                      //allocator->free_tnodes指向刚分配的100个tnode的首地址

  24.     allocator->n_free_tnodes += n_tnodes;
  25.     allocator->n_tnodes_created += n_tnodes;

  26.     /* Now add this bunch of tnodes to a list for freeing up.
  27.      * NB If we can't add this to the management list it isn't fatal
  28.      * but it just means we can't free this bunch of tnodes later.
  29.      */
  30.     tnl = kmalloc(sizeof(struct yaffs_tnode_list), GFP_NOFS);
  31.     if (!tnl) {
  32.         yaffs_trace();
  33.         return YAFFS_FAIL;
  34.     } else {
  35.         tnl->tnodes = new_tnodes;
  36.         tnl->next = allocator->alloc_tnode_list;
  37.         allocator->alloc_tnode_list = tnl;
  38.     }
  39.     return YAFFS_OK;
  40. }
特别注意: 上述在初始化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.
  1. static void yaffs_free_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
  2. {
  3.     yaffs_free_raw_tnode(dev, tn);
  4.     dev->n_tnodes--;                          //dev中己分配的tnodes减1
  5.     dev->checkpoint_blocks_required = 0;    /* force recalculation */
  6. }
2.1
yaffs_free_tnode
    --> yaffs_free_raw_tnode
  1. void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
  2. {
  3.     struct yaffs_allocator *allocator = dev->allocator;
  4.     if (tn) {
  5.         tn->internal[0] = allocator->free_tnodes;     //链表操作:将这个tnode插入到free_tnodes中
  6.         allocator->free_tnodes = tn;
  7.         allocator->n_free_tnodes++;
  8.     }
  9.     dev->checkpoint_blocks_required = 0;    /* force recalculation */
  10. }


三. tnode的使用
3.  yaffs_dev结构体中几个变量说明一下:
  1. struct yaffs_dev {
  2.     u16 chunk_grp_bits;   
  3.     u16 chunk_grp_size;   
  4.     u32 tnode_width;      //总的chunk需要多少位才能表示出来(20位)                
  5.     u32 tnode_mask;       //
  6.     u32 tnode_size;       //一个tnode占的字节数(40B)
  7. }
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.
  1. int yaffs_guts_initialise(struct yaffs_dev *dev)
  2. {
  3.     // chunks_per_block=128, internal_end_block=4084, x=0x7fa80, bits=19    
  4.     x = dev->param.chunks_per_block * (dev->internal_end_block + 1);     //计算整个nand_flash上的chunk数=0x7FA80: 每个block有128个chunk:

  5.     bits = calc_shifts_ceiling(x);                                       //总chunk需要多少位才能表示0x7FA80(19bit)
  6.     /* Set up tnode width if wide tnodes are enabled. */
  7.     if (!dev->param.wide_tnodes_disabled) {
  8.         /* bits must be even so that we end up with 32-bit words */
  9.         if (bits & 1)                                                   //为了能扩展成32bits,需要变成偶数,现在bits=20
  10.             bits++;
  11.         if (bits < 16)
  12.             dev->tnode_width = 16;
  13.         else
  14.             dev->tnode_width = bits;                                    //所以dev->tnode_width=20
  15.     } else {
  16.         dev->tnode_width = 16;
  17.     }

  18.     dev->tnode_mask = (1 << dev->tnode_width) - 1;

  19.     if (bits <= dev->tnode_width)                                       // tnode还可以分组?不过这里没有用到
  20.         dev->chunk_grp_bits = 0;                                        // dev->chunk_grp_bits = 0;
  21.     else
  22.         dev->chunk_grp_bits = bits - dev->tnode_width;

  23.     dev->tnode_size = (dev->tnode_width * YAFFS_NTNODES_LEVEL0) / 8;    //表示一个chunk要占20位, LEVEL0有16个tnode,所以需要的字节数为tnode_size=40B
  24.     if (dev->tnode_size < sizeof(struct yaffs_tnode))                   //dev->tnode_size=40, sizeof(struct yaffs_tnode)=32
  25.         dev->tnode_size = sizeof(struct yaffs_tnode);

  26.     dev->chunk_grp_size = 1 << dev->chunk_grp_bits;                    //chunk_grp_size=1
  27. }
3.2 tnode赋值
对level0的tnode进行赋值: 一个tnode可以表示16个chunk, pos是在tnode中的第几项,val是在tnode的第pos项上的值
  1. void yaffs_load_tnode_0(struct yaffs_dev *dev, struct yaffs_tnode *tn, unsigned pos, unsigned val)
  2. {
  3.     u32 *map = (u32 *) tn;
  4.     u32 bit_in_map;            
  5.     u32 bit_in_word;           
  6.     u32 word_in_map;           
  7.     u32 mask;

  8.     pos &= YAFFS_TNODES_LEVEL0_MASK;            //pos不能超过16
  9.     val >>= dev->chunk_grp_bits;

  10.     bit_in_map = pos * dev->tnode_width;          //当前要写的位置(单位bit)   
  11.     word_in_map = bit_in_map / 32;                //当前要写的位置在u32上的偏移(单位bit)
  12.     bit_in_word = bit_in_map & (32 - 1);          //当前要写的位置在第几个u32上

  13.     mask = dev->tnode_mask << bit_in_word;

  14.     map[word_in_map] &= ~mask;
  15.     map[word_in_map] |= (mask & (val << bit_in_word));
  16.    
  17.     //如果当前位置再写20位超出了一个u32的表示范围,就要写在下一个u32上
  18.     if (dev->tnode_width > (32 - bit_in_word)) {                //这个地方改成: (bit_in_word+dev->tnode_width>32)会好理解一些
  19.         bit_in_word = (32 - bit_in_word);
  20.         word_in_map++;
  21.         mask =
  22.          dev->tnode_mask >> bit_in_word;
  23.         map[word_in_map] &= ~mask;
  24.         map[word_in_map] |= (mask & (val >> bit_in_word));
  25.     }
  26. }
举例说明一下:
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

阅读(1369) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~