Linux内核---28.yaffs2的垃圾回收机制

一. 垃圾回收Garbage collection
为什么需要垃圾回收机制呢?
As we have shown so far, when a block is made up only of deleted chunks, that block can be erased and reused. However, 
consider what will happen if we have many blocks which each have a few current chunks in them. Clearly we cannot erase 
any of the current blocks or we will destroy data. What we need to do is copy the useful data chunks off a block, deleting 
the originals and allowing the block to be erased and reused. This process is referred to as garbage collection.    
当一个block中全部是己删除的chunk时,这个block是可以擦除并继续使用的.
但是当有很多block上面都有很小一部分chunk被使用时,就不能够擦除任何一个block,否则就会破坏数据.
我们需要做的就是从这些block中把数据copy出来,并把这个block擦除.  这个过程就叫做垃圾回收

yaffs2文件系统在挂载的时候会创建一个内核线程来进行gc 
  1. yaffs2_internal_read_super_mtd
  2. {
  3.     err = yaffs_guts_initialise(dev);
  4.     if (err == YAFFS_OK)
  5.        yaffs_bg_start(dev);  //就是这个家伙
  6. }

yaffs_bg_start会创建一个内核线程来进行垃圾回收
  1. static int yaffs_bg_start(struct yaffs_dev *dev)
  2. {
  3.     int retval = 0;
  4.     struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);

  5.     if (dev->read_only)
  6.         return -1;

  7.     context->bg_running = 1;
  8.                                 //创建线程并立即运行
  9.     context->bg_thread = kthread_run(yaffs_bg_thread_fn, (void *)dev, "yaffs-bg-%d", context->mount_id);        

  10.     if (IS_ERR(context->bg_thread)) {
  11.         retval = PTR_ERR(context->bg_thread);
  12.         context->bg_thread = NULL;
  13.         context->bg_running = 0;
  14.     }
  15.     return retval;
  16. }
注: kthread_create:  只是创建线程, 线程并不会立即运行 ; 线程名可以像printk一样传入
        kthread_run:  只是创建线程,线程会立即运行; 线程名可以像printk一样传入 
        kthread_stop:     线程启动后不会停止, 除非调用kthread_should_stop或者kthread_stop
1. 线程完成垃圾回收
垃圾回收并不是每一个固定的时间间隔都会进行一次GC,如果NAND_FLASH只有几个block就没有必要进行gc,
而是判断当前文件系统的使用情况,跟据文件系统的使用情况制定合适的时间间隔去进行垃圾回收.

  1. static int yaffs_bg_thread_fn(void *data)
  2. {
  3.     struct yaffs_dev *dev = (struct yaffs_dev *)data;
  4.     struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
  5.     unsigned long now = jiffies;
  6.     unsigned long next_dir_update = now;
  7.     unsigned long next_gc = now;                         //下一次垃圾回收的时间
  8.     unsigned long expires;
  9.     unsigned int urgency;

  10.     int gc_result;
  11.     struct timer_list timer;
  12.     set_freezable();
  13.     while (context->bg_running) {
  14.         if (kthread_should_stop())
  15.             break;

  16.         if (try_to_freeze())
  17.             continue;

  18.         yaffs_gross_lock(dev);

  19.         now = jiffies;

  20.         if (time_after(now, next_dir_update) && yaffs_bg_enable) {
  21.             yaffs_update_dirty_dirs(dev);                             //1. 
  22.             next_dir_update = now + HZ;
  23.         }
  24.         
  25.         if (time_after(now, next_gc) && yaffs_bg_enable) {
  26.             if (!dev->is_checkpointed) {
  27.                 urgency = yaffs_bg_gc_urgency(dev);                    //2. 如果很多block上都只有一小部分chunk被分配,那么就需要进行gc
  28.                 gc_result = yaffs_bg_gc(dev, urgency);                 //3. 进行垃圾回收                                    
  29.                 if (urgency > 1)
  30.                     next_gc = now + HZ / 20 + 1;                       //根据urgency的紧急级别,制定下一次gc的时间间隔(注)
  31.                 else if (urgency > 0)
  32.                     next_gc = now + HZ / 10 + 1;
  33.                 else
  34.                     next_gc = now + HZ * 2;
  35.             } else {            
  36.                 next_gc = next_dir_update;
  37.                 }
  38.         }
  39.         yaffs_gross_unlock(dev);

  40.         expires = next_dir_update;
  41.         if (time_before(next_gc, expires))
  42.             expires = next_gc;
  43.         if (time_before(expires, now))
  44.             expires = now + HZ;

  45.         Y_INIT_TIMER(&timer);
  46.         timer.expires = expires + 1;
  47.         timer.data = (unsigned long)current;
  48.         timer.function = yaffs_background_waker;

  49.         set_current_state(TASK_INTERRUPTIBLE);
  50.         add_timer(&timer);
  51.         schedule();
  52.         del_timer_sync(&timer);
  53.     }

  54.     return 0;
  55. }
注: urgency  =  yaffs_bg_gc_urgency ( dev ) ;  返回值urgency可取0  1   2
即gc 有三个紧急级别, 
        2最紧急next_gc  =  now  +  HZ  /  20  +  1 , 只要间隔 HZ / 20 + 1就需要gc一次
        1中度紧急next_gc  =  now  +  HZ  /  10  +  1 , 只要间隔 HZ / 1+ 1就需要gc一次
        0不紧急next_gc  =  now  +  HZ * 2 , 间隔 2*HZ才需要gc一次 Garbage collection
1.1 如果dir有改动,需要先更新dir
  1. void yaffs_update_dirty_dirs(struct yaffs_dev *dev)
  2. {
  3.     struct list_head *link;
  4.     struct yaffs_obj *obj;
  5.     struct yaffs_dir_var *d_s;
  6.     union yaffs_obj_var *o_v;

  7.     while (!list_empty(&dev->dirty_dirs)) {                        //dirty_dirs是带头结点的双链表
  8.         link = dev->dirty_dirs.next;
  9.         list_del_init(link);                                        //在双链表中删除结点
  10.         d_s = list_entry(link, struct yaffs_dir_var, dirty);
  11.         o_v = list_entry(d_s, union yaffs_obj_var, dir_variant);
  12.         obj = list_entry(o_v, struct yaffs_obj, variant);            //由list_head找到yaffs_obj真不容易啊

  13.         if (obj->dirty)
  14.             yaffs_update_oh(obj, NULL, 0, 0, 0, NULL);              //更新yaffs_obj
  15.     }
  16. }

1.2 完全是0xFF的block上的chunk 与  设备上空闲的chunk进行比较,查看进行gc的缓重程度
if we have many blocks which each have a few current chunks in them, then it needs Garbage collection
  1. static unsigned yaffs_bg_gc_urgency(struct yaffs_dev *dev)
  2. {
  3.     unsigned erased_chunks = dev->n_erased_blocks * dev->param.chunks_per_block;        //己擦除的block上面有多少个chunk,只有当这个block全是0xff是才可以n_erased_block++
  4.     struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
  5.     unsigned scattered = 0;    /* Free chunks not in an erased block */
  6.     
  7.     //完全是0xFF的block上的chunk 与 设备上空闲的chunk 的差值是scattered=己分配的block上空闲的chunk数
  8.     if (erased_chunks < dev->n_free_chunks)                      //设备上还有多少个可分配的chunk
  9.         scattered = (dev->n_free_chunks - erased_chunks);

  10.     if (!context->bg_running)
  11.         return 0;
  12.     else if (scattered < (dev->param.chunks_per_block * 2))     //差值 小于 2个block上的chunk数urgency=0
  13.         return 0;
  14.     else if (erased_chunks > dev->n_free_chunks / 2)            //完全是0xFF的block上的chunk数 大于 所有空闲chunk的一半urgency=0        
  15.         return 0;
  16.     else if (erased_chunks > dev->n_free_chunks / 4)            //完全是0xFF的block上的chunk数 在 所有空闲chunk的[1/4 --- 1/2] 之间, urgency=1
  17.         return 1;
  18.     else                        //差值 大于 2个block上的chunk数 或者 完全是0xFF的block上的chunk数 在 所有空闲chunk的[0 --- 1/4] 之间, urgency=2
  19.         return 2;               
  20. }
  注意两个变量的理解:  erased_chunksn_free_chunks
     n_erased_blocks:  己被擦除的block,假设这个block上面分配了一个chunk,那么n_erase_blocks--
    erased_chunks:  己被擦除的block上有多少个chunk, 假设这个block上面一个chunk都没有分配,才可以称是己被擦除的block
    n_free_chunks :  设备上所有的空闲chunk, 


1.3 后台运行gc
yaffs_bg_thread_fn
    --> yaffs_bg_gc
  1. int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency)
  2. {
  3.     int erased_chunks = dev->n_erased_blocks * dev->param.chunks_per_block;
  4.     yaffs_check_gc(dev, 1);                               //后台运行
  5.     return erased_chunks > dev->n_free_chunks / 2;
  6. }
进入gc的处理函数
yaffs_bg_thread_fn
    --> yaffs_bg_gc  (background=1)
            --> yaffs_check_gc
  1. static int yaffs_check_gc(struct yaffs_dev *dev, int background)
  2. {
  3.     int aggressive = 0;
  4.     int gc_ok = YAFFS_OK;
  5.     int max_tries = 0;
  6.     int min_erased;
  7.     int erased_chunks;
  8.     int checkpt_block_adjust;

  9.     if (dev->param.gc_control && (dev->param.gc_control(dev) & 1) == 0)
  10.         return YAFFS_OK;

  11.     if (dev->gc_disable)
  12.         return YAFFS_OK;
  13.     do {
  14.         max_tries++;

  15.         checkpt_block_adjust = yaffs_calc_checkpt_blocks_required(dev);              //checkpt所占用的block数                   

  16.         min_erased = dev->param.n_reserved_blocks + checkpt_block_adjust + 1;        //小未使用的block数=保留的block数+ checkpt占用的block数+1
  17.         erased_chunks = dev->n_erased_blocks * dev->param.chunks_per_block;          //完全是0xFF的block上的chunk
  18.         
  19.         if (dev->n_erased_blocks < min_erased)                                  //如果己擦除的block比最小未使用的block数还要小
  20.             aggressive = 1;                                                     //就需要进行aggressive GC   
  21.         else {
  22.             if (!background && erased_chunks > (dev->n_free_chunks / 4))           //此处background=1
  23.                 break;

  24.             if (dev->gc_skip > 20)
  25.                 dev->gc_skip = 20;
  26.             if (erased_chunks < dev->n_free_chunks / 2 || dev->gc_skip < 1 || background)
  27.                 aggressive = 0;
  28.             else {
  29.                 dev->gc_skip--;
  30.                 break;
  31.             }
  32.         }

  33.         dev->gc_skip = 5;
  34.         //dev->gc_block: 需要回收的块的块号
  35.         if (dev->gc_block < 1 && !aggressive) {                                  //dev->gc_block<1表示还没有需要回收的块的块号, 并且当前状态是非紧急情况下                            
  36.             dev->gc_block = yaffs2_find_refresh_block(dev);                      //1.那么就需要find一个   
  37.             dev->gc_chunk = 0;
  38.             dev->n_clean_ups = 0;
  39.         }
  40.         if (dev->gc_block < 1) {                                                     //如果yaffs2_find_refresh_block没有找到合适的block
  41.             dev->gc_block = yaffs_find_gc_block(dev, aggressive, background);        //2.       
  42.             dev->gc_chunk = 0;
  43.             dev->n_clean_ups = 0;
  44.         }

  45.         if (dev->gc_block > 0) {
  46.             dev->all_gcs++;
  47.             if (!aggressive)
  48.                 dev->passive_gc_count++;
  49.             gc_ok = yaffs_gc_block(dev, dev->gc_block, aggressive);                    //3. 调用最终的GC函数       
  50.         }       
  51.     } while ((dev->n_erased_blocks < dev->param.n_reserved_blocks) &&(dev->gc_block > 0) && (max_tries < 2));

  52.     return aggressive ? gc_ok : YAFFS_OK;
  53. }
1.3.1 查找一个需要GC的块的块号
yaffs_bg_thread_fn
    --> yaffs_bg_gc  (background=1)
            --> yaffs_check_gc
                -->  yaffs2_find_refresh_block
在状态为FULL的block中,寻找最先被分配的block
  1. u32 yaffs2_find_refresh_block(struct yaffs_dev *dev)
  2. {
  3.     u32 b;
  4.     u32 oldest = 0;
  5.     u32 oldest_seq = 0;
  6.     struct yaffs_block_info *bi;

  7.     if (!dev->param.is_yaffs2)
  8.         return oldest;

  9.     if (dev->param.refresh_period < 10)
  10.         return oldest;

  11.     if (dev->refresh_skip > dev->param.refresh_period)
  12.         dev->refresh_skip = dev->param.refresh_period;

  13.     if (dev->refresh_skip > 0)
  14.         return oldest;

  15.     dev->refresh_skip = dev->param.refresh_period;           //这两个值字面意思很好理解,但有什么用处还不清楚
  16.     dev->refresh_count++;                                    //
  17.     bi = dev->block_info;
  18.     for (= dev->internal_start_block; b <= dev->internal_end_block; b++) {
  19.         if (bi->block_state == YAFFS_BLOCK_STATE_FULL) {
  20.             if (oldest < 1 || bi->seq_number < oldest_seq) {     //每一个block中都有seq_number,记录被分配的顺序, seq_number是按照0  1  2  3 这样累加的
  21.                 oldest = b;                                      //所以seq_number值越小,说明它越先被分配,即从分配到现在一直很稳定
  22.                 oldest_seq = bi->seq_number;
  23.             }
  24.         }
  25.         bi++;
  26.     }
  27.     return oldest;
  28. }
注: 这儿为什么要找最稳定的块呢? 
1.3.2 
yaffs_bg_thread_fn
    --> yaffs_bg_gc  (background=1)
            --> yaffs_check_gc
                -->  yaffs_find_gc_block
  1. static unsigned yaffs_find_gc_block(struct yaffs_dev *dev, int aggressive, int background)
  2. {
  3.     int i;
  4.     int iterations;
  5.     unsigned selected = 0;
  6.     int prioritised = 0;
  7.     int prioritised_exist = 0;
  8.     struct yaffs_block_info *bi;
  9.     int threshold;
  10.    
  11.     if (dev->has_pending_prioritised_gc && !aggressive) {                                    //ECC校验失败的block优先进行回收
  12.         dev->gc_dirtiest = 0;
  13.         bi = dev->block_info;
  14.         for (= dev->internal_start_block; i <= dev->internal_end_block && !selected; i++) {
  15.             if (bi->gc_prioritise) {
  16.                 prioritised_exist = 1;
  17.                 if (bi->block_state == YAFFS_BLOCK_STATE_FULL && yaffs_block_ok_for_gc(dev, bi)) {
  18.                     selected = i;
  19.                     prioritised = 1;
  20.                 }
  21.             }
  22.             bi++;
  23.         }
  24.         if (prioritised_exist && !selected && dev->oldest_dirty_block > 0)
  25.             selected = dev->oldest_dirty_block;

  26.         if (!prioritised_exist)  
  27.             dev->has_pending_prioritised_gc = 0;
  28.     }
  29.     if (!selected) {
  30.         int pages_used;
  31.         int n_blocks = dev->internal_end_block - dev->internal_start_block + 1;
  32.         if (aggressive) {
  33.             threshold = dev->param.chunks_per_block;
  34.             iterations = n_blocks;
  35.         } else {
  36.             int max_threshold;
  37.             if (background)
  38.                 max_threshold = dev->param.chunks_per_block / 2;
  39.             else
  40.                 max_threshold = dev->param.chunks_per_block / 8;

  41.             if (max_threshold < YAFFS_GC_PASSIVE_THRESHOLD)
  42.                 max_threshold = YAFFS_GC_PASSIVE_THRESHOLD;

  43.             threshold = background ? (dev->gc_not_done + 2) * 2 : 0;
  44.             if (threshold < YAFFS_GC_PASSIVE_THRESHOLD)
  45.                 threshold = YAFFS_GC_PASSIVE_THRESHOLD;
  46.             if (threshold > max_threshold)
  47.                 threshold = max_threshold;

  48.             iterations = n_blocks / 16 + 1;
  49.             if (iterations > 100)
  50.                 iterations = 100;
  51.         }

  52.         for (= 0;  i < iterations &&   (dev->gc_dirtiest < 1 ||  dev->gc_pages_in_use > YAFFS_GC_GOOD_ENOUGH); i++) {
  53.             dev->gc_block_finder++;
  54.             if (dev->gc_block_finder < dev->internal_start_block ||  dev->gc_block_finder > dev->internal_end_block)
  55.                 dev->gc_block_finder =  dev->internal_start_block;

  56.             bi = yaffs_get_block_info(dev, dev->gc_block_finder);

  57.             pages_used = bi->pages_in_use - bi->soft_del_pages;

  58.             if (bi->block_state == YAFFS_BLOCK_STATE_FULL && pages_used < dev->param.chunks_per_block && (dev->gc_dirtiest < 1 ||
  59.              pages_used < dev->gc_pages_in_use) && yaffs_block_ok_for_gc(dev, bi)) {
  60.                 dev->gc_dirtiest = dev->gc_block_finder;
  61.                 dev->gc_pages_in_use = pages_used;
  62.             }
  63.         }

  64.         if (dev->gc_dirtiest > 0 && dev->gc_pages_in_use <= threshold)
  65.             selected = dev->gc_dirtiest;
  66.     }

  67.     if (!selected && dev->param.is_yaffs2 && dev->gc_not_done >= (background ? 10 : 20)) {
  68.         yaffs2_find_oldest_dirty_seq(dev);
  69.         if (dev->oldest_dirty_block > 0) {
  70.             selected = dev->oldest_dirty_block;
  71.             dev->gc_dirtiest = selected;
  72.             dev->oldest_dirty_gc_count++;
  73.             bi = yaffs_get_block_info(dev, selected);
  74.             dev->gc_pages_in_use =
  75.              bi->pages_in_use - bi->soft_del_pages;
  76.         } else {
  77.             dev->gc_not_done = 0;
  78.         }
  79.     }

  80.     if (selected) {
  81.         dev->n_gc_blocks++;
  82.         if (background)
  83.             dev->bg_gcs++;

  84.         dev->gc_dirtiest = 0;
  85.         dev->gc_pages_in_use = 0;
  86.         dev->gc_not_done = 0;
  87.         if (dev->refresh_skip > 0)
  88.             dev->refresh_skip--;
  89.     } else {
  90.         dev->gc_not_done++;        
  91.     }
  92.     return selected;
  93. }


1.3.3 
yaffs_bg_thread_fn
    --> yaffs_bg_gc  (background=1)
            --> yaffs_check_gc
                -->  yaffs_gc_block
  1. static int yaffs_gc_block(struct yaffs_dev *dev, int block, int whole_block)
  2. {
  3.     int old_chunk;
  4.     int ret_val = YAFFS_OK;
  5.     int i;
  6.     int is_checkpt_block;
  7.     int max_copies;
  8.     int chunks_before = yaffs_get_erased_chunks(dev);                //所有空闲页
  9.     {
  10.         //n= 全为0xFF的block上的chunk + 当前Block上的未被alloc的chunk
  11.         n = dev->n_erased_blocks * dev->param.chunks_per_block;  
  12.         if (dev->alloc_block > 0)
                n += (dev->param.chunks_per_block - dev->alloc_page);
  13.     }
  14.     int chunks_after;
  15.     struct yaffs_block_info *bi = yaffs_get_block_info(dev, block);

  16.     is_checkpt_block = (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT);

  17.     if (bi->block_state == YAFFS_BLOCK_STATE_FULL)                         //状态改变,由FULL --> COLLECTING
  18.         bi->block_state = YAFFS_BLOCK_STATE_COLLECTING;

  19.     bi->has_shrink_hdr = 0;   
  20.     dev->gc_disable = 1;
  21.     yaffs_summary_gc(dev, block);
  22.     if (is_checkpt_block || !yaffs_still_some_chunks(dev, block)) {           //如果没有chunk有数据,则整个block变dirty,可以erase,再次使用   
  23.         yaffs_block_became_dirty(dev, block);
  24.     } else {
  25.         u8 *buffer = yaffs_get_temp_buffer(dev);
  26.         yaffs_verify_blk(dev, bi, block);
  27.         max_copies = (whole_block) ? dev->param.chunks_per_block : 5;        //如果没有设whole_block,则一次移5个chunk
  28.         old_chunk = block * dev->param.chunks_per_block + dev->gc_chunk;
  29.         for (; ret_val == YAFFS_OK &dev->gc_chunk < dev->param.chunks_per_block && (bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) && max_copies > 0;
  30.          dev->gc_chunk++, old_chunk++) {
  31.             if (yaffs_check_chunk_bit(dev, block, dev->gc_chunk)) {        
  32.                max_copies--;                                 //如果chunk位图中有数据,则把这些数据移动, 每次移max_copies个chunk,没有移动完就等下次调用时再移动
  33.                ret_val = yaffs_gc_process_chunk(dev, bi,  old_chunk, buffer);  //1.把需要回收的chunk重新找个地方写入
  34.             }
  35.         }
  36.         yaffs_release_temp_buffer(dev, buffer);
  37.     }

  38.     yaffs_verify_collected_blk(dev, bi, block);

  39.     if (bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) {        
  40.         bi->block_state = YAFFS_BLOCK_STATE_FULL;                        //改变一下状态
  41.     } else {
  42.         for (= 0; i < dev->n_clean_ups; i++) {
  43.             struct yaffs_obj *object =  yaffs_find_by_number(dev, dev->gc_cleanup_list[i]);
  44.             if (object) {
  45.                 yaffs_free_tnode(dev, object->variant.file_variant.top);
  46.                 object->variant.file_variant.top = NULL;                
  47.                 yaffs_generic_obj_del(object);
  48.                 object->my_dev->n_deleted_files--;
  49.             }
  50.         }
  51.         chunks_after = yaffs_get_erased_chunks(dev);       
  52.         dev->gc_block = 0;
  53.         dev->gc_chunk = 0;
  54.         dev->n_clean_ups = 0;
  55.     }
  56.     dev->gc_disable = 0;
  57.     return ret_val;
  58. }
1.3.3.1 把需要回收的chunk重新写入到一个地方中
yaffs_bg_thread_fn
    --> yaffs_bg_gc  (background=1)
            --> yaffs_check_gc
                -->  yaffs_gc_block
                    -->  yaffs_gc_process_chunk
  1. static inline int yaffs_gc_process_chunk(struct yaffs_dev *devstruct yaffs_block_info *bi, int old_chunk, u8 *buffer)
  2. {
  3.     int new_chunk;
  4.     int mark_flash = 1;
  5.     struct yaffs_ext_tags tags;
  6.     struct yaffs_obj *object;
  7.     int matching_chunk;
  8.     int ret_val = YAFFS_OK;

  9.     memset(&tags, 0, sizeof(tags));
  10.     yaffs_rd_chunk_tags_nand(dev, old_chunk, buffer, &tags);               //从nand_flash中读取数据和tags
  11.     object = yaffs_find_by_number(dev, tags.obj_id);                       //根据tags.obj_id,找到yaffs_obj结构体

  12.     if (object && !yaffs_skip_verification(dev)) {
  13.         if (tags.chunk_id == 0)
  14.             matching_chunk = object->hdr_chunk;
  15.         else if (object->soft_del)            
  16.             matching_chunk = old_chunk;
  17.         else
  18.             matching_chunk = yaffs_find_chunk_in_file (object, tags.chunk_id, NULL);          //1
  19.     }

  20.     if (object && object->deleted &&  object->soft_del && tags.chunk_id != 0) {       
  21.         dev->n_free_chunks--;
  22.         bi->soft_del_pages--;
  23.         object->n_data_chunks--;
  24.         if (object->n_data_chunks <= 0) {
  25.             dev->gc_cleanup_list[dev->n_clean_ups] = tags.obj_id;
  26.             dev->n_clean_ups++;
  27.         }
  28.         mark_flash = 0;
  29.     } else if (object) {       
  30.         tags.serial_number++;
  31.         dev->n_gc_copies++;
  32.         if (tags.chunk_id == 0) {            
  33.             struct yaffs_obj_hdr *oh;
  34.             oh = (struct yaffs_obj_hdr *) buffer;
  35.             oh->is_shrink = 0;
  36.             tags.extra_is_shrink = 0;
  37.             oh->shadows_obj = 0;
  38.             oh->inband_shadowed_obj_id = 0;
  39.             tags.extra_shadows = 0;

  40.             if (object->variant_type == YAFFS_OBJECT_TYPE_FILE) {
  41.                 oh->file_size = object->variant.file_variant.file_size;
  42.                 tags.extra_length = oh->file_size;
  43.             }
  44.             yaffs_verify_oh(object, oh, &tags, 1);
  45.             new_chunk = yaffs_write_new_chunk(dev, (u8 *) oh, &tags, 1);
  46.         } else {
  47.             new_chunk = yaffs_write_new_chunk(dev, buffer, &tags, 1);          //2.把这个chunk中的数据写到另外的地方
  48.         }

  49.         if (new_chunk < 0) {
  50.             ret_val = YAFFS_FAIL;
  51.         } else {
  52.             if (tags.chunk_id == 0) {
  53.                 object->hdr_chunk = new_chunk;
  54.                 object->serial = tags.serial_number;
  55.             } else {
  56.                 yaffs_put_chunk_in_file(object, tags.chunk_id, new_chunk, 0);   //3.
  57.             }
  58.         }
  59.     }
  60.     if (ret_val == YAFFS_OK)    
  61.         yaffs_chunk_del(dev, old_chunk, mark_flash, __LINE__);                  //4.删除老的chunk,如果删除后block为空,则删除整个block
  62.     return ret_val;
  63. }

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值