aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs/jffs_fm.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2007-02-17 16:10:59 -0500
committerJeff Garzik <jeff@garzik.org>2007-02-17 16:10:59 -0500
commit419ee448ff76aef13526a99c2dc39ba3ae1f0970 (patch)
treeb475ef43632700d5d7eab3e9e9f1a80159aad73d /fs/jffs/jffs_fm.c
parent8a03d9a498eaf02c8a118752050a5154852c13bf (diff)
Remove JFFS (version 1), as scheduled.
Unmaintained for years, few if any users. Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'fs/jffs/jffs_fm.c')
-rw-r--r--fs/jffs/jffs_fm.c798
1 files changed, 0 insertions, 798 deletions
diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c
deleted file mode 100644
index 5a95fbdd6fdb..000000000000
--- a/fs/jffs/jffs_fm.c
+++ /dev/null
@@ -1,798 +0,0 @@
1/*
2 * JFFS -- Journaling Flash File System, Linux implementation.
3 *
4 * Copyright (C) 1999, 2000 Axis Communications AB.
5 *
6 * Created by Finn Hakansson <finn@axis.com>.
7 *
8 * This is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * $Id: jffs_fm.c,v 1.27 2001/09/20 12:29:47 dwmw2 Exp $
14 *
15 * Ported to Linux 2.3.x and MTD:
16 * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
17 *
18 */
19#include <linux/slab.h>
20#include <linux/err.h>
21#include <linux/blkdev.h>
22#include <linux/jffs.h>
23#include "jffs_fm.h"
24#include "intrep.h"
25
26#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
27static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset);
28#endif
29
30static struct jffs_fm *jffs_alloc_fm(void);
31static void jffs_free_fm(struct jffs_fm *n);
32
33extern struct kmem_cache *fm_cache;
34extern struct kmem_cache *node_cache;
35
36#if CONFIG_JFFS_FS_VERBOSE > 0
37void
38jffs_print_fmcontrol(struct jffs_fmcontrol *fmc)
39{
40 D(printk("struct jffs_fmcontrol: 0x%p\n", fmc));
41 D(printk("{\n"));
42 D(printk(" %u, /* flash_size */\n", fmc->flash_size));
43 D(printk(" %u, /* used_size */\n", fmc->used_size));
44 D(printk(" %u, /* dirty_size */\n", fmc->dirty_size));
45 D(printk(" %u, /* free_size */\n", fmc->free_size));
46 D(printk(" %u, /* sector_size */\n", fmc->sector_size));
47 D(printk(" %u, /* min_free_size */\n", fmc->min_free_size));
48 D(printk(" %u, /* max_chunk_size */\n", fmc->max_chunk_size));
49 D(printk(" 0x%p, /* mtd */\n", fmc->mtd));
50 D(printk(" 0x%p, /* head */ "
51 "(head->offset = 0x%08x)\n",
52 fmc->head, (fmc->head ? fmc->head->offset : 0)));
53 D(printk(" 0x%p, /* tail */ "
54 "(tail->offset + tail->size = 0x%08x)\n",
55 fmc->tail,
56 (fmc->tail ? fmc->tail->offset + fmc->tail->size : 0)));
57 D(printk(" 0x%p, /* head_extra */\n", fmc->head_extra));
58 D(printk(" 0x%p, /* tail_extra */\n", fmc->tail_extra));
59 D(printk("}\n"));
60}
61#endif /* CONFIG_JFFS_FS_VERBOSE > 0 */
62
63#if CONFIG_JFFS_FS_VERBOSE > 2
64static void
65jffs_print_fm(struct jffs_fm *fm)
66{
67 D(printk("struct jffs_fm: 0x%p\n", fm));
68 D(printk("{\n"));
69 D(printk(" 0x%08x, /* offset */\n", fm->offset));
70 D(printk(" %u, /* size */\n", fm->size));
71 D(printk(" 0x%p, /* prev */\n", fm->prev));
72 D(printk(" 0x%p, /* next */\n", fm->next));
73 D(printk(" 0x%p, /* nodes */\n", fm->nodes));
74 D(printk("}\n"));
75}
76#endif /* CONFIG_JFFS_FS_VERBOSE > 2 */
77
78#if 0
79void
80jffs_print_node_ref(struct jffs_node_ref *ref)
81{
82 D(printk("struct jffs_node_ref: 0x%p\n", ref));
83 D(printk("{\n"));
84 D(printk(" 0x%p, /* node */\n", ref->node));
85 D(printk(" 0x%p, /* next */\n", ref->next));
86 D(printk("}\n"));
87}
88#endif /* 0 */
89
90/* This function creates a new shiny flash memory control structure. */
91struct jffs_fmcontrol *
92jffs_build_begin(struct jffs_control *c, int unit)
93{
94 struct jffs_fmcontrol *fmc;
95 struct mtd_info *mtd;
96
97 D3(printk("jffs_build_begin()\n"));
98 fmc = kmalloc(sizeof(*fmc), GFP_KERNEL);
99 if (!fmc) {
100 D(printk("jffs_build_begin(): Allocation of "
101 "struct jffs_fmcontrol failed!\n"));
102 return (struct jffs_fmcontrol *)0;
103 }
104 DJM(no_jffs_fmcontrol++);
105
106 mtd = get_mtd_device(NULL, unit);
107
108 if (IS_ERR(mtd)) {
109 kfree(fmc);
110 DJM(no_jffs_fmcontrol--);
111 return NULL;
112 }
113
114 /* Retrieve the size of the flash memory. */
115 fmc->flash_size = mtd->size;
116 D3(printk(" fmc->flash_size = %d bytes\n", fmc->flash_size));
117
118 fmc->used_size = 0;
119 fmc->dirty_size = 0;
120 fmc->free_size = mtd->size;
121 fmc->sector_size = mtd->erasesize;
122 fmc->max_chunk_size = fmc->sector_size >> 1;
123 /* min_free_size:
124 1 sector, obviously.
125 + 1 x max_chunk_size, for when a nodes overlaps the end of a sector
126 + 1 x max_chunk_size again, which ought to be enough to handle
127 the case where a rename causes a name to grow, and GC has
128 to write out larger nodes than the ones it's obsoleting.
129 We should fix it so it doesn't have to write the name
130 _every_ time. Later.
131 + another 2 sectors because people keep getting GC stuck and
132 we don't know why. This scares me - I want formal proof
133 of correctness of whatever number we put here. dwmw2.
134 */
135 fmc->min_free_size = fmc->sector_size << 2;
136 fmc->mtd = mtd;
137 fmc->c = c;
138 fmc->head = NULL;
139 fmc->tail = NULL;
140 fmc->head_extra = NULL;
141 fmc->tail_extra = NULL;
142 mutex_init(&fmc->biglock);
143 return fmc;
144}
145
146
147/* When the flash memory scan has completed, this function should be called
148 before use of the control structure. */
149void
150jffs_build_end(struct jffs_fmcontrol *fmc)
151{
152 D3(printk("jffs_build_end()\n"));
153
154 if (!fmc->head) {
155 fmc->head = fmc->head_extra;
156 fmc->tail = fmc->tail_extra;
157 }
158 else if (fmc->head_extra) {
159 fmc->tail_extra->next = fmc->head;
160 fmc->head->prev = fmc->tail_extra;
161 fmc->head = fmc->head_extra;
162 }
163 fmc->head_extra = NULL; /* These two instructions should be omitted. */
164 fmc->tail_extra = NULL;
165 D3(jffs_print_fmcontrol(fmc));
166}
167
168
169/* Call this function when the file system is unmounted. This function
170 frees all memory used by this module. */
171void
172jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc)
173{
174 if (fmc) {
175 struct jffs_fm *next = fmc->head;
176 while (next) {
177 struct jffs_fm *cur = next;
178 next = next->next;
179 jffs_free_fm(cur);
180 }
181 put_mtd_device(fmc->mtd);
182 kfree(fmc);
183 DJM(no_jffs_fmcontrol--);
184 }
185}
186
187
188/* This function returns the size of the first chunk of free space on the
189 flash memory. This function will return something nonzero if the flash
190 memory contains any free space. */
191__u32
192jffs_free_size1(struct jffs_fmcontrol *fmc)
193{
194 __u32 head;
195 __u32 tail;
196 __u32 end = fmc->flash_size;
197
198 if (!fmc->head) {
199 /* There is nothing on the flash. */
200 return fmc->flash_size;
201 }
202
203 /* Compute the beginning and ending of the contents of the flash. */
204 head = fmc->head->offset;
205 tail = fmc->tail->offset + fmc->tail->size;
206 if (tail == end) {
207 tail = 0;
208 }
209 ASSERT(else if (tail > end) {
210 printk(KERN_WARNING "jffs_free_size1(): tail > end\n");
211 tail = 0;
212 });
213
214 if (head <= tail) {
215 return end - tail;
216 }
217 else {
218 return head - tail;
219 }
220}
221
222/* This function will return something nonzero in case there are two free
223 areas on the flash. Like this:
224
225 +----------------+------------------+----------------+
226 | FREE 1 | USED / DIRTY | FREE 2 |
227 +----------------+------------------+----------------+
228 fmc->head -----^
229 fmc->tail ------------------------^
230
231 The value returned, will be the size of the first empty area on the
232 flash, in this case marked "FREE 1". */
233__u32
234jffs_free_size2(struct jffs_fmcontrol *fmc)
235{
236 if (fmc->head) {
237 __u32 head = fmc->head->offset;
238 __u32 tail = fmc->tail->offset + fmc->tail->size;
239 if (tail == fmc->flash_size) {
240 tail = 0;
241 }
242
243 if (tail >= head) {
244 return head;
245 }
246 }
247 return 0;
248}
249
250
251/* Allocate a chunk of flash memory. If there is enough space on the
252 device, a reference to the associated node is stored in the jffs_fm
253 struct. */
254int
255jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, struct jffs_node *node,
256 struct jffs_fm **result)
257{
258 struct jffs_fm *fm;
259 __u32 free_chunk_size1;
260 __u32 free_chunk_size2;
261
262 D2(printk("jffs_fmalloc(): fmc = 0x%p, size = %d, "
263 "node = 0x%p\n", fmc, size, node));
264
265 *result = NULL;
266
267 if (!(fm = jffs_alloc_fm())) {
268 D(printk("jffs_fmalloc(): kmalloc() failed! (fm)\n"));
269 return -ENOMEM;
270 }
271
272 free_chunk_size1 = jffs_free_size1(fmc);
273 free_chunk_size2 = jffs_free_size2(fmc);
274 if (free_chunk_size1 + free_chunk_size2 != fmc->free_size) {
275 printk(KERN_WARNING "Free size accounting screwed\n");
276 printk(KERN_WARNING "free_chunk_size1 == 0x%x, free_chunk_size2 == 0x%x, fmc->free_size == 0x%x\n", free_chunk_size1, free_chunk_size2, fmc->free_size);
277 }
278
279 D3(printk("jffs_fmalloc(): free_chunk_size1 = %u, "
280 "free_chunk_size2 = %u\n",
281 free_chunk_size1, free_chunk_size2));
282
283 if (size <= free_chunk_size1) {
284 if (!(fm->nodes = (struct jffs_node_ref *)
285 kmalloc(sizeof(struct jffs_node_ref),
286 GFP_KERNEL))) {
287 D(printk("jffs_fmalloc(): kmalloc() failed! "
288 "(node_ref)\n"));
289 jffs_free_fm(fm);
290 return -ENOMEM;
291 }
292 DJM(no_jffs_node_ref++);
293 fm->nodes->node = node;
294 fm->nodes->next = NULL;
295 if (fmc->tail) {
296 fm->offset = fmc->tail->offset + fmc->tail->size;
297 if (fm->offset == fmc->flash_size) {
298 fm->offset = 0;
299 }
300 ASSERT(else if (fm->offset > fmc->flash_size) {
301 printk(KERN_WARNING "jffs_fmalloc(): "
302 "offset > flash_end\n");
303 fm->offset = 0;
304 });
305 }
306 else {
307 /* There don't have to be files in the file
308 system yet. */
309 fm->offset = 0;
310 }
311 fm->size = size;
312 fmc->free_size -= size;
313 fmc->used_size += size;
314 }
315 else if (size > free_chunk_size2) {
316 printk(KERN_WARNING "JFFS: Tried to allocate a too "
317 "large flash memory chunk. (size = %u)\n", size);
318 jffs_free_fm(fm);
319 return -ENOSPC;
320 }
321 else {
322 fm->offset = fmc->tail->offset + fmc->tail->size;
323 fm->size = free_chunk_size1;
324 fm->nodes = NULL;
325 fmc->free_size -= fm->size;
326 fmc->dirty_size += fm->size; /* Changed by simonk. This seemingly fixes a
327 bug that caused infinite garbage collection.
328 It previously set fmc->dirty_size to size (which is the
329 size of the requested chunk).
330 */
331 }
332
333 fm->next = NULL;
334 if (!fmc->head) {
335 fm->prev = NULL;
336 fmc->head = fm;
337 fmc->tail = fm;
338 }
339 else {
340 fm->prev = fmc->tail;
341 fmc->tail->next = fm;
342 fmc->tail = fm;
343 }
344
345 D3(jffs_print_fmcontrol(fmc));
346 D3(jffs_print_fm(fm));
347 *result = fm;
348 return 0;
349}
350
351
352/* The on-flash space is not needed anymore by the passed node. Remove
353 the reference to the node from the node list. If the data chunk in
354 the flash memory isn't used by any more nodes anymore (fm->nodes == 0),
355 then mark that chunk as dirty. */
356int
357jffs_fmfree(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, struct jffs_node *node)
358{
359 struct jffs_node_ref *ref;
360 struct jffs_node_ref *prev;
361 ASSERT(int del = 0);
362
363 D2(printk("jffs_fmfree(): node->ino = %u, node->version = %u\n",
364 node->ino, node->version));
365
366 ASSERT(if (!fmc || !fm || !fm->nodes) {
367 printk(KERN_ERR "jffs_fmfree(): fmc: 0x%p, fm: 0x%p, "
368 "fm->nodes: 0x%p\n",
369 fmc, fm, (fm ? fm->nodes : NULL));
370 return -1;
371 });
372
373 /* Find the reference to the node that is going to be removed
374 and remove it. */
375 for (ref = fm->nodes, prev = NULL; ref; ref = ref->next) {
376 if (ref->node == node) {
377 if (prev) {
378 prev->next = ref->next;
379 }
380 else {
381 fm->nodes = ref->next;
382 }
383 kfree(ref);
384 DJM(no_jffs_node_ref--);
385 ASSERT(del = 1);
386 break;
387 }
388 prev = ref;
389 }
390
391 /* If the data chunk in the flash memory isn't used anymore
392 just mark it as obsolete. */
393 if (!fm->nodes) {
394 /* No node uses this chunk so let's remove it. */
395 fmc->used_size -= fm->size;
396 fmc->dirty_size += fm->size;
397#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
398 if (jffs_mark_obsolete(fmc, fm->offset) < 0) {
399 D1(printk("jffs_fmfree(): Failed to mark an on-flash "
400 "node obsolete!\n"));
401 return -1;
402 }
403#endif
404 }
405
406 ASSERT(if (!del) {
407 printk(KERN_WARNING "***jffs_fmfree(): "
408 "Didn't delete any node reference!\n");
409 });
410
411 return 0;
412}
413
414
415/* This allocation function is used during the initialization of
416 the file system. */
417struct jffs_fm *
418jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset, __u32 size,
419 struct jffs_node *node)
420{
421 struct jffs_fm *fm;
422
423 D3(printk("jffs_fmalloced()\n"));
424
425 if (!(fm = jffs_alloc_fm())) {
426 D(printk("jffs_fmalloced(0x%p, %u, %u, 0x%p): failed!\n",
427 fmc, offset, size, node));
428 return NULL;
429 }
430 fm->offset = offset;
431 fm->size = size;
432 fm->prev = NULL;
433 fm->next = NULL;
434 fm->nodes = NULL;
435 if (node) {
436 /* `node' exists and it should be associated with the
437 jffs_fm structure `fm'. */
438 if (!(fm->nodes = (struct jffs_node_ref *)
439 kmalloc(sizeof(struct jffs_node_ref),
440 GFP_KERNEL))) {
441 D(printk("jffs_fmalloced(): !fm->nodes\n"));
442 jffs_free_fm(fm);
443 return NULL;
444 }
445 DJM(no_jffs_node_ref++);
446 fm->nodes->node = node;
447 fm->nodes->next = NULL;
448 fmc->used_size += size;
449 fmc->free_size -= size;
450 }
451 else {
452 /* If there is no node, then this is just a chunk of dirt. */
453 fmc->dirty_size += size;
454 fmc->free_size -= size;
455 }
456
457 if (fmc->head_extra) {
458 fm->prev = fmc->tail_extra;
459 fmc->tail_extra->next = fm;
460 fmc->tail_extra = fm;
461 }
462 else if (!fmc->head) {
463 fmc->head = fm;
464 fmc->tail = fm;
465 }
466 else if (fmc->tail->offset + fmc->tail->size < offset) {
467 fmc->head_extra = fm;
468 fmc->tail_extra = fm;
469 }
470 else {
471 fm->prev = fmc->tail;
472 fmc->tail->next = fm;
473 fmc->tail = fm;
474 }
475 D3(jffs_print_fmcontrol(fmc));
476 D3(jffs_print_fm(fm));
477 return fm;
478}
479
480
481/* Add a new node to an already existing jffs_fm struct. */
482int
483jffs_add_node(struct jffs_node *node)
484{
485 struct jffs_node_ref *ref;
486
487 D3(printk("jffs_add_node(): ino = %u\n", node->ino));
488
489 ref = kmalloc(sizeof(*ref), GFP_KERNEL);
490 if (!ref)
491 return -ENOMEM;
492
493 DJM(no_jffs_node_ref++);
494 ref->node = node;
495 ref->next = node->fm->nodes;
496 node->fm->nodes = ref;
497 return 0;
498}
499
500
501/* Free a part of some allocated space. */
502void
503jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, __u32 size)
504{
505 D1(printk("***jffs_fmfree_partly(): fm = 0x%p, fm->nodes = 0x%p, "
506 "fm->nodes->node->ino = %u, size = %u\n",
507 fm, (fm ? fm->nodes : 0),
508 (!fm ? 0 : (!fm->nodes ? 0 : fm->nodes->node->ino)), size));
509
510 if (fm->nodes) {
511 kfree(fm->nodes);
512 DJM(no_jffs_node_ref--);
513 fm->nodes = NULL;
514 }
515 fmc->used_size -= fm->size;
516 if (fm == fmc->tail) {
517 fm->size -= size;
518 fmc->free_size += size;
519 }
520 fmc->dirty_size += fm->size;
521}
522
523
524/* Find the jffs_fm struct that contains the end of the data chunk that
525 begins at the logical beginning of the flash memory and spans `size'
526 bytes. If we want to erase a sector of the flash memory, we use this
527 function to find where the sector limit cuts a chunk of data. */
528struct jffs_fm *
529jffs_cut_node(struct jffs_fmcontrol *fmc, __u32 size)
530{
531 struct jffs_fm *fm;
532 __u32 pos = 0;
533
534 if (size == 0) {
535 return NULL;
536 }
537
538 ASSERT(if (!fmc) {
539 printk(KERN_ERR "jffs_cut_node(): fmc == NULL\n");
540 return NULL;
541 });
542
543 fm = fmc->head;
544
545 while (fm) {
546 pos += fm->size;
547 if (pos < size) {
548 fm = fm->next;
549 }
550 else if (pos > size) {
551 break;
552 }
553 else {
554 fm = NULL;
555 break;
556 }
557 }
558
559 return fm;
560}
561
562
563/* Move the head of the fmc structures and delete the obsolete parts. */
564void
565jffs_sync_erase(struct jffs_fmcontrol *fmc, int erased_size)
566{
567 struct jffs_fm *fm;
568 struct jffs_fm *del;
569
570 ASSERT(if (!fmc) {
571 printk(KERN_ERR "jffs_sync_erase(): fmc == NULL\n");
572 return;
573 });
574
575 fmc->dirty_size -= erased_size;
576 fmc->free_size += erased_size;
577
578 for (fm = fmc->head; fm && (erased_size > 0);) {
579 if (erased_size >= fm->size) {
580 erased_size -= fm->size;
581 del = fm;
582 fm = fm->next;
583 fm->prev = NULL;
584 fmc->head = fm;
585 jffs_free_fm(del);
586 }
587 else {
588 fm->size -= erased_size;
589 fm->offset += erased_size;
590 break;
591 }
592 }
593}
594
595
596/* Return the oldest used node in the flash memory. */
597struct jffs_node *
598jffs_get_oldest_node(struct jffs_fmcontrol *fmc)
599{
600 struct jffs_fm *fm;
601 struct jffs_node_ref *nref;
602 struct jffs_node *node = NULL;
603
604 ASSERT(if (!fmc) {
605 printk(KERN_ERR "jffs_get_oldest_node(): fmc == NULL\n");
606 return NULL;
607 });
608
609 for (fm = fmc->head; fm && !fm->nodes; fm = fm->next);
610
611 if (!fm) {
612 return NULL;
613 }
614
615 /* The oldest node is the last one in the reference list. This list
616 shouldn't be too long; just one or perhaps two elements. */
617 for (nref = fm->nodes; nref; nref = nref->next) {
618 node = nref->node;
619 }
620
621 D2(printk("jffs_get_oldest_node(): ino = %u, version = %u\n",
622 (node ? node->ino : 0), (node ? node->version : 0)));
623
624 return node;
625}
626
627
628#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
629
630/* Mark an on-flash node as obsolete.
631
632 Note that this is just an optimization that isn't necessary for the
633 filesystem to work. */
634
635static int
636jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset)
637{
638 /* The `accurate_pos' holds the position of the accurate byte
639 in the jffs_raw_inode structure that we are going to mark
640 as obsolete. */
641 __u32 accurate_pos = fm_offset + JFFS_RAW_INODE_ACCURATE_OFFSET;
642 unsigned char zero = 0x00;
643 size_t len;
644
645 D3(printk("jffs_mark_obsolete(): accurate_pos = %u\n", accurate_pos));
646 ASSERT(if (!fmc) {
647 printk(KERN_ERR "jffs_mark_obsolete(): fmc == NULL\n");
648 return -1;
649 });
650
651 /* Write 0x00 to the raw inode's accurate member. Don't care
652 about the return value. */
653 MTD_WRITE(fmc->mtd, accurate_pos, 1, &len, &zero);
654 return 0;
655}
656
657#endif /* JFFS_MARK_OBSOLETE */
658
659/* check if it's possible to erase the wanted range, and if not, return
660 * the range that IS erasable, or a negative error code.
661 */
662static long
663jffs_flash_erasable_size(struct mtd_info *mtd, __u32 offset, __u32 size)
664{
665 u_long ssize;
666
667 /* assume that sector size for a partition is constant even
668 * if it spans more than one chip (you usually put the same
669 * type of chips in a system)
670 */
671
672 ssize = mtd->erasesize;
673
674 if (offset % ssize) {
675 printk(KERN_WARNING "jffs_flash_erasable_size() given non-aligned offset %x (erasesize %lx)\n", offset, ssize);
676 /* The offset is not sector size aligned. */
677 return -1;
678 }
679 else if (offset > mtd->size) {
680 printk(KERN_WARNING "jffs_flash_erasable_size given offset off the end of device (%x > %x)\n", offset, mtd->size);
681 return -2;
682 }
683 else if (offset + size > mtd->size) {
684 printk(KERN_WARNING "jffs_flash_erasable_size() given length which runs off the end of device (ofs %x + len %x = %x, > %x)\n", offset,size, offset+size, mtd->size);
685 return -3;
686 }
687
688 return (size / ssize) * ssize;
689}
690
691
692/* How much dirty flash memory is possible to erase at the moment? */
693long
694jffs_erasable_size(struct jffs_fmcontrol *fmc)
695{
696 struct jffs_fm *fm;
697 __u32 size = 0;
698 long ret;
699
700 ASSERT(if (!fmc) {
701 printk(KERN_ERR "jffs_erasable_size(): fmc = NULL\n");
702 return -1;
703 });
704
705 if (!fmc->head) {
706 /* The flash memory is totally empty. No nodes. No dirt.
707 Just return. */
708 return 0;
709 }
710
711 /* Calculate how much space that is dirty. */
712 for (fm = fmc->head; fm && !fm->nodes; fm = fm->next) {
713 if (size && fm->offset == 0) {
714 /* We have reached the beginning of the flash. */
715 break;
716 }
717 size += fm->size;
718 }
719
720 /* Someone's signature contained this:
721 There's a fine line between fishing and just standing on
722 the shore like an idiot... */
723 ret = jffs_flash_erasable_size(fmc->mtd, fmc->head->offset, size);
724
725 ASSERT(if (ret < 0) {
726 printk("jffs_erasable_size: flash_erasable_size() "
727 "returned something less than zero (%ld).\n", ret);
728 printk("jffs_erasable_size: offset = 0x%08x\n",
729 fmc->head->offset);
730 });
731
732 /* If there is dirt on the flash (which is the reason to why
733 this function was called in the first place) but no space is
734 possible to erase right now, the initial part of the list of
735 jffs_fm structs, that hold place for dirty space, could perhaps
736 be shortened. The list's initial "dirty" elements are merged
737 into just one large dirty jffs_fm struct. This operation must
738 only be performed if nothing is possible to erase. Otherwise,
739 jffs_clear_end_of_node() won't work as expected. */
740 if (ret == 0) {
741 struct jffs_fm *head = fmc->head;
742 struct jffs_fm *del;
743 /* While there are two dirty nodes beside each other.*/
744 while (head->nodes == 0
745 && head->next
746 && head->next->nodes == 0) {
747 del = head->next;
748 head->size += del->size;
749 head->next = del->next;
750 if (del->next) {
751 del->next->prev = head;
752 }
753 jffs_free_fm(del);
754 }
755 }
756
757 return (ret >= 0 ? ret : 0);
758}
759
760static struct jffs_fm *jffs_alloc_fm(void)
761{
762 struct jffs_fm *fm;
763
764 fm = kmem_cache_alloc(fm_cache,GFP_KERNEL);
765 DJM(if (fm) no_jffs_fm++;);
766
767 return fm;
768}
769
770static void jffs_free_fm(struct jffs_fm *n)
771{
772 kmem_cache_free(fm_cache,n);
773 DJM(no_jffs_fm--);
774}
775
776
777
778struct jffs_node *jffs_alloc_node(void)
779{
780 struct jffs_node *n;
781
782 n = (struct jffs_node *)kmem_cache_alloc(node_cache,GFP_KERNEL);
783 if(n != NULL)
784 no_jffs_node++;
785 return n;
786}
787
788void jffs_free_node(struct jffs_node *n)
789{
790 kmem_cache_free(node_cache,n);
791 no_jffs_node--;
792}
793
794
795int jffs_get_node_inuse(void)
796{
797 return no_jffs_node;
798}