2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2018 Aleph One Ltd.
6 * Created by Charles Manning <charles@aleph1.co.uk>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include "yaffs_cache.h"
15 /*------------------------ Short Operations Cache ------------------------------
16 * In many situations where there is no high level buffering a lot of
17 * reads might be short sequential reads, and a lot of writes may be short
18 * sequential writes. eg. scanning/writing a jpeg file.
19 * In these cases, a short read/write cache can provide a huge perfomance
20 * benefit with dumb-as-a-rock code.
21 * In Linux, the page cache provides read buffering and the short op cache
22 * provides write buffering.
24 * There are a small number (~10) of cache chunks per device so that we don't
25 * need a very intelligent search.
28 int yaffs_obj_cache_dirty(struct yaffs_obj *obj)
30 struct yaffs_dev *dev = obj->my_dev;
32 struct yaffs_cache_manager *mgr = &dev->cache_mgr;
34 for (i = 0; i < mgr->n_caches; i++) {
35 struct yaffs_cache *cache = &mgr->cache[i];
37 if (cache->object == obj && cache->dirty)
44 void yaffs_flush_single_cache(struct yaffs_cache *cache, int discard)
47 if (!cache || cache->locked)
50 /* Write it out and free it up if need be.*/
52 yaffs_wr_data_obj(cache->object,
65 void yaffs_flush_file_cache(struct yaffs_obj *obj, int discard)
67 struct yaffs_dev *dev = obj->my_dev;
69 struct yaffs_cache_manager *mgr = &dev->cache_mgr;
71 if (mgr->n_caches < 1)
75 /* Find the chunks for this object and flush them. */
76 for (i = 0; i < mgr->n_caches; i++) {
77 struct yaffs_cache *cache = &mgr->cache[i];
79 if (cache->object == obj)
80 yaffs_flush_single_cache(cache, discard);
86 void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard)
88 struct yaffs_cache_manager *mgr = &dev->cache_mgr;
89 struct yaffs_obj *obj;
92 /* Find a dirty object in the cache and flush it...
93 * until there are no further dirty objects.
97 for (i = 0; i < mgr->n_caches && !obj; i++) {
98 struct yaffs_cache *cache = &mgr->cache[i];
99 if (cache->object && cache->dirty)
103 yaffs_flush_file_cache(obj, discard);
108 /* Grab us an unused cache chunk for use.
109 * First look for an empty one.
110 * Then look for the least recently used non-dirty one.
111 * Then look for the least recently used dirty one...., flush and look again.
113 static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev)
115 struct yaffs_cache_manager *mgr = &dev->cache_mgr;
118 for (i = 0; i < mgr->n_caches; i++) {
119 struct yaffs_cache *cache = &mgr->cache[i];
127 struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev)
129 struct yaffs_cache_manager *mgr = &dev->cache_mgr;
130 struct yaffs_cache *cache;
134 if (mgr->n_caches < 1)
137 /* First look for an unused cache */
139 cache = yaffs_grab_chunk_worker(dev);
145 * Thery were all in use.
146 * Find the LRU cache and flush it if it is dirty.
152 for (i = 0; i < mgr->n_caches; i++) {
153 struct yaffs_cache *this_cache = &mgr->cache[i];
155 if (this_cache->object &&
156 !this_cache->locked &&
157 (this_cache->last_use < usage || !cache)) {
158 usage = this_cache->last_use;
164 yaffs_flush_single_cache(cache, 1);
166 yaffs_flush_file_cache(cache->object, 1);
167 cache = yaffs_grab_chunk_worker(dev);
173 /* Find a cached chunk */
174 struct yaffs_cache *yaffs_find_chunk_cache(const struct yaffs_obj *obj,
177 struct yaffs_dev *dev = obj->my_dev;
178 struct yaffs_cache_manager *mgr = &dev->cache_mgr;
181 if (mgr->n_caches < 1)
184 for (i = 0; i < mgr->n_caches; i++) {
185 struct yaffs_cache *cache = &mgr->cache[i];
187 if (cache->object == obj &&
188 cache->chunk_id == chunk_id) {
196 /* Mark the chunk for the least recently used algorithym */
197 void yaffs_use_cache(struct yaffs_dev *dev, struct yaffs_cache *cache,
200 struct yaffs_cache_manager *mgr = &dev->cache_mgr;
203 if (mgr->n_caches < 1)
206 if (mgr->cache_last_use < 0 ||
207 mgr->cache_last_use > 100000000) {
208 /* Reset the cache usages */
209 for (i = 1; i < mgr->n_caches; i++)
210 mgr->cache[i].last_use = 0;
212 mgr->cache_last_use = 0;
214 mgr->cache_last_use++;
215 cache->last_use = mgr->cache_last_use;
221 /* Invalidate a single cache page.
222 * Do this when a whole page gets written,
223 * ie the short cache for this page is no longer valid.
225 void yaffs_invalidate_chunk_cache(struct yaffs_obj *object, int chunk_id)
227 struct yaffs_cache *cache;
229 cache = yaffs_find_chunk_cache(object, chunk_id);
231 cache->object = NULL;
234 /* Invalidate all the cache pages associated with this object
235 * Do this whenever the file is deleted or resized.
237 void yaffs_invalidate_file_cache(struct yaffs_obj *in)
240 struct yaffs_dev *dev = in->my_dev;
241 struct yaffs_cache_manager *mgr = &dev->cache_mgr;
244 for (i = 0; i < mgr->n_caches; i++) {
245 struct yaffs_cache *cache = &mgr->cache[i];
247 if (cache->object == in)
248 cache->object = NULL;
252 int yaffs_count_dirty_caches(struct yaffs_dev *dev)
256 struct yaffs_cache_manager *mgr = &dev->cache_mgr;
258 for (n_dirty= 0, i = 0; i < mgr->n_caches; i++) {
259 if (mgr->cache[i].dirty)
266 int yaffs_cache_init(struct yaffs_dev *dev)
268 struct yaffs_cache_manager *mgr = &dev->cache_mgr;
271 if (dev->param.n_caches > YAFFS_MAX_SHORT_OP_CACHES)
272 dev->param.n_caches = YAFFS_MAX_SHORT_OP_CACHES;
274 mgr->n_caches = dev->param.n_caches;
275 if (mgr->n_caches > 0) {
279 mgr->n_caches * sizeof(struct yaffs_cache);
283 mgr->cache = kmalloc(cache_bytes, GFP_NOFS);
285 buf = (u8 *) mgr->cache;
288 memset(mgr->cache, 0, cache_bytes);
290 for (i = 0; i < mgr->n_caches && buf; i++) {
291 struct yaffs_cache *cache = &mgr->cache[i];
293 cache->object = NULL;
297 kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS);
302 mgr->cache_last_use = 0;
305 return init_failed ? -1 : 0;
308 void yaffs_cache_deinit(struct yaffs_dev *dev)
310 struct yaffs_cache_manager *mgr = &dev->cache_mgr;
313 if (mgr->n_caches < 1 || !mgr->cache)
316 for (i = 0; i < mgr->n_caches; i++) {
318 struct yaffs_cache *cache = &mgr->cache[i];