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;
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.
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;
}
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);
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;