From: Charles Manning Date: Tue, 16 Mar 2021 23:10:16 +0000 (+1300) Subject: Some clean up and more modular cache management X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=commitdiff_plain;h=223ff79f689aba309ebc3ef856fb46095148d40e Some clean up and more modular cache management Signed-off-by: Charles Manning --- diff --git a/direct/test-framework/basic-tests/dtest.c b/direct/test-framework/basic-tests/dtest.c index 8b58762..405f00a 100644 --- a/direct/test-framework/basic-tests/dtest.c +++ b/direct/test-framework/basic-tests/dtest.c @@ -118,9 +118,6 @@ int check_pattern_file(char *fn) } - - - int dump_file_data(char *fn) { int h; @@ -1524,6 +1521,40 @@ void fill_disk_test(const char *mountpt) } +void fill_n_file_test(const char *mountpt, int n, int syz) +{ + int i; + int l; + + yaffs_start_up(); + + yaffs_format(mountpt, 0, 0, 0); + yaffs_mount(mountpt); + + + for(i = 0; i < n; i++) + { + int h; + char fname[200]; + + sprintf(fname, "%s/%d", mountpt, i); + + h = yaffs_open(fname, O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); + + l = syz; + + while(l > 0) { + yaffs_write(h, fname, sizeof(fname)); + l -= sizeof(fname); + } + + yaffs_close(h); + + } + +} + + void fill_files_test(const char *mountpt) { int i; @@ -3431,6 +3462,9 @@ int simulate_power_failure; int main(int argc, char *argv[]) { + //unlink("emfile-nand"); + + atexit(dump_yaffs_malloc_usage); (void) argc; @@ -3459,7 +3493,8 @@ int main(int argc, char *argv[]) //link_test0("/nand"); //link_test1("yaffs2"); //scan_pattern_test("/flash",10000,10); - short_scan_test("/yflash2",40000,200); + //short_scan_test("/yflash2",40000,200); + //short_scan_test("/nand128MB",40000,200); //small_mount_test("/flash/flash",1000); //small_overwrite_test("/flash/flash",1000); //seek_overwrite_test("/flash/flash",1000); @@ -3476,7 +3511,7 @@ int main(int argc, char *argv[]) //long_test_on_path("/ram2k"); // long_test_on_path("/flash"); //simple_rw_test("/flash/flash"); - //fill_disk_test("/nand"); + fill_n_file_test("/nand128MB", 50, 128000000/50); // rename_over_test("/flash"); //lookup_test("/flash"); //freespace_test("/flash/flash"); diff --git a/direct/test-framework/yaffs_nand_drv.c b/direct/test-framework/yaffs_nand_drv.c index 3a06bd7..8f25579 100644 --- a/direct/test-framework/yaffs_nand_drv.c +++ b/direct/test-framework/yaffs_nand_drv.c @@ -67,7 +67,7 @@ static int yaffs_nand_drv_WriteChunk(struct yaffs_dev *dev, int nand_chunk, struct nanddrv_transfer tr[2]; int i; - if(!data || !oob) + if(!data) return YAFFS_FAIL; @@ -78,7 +78,8 @@ static int yaffs_nand_drv_WriteChunk(struct yaffs_dev *dev, int nand_chunk, for(i = 0, e = buffer + 2; i < chip->data_bytes_per_page; i+=256, e+=3) yaffs_ecc_calc(data + i, e); - memcpy(buffer + 26, oob, oob_len); + if (oob) + memcpy(buffer + 26, oob, oob_len); /* Set up and execute transfer */ diff --git a/direct/test-framework/yaffs_nandsim_file.c b/direct/test-framework/yaffs_nandsim_file.c index db9545d..f9e67fe 100644 --- a/direct/test-framework/yaffs_nandsim_file.c +++ b/direct/test-framework/yaffs_nandsim_file.c @@ -21,7 +21,9 @@ struct yaffs_dev *yaffs_nandsim_install_drv(const char *dev_name, const char *backing_file_name, - int n_blocks) + int n_blocks, + int n_caches, + int inband_tags) { struct yaffs_dev *dev; char *name_copy = NULL; @@ -52,8 +54,9 @@ struct yaffs_dev *yaffs_nandsim_install_drv(const char *dev_name, param->end_block = n_blocks - 1; // Last block param->is_yaffs2 = 1; param->use_nand_ecc = 1; - param->n_caches = 10; + param->n_caches = n_caches; param->stored_endian = 2; + param->inband_tags = inband_tags; if(yaffs_nand_install_drv(dev, chip) != YAFFS_OK) goto fail; diff --git a/direct/test-framework/yaffs_nandsim_file.h b/direct/test-framework/yaffs_nandsim_file.h index e5d96c0..c09f30c 100644 --- a/direct/test-framework/yaffs_nandsim_file.h +++ b/direct/test-framework/yaffs_nandsim_file.h @@ -19,6 +19,8 @@ struct yaffs_dev; struct yaffs_dev *yaffs_nandsim_install_drv(const char *dev_name, const char *backing_file_name, - int n_blocks); + int n_blocks, + int n_caches, + int inband_tags); #endif diff --git a/direct/test-framework/yaffs_ramem2k.c b/direct/test-framework/yaffs_ramem2k.c index 6bd3a0e..73195c9 100644 --- a/direct/test-framework/yaffs_ramem2k.c +++ b/direct/test-framework/yaffs_ramem2k.c @@ -175,9 +175,11 @@ static int CheckInit(void) } kfree(ned.block); + (void) sizeInMB; + yaffs_trace(YAFFS_TRACE_ALWAYS, "Allocation failed, could only allocate %dMB of %dMB requested.\n", - nAllocated/64,sizeInMB); + nAllocated/64, sizeInMB); return 0; } diff --git a/direct/test-framework/yaffscfg2k.c b/direct/test-framework/yaffscfg2k.c index 3145317..7f8aba0 100644 --- a/direct/test-framework/yaffscfg2k.c +++ b/direct/test-framework/yaffscfg2k.c @@ -65,7 +65,8 @@ int yaffs_start_up(void) yflash2_install_drv("yflash2"); yaffs_m18_install_drv("M18-1"); yaffs_nor_install_drv("nor"); - yaffs_nandsim_install_drv("nand", "emfile-nand", 256); + yaffs_nandsim_install_drv("nand", "emfile-nand", 256, 4, 1); + yaffs_nandsim_install_drv("nand128MB", "emfile-nand128MB", 1024, 4, 1); return 0; } diff --git a/direct/ydirectenv.h b/direct/ydirectenv.h index 332c10e..b477343 100644 --- a/direct/ydirectenv.h +++ b/direct/ydirectenv.h @@ -74,13 +74,13 @@ size_t strnlen(const char *s, size_t maxlen); #define cond_resched() do {} while (0) #ifdef CONFIG_YAFFS_NO_TRACE +#define yaffs_trace(...) do { } while (0) +#else #define yaffs_trace(msk, fmt, ...) do { \ if (yaffs_trace_mask & (msk)) \ printf("yaffs: " fmt "\n", ##__VA_ARGS__); \ } while (0) -#else -#define yaffs_trace(...) do { } while (0) #endif #define YAFFS_LOSTNFOUND_NAME "lost+found" diff --git a/yaffs_cache.c b/yaffs_cache.c index 27f54e2..3f94a8f 100644 --- a/yaffs_cache.c +++ b/yaffs_cache.c @@ -29,11 +29,11 @@ int yaffs_obj_cache_dirty(struct yaffs_obj *obj) { struct yaffs_dev *dev = obj->my_dev; int i; - struct yaffs_cache *cache; - int n_caches = obj->my_dev->param.n_caches; + struct yaffs_cache_manager *mgr = &dev->cache_mgr; + + for (i = 0; i < mgr->n_caches; i++) { + struct yaffs_cache *cache = &mgr->cache[i]; - for (i = 0; i < n_caches; i++) { - cache = &dev->cache[i]; if (cache->object == obj && cache->dirty) return 1; } @@ -66,16 +66,16 @@ void yaffs_flush_file_cache(struct yaffs_obj *obj, int discard) { struct yaffs_dev *dev = obj->my_dev; int i; - struct yaffs_cache *cache; - int n_caches = obj->my_dev->param.n_caches; + struct yaffs_cache_manager *mgr = &dev->cache_mgr; - if (n_caches < 1) + if (mgr->n_caches < 1) return; /* Find the chunks for this object and flush them. */ - for (i = 0; i < n_caches; i++) { - cache = &dev->cache[i]; + for (i = 0; i < mgr->n_caches; i++) { + struct yaffs_cache *cache = &mgr->cache[i]; + if (cache->object == obj) yaffs_flush_single_cache(cache, discard); } @@ -85,8 +85,8 @@ void yaffs_flush_file_cache(struct yaffs_obj *obj, int discard) void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard) { + struct yaffs_cache_manager *mgr = &dev->cache_mgr; struct yaffs_obj *obj; - int n_caches = dev->param.n_caches; int i; /* Find a dirty object in the cache and flush it... @@ -94,9 +94,10 @@ void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard) */ do { obj = NULL; - for (i = 0; i < n_caches && !obj; i++) { - if (dev->cache[i].object && dev->cache[i].dirty) - obj = dev->cache[i].object; + for (i = 0; i < mgr->n_caches && !obj; i++) { + struct yaffs_cache *cache = &mgr->cache[i]; + if (cache->object && cache->dirty) + obj = cache->object; } if (obj) yaffs_flush_file_cache(obj, discard); @@ -111,13 +112,13 @@ void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard) */ static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev) { - u32 i; + struct yaffs_cache_manager *mgr = &dev->cache_mgr; + int i; - if (dev->param.n_caches > 0) { - for (i = 0; i < dev->param.n_caches; i++) { - if (!dev->cache[i].object) - return &dev->cache[i]; - } + for (i = 0; i < mgr->n_caches; i++) { + struct yaffs_cache *cache = &mgr->cache[i]; + if (!cache->object) + return cache; } return NULL; @@ -125,11 +126,12 @@ static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev) struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev) { + struct yaffs_cache_manager *mgr = &dev->cache_mgr; struct yaffs_cache *cache; int usage; - u32 i; + int i; - if (dev->param.n_caches < 1) + if (mgr->n_caches < 1) return NULL; /* First look for an unused cache */ @@ -147,12 +149,14 @@ struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev) usage = -1; cache = NULL; - for (i = 0; i < dev->param.n_caches; i++) { - if (dev->cache[i].object && - !dev->cache[i].locked && - (dev->cache[i].last_use < usage || !cache)) { - usage = dev->cache[i].last_use; - cache = &dev->cache[i]; + for (i = 0; i < mgr->n_caches; i++) { + struct yaffs_cache *this_cache = &mgr->cache[i]; + + if (this_cache->object && + !this_cache->locked && + (this_cache->last_use < usage || !cache)) { + usage = this_cache->last_use; + cache = this_cache; } } @@ -171,17 +175,19 @@ struct yaffs_cache *yaffs_find_chunk_cache(const struct yaffs_obj *obj, int chunk_id) { struct yaffs_dev *dev = obj->my_dev; - u32 i; + struct yaffs_cache_manager *mgr = &dev->cache_mgr; + int i; - if (dev->param.n_caches < 1) + if (mgr->n_caches < 1) return NULL; - for (i = 0; i < dev->param.n_caches; i++) { - if (dev->cache[i].object == obj && - dev->cache[i].chunk_id == chunk_id) { - dev->cache_hits++; + for (i = 0; i < mgr->n_caches; i++) { + struct yaffs_cache *cache = &mgr->cache[i]; - return &dev->cache[i]; + if (cache->object == obj && + cache->chunk_id == chunk_id) { + dev->cache_hits++; + return cache; } } return NULL; @@ -191,21 +197,22 @@ struct yaffs_cache *yaffs_find_chunk_cache(const struct yaffs_obj *obj, void yaffs_use_cache(struct yaffs_dev *dev, struct yaffs_cache *cache, int is_write) { - u32 i; + struct yaffs_cache_manager *mgr = &dev->cache_mgr; + int i; - if (dev->param.n_caches < 1) + if (mgr->n_caches < 1) return; - if (dev->cache_last_use < 0 || - dev->cache_last_use > 100000000) { + if (mgr->cache_last_use < 0 || + mgr->cache_last_use > 100000000) { /* Reset the cache usages */ - for (i = 1; i < dev->param.n_caches; i++) - dev->cache[i].last_use = 0; + for (i = 1; i < mgr->n_caches; i++) + mgr->cache[i].last_use = 0; - dev->cache_last_use = 0; + mgr->cache_last_use = 0; } - dev->cache_last_use++; - cache->last_use = dev->cache_last_use; + mgr->cache_last_use++; + cache->last_use = mgr->cache_last_use; if (is_write) cache->dirty = 1; @@ -219,63 +226,80 @@ void yaffs_invalidate_chunk_cache(struct yaffs_obj *object, int chunk_id) { struct yaffs_cache *cache; - if (object->my_dev->param.n_caches > 0) { - cache = yaffs_find_chunk_cache(object, chunk_id); - - if (cache) - cache->object = NULL; - } + cache = yaffs_find_chunk_cache(object, chunk_id); + if (cache) + cache->object = NULL; } /* Invalidate all the cache pages associated with this object - * Do this whenever ther file is deleted or resized. + * Do this whenever the file is deleted or resized. */ void yaffs_invalidate_file_cache(struct yaffs_obj *in) { - u32 i; + int i; struct yaffs_dev *dev = in->my_dev; + struct yaffs_cache_manager *mgr = &dev->cache_mgr; - if (dev->param.n_caches > 0) { - /* Invalidate it. */ - for (i = 0; i < dev->param.n_caches; i++) { - if (dev->cache[i].object == in) - dev->cache[i].object = NULL; - } + /* Invalidate it. */ + for (i = 0; i < mgr->n_caches; i++) { + struct yaffs_cache *cache = &mgr->cache[i]; + + if (cache->object == in) + cache->object = NULL; } } +int yaffs_count_dirty_caches(struct yaffs_dev *dev) +{ + int n_dirty; + int i; + struct yaffs_cache_manager *mgr = &dev->cache_mgr; + + for (n_dirty= 0, i = 0; i < mgr->n_caches; i++) { + if (mgr->cache[i].dirty) + n_dirty++; + } + + return n_dirty; +} int yaffs_cache_init(struct yaffs_dev *dev) { - int init_failed; + struct yaffs_cache_manager *mgr = &dev->cache_mgr; + int init_failed = 0; + + if (dev->param.n_caches > YAFFS_MAX_SHORT_OP_CACHES) + dev->param.n_caches = YAFFS_MAX_SHORT_OP_CACHES; - if (dev->param.n_caches > 0) { - u32 i; + mgr->n_caches = dev->param.n_caches; + if (mgr->n_caches > 0) { + int i; void *buf; u32 cache_bytes = - dev->param.n_caches * sizeof(struct yaffs_cache); + mgr->n_caches * sizeof(struct yaffs_cache); + - if (dev->param.n_caches > YAFFS_MAX_SHORT_OP_CACHES) - dev->param.n_caches = YAFFS_MAX_SHORT_OP_CACHES; - dev->cache = kmalloc(cache_bytes, GFP_NOFS); + mgr->cache = kmalloc(cache_bytes, GFP_NOFS); - buf = (u8 *) dev->cache; + buf = (u8 *) mgr->cache; - if (dev->cache) - memset(dev->cache, 0, cache_bytes); + if (mgr->cache) + memset(mgr->cache, 0, cache_bytes); - for (i = 0; i < dev->param.n_caches && buf; i++) { - dev->cache[i].object = NULL; - dev->cache[i].last_use = 0; - dev->cache[i].dirty = 0; - dev->cache[i].data = buf = + for (i = 0; i < mgr->n_caches && buf; i++) { + struct yaffs_cache *cache = &mgr->cache[i]; + + cache->object = NULL; + cache->last_use = 0; + cache->dirty = 0; + cache->data = buf = kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS); } if (!buf) init_failed = 1; - dev->cache_last_use = 0; + mgr->cache_last_use = 0; } return init_failed ? -1 : 0; @@ -283,16 +307,19 @@ int yaffs_cache_init(struct yaffs_dev *dev) void yaffs_cache_deinit(struct yaffs_dev *dev) { + struct yaffs_cache_manager *mgr = &dev->cache_mgr; + int i; - if (dev->param.n_caches > 0 && dev->cache) { - u32 i; + if (mgr->n_caches < 1 || !mgr->cache) + return; - for (i = 0; i < dev->param.n_caches; i++) { - kfree(dev->cache[i].data); - dev->cache[i].data = NULL; - } + for (i = 0; i < mgr->n_caches; i++) { - kfree(dev->cache); - dev->cache = NULL; + struct yaffs_cache *cache = &mgr->cache[i]; + kfree(cache->data); + cache->data = NULL; } + + kfree(mgr->cache); + mgr->cache = NULL; } diff --git a/yaffs_cache.h b/yaffs_cache.h index 1dcd7e7..0bd7ff9 100644 --- a/yaffs_cache.h +++ b/yaffs_cache.h @@ -46,6 +46,9 @@ void yaffs_invalidate_chunk_cache(struct yaffs_obj *object, */ void yaffs_invalidate_file_cache(struct yaffs_obj *in); + +int yaffs_count_dirty_caches(struct yaffs_dev *dev); + /* Init/deinit. */ int yaffs_cache_init(struct yaffs_dev *dev); void yaffs_cache_deinit(struct yaffs_dev *dev); diff --git a/yaffs_guts.c b/yaffs_guts.c index 3023011..ba7fc84 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -2471,6 +2471,8 @@ static unsigned yaffs_find_gc_block(struct yaffs_dev *dev, struct yaffs_block_info *bi; u32 threshold = dev->param.chunks_per_block; + (void) prioritised; + /* First let's see if we need to grab a prioritised block */ if (dev->has_pending_prioritised_gc && !aggressive) { dev->gc_dirtiest = 0; @@ -2725,6 +2727,7 @@ int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency) { int erased_chunks = dev->n_erased_blocks * dev->param.chunks_per_block; + (void) urgency; yaffs_trace(YAFFS_TRACE_BACKGROUND, "Background gc %u", urgency); yaffs_check_gc(dev, 1); @@ -2759,6 +2762,7 @@ void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash, struct yaffs_ext_tags tags; struct yaffs_block_info *bi; + (void) lyn; if (chunk_id <= 0) return; @@ -4694,9 +4698,6 @@ int yaffs_guts_initialise(struct yaffs_dev *dev) dev->gc_cleanup_list = NULL; - - dev->cache = NULL; - if (!init_failed) init_failed = yaffs_cache_init(dev) < 0; @@ -4860,18 +4861,12 @@ int yaffs_get_n_free_chunks(struct yaffs_dev *dev) int n_free; int n_dirty_caches; int blocks_for_checkpt; - u32 i; n_free = dev->n_free_chunks; n_free += dev->n_deleted_files; /* Now count and subtract the number of dirty chunks in the cache. */ - - for (n_dirty_caches = 0, i = 0; i < dev->param.n_caches; i++) { - if (dev->cache[i].dirty) - n_dirty_caches++; - } - + n_dirty_caches = yaffs_count_dirty_caches(dev); n_free -= n_dirty_caches; n_free -= diff --git a/yaffs_guts.h b/yaffs_guts.h index 5fa1877..96fd547 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -125,7 +125,7 @@ /* Special sequence number for bad block that failed to be marked bad */ #define YAFFS_SEQUENCE_BAD_BLOCK 0xffff0000 -/* ChunkCache is used for short read/write operations.*/ +/* Chunk cache is used for short read/write operations.*/ struct yaffs_cache { struct yaffs_obj *object; int chunk_id; @@ -136,6 +136,13 @@ struct yaffs_cache { u8 *data; }; +struct yaffs_cache_manager { + struct yaffs_cache *cache; + int n_caches; + int cache_last_use; + int n_temp_buffers; +}; + /* yaffs1 tags structures in RAM * NB This uses bitfield. Bitfields should not straddle a u32 boundary * otherwise the structure size will get blown out. @@ -741,8 +748,7 @@ struct yaffs_dev { int buffered_block; /* Which block is buffered here? */ int doing_buffered_block_rewrite; - struct yaffs_cache *cache; - int cache_last_use; + struct yaffs_cache_manager cache_mgr; /* Stuff for background deletion and unlinked files. */ struct yaffs_obj *unlinked_dir; /* Directory where unlinked and deleted diff --git a/yaffs_packedtags2.c b/yaffs_packedtags2.c index e8fd945..905593c 100644 --- a/yaffs_packedtags2.c +++ b/yaffs_packedtags2.c @@ -40,6 +40,8 @@ static void yaffs_dump_packed_tags2_tags_only( const struct yaffs_packed_tags2_tags_only *ptt) { + (void) ptt; + yaffs_trace(YAFFS_TRACE_MTD, "packed tags obj %d chunk %d byte %d seq %d", ptt->obj_id, ptt->chunk_id, ptt->n_bytes, ptt->seq_number); @@ -52,6 +54,8 @@ static void yaffs_dump_packed_tags2(const struct yaffs_packed_tags2 *pt) static void yaffs_dump_tags2(const struct yaffs_ext_tags *t) { + + (void) t; yaffs_trace(YAFFS_TRACE_MTD, "ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d", t->ecc_result, t->block_bad, t->chunk_used, t->obj_id, diff --git a/yaffs_verify.c b/yaffs_verify.c index 9141eb5..ba9b9f4 100644 --- a/yaffs_verify.c +++ b/yaffs_verify.c @@ -53,6 +53,8 @@ void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi, int n) int actually_used; int in_use; + (void) block_state_name; + if (yaffs_skip_verification(dev)) return; diff --git a/yaffs_yaffs1.c b/yaffs_yaffs1.c index e357347..1440021 100644 --- a/yaffs_yaffs1.c +++ b/yaffs_yaffs1.c @@ -20,7 +20,7 @@ int yaffs1_scan(struct yaffs_dev *dev) { -#ifdef CONFIG_NO_YAFFS1 +#ifdef CONFIG_YAFFS_NO_YAFFS1 return YAFFS_FAIL; #else struct yaffs_ext_tags tags; diff --git a/yaffs_yaffs2.c b/yaffs_yaffs2.c index 9eb42f7..6be3d6a 100644 --- a/yaffs_yaffs2.c +++ b/yaffs_yaffs2.c @@ -707,6 +707,8 @@ static int yaffs2_wr_checkpt_objs(struct yaffs_dev *dev) * dumping them to the checkpointing stream. */ + (void) cp_variant_type; + for (i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++) { list_for_each(lh, &dev->obj_bucket[i].list) { obj = list_entry(lh, struct yaffs_obj, hash_link);