Linux内核---27.yaffs2的文件操作

一. yaffs是怎样创建文件的呢
启动linux完成进入shell后,在shell中执行如下命令,会发生什么情况呢?当前文件系统是yaffs2
[root@OK6410]# touch 123
调用过程如下,先不分析与yaffs2无关的
  1. sys_open
  2. do_sys_open
  3. do_filp_open
  4. path_openat
  5. do_last
  6. vfs_create
  7. yaffs_create
  8.     --> yaffs_mknod
  9.         --> yaffs_create_file
  10.             --> yaffs_create_obj

1. 创建文件,目录,特殊文件,软链接,硬链接都需要调用函数yaffs_create_obj
  1. static struct yaffs_obj *yaffs_create_obj(enum yaffs_obj_type type, struct yaffs_obj *parent, const YCHAR *name,
  2.                       u32 modeu32 uid, u32 gid, struct yaffs_obj *equiv_obj, const YCHAR *alias_str, u32 rdev)
  3. {
  4.     struct yaffs_obj *in;
  5.     YCHAR *str = NULL;
  6.     struct yaffs_dev *dev = parent->my_dev;

  7.     if (yaffs_find_by_name(parent, name))                //1. 检查是否有重名文件存在            
  8.         return NULL;

  9.     if (type == YAFFS_OBJECT_TYPE_SYMLINK) {
  10.         str = yaffs_clone_str(alias_str);                //2.如果是软链接 clone
  11.         if (!str)
  12.             return NULL;
  13.     }

  14.     in = yaffs_new_obj(dev, -1, type);                    //3.new一个obj

  15.     in->hdr_chunk = 0;
  16.     in->valid = 1;
  17.     in->variant_type = type;

  18.     in->yst_mode = mode;

  19.     yaffs_attribs_init(in, gid, uid, rdev);              //4. 权限初始化

  20.     in->n_data_chunks = 0;
  21.     yaffs_set_obj_name(in, name);                        //5. 命名;并对文件名取sum,保存在in->sum中
  22.     in->dirty = 1;

  23.     yaffs_add_obj_to_dir(parent, in);                    //6. 把文件添加到目录     

  24.     in->my_dev = parent->my_dev;

  25.     switch (type) {
  26.     case YAFFS_OBJECT_TYPE_SYMLINK:
  27.         in->variant.symlink_variant.alias = str;
  28.         break;
  29.     case YAFFS_OBJECT_TYPE_HARDLINK:
  30.         in->variant.hardlink_variant.equiv_obj = equiv_obj;
  31.         in->variant.hardlink_variant.equiv_id = equiv_obj->obj_id;
  32.         list_add(&in->hard_links, &equiv_obj->hard_links);
  33.         break;
  34.     case YAFFS_OBJECT_TYPE_FILE:
  35.     case YAFFS_OBJECT_TYPE_DIRECTORY:
  36.     case YAFFS_OBJECT_TYPE_SPECIAL:
  37.     case YAFFS_OBJECT_TYPE_UNKNOWN:
  38.         /* do nothing */
  39.         break;
  40.     }

  41.     if (yaffs_update_oh(in, name, 0, 0, 0, NULL) < 0) {        //7.把信息写入
  42.         yaffs_del_obj(in);
  43.         in = NULL;
  44.     }

  45.     if (in)
  46.         yaffs_update_parent(parent);                            //8.把信息写入到parent

  47.     return in;
  48. }

1.1 在目录directory中查找是否有重名的,没有重名返回NULL
  1. struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *directoryconst YCHAR *name)
  2. {
  3.     int sum;
  4.     struct list_head *i;
  5.     YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
  6.     struct yaffs_obj *l;

  7.    
  8.     if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {  //首先检查参数,directory的类型是DIRECTORY  
  9.        BUG();
  10.     }

  11.     sum = yaffs_calc_name_sum(name);                                //对文件名取个sum,可以认为是个标志

  12.     list_for_each(i, &directory->variant.dir_variant.children) {
  13.         l = list_entry(i, struct yaffs_obj, siblings);

  14.         if (l->parent != directory)
  15.             BUG();

  16.         yaffs_check_obj_details_loaded(l);

  17.         if (l->obj_id == YAFFS_OBJECTID_LOSTNFOUND) {
  18.             if (!strcmp(name, YAFFS_LOSTNFOUND_NAME))
  19.                 return l;
  20.         } else if (l->sum == sum || l->hdr_chunk <= 0) {                  //拿刚才作的sum与该目录下所有的文件进行比较          
  21.             yaffs_get_obj_name(l, buffer, YAFFS_MAX_NAME_LENGTH + 1);     // 如果sum值相等,再进行真正的字符串比较,看两个文件是否真的一样
  22.             if (strncmp(name, buffer, YAFFS_MAX_NAME_LENGTH) == 0)
  23.                 return l;
  24.         }
  25.     }
  26.     return NULL;
  27. }
注意: 这个查找重名函数,并不是将要创建文件的name与目录下所有的文件都按字符串进行比较,
        而是对要创建的文件按名作sum,则比
较时只比较sum值是不是相等,这样可以缩减比较时间;  
        如果相等了再按照字符串对两个文个进行比较,看是否真的一样.
        同时其它文件的sum值会在开机启动时调用yaffs_lookup进行扫描时保存在文件结构体的in->sum中.


1.3 申请一个obj结构体
  1. struct yaffs_obj *yaffs_new_obj(struct yaffs_dev *dev, int numberenum yaffs_obj_type type)
  2. {
  3.     struct yaffs_obj *the_obj = NULL;
  4.     struct yaffs_tnode *tn = NULL;

  5.     if (number < 0)
  6.         number = yaffs_new_obj_id(dev);                //在hash表中找到一个未用的obj_id

  7.     if (type == YAFFS_OBJECT_TYPE_FILE) {
  8.         tn = yaffs_get_tnode(dev);                     //申请一个tnode结构体   
  9.         if (!tn)
  10.             return NULL;
  11.     }

  12.     the_obj = yaffs_alloc_empty_obj(dev);               //申请一个yaffs_obj结构体
  13.     if (!the_obj) {
  14.         if (tn)
  15.             yaffs_free_tnode(dev, tn);
  16.         return NULL;
  17.     }

  18.     the_obj->fake = 0;
  19.     the_obj->rename_allowed = 1;
  20.     the_obj->unlink_allowed = 1;
  21.     the_obj->obj_id = number;                            
  22.     yaffs_hash_obj(the_obj);                            //把yaffs_obj按obj_id,存于hash表中
  23.     the_obj->variant_type = type;
  24.     yaffs_load_current_time(the_obj, 1, 1);             //对obj设置当前时间

  25.     switch (type) {
  26.     case YAFFS_OBJECT_TYPE_FILE:
  27.         the_obj->variant.file_variant.file_size = 0;
  28.         the_obj->variant.file_variant.scanned_size = 0;
  29.         the_obj->variant.file_variant.shrink_size = ~0; /* max */
  30.         the_obj->variant.file_variant.top_level = 0;
  31.         the_obj->variant.file_variant.top = tn;            //如果是普通文件,第一个tnode就是刚才申请的tnode
  32.         break;
  33.     case YAFFS_OBJECT_TYPE_DIRECTORY:
  34.         INIT_LIST_HEAD(&the_obj->variant.dir_variant.children); //如果是目录就创建两个list 
  35.         INIT_LIST_HEAD(&the_obj->variant.dir_variant.dirty);    //一个作为文件列表,另一个回收
  36.         break;
  37.     case YAFFS_OBJECT_TYPE_SYMLINK:
  38.     case YAFFS_OBJECT_TYPE_HARDLINK:
  39.     case YAFFS_OBJECT_TYPE_SPECIAL:
  40.         /* No action required */
  41.         break;
  42.     case YAFFS_OBJECT_TYPE_UNKNOWN:
  43.         /* todo this should not happen */
  44.         break;
  45.     }
  46.     return the_obj;
  47. }
1.5 设置文件名的同时,计算文件名的sum值
  1. void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR * name)
  2. {
  3.     memset(obj->short_name, 0, sizeof(obj->short_name));
  4.     if (name && strnlen(name, YAFFS_SHORT_NAME_LENGTH + 1) <= YAFFS_SHORT_NAME_LENGTH)
  5.         strcpy(obj->short_name, name);            //直接strcpy
  6.     else
  7.         obj->short_name[0] = _Y('\0');
  8.     obj->sum = yaffs_calc_name_sum(name);        //将计算出的sum值保存在obj->sum中
  9. }
1.6 把obj添加到目录
  1. void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj)
  2. {
  3.     if (!directory)
  4.         return;
  5.     
  6.     if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)         
  7.        BUG();    

  8.     if (obj->siblings.prev == NULL) 
  9.         BUG();    

  10.     yaffs_verify_dir(directory);

  11.     yaffs_remove_obj_from_dir(obj);        //为什么这儿要remove呢?因为初始化时parent=root_dir

  12.     list_add(&obj->siblings, &directory->variant.dir_variant.children);     //添加到parent
  13.     obj->parent = directory;

  14.     if (directory == obj->my_dev->unlinked_dir   || directory == obj->my_dev->del_dir) {
  15.         obj->unlinked = 1;
  16.         obj->my_dev->n_unlinked_files++;
  17.         obj->rename_allowed = 0;
  18.     }

  19.     yaffs_verify_dir(directory);
  20.     yaffs_verify_obj_in_dir(obj);
  21. }
在添加到新目录之前,要删掉它在旧目录的指针.
yaffs_add_obj_to_dir
    --> yaffs_remove_obj_from_dir
  1. static void yaffs_remove_obj_from_dir(struct yaffs_obj *obj)
  2. {
  3.     struct yaffs_dev *dev = obj->my_dev;
  4.     struct yaffs_obj *parent;

  5.     yaffs_verify_obj_in_dir(obj);
  6.     parent = obj->parent;                        //获取parent目录指针

  7.     yaffs_verify_dir(parent);

  8.     if (dev && dev->param.remove_obj_fn)
  9.         dev->param.remove_obj_fn(obj);          //从parent目录中去掉obj

  10.     list_del_init(&obj->siblings);
  11.     obj->parent = NULL;

  12.     yaffs_verify_dir(parent);
  13. }
注:为什么要调用yaffs_remove_obj_from_dir呢?因为在创建empty_obj时,会将obj的parent初始化为root_dir,所以这个地方要先从root_dir中删掉
yaffs_create_obj-->yaffs_new_obj--> yaffs_alloc_empty_obj
  1. static struct yaffs_obj *yaffs_alloc_empty_obj(struct yaffs_dev *dev)
  2. {
  3.     if (dev->root_dir) {
  4.         obj->parent = dev->root_dir;
  5.         list_add(&(obj->siblings), &dev->root_dir->variant.dir_variant.children);
  6.     }
  7. }
yaffs_add_obj_to_dir
    --> yaffs_remove_obj_from_dir
            --> dev - > param . remove_obj_fn
  1. static void yaffs_remove_obj_callback(struct yaffs_obj *obj)            //这个地方还没有看明白
  2. {

  3.     struct list_head *i;
  4.     struct yaffs_search_context *sc;
  5.     struct list_head *search_contexts =  &(yaffs_dev_to_lc(obj->my_dev)->search_contexts);

  6.     /* Iterate through the directory search contexts.
  7.      * If any are currently on the object being removed, then advance
  8.      * the search context to the next object to prevent a hanging pointer.
  9.      */
  10.     list_for_each(i, search_contexts) {
  11.         sc = list_entry(i, struct yaffs_search_context, others);
  12.         if (sc->next_return == obj)
  13.             yaffs_search_advance(sc);
  14.     }

  15. }
1.7 更新object_header并把信息写到nand_flash中
   yaffs_create_obj 
        -->yaffs_update_oh(in, name, 0, 0, 0, NULL)
  1. /* UpdateObjectHeader updates the header on NAND for an object.
  2.  * If name is not NULL, then that new name is used.
  3.  */
  4. int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force,
  5.          int is_shrink, int shadows, struct yaffs_xattr_mod *xmod)
  6. {

  7.     struct yaffs_block_info *bi;
  8.     struct yaffs_dev *dev = in->my_dev;
  9.     int prev_chunk_id;
  10.     int ret_val = 0;
  11.     int result = 0;
  12.     int new_chunk_id;
  13.     struct yaffs_ext_tags new_tags;
  14.     struct yaffs_ext_tags old_tags;
  15.     const YCHAR *alias = NULL;
  16.     u8 *buffer = NULL;
  17.     YCHAR old_name[YAFFS_MAX_NAME_LENGTH + 1];
  18.     struct yaffs_obj_hdr *oh = NULL;

  19.     strcpy(old_name, _Y("silly old name"));

  20.     if (in->fake && in != dev->root_dir && !force && !xmod)
  21.         return ret_val;

  22.     yaffs_check_gc(dev, 0);
  23.     yaffs_check_obj_details_loaded(in);               //在yaffs_create_obj中 in->hdr_chunk=0,这个函数直接返回  
  24.     buffer = yaffs_get_temp_buffer(in->my_dev);        //1. 获取temp_buffer
  25.     oh = (struct yaffs_obj_hdr *)buffer;

  26.     prev_chunk_id = in->hdr_chunk;
  27.     
  28.     if (prev_chunk_id > 0) {                          //在yaffs_create_obj中 in->hdr_chunk=0                        
  29.         result = yaffs_rd_chunk_tags_nand(dev, prev_chunk_id, buffer, &old_tags);
  30.         yaffs_verify_oh(in, oh, &old_tags, 0);
  31.         memcpy(old_name, oh->name, sizeof(oh->name));
  32.         memset(buffer, 0xff, sizeof(struct yaffs_obj_hdr));
  33.     } else {
  34.         memset(buffer, 0xff, dev->data_bytes_per_chunk);    //设置chunk的数值都为0xff
  35.     }

  36.     oh->type = in->variant_type;                              /*  填充oh结构体  
  37.     oh->yst_mode = in->yst_mode;                               *  
  38.     oh->shadows_obj = oh->inband_shadowed_obj_id = shadows;    *
  39.     yaffs_load_attribs_oh(oh, in);                             */

  40.     if (in->parent)
  41.         oh->parent_obj_id = in->parent->obj_id;
  42.     else
  43.         oh->parent_obj_id = 0;

  44.     if (name && *name) {
  45.         memset(oh->name, 0, sizeof(oh->name));
  46.         yaffs_load_oh_from_name(dev, oh->name, name);        //文件名copy
  47.     } else if (prev_chunk_id > 0) {
  48.         memcpy(oh->name, old_name, sizeof(oh->name));
  49.     } else {
  50.         memset(oh->name, 0, sizeof(oh->name));
  51.     }

  52.     oh->is_shrink = is_shrink;

  53.     switch (in->variant_type) {
  54.     case YAFFS_OBJECT_TYPE_UNKNOWN:
  55.         /* Should not happen */
  56.         break;
  57.     case YAFFS_OBJECT_TYPE_FILE:
  58.         oh->file_size =(oh->parent_obj_id == YAFFS_OBJECTID_DELETED ||  oh->parent_obj_id == YAFFS_OBJECTID_UNLINKED) ?
  59.          0 : in->variant.file_variant.file_size;
  60.         break;
  61.     case YAFFS_OBJECT_TYPE_HARDLINK:
  62.         oh->equiv_id = in->variant.hardlink_variant.equiv_id;
  63.         break;
  64.     case YAFFS_OBJECT_TYPE_SPECIAL:
  65.         /* Do nothing */
  66.         break;
  67.     case YAFFS_OBJECT_TYPE_DIRECTORY:
  68.         /* Do nothing */
  69.         break;
  70.     case YAFFS_OBJECT_TYPE_SYMLINK:
  71.         alias = in->variant.symlink_variant.alias;
  72.         if (!alias)
  73.             alias = _Y("no alias");
  74.         strncpy(oh->alias, alias, YAFFS_MAX_ALIAS_LENGTH);
  75.         oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0;
  76.         break;
  77.     }

  78.     /* Tags */
  79.     memset(&new_tags, 0, sizeof(new_tags));
  80.     in->serial++;
  81.     new_tags.chunk_id = 0;
  82.     new_tags.obj_id = in->obj_id;
  83.     new_tags.serial_number = in->serial;

  84.     /* Add extra info for file header */
  85.     new_tags.extra_available = 1;
  86.     new_tags.extra_parent_id = oh->parent_obj_id;
  87.     new_tags.extra_length = oh->file_size;
  88.     new_tags.extra_is_shrink = oh->is_shrink;
  89.     new_tags.extra_equiv_id = oh->equiv_id;
  90.     new_tags.extra_shadows = (oh->shadows_obj > 0) ? 1 : 0;
  91.     new_tags.extra_obj_type = in->variant_type;
  92.     yaffs_verify_oh(in, oh, &new_tags, 1);

  93.     /* Create new chunk in NAND */
  94.     new_chunk_id = yaffs_write_new_chunk(dev, buffer, &new_tags, (prev_chunk_id > 0) ? 1 : 0);    //将数据写入到nand_flash中

  95.     if (buffer)
  96.         yaffs_release_temp_buffer(dev, buffer);

  97.     if (new_chunk_id < 0)
  98.         return new_chunk_id;

  99.     in->hdr_chunk = new_chunk_id;            //返回新的chunk_id,就是刚才写入到nand_flash中的chunk_id,把它保存起来

  100.     if (prev_chunk_id > 0)
  101.         yaffs_chunk_del(dev, prev_chunk_id, 1, __LINE__);

  102.     if (!yaffs_obj_cache_dirty(in))
  103.         in->dirty = 0;

  104.     /* If this was a shrink, then mark the block
  105.      * that the chunk lives on */
  106.     if (is_shrink) {
  107.         bi = yaffs_get_block_info(in->my_dev,
  108.                      new_chunk_id /
  109.                      in->my_dev->param.chunks_per_block);
  110.         bi->has_shrink_hdr = 1;
  111.     }


  112.     return new_chunk_id;
  113. }
1.7.2  写数据到nand_flash
   yaffs_create_obj 
        -->yaffs_update_oh(in, name, 0, 0, 0, NULL)
            -->  yaffs_write_new_chunk
  1. static int yaffs_write_new_chunk(struct yaffs_dev *dev, const u8 *data, struct yaffs_ext_tags *tags, int use_reserver)
  2. {
  3.     int attempts = 0;
  4.     int write_ok = 0;
  5.     int chunk;

  6.     yaffs2_checkpt_invalidate(dev);

  7.     do {
  8.         struct yaffs_block_info *bi = 0;
  9.         int erased_ok = 0;

  10.         chunk = yaffs_alloc_chunk(dev, use_reserver, &bi);             //申请一个chunk
  11.         if (chunk < 0) {
  12.             /* no space */
  13.             break;
  14.         }
  15.         attempts++;

  16.         if (dev->param.always_check_erased)
  17.             bi->skip_erased_check = 0;

  18.         if (!bi->skip_erased_check) {
  19.             erased_ok = yaffs_check_chunk_erased(dev, chunk);        //1.检查这个chunk是否己擦除,即chunk中全是0xff
  20.             if (erased_ok != YAFFS_OK) {               
  21.                 yaffs_chunk_del(dev, chunk, 1, __LINE__);            //经检查这个chunk没有被擦除,把这个chunk del
  22.                 yaffs_skip_rest_of_block(dev);                       //到下一次循环时重新申请一个chunk,再检查
  23.                 continue;
  24.             }
  25.         }

  26.         write_ok = yaffs_wr_chunk_tags_nand(dev, chunk, data, tags);  //2.此时的chunk己擦除过的,就把tags写入到这个nand_flash中

  27.         if (!bi->skip_erased_check)
  28.             write_ok = yaffs_verify_chunk_written(dev, chunk, data, tags);

  29.         if (write_ok != YAFFS_OK) {          
  30.             yaffs_handle_chunk_wr_error(dev, chunk, erased_ok);
  31.             continue;
  32.         }

  33.         bi->skip_erased_check = 1;
  34.         
  35.         yaffs_handle_chunk_wr_ok(dev, chunk, data, tags);            //3.把文件中的数据写入到nand_flash中

  36.     } while (write_ok != YAFFS_OK && (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts));

  37.     if (!write_ok)
  38.         chunk = -1;

  39.     if (attempts > 1) {
  40.         dev->n_retried_writes += (attempts - 1);
  41.     }

  42.     return chunk;
  43. }
1.7.2.1 检查某个chunk是否擦除过
 yaffs_create_obj 
        -->yaffs_update_oh(in, name, 0, 0, 0, NULL)
            -->  yaffs_write_new_chunk (dev, buffer, &new_tags,  0);
                    --> yaffs_check_chunk_erased
  1. static int yaffs_check_chunk_erased(struct yaffs_dev *dev, int nand_chunk)
  2. {
  3.     int retval = YAFFS_OK;
  4.     u8 *data = yaffs_get_temp_buffer(dev);
  5.     struct yaffs_ext_tags tags;
  6.     int result;

  7.     result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, data, &tags);       //读取chunk的数据到data

  8.     if (tags.ecc_result > YAFFS_ECC_RESULT_NO_ERROR)
  9.         retval = YAFFS_FAIL;

  10.     if (!yaffs_check_ff(data, dev->data_bytes_per_chunk) ||                //检查是不是每个字节都是0xff
  11.         tags.chunk_used) {       
  12.         retval = YAFFS_FAIL;
  13.     }

  14.     yaffs_release_temp_buffer(dev, data);

  15.     return retval;                                                         //如果每个字节都是0xff,返回YAFFS_OK   

  16. }
1.7.2.1.1 读取chunk中的数据到buffer
  1. int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunku8 *buffer, struct yaffs_ext_tags *tags)
  2. {
  3.     int result;
  4.     struct yaffs_ext_tags local_tags;
  5.     int flash_chunk = nand_chunk - dev->chunk_offset;

  6.     dev->n_page_reads++;

  7.     if (!tags)
  8.         tags = &local_tags;

  9.     if (dev->param.read_chunk_tags_fn)
  10.         result = dev->param.read_chunk_tags_fn(dev, flash_chunk, buffer, tags);          //直接调用的param.read_chunk_tags_fn来读取
  11.     else
  12.         result = yaffs_tags_compat_rd(dev, flash_chunk, buffer, tags);
  13.     if (tags && tags->ecc_result > YAFFS_ECC_RESULT_NO_ERROR) {
  14.         struct yaffs_block_info *bi;
  15.         bi = yaffs_get_block_info(dev,  nand_chunk/dev->param.chunks_per_block);
  16.         yaffs_handle_chunk_error(dev, bi);
  17.     }
  18.     return result;
  19. }

1.7.2.2 将buffer中的数据到nand_flash中的chunk上
 yaffs_create_obj 
        -->yaffs_update_oh(in, name, 0, 0, 0, NULL)
            -->  yaffs_write_new_chunk (dev, buffer, &new_tags,  0);
                    -->  yaffs_wr_chunk_tags_nand
  1. int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, const u8 *buffer, struct yaffs_ext_tags *tags)
  2. {
  3.     int result;
  4.     int flash_chunk = nand_chunk - dev->chunk_offset;

  5.     dev->n_page_writes++;
  6.     if (tags) {
  7.         tags->seq_number = dev->seq_number;
  8.         tags->chunk_used = 1;       
  9.     } else {        
  10.         return YAFFS_FAIL;
  11.     }

  12.     if (dev->param.write_chunk_tags_fn)
  13.         result = dev->param.write_chunk_tags_fn(dev, flash_chunk, buffer, tags);        //直接调用param.write_chunk_tags_fn写入
  14.     else
  15.         result = yaffs_tags_compat_wr(dev, flash_chunk, buffer, tags);

  16.     yaffs_summary_add(dev, tags, nand_chunk);

  17.     return result;
  18. }

其中两个函数指针:
dev - > param . write_chunk_tags_fn
dev->param.read_chunk_tags_fn
的初始化是在yaffs_internal_read_super中
  1. yaffs_internal_read_super()
  2. {
  3.     if (yaffs_version == 2) {
  4.         param->write_chunk_tags_fn = nandmtd2_write_chunk_tags;
  5.         param->read_chunk_tags_fn = nandmtd2_read_chunk_tags;
  6.         param->bad_block_fn = nandmtd2_mark_block_bad;
  7.         param->query_block_fn = nandmtd2_query_block;
  8.     }    
  9. }
下面是读取过程
  1. int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, u8 *data, struct yaffs_ext_tags *tags)
  2. {
  3.     struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  4.     struct mtd_oob_ops ops;
  5.     size_t dummy;
  6.     int retval = 0;
  7.     int local_data = 0;

  8.     loff_t addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;

  9.     struct yaffs_packed_tags2 pt;

  10.     int packed_tags_size =  dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);     //dev->param.no_tags_ecc=1
  11.     void *packed_tags_ptr = dev->param.no_tags_ecc ? (void *)&pt.: (void *)&pt;   //packed_tags_size=16, packed_tags_ptr=pt.t

  12.    if (tags) {
  13.         ops.mode = MTD_OOB_AUTO;
  14.         ops.ooblen = packed_tags_size;
  15.         ops.len = data ? dev->data_bytes_per_chunk : packed_tags_size;
  16.         ops.ooboffs = 0;
  17.         ops.datbuf = data;
  18.         ops.oobbuf = yaffs_dev_to_lc(dev)->spare_buffer;
  19.         retval = mtd->read_oob(mtd, addr, &ops);                       //从nand_flash中读取nand_chunk到data中,oob读到ops.oobbuf中
  20.     }
  21.     if (tags) {
  22.         memcpy(packed_tags_ptr, yaffs_dev_to_lc(dev)->spare_buffer, packed_tags_size);  //将oobbuf中的数据cp到pt.t中  
  23.         yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc);                         //如果param.no_tags_ecc=0,就要对pt->t进行ecc校验,并修正,但是这儿param.no_tags_ecc=1,所以不校验
  24.     }                                                                                   //将 struct yaffs_packed_tags2 *pt 转化为struct yaffs_ext_tags *tags                   

  25.     if (local_data)
  26.         yaffs_release_temp_buffer(dev, data);

  27.     if (tags && retval == -EBADMSG  && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
  28.         tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED;
  29.         dev->n_ecc_unfixed++;
  30.     }
  31.     if (tags && retval == -EUCLEAN && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
  32.         tags->ecc_result = YAFFS_ECC_RESULT_FIXED;
  33.         dev->n_ecc_fixed++;

  34.         retval = 0; // gjl
  35.     }
  36.     if (retval == 0)
  37.         return YAFFS_OK;
  38.     else
  39.         return YAFFS_FAIL;
  40. }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值