diff options
author | Charles Manning <cdhmanning@gmail.com> | 2011-04-28 15:57:52 +1200 |
---|---|---|
committer | Charles Manning <cdhmanning@gmail.com> | 2011-04-28 15:57:52 +1200 |
commit | c4e8d85455d0acf2a3da23c20cd2db66d30caf1b (patch) | |
tree | abfa55c23a80b73f76a001fd7d32a028983ee9ce | |
parent | 7715144e7d55b2854f907001c432348e4caa5954 (diff) | |
parent | 447f47497bcd9acf7e59823a4e43888356200dc9 (diff) |
Merge branch 'block-summary'
Conflicts:
yaffs_vfs_multi.c
Signed-off-by: Charles Manning <cdhmanning@gmail.com>
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | direct/basic-test/Makefile | 6 | ||||
-rw-r--r-- | direct/basic-test/dtest.c | 2 | ||||
-rw-r--r-- | direct/tests/Makefile | 6 | ||||
-rw-r--r-- | yaffs_guts.c | 12 | ||||
-rw-r--r-- | yaffs_guts.h | 18 | ||||
-rw-r--r-- | yaffs_nand.c | 21 | ||||
-rw-r--r-- | yaffs_summary.c | 254 | ||||
-rw-r--r-- | yaffs_summary.h | 37 | ||||
-rw-r--r-- | yaffs_vfs_multi.c | 6 | ||||
-rw-r--r-- | yaffs_yaffs2.c | 32 |
11 files changed, 376 insertions, 20 deletions
@@ -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 diff --git a/direct/basic-test/Makefile b/direct/basic-test/Makefile index 92891ae..afe0ef0 100644 --- a/direct/basic-test/Makefile +++ b/direct/basic-test/Makefile @@ -44,7 +44,8 @@ COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o \ yaffs_bitmap.o \ yaffs_yaffs1.o \ yaffs_yaffs2.o \ - yaffs_verify.o + yaffs_verify.o \ + yaffs_summary.o # yaffs_checkptrwtest.o\ @@ -59,7 +60,8 @@ YAFFSSYMLINKS = yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscomp yaffs_yaffs1.c yaffs_yaffs1.h \ yaffs_yaffs2.c yaffs_yaffs2.h \ yaffs_bitmap.c yaffs_bitmap.h \ - yaffs_verify.c yaffs_verify.h + yaffs_verify.c yaffs_verify.h \ + yaffs_summary.c yaffs_summary.h YAFFSDIRECTSYMLINKS = yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\ yaffsfs.h yaffs_osglue.h ydirectenv.h \ diff --git a/direct/basic-test/dtest.c b/direct/basic-test/dtest.c index f8c6170..97e8fbe 100644 --- a/direct/basic-test/dtest.c +++ b/direct/basic-test/dtest.c @@ -2775,7 +2775,7 @@ int main(int argc, char *argv[]) //null_name_test("yaffs2"); test_flash_traffic("yaffs2"); - link_follow_test("/yaffs2"); + // link_follow_test("/yaffs2"); return 0; diff --git a/direct/tests/Makefile b/direct/tests/Makefile index 76dcd2b..1389552 100644 --- a/direct/tests/Makefile +++ b/direct/tests/Makefile @@ -41,7 +41,8 @@ COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o\ yaffs_bitmap.o \ yaffs_yaffs1.o \ yaffs_yaffs2.o \ - yaffs_verify.o + yaffs_verify.o \ + yaffs_summary.o # yaffs_checkptrwtest.o\ @@ -60,7 +61,8 @@ YAFFSSYMLINKS = yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscomp yaffs_yaffs1.c yaffs_yaffs1.h \ yaffs_yaffs2.c yaffs_yaffs2.h \ yaffs_bitmap.c yaffs_bitmap.h \ - yaffs_verify.c yaffs_verify.h + yaffs_verify.c yaffs_verify.h \ + yaffs_summary.c yaffs_summary.h YAFFSDIRECTSYMLINKS = yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\ yaffsfs.h yaffs_osglue.h ydirectenv.h \ diff --git a/yaffs_guts.c b/yaffs_guts.c index cd70c54..d72aa5b 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -27,6 +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 @@ -2380,6 +2381,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); @@ -2555,6 +2558,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", @@ -4806,6 +4811,11 @@ 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 && + !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 +4901,8 @@ void yaffs_deinitialise(struct yaffs_dev *dev) 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 --git a/yaffs_guts.h b/yaffs_guts.h index 77c05d3..6ec8a47 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -78,10 +78,12 @@ #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 @@ -278,6 +280,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 */ u32 has_shrink_hdr:1; /* This block has at least one shrink header */ u32 seq_number; /* block sequence number for yaffs2 */ @@ -582,6 +585,8 @@ struct yaffs_param { int auto_unicode; #endif int always_check_erased; /* Force chunk erased check always on */ + + int disable_summary; }; struct yaffs_dev { @@ -681,6 +686,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; @@ -723,7 +729,11 @@ struct yaffs_dev { /* 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; @@ -744,6 +754,8 @@ struct yaffs_dev { u32 n_unmarked_deletions; u32 refresh_count; u32 cache_hits; + u32 tags_used; + u32 summary_used; }; diff --git a/yaffs_nand.c b/yaffs_nand.c index 0b59ec7..165d010 100644 --- a/yaffs_nand.c +++ b/yaffs_nand.c @@ -15,13 +15,14 @@ #include "yaffs_tagscompat.h" #include "yaffs_getblockinfo.h" +#include "yaffs_summary.h" int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, u8 *buffer, struct yaffs_ext_tags *tags) { int result; struct yaffs_ext_tags local_tags; - int realigned_chunk = nand_chunk - dev->chunk_offset; + int flash_chunk = nand_chunk - dev->chunk_offset; dev->n_page_reads++; @@ -31,11 +32,11 @@ int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, if (dev->param.read_chunk_tags_fn) result = - dev->param.read_chunk_tags_fn(dev, realigned_chunk, buffer, + dev->param.read_chunk_tags_fn(dev, flash_chunk, buffer, tags); else result = yaffs_tags_compat_rd(dev, - realigned_chunk, buffer, tags); + flash_chunk, buffer, tags); if (tags && tags->ecc_result > YAFFS_ECC_RESULT_NO_ERROR) { struct yaffs_block_info *bi; @@ -51,8 +52,10 @@ int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, const u8 *buffer, struct yaffs_ext_tags *tags) { + int result; + int flash_chunk = nand_chunk - dev->chunk_offset; + dev->n_page_writes++; - nand_chunk -= dev->chunk_offset; if (tags) { tags->seq_number = dev->seq_number; @@ -67,10 +70,14 @@ int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev, } if (dev->param.write_chunk_tags_fn) - return dev->param.write_chunk_tags_fn(dev, nand_chunk, buffer, - tags); + result = dev->param.write_chunk_tags_fn(dev, flash_chunk, + buffer, tags); + else + result = yaffs_tags_compat_wr(dev, flash_chunk, buffer, tags); - return yaffs_tags_compat_wr(dev, nand_chunk, buffer, tags); + yaffs_summary_add(dev, tags, nand_chunk); + + return result; } int yaffs_mark_bad(struct yaffs_dev *dev, int block_no) diff --git a/yaffs_summary.c b/yaffs_summary.c new file mode 100644 index 0000000..b9ef0d2 --- /dev/null +++ b/yaffs_summary.c @@ -0,0 +1,254 @@ +/* + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. + * + * Copyright (C) 2002-2011 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning <charles@aleph1.co.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* Summaries write the useful part of the tags for the chunks in a block into an + * an array which is written to the last n chunks of the block. + * Reading the summaries gives all the tags for the block in one read. Much + * faster. + * + * Chunks holding summaries are marked with tags making it look like + * they are part of a fake file. + * + * The summary could also be used during gc. + * + */ + +#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 because that is redundant. */ +struct yaffs_summary_tags { + unsigned obj_id; + unsigned chunk_id; + unsigned n_bytes; +}; + +static void yaffs_summary_clear(struct yaffs_dev *dev) +{ + if(!dev->sum_tags) + return; + memset(dev->sum_tags, 0, dev->chunks_per_summary * + sizeof(struct yaffs_summary_tags)); +} + +int yaffs_summary_init(struct yaffs_dev *dev) +{ + int sum_bytes; + int chunks_used; /* Number of chunks used by summary */ + + sum_bytes = dev->param.chunks_per_block * + sizeof(struct yaffs_summary_tags); + + 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; + dev->sum_tags = kmalloc(sizeof(struct yaffs_summary_tags) * + dev->chunks_per_summary, GFP_NOFS); + 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; + } + + yaffs_summary_clear(dev); + + return YAFFS_OK; +} + +void yaffs_summary_deinit(struct yaffs_dev *dev) +{ + kfree(dev->sum_tags); + dev->sum_tags = NULL; + kfree(dev->gc_sum_tags); + dev->gc_sum_tags = NULL; + dev->chunks_per_summary = 0; +} + +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 { + this_tx = n_bytes; + if (this_tx > dev->data_bytes_per_chunk) + this_tx = dev->data_bytes_per_chunk; + memcpy(buffer, sum_buffer, this_tx); + 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, + struct yaffs_summary_tags *st, + int blk) +{ + struct yaffs_ext_tags tags; + u8 *buffer; + 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; + do { + this_tx = n_bytes; + if(this_tx > dev->data_bytes_per_chunk) + this_tx = dev->data_bytes_per_chunk; + result = yaffs_rd_chunk_tags_nand(dev, chunk_in_nand, + buffer, &tags); + + if (tags.chunk_id != chunk_id || + tags.obj_id != YAFFS_OBJECTID_SUMMARY || + tags.chunk_used == 0 || + tags.ecc_result > YAFFS_ECC_RESULT_FIXED || + this_tx != tags.n_bytes) + result = YAFFS_FAIL; + 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++; + } 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, + struct yaffs_ext_tags *tags, + int chunk_in_nand) +{ + 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; + + 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; + + if(chunk_in_block == dev->chunks_per_summary - 1) { + /* Time to write out the summary */ + yaffs_summary_write(dev, block_in_nand); + yaffs_summary_clear(dev); + yaffs_skip_rest_of_block(dev); + } + } + return YAFFS_OK; +} + +int yaffs_summary_fetch(struct yaffs_dev *dev, + struct yaffs_ext_tags *tags, + int chunk_in_block) +{ + struct yaffs_packed_tags2_tags_only tags_only; + struct yaffs_summary_tags *sum_tags; + if(chunk_in_block >= 0 && chunk_in_block < dev->chunks_per_summary) { + sum_tags = &dev->sum_tags[chunk_in_block]; + tags_only.chunk_id = sum_tags->chunk_id; + tags_only.n_bytes = sum_tags->n_bytes; + tags_only.obj_id = sum_tags->obj_id; + yaffs_unpack_tags2_tags_only(tags, &tags_only); + return YAFFS_OK; + } + 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++) { + if( yaffs_check_chunk_bit(dev, blk, i)) { + yaffs_clear_chunk_bit(dev, blk, i); + bi->pages_in_use--; + dev->n_free_chunks++; + } + } + +} diff --git a/yaffs_summary.h b/yaffs_summary.h new file mode 100644 index 0000000..be141d0 --- /dev/null +++ b/yaffs_summary.h @@ -0,0 +1,37 @@ +/* + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. + * + * Copyright (C) 2002-2011 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning <charles@aleph1.co.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. + */ + +#ifndef __YAFFS_SUMMARY_H__ +#define __YAFFS_SUMMARY_H__ + +#include "yaffs_packedtags2.h" + + +int yaffs_summary_init(struct yaffs_dev *dev); +void yaffs_summary_deinit(struct yaffs_dev *dev); + +int yaffs_summary_add(struct yaffs_dev *dev, + struct yaffs_ext_tags *tags, + int chunk_in_block); +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, + struct yaffs_summary_tags *st, + int blk); +void yaffs_summary_gc(struct yaffs_dev *dev, int blk); + + +#endif diff --git a/yaffs_vfs_multi.c b/yaffs_vfs_multi.c index 7e28c40..cf9df09 100644 --- a/yaffs_vfs_multi.c +++ b/yaffs_vfs_multi.c @@ -2524,6 +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 +2566,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; @@ -2837,6 +2840,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, param->empty_lost_n_found = 1; param->refresh_period = 500; + param->disable_summary = options.disable_summary; if (options.empty_lost_and_found_overridden) param->empty_lost_n_found = options.empty_lost_and_found; @@ -3124,6 +3128,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; } diff --git a/yaffs_yaffs2.c b/yaffs_yaffs2.c index f4a7a7f..093e485 100644 --- a/yaffs_yaffs2.c +++ b/yaffs_yaffs2.c @@ -20,6 +20,7 @@ #include "yaffs_getblockinfo.h" #include "yaffs_verify.h" #include "yaffs_attribs.h" +#include "yaffs_summary.h" /* * Checkpoints are really no benefit on very small partitions. @@ -934,7 +935,8 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev, int blk, int chunk_in_block, int *found_chunks, u8 *chunk_data, - struct list_head *hard_list) + struct list_head *hard_list, + int summary_available) { struct yaffs_obj_hdr *oh; struct yaffs_obj *in; @@ -951,7 +953,17 @@ static inline int yaffs2_scan_chunk(struct yaffs_dev *dev, struct yaffs_hardlink_var *hl_var; struct yaffs_symlink_var *sl_var; - result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL, &tags); + if (summary_available) { + result = yaffs_summary_fetch(dev, &tags, chunk_in_block); + tags.seq_number = bi->seq_number; + } + + 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... */ @@ -1346,6 +1358,7 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev) int alloc_failed = 0; struct yaffs_block_index *block_index = NULL; int alt_block_index = 0; + int summary_available; yaffs_trace(YAFFS_TRACE_SCAN, "yaffs2_scan_backwards starts intstartblk %d intendblk %d...", @@ -1455,18 +1468,27 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev) bi = yaffs_get_block_info(dev, blk); deleted = 0; + summary_available = yaffs_summary_read(dev, dev->sum_tags, blk); + /* For each chunk in each block that needs scanning.... */ found_chunks = 0; - for (c = dev->param.chunks_per_block - 1; + if(summary_available) + c = dev->chunks_per_summary - 1; + else + c = dev->param.chunks_per_block - 1; + + for (/* c is already initialised */; !alloc_failed && c >= 0 && (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN || - bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING); c--) { + bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING); + c--) { /* Scan backwards... * Read the tags and decide what to do */ if (yaffs2_scan_chunk(dev, bi, blk, c, &found_chunks, chunk_data, - &hard_list) == YAFFS_FAIL) + &hard_list, summary_available) == + YAFFS_FAIL) alloc_failed = 1; } |