Merge branch 'block-summary'
authorCharles Manning <cdhmanning@gmail.com>
Thu, 28 Apr 2011 03:57:52 +0000 (15:57 +1200)
committerCharles Manning <cdhmanning@gmail.com>
Thu, 28 Apr 2011 03:57:52 +0000 (15:57 +1200)
Conflicts:
yaffs_vfs_multi.c

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
1  2 
yaffs_guts.c
yaffs_guts.h
yaffs_vfs_multi.c

diff --combined yaffs_guts.c
index cd70c5415d72af03ea6a08e471fe89394f9f324c,dfabf4c29d23ea75e1b0e9bfb4d0b6a5e7360ab4..d72aa5ba9e5a59c1c3722664fccd881b7694d3c1
@@@ -27,6 -27,7 +27,7 @@@
  #include "yaffs_nameval.h"
  #include "yaffs_allocator.h"
  #include "yaffs_attribs.h"
+ #include "yaffs_summary.h"
  
  /* Note YAFFS_GC_GOOD_ENOUGH must be <= YAFFS_GC_PASSIVE_THRESHOLD */
  #define YAFFS_GC_GOOD_ENOUGH 2
@@@ -671,6 -672,7 +672,6 @@@ static u16 yaffs_calc_name_sum(const YC
  
  void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR * name)
  {
 -#ifndef CONFIG_YAFFS_NO_SHORT_NAMES
        memset(obj->short_name, 0, sizeof(obj->short_name));
        if (name &&
                strnlen(name, YAFFS_SHORT_NAME_LENGTH + 1) <=
                strcpy(obj->short_name, name);
        else
                obj->short_name[0] = _Y('\0');
 -#endif
        obj->sum = yaffs_calc_name_sum(name);
  }
  
@@@ -2380,6 -2383,8 +2381,8 @@@ void yaffs_block_became_dirty(struct ya
        bi->has_shrink_hdr = 0;
        bi->skip_erased_check = 1;      /* Clean, so no need to check */
        bi->gc_prioritise = 0;
+       bi->has_summary=0;
        yaffs_clear_chunk_bits(dev, block_no);
  
        yaffs_trace(YAFFS_TRACE_ERASE, "Erased block %d", block_no);
@@@ -2555,6 -2560,8 +2558,8 @@@ static int yaffs_gc_block(struct yaffs_
  
        dev->gc_disable = 1;
  
+       yaffs_summary_gc(dev, block);
        if (is_checkpt_block || !yaffs_still_some_chunks(dev, block)) {
                yaffs_trace(YAFFS_TRACE_TRACING,
                        "Collecting block %d that has no chunks in use",
@@@ -4411,11 -4418,13 +4416,11 @@@ int yaffs_get_obj_name(struct yaffs_ob
  {
        memset(name, 0, buffer_size * sizeof(YCHAR));
        yaffs_check_obj_details_loaded(obj);
 -      if (obj->obj_id == YAFFS_OBJECTID_LOSTNFOUND)
 +      if (obj->obj_id == YAFFS_OBJECTID_LOSTNFOUND) {
                strncpy(name, YAFFS_LOSTNFOUND_NAME, buffer_size - 1);
 -#ifndef CONFIG_YAFFS_NO_SHORT_NAMES
 -      else if (obj->short_name[0])
 +      } else if (obj->short_name[0]) {
                strcpy(name, obj->short_name);
 -#endif
 -      else if (obj->hdr_chunk > 0) {
 +      } else if (obj->hdr_chunk > 0) {
                int result;
                u8 *buffer = yaffs_get_temp_buffer(obj->my_dev);
  
@@@ -4529,6 -4538,8 +4534,6 @@@ static int yaffs_check_dev_fns(const st
        if (!dev->param.erase_fn || !dev->param.initialise_flash_fn)
                return 0;
  
 -#ifdef CONFIG_YAFFS_YAFFS2
 -
        /* Can use the "with tags" style interface for yaffs1 or yaffs2 */
        if (dev->param.write_chunk_tags_fn &&
            dev->param.read_chunk_tags_fn &&
            !dev->param.read_chunk_fn &&
            dev->param.bad_block_fn && dev->param.query_block_fn)
                return 1;
 -#endif
  
        /* Can use the "spare" style interface for yaffs1 */
        if (!dev->param.is_yaffs2 &&
@@@ -4806,6 -4818,11 +4811,11 @@@ int yaffs_guts_initialise(struct yaffs_
        if (!init_failed && !yaffs_create_initial_dir(dev))
                init_failed = 1;
  
+       if(!init_failed && dev->param.is_yaffs2 &&
+               !dev->param.disable_summary &&
+               !yaffs_summary_init(dev))
+               init_failed = 1;
        if (!init_failed) {
                /* Now scan the flash. */
                if (dev->param.is_yaffs2) {
@@@ -4891,6 -4908,8 +4901,8 @@@ void yaffs_deinitialise(struct yaffs_de
  
                yaffs_deinit_blocks(dev);
                yaffs_deinit_tnodes_and_objs(dev);
+               yaffs_summary_deinit(dev);
                if (dev->param.n_caches > 0 && dev->cache) {
  
                        for (i = 0; i < dev->param.n_caches; i++) {
diff --combined yaffs_guts.h
index 77c05d3b4924357cb2a9c31531e6392346aea2b5,fc311435207c08bcdbbbd115695e702d610d6aa8..6ec8a47b1d45d89413e9f999d8daaa2fc51f3bf3
  #define YAFFS_TNODES_INTERNAL_MASK    0x7
  #define YAFFS_TNODES_MAX_LEVEL                6
  
 -#ifndef CONFIG_YAFFS_NO_YAFFS1
 +
 +/* Constants for YAFFS1 mode */
  #define YAFFS_BYTES_PER_SPARE         16
  #define YAFFS_BYTES_PER_CHUNK         512
  #define YAFFS_CHUNK_SIZE_SHIFT                9
  #define YAFFS_CHUNKS_PER_BLOCK                32
  #define YAFFS_BYTES_PER_BLOCK (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK)
 -#endif
  
  #define YAFFS_MIN_YAFFS2_CHUNK_SIZE   1024
  #define YAFFS_MIN_YAFFS2_SPARE_SIZE   32
  #define YAFFS_OBJECTID_UNLINKED               3
  #define YAFFS_OBJECTID_DELETED                4
  
+ /* Fake object Id for summary data */
+ #define YAFFS_OBJECTID_SUMMARY                0x10
  /* Pseudo object ids for checkpointing */
- #define YAFFS_OBJECTID_SB_HEADER      0x10
  #define YAFFS_OBJECTID_CHECKPOINT_DATA        0x20
- #define YAFFS_SEQUENCE_CHECKPOINT_DATA  0x21
+ #define YAFFS_SEQUENCE_CHECKPOINT_DATA        0x21
  
  #define YAFFS_MAX_SHORT_OP_CACHES     20
  
@@@ -117,11 -119,12 +119,11 @@@ struct yaffs_cache 
        u8 *data;
  };
  
 -/* Tags structures in RAM
 +/* yaffs1 tags structures in RAM
   * NB This uses bitfield. Bitfields should not straddle a u32 boundary
   * otherwise the structure size will get blown out.
   */
  
 -#ifndef CONFIG_YAFFS_NO_YAFFS1
  struct yaffs_tags {
        unsigned chunk_id:20;
        unsigned serial_number:2;
@@@ -136,6 -139,7 +138,6 @@@ union yaffs_tags_union 
        u8 as_bytes[8];
  };
  
 -#endif
  
  /* Stuff used for extended tags in YAFFS2 */
  
@@@ -278,9 -282,12 +280,10 @@@ struct yaffs_block_info 
                                   Block should be prioritised for GC */
        u32 chunk_error_strikes:3;      /* How many times we've had ecc etc
                                failures on this block and tried to reuse it */
+       u32 has_summary:1;      /* The block has a summary */
  
 -#ifdef CONFIG_YAFFS_YAFFS2
        u32 has_shrink_hdr:1;   /* This block has at least one shrink header */
        u32 seq_number;         /* block sequence number for yaffs2 */
 -#endif
  
  };
  
@@@ -429,7 -436,9 +432,7 @@@ struct yaffs_obj 
  
        u32 yst_mode;
  
 -#ifndef CONFIG_YAFFS_NO_SHORT_NAMES
        YCHAR short_name[YAFFS_SHORT_NAME_LENGTH + 1];
 -#endif
  
  #ifdef CONFIG_YAFFS_WINCE
        u32 win_ctime[2];
@@@ -515,7 -524,6 +518,7 @@@ struct yaffs_param 
                                 */
        int use_nand_ecc;       /* Flag to decide whether or not to use
                                 * NAND driver ECC on data (yaffs1) */
 +        int tags_9bytes;      /* Use 9 byte tags */
        int no_tags_ecc;        /* Flag to decide whether or not to do ECC
                                 * on packed tags (yaffs2) */
  
        int (*initialise_flash_fn) (struct yaffs_dev *dev);
        int (*deinitialise_flash_fn) (struct yaffs_dev *dev);
  
 -#ifdef CONFIG_YAFFS_YAFFS2
 +      /* yaffs2 mode functions */
        int (*write_chunk_tags_fn) (struct yaffs_dev *dev,
                                    int nand_chunk, const u8 *data,
                                    const struct yaffs_ext_tags *tags);
        int (*query_block_fn) (struct yaffs_dev *dev, int block_no,
                               enum yaffs_block_state *state,
                               u32 *seq_number);
 -#endif
  
        /* The remove_obj_fn function must be supplied by OS flavours that
         * need it.
        int auto_unicode;
  #endif
        int always_check_erased;        /* Force chunk erased check always on */
+       int disable_summary;
  };
  
  struct yaffs_dev {
        unsigned gc_block;
        unsigned gc_chunk;
        unsigned gc_skip;
+       struct yaffs_summary_tags *gc_sum_tags;
  
        /* Special directories */
        struct yaffs_obj *root_dir;
        /* Dirty directory handling */
        struct list_head dirty_dirs;    /* List of dirty directories */
  
-       /* Statistcs */
+       /* Summary */
+       int chunks_per_summary;
+       struct yaffs_summary_tags *sum_tags;
+       /* Statistics */
        u32 n_page_writes;
        u32 n_page_reads;
        u32 n_erasures;
        u32 n_unmarked_deletions;
        u32 refresh_count;
        u32 cache_hits;
+       u32 tags_used;
+       u32 summary_used;
  
  };
  
diff --combined yaffs_vfs_multi.c
index 7e28c40514242dbf3c8dbf624a9a12f2fba78a17,15ff4ffdfb838d5ef00f2f0a946228d1ebb635f9..cf9df092390301af2413a5b005b36f0719342d20
@@@ -176,7 -176,7 +176,7 @@@ unsigned int yaffs_wr_attempts = YAFFS_
  unsigned int yaffs_auto_checkpoint = 1;
  unsigned int yaffs_gc_control = 1;
  unsigned int yaffs_bg_enable = 1;
 -
 +unsigned int yaffs_auto_select = 1;
  /* Module Parameters */
  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  module_param(yaffs_trace_mask, uint, 0644);
@@@ -307,12 -307,14 +307,12 @@@ static int yaffs_writepage(struct page 
  static int yaffs_writepage(struct page *page);
  #endif
  
 -#ifdef CONFIG_YAFFS_XATTR
  static int yaffs_setxattr(struct dentry *dentry, const char *name,
                   const void *value, size_t size, int flags);
  static ssize_t yaffs_getxattr(struct dentry *dentry, const char *name,
                                void *buff, size_t size);
  static int yaffs_removexattr(struct dentry *dentry, const char *name);
  static ssize_t yaffs_listxattr(struct dentry *dentry, char *buff, size_t size);
 -#endif
  
  #if (YAFFS_USE_WRITE_BEGIN_END != 0)
  static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
@@@ -407,10 -409,12 +407,10 @@@ static void zero_user_segment(struct pa
  
  static const struct inode_operations yaffs_file_inode_operations = {
        .setattr = yaffs_setattr,
 -#ifdef CONFIG_YAFFS_XATTR
        .setxattr = yaffs_setxattr,
        .getxattr = yaffs_getxattr,
        .listxattr = yaffs_listxattr,
        .removexattr = yaffs_removexattr,
 -#endif
  };
  
  static const struct inode_operations yaffs_symlink_inode_operations = {
        .put_link = yaffs_put_link,
  #endif
        .setattr = yaffs_setattr,
 -#ifdef CONFIG_YAFFS_XATTR
        .setxattr = yaffs_setxattr,
        .getxattr = yaffs_getxattr,
        .listxattr = yaffs_listxattr,
        .removexattr = yaffs_removexattr,
 -#endif
  };
  
  static const struct inode_operations yaffs_dir_inode_operations = {
        .mknod = yaffs_mknod,
        .rename = yaffs_rename,
        .setattr = yaffs_setattr,
 -#ifdef CONFIG_YAFFS_XATTR
        .setxattr = yaffs_setxattr,
        .getxattr = yaffs_getxattr,
        .listxattr = yaffs_listxattr,
        .removexattr = yaffs_removexattr,
 -#endif
  };
  
  static const struct file_operations yaffs_dir_operations = {
@@@ -1954,6 -1962,7 +1954,6 @@@ static int yaffs_setattr(struct dentry 
        return error;
  }
  
 -#ifdef CONFIG_YAFFS_XATTR
  static int yaffs_setxattr(struct dentry *dentry, const char *name,
                   const void *value, size_t size, int flags)
  {
@@@ -2056,6 -2065,7 +2056,6 @@@ static ssize_t yaffs_listxattr(struct d
        return error;
  }
  
 -#endif
  
  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf)
@@@ -2524,6 -2534,7 +2524,7 @@@ struct yaffs_options 
        int lazy_loading_overridden;
        int empty_lost_and_found;
        int empty_lost_and_found_overridden;
+       int disable_summary;
  };
  
  #define MAX_OPT_LEN 30
@@@ -2565,6 -2576,8 +2566,8 @@@ static int yaffs_parse_options(struct y
                } else if (!strcmp(cur_opt, "lazy-loading-on")) {
                        options->lazy_loading_enabled = 1;
                        options->lazy_loading_overridden = 1;
+               } else if (!strcmp(cur_opt, "disable_summary")) {
+                       options->disable_summary = 1;
                } else if (!strcmp(cur_opt, "empty-lost-and-found-off")) {
                        options->empty_lost_and_found = 0;
                        options->empty_lost_and_found_overridden = 1;
@@@ -2699,7 -2712,9 +2702,7 @@@ static struct super_block *yaffs_intern
        yaffs_trace(YAFFS_TRACE_OS, " size %lld", mtd->size);
  #endif
  
 -#ifdef CONFIG_YAFFS_AUTO_YAFFS2
 -
 -      if (yaffs_version == 1 && WRITE_SIZE(mtd) >= 2048) {
 +      if (yaffs_auto_select && yaffs_version == 1 && WRITE_SIZE(mtd) >= 2048) {
                yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs2");
                yaffs_version = 2;
        }
                yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs1");
                yaffs_version = 1;
        }
 -#endif
  
        if (yaffs_version == 2) {
                /* Check for version 2 style functions */
        param->n_caches = (options.no_cache) ? 0 : 10;
        param->inband_tags = options.inband_tags;
  
 -#ifdef CONFIG_YAFFS_DISABLE_LAZY_LOAD
 -      param->disable_lazy_load = 1;
 -#endif
 -#ifdef CONFIG_YAFFS_XATTR
        param->enable_xattr = 1;
 -#endif
        if (options.lazy_loading_overridden)
                param->disable_lazy_load = !options.lazy_loading_enabled;
  
 -#ifdef CONFIG_YAFFS_DISABLE_TAGS_ECC
 -      param->no_tags_ecc = 1;
 -#endif
 -
 -#ifdef CONFIG_YAFFS_DISABLE_BACKGROUND
 -#else
        param->defered_dir_update = 1;
 -#endif
  
        if (options.tags_ecc_overridden)
                param->no_tags_ecc = !options.tags_ecc_on;
  
 -#ifdef CONFIG_YAFFS_EMPTY_LOST_AND_FOUND
        param->empty_lost_n_found = 1;
 -#endif
 -
 -#ifdef CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING
 -      param->refresh_period = 0;
 -#else
        param->refresh_period = 500;
 -#endif
 -
 -#ifdef CONFIG_YAFFS__ALWAYS_CHECK_CHUNK_ERASED
 -      param->always_check_erased = 1;
 -#endif
+       param->disable_summary = options.disable_summary;
  
        if (options.empty_lost_and_found_overridden)
                param->empty_lost_n_found = options.empty_lost_and_found;
  
        yaffs_dev_to_lc(dev)->super = sb;
  
 -#ifndef CONFIG_YAFFS_DOES_ECC
        param->use_nand_ecc = 1;
 -#endif
 -
 -#ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES
 -      param->wide_tnodes_disabled = 1;
 -#endif
  
        param->skip_checkpt_rd = options.skip_checkpoint_read;
        param->skip_checkpt_wr = options.skip_checkpoint_write;
@@@ -3007,6 -3053,7 +3011,6 @@@ static DECLARE_FSTYPE(yaffs_fs_type, "y
                      FS_REQUIRES_DEV);
  #endif
  
 -#ifdef CONFIG_YAFFS_YAFFS2
  
  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
@@@ -3052,6 -3099,7 +3056,6 @@@ static DECLARE_FSTYPE(yaffs2_fs_type, "
                      FS_REQUIRES_DEV);
  #endif
  
 -#endif /* CONFIG_YAFFS_YAFFS2 */
  
  static struct proc_dir_entry *my_proc_entry;
  
@@@ -3124,6 -3172,8 +3128,8 @@@ static char *yaffs_dump_dev_part1(char 
                                dev->n_unlinked_files);
        buf += sprintf(buf, "refresh_count........ %u\n", dev->refresh_count);
        buf += sprintf(buf, "n_bg_deletions....... %u\n", dev->n_bg_deletions);
+       buf += sprintf(buf, "tags_used............ %u\n", dev->tags_used);
+       buf += sprintf(buf, "summary_used......... %u\n", dev->summary_used);
  
        return buf;
  }
@@@ -3350,6 -3400,12 +3356,6 @@@ static int __init init_yaffs_fs(void
        yaffs_trace(YAFFS_TRACE_ALWAYS,
                "yaffs built " __DATE__ " " __TIME__ " Installing.");
  
 -#ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED
 -      yaffs_trace(YAFFS_TRACE_ALWAYS,
 -              " \n\n\n\nYAFFS-WARNING CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED selected.\n\n\n\n"
 -      );
 -#endif
 -
        mutex_init(&yaffs_context_lock);
  
        /* Install the proc_fs entries */