X-Git-Url: https://yaffs.net/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=6a12aba23ebdaf89543980b3cf0fda1c4805a9ba;hp=1de2817356c29030bb85ae616908a37ff77488c5;hb=30f956c32c235e6b5fa77fb29965ababbd497561;hpb=4e188b08c5531f99f73383a85251e03a1e667b26 diff --git a/yaffs_guts.c b/yaffs_guts.c index 1de2817..6a12aba 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -1377,56 +1377,49 @@ static int yaffs_obj_cache_dirty(struct yaffs_obj *obj) return 0; } -static void yaffs_flush_file_cache(struct yaffs_obj *obj) +static void yaffs_flush_single_cache(struct yaffs_cache *cache, int discard) +{ + + if (!cache || cache->locked) + return; + + /* Write it out and free it up if need be.*/ + if (cache->dirty) { + yaffs_wr_data_obj(cache->object, + cache->chunk_id, + cache->data, + cache->n_bytes, + 1); + + cache->dirty = 0; + } + + if (discard) + cache->object = NULL; +} + +static void yaffs_flush_file_cache(struct yaffs_obj *obj, int discard) { struct yaffs_dev *dev = obj->my_dev; - int lowest = -99; /* Stop compiler whining. */ int i; struct yaffs_cache *cache; - int chunk_written = 0; int n_caches = obj->my_dev->param.n_caches; if (n_caches < 1) return; - do { - cache = NULL; - - /* Find the lowest dirty chunk for this object */ - for (i = 0; i < n_caches; i++) { - if (dev->cache[i].object == obj && - dev->cache[i].dirty) { - if (!cache || - dev->cache[i].chunk_id < lowest) { - cache = &dev->cache[i]; - lowest = cache->chunk_id; - } - } - } - if (cache && !cache->locked) { - /* Write it out and free it up */ - chunk_written = - yaffs_wr_data_obj(cache->object, - cache->chunk_id, - cache->data, - cache->n_bytes, 1); - cache->dirty = 0; - cache->object = NULL; - } - } while (cache && chunk_written > 0); - if (cache) - /* Hoosterman, disk full while writing cache out. */ - yaffs_trace(YAFFS_TRACE_ERROR, - "yaffs tragedy: no space during cache write"); + /* Find the chunks for this object and flush them. */ + for (i = 0; i < n_caches; i++) { + cache = &dev->cache[i]; + if (cache->object == obj) + yaffs_flush_single_cache(cache, discard); + } + } -/*yaffs_flush_whole_cache(dev) - * - * - */ -void yaffs_flush_whole_cache(struct yaffs_dev *dev) +void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard) { struct yaffs_obj *obj; int n_caches = dev->param.n_caches; @@ -1442,12 +1435,12 @@ void yaffs_flush_whole_cache(struct yaffs_dev *dev) obj = dev->cache[i].object; } if (obj) - yaffs_flush_file_cache(obj); + yaffs_flush_file_cache(obj, discard); } while (obj); } -/* Grab us a cache chunk for use. +/* Grab us an unused cache chunk for use. * First look for an empty one. * Then look for the least recently used non-dirty one. * Then look for the least recently used dirty one...., flush and look again. @@ -1462,56 +1455,50 @@ static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev) return &dev->cache[i]; } } + return NULL; } static struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev) { struct yaffs_cache *cache; - struct yaffs_obj *the_obj; int usage; int i; - int pushout; if (dev->param.n_caches < 1) return NULL; - /* Try find a non-dirty one... */ + /* First look for an unused cache */ cache = yaffs_grab_chunk_worker(dev); - if (!cache) { - /* They were all dirty, find the LRU object and flush - * its cache, then find again. - * NB what's here is not very accurate, - * we actually flush the object with the LRU chunk. - */ + if (cache) + return cache; - /* With locking we can't assume we can use entry zero, - * Set the_obj to a valid pointer for Coverity. */ - the_obj = dev->cache[0].object; - usage = -1; - cache = NULL; - pushout = -1; + /* + * Thery were all in use. + * Find the LRU cache and flush it if it is dirty. + */ - 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 = -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; - the_obj = dev->cache[i].object; cache = &dev->cache[i]; - pushout = i; - } - } - - if (!cache || cache->dirty) { - /* Flush and try again */ - yaffs_flush_file_cache(the_obj); - cache = yaffs_grab_chunk_worker(dev); } } + +#if 1 + yaffs_flush_single_cache(cache, 1); +#else + yaffs_flush_file_cache(cache->object, 1); + cache = yaffs_grab_chunk_worker(dev); +#endif + return cache; } @@ -3765,7 +3752,7 @@ int yaffs_resize_file(struct yaffs_obj *in, loff_t new_size) struct yaffs_dev *dev = in->my_dev; loff_t old_size = in->variant.file_variant.file_size; - yaffs_flush_file_cache(in); + yaffs_flush_file_cache(in, 1); yaffs_invalidate_whole_cache(in); yaffs_check_gc(dev, 0); @@ -3798,12 +3785,15 @@ int yaffs_resize_file(struct yaffs_obj *in, loff_t new_size) return YAFFS_OK; } -int yaffs_flush_file(struct yaffs_obj *in, int update_time, int data_sync) +int yaffs_flush_file(struct yaffs_obj *in, + int update_time, + int data_sync, + int discard_cache) { if (!in->dirty) return YAFFS_OK; - yaffs_flush_file_cache(in); + yaffs_flush_file_cache(in, discard_cache); if (data_sync) return YAFFS_OK;