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