yaffs: Tweaks to summary code
authorCharles Manning <cdhmanning@gmail.com>
Thu, 31 Mar 2011 01:42:56 +0000 (14:42 +1300)
committerCharles Manning <cdhmanning@gmail.com>
Thu, 31 Mar 2011 01:42:56 +0000 (14:42 +1300)
Trying some different ideas for handling free space cleaner.

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
Makefile
yaffs_guts.c
yaffs_guts.h
yaffs_summary.c
yaffs_summary.h
yaffs_vfs_multi.c
yaffs_yaffs2.c

index 14e3a2912d193f99fda642c44b1cc8451ac7fcbe..db1b5c21e9dfe8b3a1389da1f2b18e1b67ec327e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -37,6 +37,7 @@ ifneq ($(KERNELRELEASE),)
        yaffs2-objs += yaffs_yaffs1.o
        yaffs2-objs += yaffs_yaffs2.o
        yaffs2-objs += yaffs_verify.o
+       yaffs2-objs += yaffs_summary.o
 
        yaffs2multi-objs := yaffs_mtdif.o yaffs_mtdif2_multi.o
        yaffs2multi-objs += yaffs_mtdif1_multi.o yaffs_packedtags1.o
@@ -49,6 +50,7 @@ ifneq ($(KERNELRELEASE),)
        yaffs2multi-objs += yaffs_yaffs1.o
        yaffs2multi-objs += yaffs_yaffs2.o
        yaffs2multi-objs += yaffs_verify.o
+       yaffs2multi-objs += yaffs_summary.o
 
 else
        KERNELDIR ?= /lib/modules/$(shell uname -r)/build
index 24126a140abfbe225678f3a907d89b6b684ea7a9..dfabf4c29d23ea75e1b0e9bfb4d0b6a5e7360ab4 100644 (file)
@@ -2383,6 +2383,8 @@ void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no)
        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);
@@ -2558,6 +2560,8 @@ static int yaffs_gc_block(struct yaffs_dev *dev, int block, int whole_block)
 
        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",
@@ -4814,7 +4818,9 @@ int yaffs_guts_initialise(struct yaffs_dev *dev)
        if (!init_failed && !yaffs_create_initial_dir(dev))
                init_failed = 1;
 
-       if(!init_failed && dev->param.is_yaffs2 && !yaffs_summary_init(dev))
+       if(!init_failed && dev->param.is_yaffs2 &&
+               !dev->param.disable_summary &&
+               !yaffs_summary_init(dev))
                init_failed = 1;
 
        if (!init_failed) {
index 631bd65b52b0aba1e1aa36c249d7aca5437ea3e1..fc311435207c08bcdbbbd115695e702d610d6aa8 100644 (file)
@@ -282,6 +282,7 @@ 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 */
@@ -590,6 +591,8 @@ struct yaffs_param {
        int auto_unicode;
 #endif
        int always_check_erased;        /* Force chunk erased check always on */
+
+       int disable_summary;
 };
 
 struct yaffs_dev {
@@ -689,6 +692,7 @@ 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;
@@ -735,7 +739,7 @@ struct yaffs_dev {
        int chunks_per_summary;
        struct yaffs_summary_tags *sum_tags;
 
-       /* Statistcs */
+       /* Statistics */
        u32 n_page_writes;
        u32 n_page_reads;
        u32 n_erasures;
@@ -756,6 +760,8 @@ struct yaffs_dev {
        u32 n_unmarked_deletions;
        u32 refresh_count;
        u32 cache_hits;
+       u32 tags_used;
+       u32 summary_used;
 
 };
 
index 04ef96b09e84712634ffbc28ecd6a08d7acc491a..31d443a872710fec5ff406892579ad4bc2608dc5 100644 (file)
  *
  * Chunks holding summaries are marked with tags making it look like
  * they are part of a fake file.
+ *
+ * The chunks that hold the summary are removed from free space and are marked
+ * as being in use.
+ *
+ * THa above might need to be revisited.
  */
 
 #include "yaffs_summary.h"
 #include "yaffs_packedtags2.h"
 #include "yaffs_nand.h"
+#include "yaffs_getblockinfo.h"
+#include "yaffs_bitmap.h"
 
 /* Summary tags don't need the sequence number becase that is redundant. */
 struct yaffs_summary_tags {
@@ -41,7 +48,6 @@ static void yaffs_summary_clear(struct yaffs_dev *dev)
 
 int yaffs_summary_init(struct yaffs_dev *dev)
 {
-       struct yaffs_summary_tags *sum;
        int sum_bytes;
        int chunks_used; /* Number of chunks used by summary */
 
@@ -51,12 +57,16 @@ int yaffs_summary_init(struct yaffs_dev *dev)
        chunks_used = (sum_bytes + dev->data_bytes_per_chunk - 1)/
                        dev->data_bytes_per_chunk;
        dev->chunks_per_summary = dev->param.chunks_per_block - chunks_used;
-       sum = kmalloc(sizeof(struct yaffs_summary_tags) *
+       dev->sum_tags = kmalloc(sizeof(struct yaffs_summary_tags) *
                                dev->chunks_per_summary, GFP_NOFS);
-       if(!sum)
+       dev->gc_sum_tags = kmalloc(sizeof(struct yaffs_summary_tags) *
+                               dev->chunks_per_summary, GFP_NOFS);
+       if(!dev->sum_tags || !dev->gc_sum_tags) {
+               kfree(dev->sum_tags);
+               kfree(dev->gc_sum_tags);
                return YAFFS_FAIL;
+       }
 
-       dev->sum_tags = sum;
        yaffs_summary_clear(dev);
 
        return YAFFS_OK;
@@ -64,28 +74,31 @@ int yaffs_summary_init(struct yaffs_dev *dev)
 
 void yaffs_summary_deinit(struct yaffs_dev *dev)
 {
-       if(dev->sum_tags) {
-               kfree(dev->sum_tags);
-               dev->sum_tags = NULL;
-       }
+       kfree(dev->sum_tags);
+       dev->sum_tags = NULL;
+       kfree(dev->sum_tags);
+       dev->sum_tags = NULL;
        dev->chunks_per_summary = 0;
 }
 
-static int yaffs_summary_write(struct yaffs_dev *dev)
+static int yaffs_summary_write(struct yaffs_dev *dev, int blk)
 {
        struct yaffs_ext_tags tags;
        u8 *buffer;
        u8 *sum_buffer = (u8 *)dev->sum_tags;
        int n_bytes;
        int chunk_in_nand;
+       int chunk_in_block;
        int result;
        int this_tx;
+       struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk);
 
        buffer = yaffs_get_temp_buffer(dev);
        n_bytes = sizeof(struct yaffs_summary_tags) * dev->chunks_per_summary;
        memset(&tags, 0, sizeof(struct yaffs_ext_tags));
        tags.obj_id = YAFFS_OBJECTID_SUMMARY;
        tags.chunk_id = 1;
+       chunk_in_block = dev-> chunks_per_summary;
        chunk_in_nand = dev->alloc_block * dev->param.chunks_per_block +
                                                dev-> chunks_per_summary;
        do {
@@ -96,28 +109,49 @@ static int yaffs_summary_write(struct yaffs_dev *dev)
                tags.n_bytes = this_tx;
                result = yaffs_wr_chunk_tags_nand(dev, chunk_in_nand,
                                                buffer, &tags);
+
+               if (result != YAFFS_OK)
+                       break;
+               yaffs_set_chunk_bit(dev, blk, chunk_in_block);
+               bi->pages_in_use++;
+               dev->n_free_chunks--;
+
                n_bytes -= this_tx;
                sum_buffer += this_tx;
                chunk_in_nand++;
+               chunk_in_block++;
                tags.chunk_id++;
+
+               chunk_in_block++;
        } while (result == YAFFS_OK && n_bytes > 0);
        yaffs_release_temp_buffer(dev, buffer);
+
+
+       if (result == YAFFS_OK)
+               bi->has_summary = 1;
+
+
        return result;
 }
 
-int yaffs_summary_read(struct yaffs_dev *dev, int blk)
+int yaffs_summary_read(struct yaffs_dev *dev,
+                       struct yaffs_summary_tags *st,
+                       int blk)
 {
        struct yaffs_ext_tags tags;
        u8 *buffer;
-       u8 *sum_buffer = (u8 *)dev->sum_tags;
+       u8 *sum_buffer = (u8 *)st;
        int n_bytes;
        int chunk_id;
        int chunk_in_nand;
+       int chunk_in_block;
        int result;
        int this_tx;
+       struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk);
 
        buffer = yaffs_get_temp_buffer(dev);
        n_bytes = sizeof(struct yaffs_summary_tags) * dev->chunks_per_summary;
+       chunk_in_block = dev->chunks_per_summary;
        chunk_in_nand = blk * dev->param.chunks_per_block +
                                                        dev->chunks_per_summary;
        chunk_id = 1;
@@ -137,14 +171,24 @@ int yaffs_summary_read(struct yaffs_dev *dev, int blk)
                if (result != YAFFS_OK)
                        break;
 
+               if (st == dev->sum_tags) {
+                       /* If we're scanning then update the block info */
+                       yaffs_set_chunk_bit(dev, blk, chunk_in_block);
+                       bi->pages_in_use++;
+               }
+
                memcpy(sum_buffer, buffer, this_tx);
                n_bytes -= this_tx;
                sum_buffer += this_tx;
                chunk_in_nand++;
+               chunk_in_block++;
                chunk_id++;
-               dev->n_free_chunks--;
        } while (result == YAFFS_OK && n_bytes > 0);
        yaffs_release_temp_buffer(dev, buffer);
+
+       if (st == dev->sum_tags && result == YAFFS_OK)
+               bi->has_summary = 1;
+
        return result;
 }
 int yaffs_summary_add(struct yaffs_dev *dev,
@@ -153,30 +197,26 @@ int yaffs_summary_add(struct yaffs_dev *dev,
 {
        struct yaffs_packed_tags2_tags_only tags_only;
        struct yaffs_summary_tags *sum_tags;
+       int block_in_nand = chunk_in_nand / dev->param.chunks_per_block;
        int chunk_in_block = chunk_in_nand % dev->param.chunks_per_block;
 
        if(!dev->sum_tags)
                return YAFFS_OK;
 
-       printf("Add summary for chunk %d tags (%d %d %d)",chunk_in_block,
-                       tags->seq_number, tags->obj_id, tags->chunk_id);
        if(chunk_in_block >= 0 && chunk_in_block < dev->chunks_per_summary) {
                yaffs_pack_tags2_tags_only(&tags_only, tags);
                sum_tags = &dev->sum_tags[chunk_in_block];
                sum_tags->chunk_id = tags_only.chunk_id;
                sum_tags->n_bytes = tags_only.n_bytes;
                sum_tags->obj_id = tags_only.obj_id;
-               printf(" added %d %d %d", sum_tags->obj_id, sum_tags->chunk_id, sum_tags->n_bytes);
 
                if(chunk_in_block == dev->chunks_per_summary - 1) {
-                       printf(" Write summary");
                        /* Time to write out the summary */
-                       yaffs_summary_write(dev);
+                       yaffs_summary_write(dev, block_in_nand);
                        yaffs_summary_clear(dev);
                        yaffs_skip_rest_of_block(dev);
                }
        }
-       printf("\n");
        return YAFFS_OK;
 }
 
@@ -196,3 +236,15 @@ int yaffs_summary_fetch(struct yaffs_dev *dev,
        }
        return YAFFS_FAIL;
 }
+
+void yaffs_summary_gc(struct yaffs_dev *dev, int blk)
+{
+       struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk);
+       int i;
+
+       if (!bi->has_summary)
+               return;
+
+       for (i = dev->chunks_per_summary; i < dev->param.chunks_per_block; i++)
+               yaffs_clear_chunk_bit(dev, blk, i);
+}
index e2197455774514c9a57fc0141526e3d093fce306..be141d0733696b59cd55620e1d4f652b15fabf8f 100644 (file)
@@ -28,6 +28,10 @@ int yaffs_summary_add(struct yaffs_dev *dev,
 int yaffs_summary_fetch(struct yaffs_dev *dev,
                        struct yaffs_ext_tags *tags,
                        int chunk_in_block);
-int yaffs_summary_read(struct yaffs_dev *dev, int blk);
+int yaffs_summary_read(struct yaffs_dev *dev,
+                       struct yaffs_summary_tags *st,
+                       int blk);
+void yaffs_summary_gc(struct yaffs_dev *dev, int blk);
+
 
 #endif
index acf43480b69bd13ad931be86d2e9364184f865f3..15ff4ffdfb838d5ef00f2f0a946228d1ebb635f9 100644 (file)
@@ -2534,6 +2534,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
@@ -2575,6 +2576,8 @@ static int yaffs_parse_options(struct yaffs_options *options,
                } 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;
@@ -2873,6 +2876,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
 #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;
@@ -3168,6 +3172,8 @@ static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev)
                                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;
 }
index 34c0bde985cb5d972624d31b9e905b5aa489511d..093e485ac2d064318db67b60b1eb5b508e90b555 100644 (file)
@@ -957,9 +957,13 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
                result = yaffs_summary_fetch(dev, &tags, chunk_in_block);
                tags.seq_number = bi->seq_number;
        }
-       
-       if (!summary_available || tags.obj_id == 0)
+
+       if (!summary_available || tags.obj_id == 0) {
                result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL, &tags);
+               dev->tags_used++;
+       } else {
+               dev->summary_used++;
+       }
 
        /* Let's have a good look at this chunk... */
 
@@ -1464,7 +1468,7 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev)
                bi = yaffs_get_block_info(dev, blk);
                deleted = 0;
 
-               summary_available = yaffs_summary_read(dev, blk);
+               summary_available = yaffs_summary_read(dev, dev->sum_tags, blk);
 
                /* For each chunk in each block that needs scanning.... */
                found_chunks = 0;