Merge branch 'master' of ssh://www.aleph1.co.uk/home/aleph1/git/yaffs2
authorCharles Manning <cdhmanning@gmail.com>
Thu, 11 Jul 2013 05:46:25 +0000 (17:46 +1200)
committerCharles Manning <cdhmanning@gmail.com>
Thu, 11 Jul 2013 05:46:25 +0000 (17:46 +1200)
1  2 
yaffs_guts.c
yaffs_guts.h
yaffs_vfs_multi.c

diff --combined yaffs_guts.c
index 8507c2d94a7b128af414c7c0ad572716d73b163d,3672e8d41b692bf93088f317d303a8e4ce345f0a..1fd464d68af798c5fcdd02c537c7804bcbd05a5f
@@@ -980,7 -980,7 +980,7 @@@ static int yaffs_find_chunk_in_group(st
        return -1;
  }
  
 -static int yaffs_find_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
 +int yaffs_find_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
                                    struct yaffs_ext_tags *tags)
  {
        /*Get the Tnode, then get the level 0 offset chunk offset */
@@@ -4602,9 -4602,7 +4602,7 @@@ int yaffs_guts_ll_init(struct yaffs_de
  {
  
  
-       yaffs_trace(YAFFS_TRACE_TRACING, "yaffs: yaffs_guts_initialise()");
-       /* Check stuff that must be set */
+       yaffs_trace(YAFFS_TRACE_TRACING, "yaffs: yaffs_ll_init()");
  
        if (!dev) {
                yaffs_trace(YAFFS_TRACE_ALWAYS,
                return YAFFS_FAIL;
        }
  
-       if (dev->is_mounted) {
-               yaffs_trace(YAFFS_TRACE_ALWAYS, "device already mounted");
-               return YAFFS_FAIL;
-       }
+       if (dev->ll_init)
+               return YAFFS_OK;
  
        dev->internal_start_block = dev->param.start_block;
        dev->internal_end_block = dev->param.end_block;
                return YAFFS_FAIL;
        }
  
+       if (yaffs_init_nand(dev) != YAFFS_OK) {
+               yaffs_trace(YAFFS_TRACE_ALWAYS, "InitialiseNAND failed");
+               return YAFFS_FAIL;
+       }
+       return YAFFS_OK;
+ }
+ int yaffs_format_dev(struct yaffs_dev *dev)
+ {
+       int i;
+       enum yaffs_block_state state;
+       u32 dummy;
+       if(yaffs_guts_ll_init(dev) != YAFFS_OK)
+               return YAFFS_FAIL;
+       if(dev->is_mounted)
+               return YAFFS_FAIL;
+       for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
+               yaffs_query_init_block_state(dev, i, &state, &dummy);
+               if (state != YAFFS_BLOCK_STATE_DEAD)
+                       yaffs_erase_block(dev, i);
+       }
        return YAFFS_OK;
  }
  
@@@ -4686,9 -4709,8 +4709,8 @@@ int yaffs_guts_initialise(struct yaffs_
        if(yaffs_guts_ll_init(dev) != YAFFS_OK)
                return YAFFS_FAIL;
  
-       if (yaffs_init_nand(dev) != YAFFS_OK) {
-               yaffs_trace(YAFFS_TRACE_ALWAYS, "InitialiseNAND failed");
+       if (dev->is_mounted) {
+               yaffs_trace(YAFFS_TRACE_ALWAYS, "device already mounted");
                return YAFFS_FAIL;
        }
  
@@@ -5015,40 -5037,6 +5037,6 @@@ int yaffs_get_n_free_chunks(struct yaff
  }
  
  
- int yaffs_format_dev(struct yaffs_dev *dev)
- {
-       int i;
-       enum yaffs_block_state state;
-       u32 dummy;
-       if(dev->is_mounted)
-               return YAFFS_FAIL;
-       /*
-       * The runtime variables might not have been set up,
-       * so set up what we need.
-       */
-       dev->internal_start_block = dev->param.start_block;
-       dev->internal_end_block = dev->param.end_block;
-       dev->block_offset = 0;
-       dev->chunk_offset = 0;
-       if (dev->param.start_block == 0) {
-               dev->internal_start_block = dev->param.start_block + 1;
-               dev->internal_end_block = dev->param.end_block + 1;
-               dev->block_offset = 1;
-               dev->chunk_offset = dev->param.chunks_per_block;
-       }
-       for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
-               yaffs_query_init_block_state(dev, i, &state, &dummy);
-               if (state != YAFFS_BLOCK_STATE_DEAD)
-                       yaffs_erase_block(dev, i);
-       }
-       return YAFFS_OK;
- }
  
  /*
   * Marshalling functions to get loff_t file sizes into and out of
@@@ -5072,23 -5060,3 +5060,23 @@@ loff_t yaffs_oh_to_size(struct yaffs_ob
  
        return retval;
  }
 +
 +
 +void yaffs_count_blocks_by_state(struct yaffs_dev *dev, int bs[10])
 +{
 +      int i;
 +      struct yaffs_block_info *bi;
 +      int s;
 +
 +      for(i = 0; i < 10; i++)
 +              bs[i] = 0;
 +
 +      for(i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
 +              bi = yaffs_get_block_info(dev, i);
 +              s = bi->block_state;
 +              if(s > YAFFS_BLOCK_STATE_DEAD || s < YAFFS_BLOCK_STATE_UNKNOWN)
 +                      bs[0]++;
 +              else
 +                      bs[s]++;
 +      }
 +}
diff --combined yaffs_guts.h
index 9d71c2b6b8b67d782d7e79cf323ca339afbcdbce,fef4fc7011dc6aa78eb0a9fe4c4a1937659ce90b..05785367cb2e30a00daba4f928165d14ddaf0c33
@@@ -637,6 -637,7 +637,7 @@@ struct yaffs_dev 
  
        struct list_head dev_list;
  
+       int ll_init;
        /* Runtime parameters. Set up by YAFFS. */
        int data_bytes_per_chunk;
  
@@@ -989,14 -990,5 +990,14 @@@ void yaffs_oh_size_load(struct yaffs_ob
  loff_t yaffs_oh_to_size(struct yaffs_obj_hdr *oh);
  loff_t yaffs_max_file_size(struct yaffs_dev *dev);
  
 +/*
 + * Debug function to count number of blocks in each state
 + * NB Needs to be called with correct number of integers
 + */
 +
 +void yaffs_count_blocks_by_state(struct yaffs_dev *dev, int bs[10]);
 +
 +int yaffs_find_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
 +                                  struct yaffs_ext_tags *tags);
  
  #endif
diff --combined yaffs_vfs_multi.c
index 85826553043b2d7e3741f76d08bae118e10cd425,09aed4afa45f62911d0c3337b1c7e4de154db711..67050d4e3d2c1f7dd7b88a946567968a203ee251
@@@ -177,13 -177,8 +177,13 @@@ static uint32_t YCALCBLOCKS(uint64_t pa
  
  #include "yaffs_mtdif.h"
  #include "yaffs_packedtags2.h"
 +#include "yaffs_getblockinfo.h"
 +
 +unsigned int yaffs_trace_mask =
 +              YAFFS_TRACE_BAD_BLOCKS |
 +              YAFFS_TRACE_ALWAYS |
 +              0;
  
 -unsigned int yaffs_trace_mask = YAFFS_TRACE_BAD_BLOCKS | YAFFS_TRACE_ALWAYS;
  unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
  unsigned int yaffs_auto_checkpoint = 1;
  unsigned int yaffs_gc_control = 1;
@@@ -2610,6 -2605,7 +2610,7 @@@ static struct super_block *yaffs_intern
        struct yaffs_param *param;
  
        int read_only = 0;
+       int inband_tags = 0;
  
        struct yaffs_options options;
  
                yaffs_version = 1;
        }
  
-       if(yaffs_verify_mtd(mtd, yaffs_version, options.inband_tags) < 0)
+       if (mtd->oobavail < sizeof(struct yaffs_packed_tags2) ||
+           options.inband_tags)
+               inband_tags = 1;
+       if(yaffs_verify_mtd(mtd, yaffs_version, inband_tags) < 0)
                return NULL;
  
        /* OK, so if we got here, we have an MTD that's NAND and looks
  
        param->n_reserved_blocks = 5;
        param->n_caches = (options.no_cache) ? 0 : 10;
-       if (mtd->oobavail < sizeof(struct yaffs_packed_tags2) ||
-           options.inband_tags)
-               param->inband_tags = 1;
+       param->inband_tags = inband_tags;
  
        param->enable_xattr = 1;
        if (options.lazy_loading_overridden)
@@@ -3001,9 -2998,6 +3003,9 @@@ static struct proc_dir_entry *my_proc_e
  static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
  {
        struct yaffs_param *param = &dev->param;
 +      int bs[10];
 +
 +      yaffs_count_blocks_by_state(dev,bs);
  
        buf += sprintf(buf, "start_block.......... %d\n", param->start_block);
        buf += sprintf(buf, "end_block............ %d\n", param->end_block);
        buf += sprintf(buf, "always_check_erased.. %d\n",
                                param->always_check_erased);
        buf += sprintf(buf, "\n");
 +      buf += sprintf(buf, "block count by state\n");
 +      buf += sprintf(buf, "0:%d 1:%d 2:%d 3:%d 4:%d\n",
 +                              bs[0], bs[1], bs[2], bs[3], bs[4]);
 +      buf += sprintf(buf, "5:%d 6:%d 7:%d 8:%d 9:%d\n",
 +                              bs[5], bs[6], bs[7], bs[8], bs[9]);
  
        return buf;
  }
@@@ -3281,92 -3270,9 +3283,92 @@@ static int yaffs_proc_write_trace_optio
        return count;
  }
  
 +/* Debug strings are of the form:
 + * .bnnn         print info on block n
 + * .cobjn,chunkn print nand chunk id for objn:chunkn
 + */
 +
 +static int yaffs_proc_debug_write(struct file *file, const char *buf,
 +                                        unsigned long count, void *data)
 +{
 +
 +      char str[100];
 +      char *p0;
 +      char *p1;
 +      long p1_val;
 +      long p0_val;
 +      char cmd;
 +      struct list_head *item;
 +
 +      memset(str, 0, sizeof(str));
 +      memcpy(str, buf, min(count, sizeof(str) -1));
 +
 +      cmd = str[1];
 +
 +      p0 = str + 2;
 +
 +      p1 = p0;
 +
 +      while (*p1 && *p1 != ',') {
 +              p1++;
 +      }
 +      *p1 = '\0';
 +      p1++;
 +
 +      p0_val = simple_strtol(p0, NULL, 0);
 +      p1_val = simple_strtol(p1, NULL, 0);
 +
 +
 +      mutex_lock(&yaffs_context_lock);
 +
 +      /* Locate and print the Nth entry.  Order N-squared but N is small. */
 +      list_for_each(item, &yaffs_context_list) {
 +              struct yaffs_linux_context *dc =
 +                  list_entry(item, struct yaffs_linux_context,
 +                             context_list);
 +              struct yaffs_dev *dev = dc->dev;
 +
 +              if (cmd == 'b') {
 +                      struct yaffs_block_info *bi;
 +
 +                      bi = yaffs_get_block_info(dev,p0_val);
 +
 +                      if(bi) {
 +                              printk("Block %d: state %d, retire %d, use %d, seq %d\n",
 +                                      (int)p0_val, bi->block_state,
 +                                      bi->needs_retiring, bi->pages_in_use,
 +                                      bi->seq_number);
 +                      }
 +              } else if (cmd == 'c') {
 +                      struct yaffs_obj *obj;
 +                      int nand_chunk;
 +
 +                      obj = yaffs_find_by_number(dev, p0_val);
 +                      if (!obj)
 +                              printk("No obj %d\n", (int)p0_val);
 +                      else {
 +                              if(p1_val == 0)
 +                                      nand_chunk = obj->hdr_chunk;
 +                              else
 +                                      nand_chunk =
 +                                              yaffs_find_chunk_in_file(obj,
 +                                                      p1_val, NULL);
 +                              printk("Nand chunk for %d:%d is %d\n",
 +                                      (int)p0_val, (int)p1_val, nand_chunk);
 +                      }
 +              }
 +      }
 +
 +      mutex_unlock(&yaffs_context_lock);
 +
 +      return count;
 +}
 +
  static int yaffs_proc_write(struct file *file, const char *buf,
                            unsigned long count, void *data)
  {
 +      if (buf[0] == '.')
 +              return yaffs_proc_debug_write(file, buf, count, data);
        return yaffs_proc_write_trace_options(file, buf, count, data);
  }