2 * JFFS2 -- Journalling Flash File System, Version 2.
4 * Copyright (C) 2001-2003 Red Hat, Inc.
6 * Created by David Woodhouse <dwmw2@redhat.com>
8 * For licensing information, see the file 'LICENCE' in this directory.
10 * $Id: nodelist.c,v 1.86 2003/10/31 15:37:51 dwmw2 Exp $
14 #include <linux/kernel.h>
15 #include <linux/sched.h>
17 #include <linux/mtd/mtd.h>
18 #include <linux/rbtree.h>
19 #include <linux/crc32.h>
20 #include <linux/slab.h>
21 #include <linux/pagemap.h>
24 void jffs2_add_fd_to_list(struct jffs2_sb_info
*c
, struct jffs2_full_dirent
*new, struct jffs2_full_dirent
**list
)
26 struct jffs2_full_dirent
**prev
= list
;
27 D1(printk(KERN_DEBUG
"jffs2_add_fd_to_list( %p, %p (->%p))\n", new, list
, *list
));
29 while ((*prev
) && (*prev
)->nhash
<= new->nhash
) {
30 if ((*prev
)->nhash
== new->nhash
&& !strcmp((*prev
)->name
, new->name
)) {
31 /* Duplicate. Free one */
32 if (new->version
< (*prev
)->version
) {
33 D1(printk(KERN_DEBUG
"Eep! Marking new dirent node obsolete\n"));
34 D1(printk(KERN_DEBUG
"New dirent is \"%s\"->ino #%u. Old is \"%s\"->ino #%u\n", new->name
, new->ino
, (*prev
)->name
, (*prev
)->ino
));
35 jffs2_mark_node_obsolete(c
, new->raw
);
36 jffs2_free_full_dirent(new);
38 D1(printk(KERN_DEBUG
"Marking old dirent node (ino #%u) obsolete\n", (*prev
)->ino
));
39 new->next
= (*prev
)->next
;
40 jffs2_mark_node_obsolete(c
, ((*prev
)->raw
));
41 jffs2_free_full_dirent(*prev
);
46 prev
= &((*prev
)->next
);
53 printk(KERN_DEBUG
"Dirent \"%s\" (hash 0x%08x, ino #%u\n", (*list
)->name
, (*list
)->nhash
, (*list
)->ino
);
54 list
= &(*list
)->next
;
58 /* Put a new tmp_dnode_info into the list, keeping the list in
59 order of increasing version
61 static void jffs2_add_tn_to_list(struct jffs2_tmp_dnode_info
*tn
, struct jffs2_tmp_dnode_info
**list
)
63 struct jffs2_tmp_dnode_info
**prev
= list
;
65 while ((*prev
) && (*prev
)->version
< tn
->version
) {
66 prev
= &((*prev
)->next
);
72 static void jffs2_free_tmp_dnode_info_list(struct jffs2_tmp_dnode_info
*tn
)
74 struct jffs2_tmp_dnode_info
*next
;
79 jffs2_free_full_dnode(next
->fn
);
80 jffs2_free_tmp_dnode_info(next
);
84 static void jffs2_free_full_dirent_list(struct jffs2_full_dirent
*fd
)
86 struct jffs2_full_dirent
*next
;
90 jffs2_free_full_dirent(fd
);
96 /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
97 with this ino, returning the former in order of version */
99 int jffs2_get_inode_nodes(struct jffs2_sb_info
*c
, ino_t ino
, struct jffs2_inode_info
*f
,
100 struct jffs2_tmp_dnode_info
**tnp
, struct jffs2_full_dirent
**fdp
,
101 uint32_t *highest_version
, uint32_t *latest_mctime
,
102 uint32_t *mctime_ver
)
104 struct jffs2_raw_node_ref
*ref
= f
->inocache
->nodes
;
105 struct jffs2_tmp_dnode_info
*tn
, *ret_tn
= NULL
;
106 struct jffs2_full_dirent
*fd
, *ret_fd
= NULL
;
108 union jffs2_node_union node
;
114 D1(printk(KERN_DEBUG
"jffs2_get_inode_nodes(): ino #%lu\n", ino
));
115 if (!f
->inocache
->nodes
) {
116 printk(KERN_WARNING
"Eep. no nodes for ino #%lu\n", (unsigned long)ino
);
119 spin_lock(&c
->erase_completion_lock
);
121 for (ref
= f
->inocache
->nodes
; ref
&& ref
->next_in_ino
; ref
= ref
->next_in_ino
) {
122 /* Work out whether it's a data node or a dirent node */
123 if (ref_obsolete(ref
)) {
124 /* FIXME: On NAND flash we may need to read these */
125 D1(printk(KERN_DEBUG
"node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref
)));
128 /* We can hold a pointer to a non-obsolete node without the spinlock,
129 but _obsolete_ nodes may disappear at any time, if the block
130 they're in gets erased */
131 spin_unlock(&c
->erase_completion_lock
);
136 err
= jffs2_flash_read(c
, (ref_offset(ref
)),
137 min_t(uint32_t, ref_totlen(c
, NULL
, ref
), sizeof(node
)),
138 &retlen
, (void *)&node
);
140 printk(KERN_WARNING
"error %d reading node at 0x%08x in get_inode_nodes()\n", err
, ref_offset(ref
));
145 /* Check we've managed to read at least the common node header */
146 if (retlen
< min_t(uint32_t, ref_totlen(c
, NULL
, ref
), sizeof(node
.u
))) {
147 printk(KERN_WARNING
"short read in get_inode_nodes()\n");
152 switch (je16_to_cpu(node
.u
.nodetype
)) {
153 case JFFS2_NODETYPE_DIRENT
:
154 D1(printk(KERN_DEBUG
"Node at %08x (%d) is a dirent node\n", ref_offset(ref
), ref_flags(ref
)));
155 if (ref_flags(ref
) == REF_UNCHECKED
) {
156 printk(KERN_WARNING
"BUG: Dirent node at 0x%08x never got checked? How?\n", ref_offset(ref
));
159 if (retlen
< sizeof(node
.d
)) {
160 printk(KERN_WARNING
"short read in get_inode_nodes()\n");
165 if (PAD((node
.d
.nsize
+ sizeof (node
.d
))) != PAD(je32_to_cpu (node
.d
.totlen
))) {
166 printk(KERN_NOTICE
"jffs2_get_inode_nodes(): Illegal nsize in node at 0x%08x: nsize 0x%02x, totlen %04x\n",
167 ref_offset(ref
), node
.d
.nsize
, je32_to_cpu(node
.d
.totlen
));
168 jffs2_mark_node_obsolete(c
, ref
);
169 spin_lock(&c
->erase_completion_lock
);
172 if (je32_to_cpu(node
.d
.version
) > *highest_version
)
173 *highest_version
= je32_to_cpu(node
.d
.version
);
174 if (ref_obsolete(ref
)) {
175 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
176 printk(KERN_ERR
"Dirent node at 0x%08x became obsolete while we weren't looking\n",
181 fd
= jffs2_alloc_full_dirent(node
.d
.nsize
+1);
186 memset(fd
,0,sizeof(struct jffs2_full_dirent
) + node
.d
.nsize
+1);
188 fd
->version
= je32_to_cpu(node
.d
.version
);
189 fd
->ino
= je32_to_cpu(node
.d
.ino
);
190 fd
->type
= node
.d
.type
;
192 /* Pick out the mctime of the latest dirent */
193 if(fd
->version
> *mctime_ver
) {
194 *mctime_ver
= fd
->version
;
195 *latest_mctime
= je32_to_cpu(node
.d
.mctime
);
198 /* memcpy as much of the name as possible from the raw
199 dirent we've already read from the flash
201 if (retlen
> sizeof(struct jffs2_raw_dirent
))
202 memcpy(&fd
->name
[0], &node
.d
.name
[0], min_t(uint32_t, node
.d
.nsize
, (retlen
-sizeof(struct jffs2_raw_dirent
))));
204 /* Do we need to copy any more of the name directly
207 if (node
.d
.nsize
+ sizeof(struct jffs2_raw_dirent
) > retlen
) {
209 int already
= retlen
- sizeof(struct jffs2_raw_dirent
);
211 err
= jffs2_flash_read(c
, (ref_offset(ref
)) + retlen
,
212 node
.d
.nsize
- already
, &retlen
, &fd
->name
[already
]);
213 if (!err
&& retlen
!= node
.d
.nsize
- already
)
217 printk(KERN_WARNING
"Read remainder of name in jffs2_get_inode_nodes(): error %d\n", err
);
218 jffs2_free_full_dirent(fd
);
222 fd
->nhash
= full_name_hash(fd
->name
, node
.d
.nsize
);
224 /* Wheee. We now have a complete jffs2_full_dirent structure, with
225 the name in it and everything. Link it into the list
227 D1(printk(KERN_DEBUG
"Adding fd \"%s\", ino #%u\n", fd
->name
, fd
->ino
));
228 jffs2_add_fd_to_list(c
, fd
, &ret_fd
);
231 case JFFS2_NODETYPE_INODE
:
232 D1(printk(KERN_DEBUG
"Node at %08x (%d) is a data node\n", ref_offset(ref
), ref_flags(ref
)));
233 if (retlen
< sizeof(node
.i
)) {
234 printk(KERN_WARNING
"read too short for dnode\n");
238 if (je32_to_cpu(node
.i
.version
) > *highest_version
)
239 *highest_version
= je32_to_cpu(node
.i
.version
);
240 D1(printk(KERN_DEBUG
"version %d, highest_version now %d\n", je32_to_cpu(node
.i
.version
), *highest_version
));
242 if (ref_obsolete(ref
)) {
243 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
244 printk(KERN_ERR
"Inode node at 0x%08x became obsolete while we weren't looking\n",
249 /* If we've never checked the CRCs on this node, check them now. */
250 if (ref_flags(ref
) == REF_UNCHECKED
) {
252 struct jffs2_eraseblock
*jeb
;
254 crc
= crc32(0, &node
, sizeof(node
.i
)-8);
255 if (crc
!= je32_to_cpu(node
.i
.node_crc
)) {
256 printk(KERN_NOTICE
"jffs2_get_inode_nodes(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
257 ref_offset(ref
), je32_to_cpu(node
.i
.node_crc
), crc
);
258 jffs2_mark_node_obsolete(c
, ref
);
259 spin_lock(&c
->erase_completion_lock
);
264 if ( je32_to_cpu(node
.i
.offset
) > je32_to_cpu(node
.i
.isize
) ||
265 PAD(je32_to_cpu(node
.i
.csize
) + sizeof (node
.i
)) != PAD(je32_to_cpu(node
.i
.totlen
))) {
266 printk(KERN_NOTICE
"jffs2_get_inode_nodes(): Inode corrupted at 0x%08x, totlen %d, #ino %d, version %d, isize %d, csize %d, dsize %d \n",
267 ref_offset(ref
), je32_to_cpu(node
.i
.totlen
), je32_to_cpu(node
.i
.ino
),
268 je32_to_cpu(node
.i
.version
), je32_to_cpu(node
.i
.isize
),
269 je32_to_cpu(node
.i
.csize
), je32_to_cpu(node
.i
.dsize
));
270 jffs2_mark_node_obsolete(c
, ref
);
271 spin_lock(&c
->erase_completion_lock
);
275 if (node
.i
.compr
!= JFFS2_COMPR_ZERO
&& je32_to_cpu(node
.i
.csize
)) {
276 unsigned char *buf
=NULL
;
277 uint32_t pointed
= 0;
280 err
= c
->mtd
->point (c
->mtd
, ref_offset(ref
) + sizeof(node
.i
), je32_to_cpu(node
.i
.csize
),
282 if (!err
&& retlen
< je32_to_cpu(node
.i
.csize
)) {
283 D1(printk(KERN_DEBUG
"MTD point returned len too short: 0x%zx\n", retlen
));
284 c
->mtd
->unpoint(c
->mtd
, buf
, ref_offset(ref
) + sizeof(node
.i
), je32_to_cpu(node
.i
.csize
));
286 D1(printk(KERN_DEBUG
"MTD point failed %d\n", err
));
288 pointed
= 1; /* succefully pointed to device */
292 buf
= kmalloc(je32_to_cpu(node
.i
.csize
), GFP_KERNEL
);
296 err
= jffs2_flash_read(c
, ref_offset(ref
) + sizeof(node
.i
), je32_to_cpu(node
.i
.csize
),
298 if (!err
&& retlen
!= je32_to_cpu(node
.i
.csize
))
305 crc
= crc32(0, buf
, je32_to_cpu(node
.i
.csize
));
310 c
->mtd
->unpoint(c
->mtd
, buf
, ref_offset(ref
) + sizeof(node
.i
), je32_to_cpu(node
.i
.csize
));
313 if (crc
!= je32_to_cpu(node
.i
.data_crc
)) {
314 printk(KERN_NOTICE
"jffs2_get_inode_nodes(): Data CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
315 ref_offset(ref
), je32_to_cpu(node
.i
.data_crc
), crc
);
316 jffs2_mark_node_obsolete(c
, ref
);
317 spin_lock(&c
->erase_completion_lock
);
323 /* Mark the node as having been checked and fix the accounting accordingly */
324 spin_lock(&c
->erase_completion_lock
);
325 jeb
= &c
->blocks
[ref
->flash_offset
/ c
->sector_size
];
326 len
= ref_totlen(c
, jeb
, ref
);
328 jeb
->used_size
+= len
;
329 jeb
->unchecked_size
-= len
;
331 c
->unchecked_size
-= len
;
333 /* If node covers at least a whole page, or if it starts at the
334 beginning of a page and runs to the end of the file, or if
335 it's a hole node, mark it REF_PRISTINE, else REF_NORMAL.
337 If it's actually overlapped, it'll get made NORMAL (or OBSOLETE)
338 when the overlapping node(s) get added to the tree anyway.
340 if ((je32_to_cpu(node
.i
.dsize
) >= PAGE_CACHE_SIZE
) ||
341 ( ((je32_to_cpu(node
.i
.offset
)&(PAGE_CACHE_SIZE
-1))==0) &&
342 (je32_to_cpu(node
.i
.dsize
)+je32_to_cpu(node
.i
.offset
) == je32_to_cpu(node
.i
.isize
)))) {
343 D1(printk(KERN_DEBUG
"Marking node at 0x%08x REF_PRISTINE\n", ref_offset(ref
)));
344 ref
->flash_offset
= ref_offset(ref
) | REF_PRISTINE
;
346 D1(printk(KERN_DEBUG
"Marking node at 0x%08x REF_NORMAL\n", ref_offset(ref
)));
347 ref
->flash_offset
= ref_offset(ref
) | REF_NORMAL
;
349 spin_unlock(&c
->erase_completion_lock
);
352 tn
= jffs2_alloc_tmp_dnode_info();
354 D1(printk(KERN_DEBUG
"alloc tn failed\n"));
359 tn
->fn
= jffs2_alloc_full_dnode();
361 D1(printk(KERN_DEBUG
"alloc fn failed\n"));
363 jffs2_free_tmp_dnode_info(tn
);
366 tn
->version
= je32_to_cpu(node
.i
.version
);
367 tn
->fn
->ofs
= je32_to_cpu(node
.i
.offset
);
368 /* There was a bug where we wrote hole nodes out with
369 csize/dsize swapped. Deal with it */
370 if (node
.i
.compr
== JFFS2_COMPR_ZERO
&& !je32_to_cpu(node
.i
.dsize
) && je32_to_cpu(node
.i
.csize
))
371 tn
->fn
->size
= je32_to_cpu(node
.i
.csize
);
372 else // normal case...
373 tn
->fn
->size
= je32_to_cpu(node
.i
.dsize
);
375 D1(printk(KERN_DEBUG
"dnode @%08x: ver %u, offset %04x, dsize %04x\n",
376 ref_offset(ref
), je32_to_cpu(node
.i
.version
),
377 je32_to_cpu(node
.i
.offset
), je32_to_cpu(node
.i
.dsize
)));
378 jffs2_add_tn_to_list(tn
, &ret_tn
);
382 if (ref_flags(ref
) == REF_UNCHECKED
) {
383 struct jffs2_eraseblock
*jeb
;
386 printk(KERN_ERR
"Eep. Unknown node type %04x at %08x was marked REF_UNCHECKED\n",
387 je16_to_cpu(node
.u
.nodetype
), ref_offset(ref
));
389 /* Mark the node as having been checked and fix the accounting accordingly */
390 spin_lock(&c
->erase_completion_lock
);
391 jeb
= &c
->blocks
[ref
->flash_offset
/ c
->sector_size
];
392 len
= ref_totlen(c
, jeb
, ref
);
394 jeb
->used_size
+= len
;
395 jeb
->unchecked_size
-= len
;
397 c
->unchecked_size
-= len
;
399 mark_ref_normal(ref
);
400 spin_unlock(&c
->erase_completion_lock
);
402 node
.u
.nodetype
= cpu_to_je16(JFFS2_NODE_ACCURATE
| je16_to_cpu(node
.u
.nodetype
));
403 if (crc32(0, &node
, sizeof(struct jffs2_unknown_node
)-4) != je32_to_cpu(node
.u
.hdr_crc
)) {
404 /* Hmmm. This should have been caught at scan time. */
405 printk(KERN_ERR
"Node header CRC failed at %08x. But it must have been OK earlier.\n",
407 printk(KERN_ERR
"Node was: { %04x, %04x, %08x, %08x }\n",
408 je16_to_cpu(node
.u
.magic
), je16_to_cpu(node
.u
.nodetype
), je32_to_cpu(node
.u
.totlen
),
409 je32_to_cpu(node
.u
.hdr_crc
));
410 jffs2_mark_node_obsolete(c
, ref
);
411 } else switch(je16_to_cpu(node
.u
.nodetype
) & JFFS2_COMPAT_MASK
) {
412 case JFFS2_FEATURE_INCOMPAT
:
413 printk(KERN_NOTICE
"Unknown INCOMPAT nodetype %04X at %08x\n", je16_to_cpu(node
.u
.nodetype
), ref_offset(ref
));
417 case JFFS2_FEATURE_ROCOMPAT
:
418 printk(KERN_NOTICE
"Unknown ROCOMPAT nodetype %04X at %08x\n", je16_to_cpu(node
.u
.nodetype
), ref_offset(ref
));
419 if (!(c
->flags
& JFFS2_SB_FLAG_RO
))
422 case JFFS2_FEATURE_RWCOMPAT_COPY
:
423 printk(KERN_NOTICE
"Unknown RWCOMPAT_COPY nodetype %04X at %08x\n", je16_to_cpu(node
.u
.nodetype
), ref_offset(ref
));
425 case JFFS2_FEATURE_RWCOMPAT_DELETE
:
426 printk(KERN_NOTICE
"Unknown RWCOMPAT_DELETE nodetype %04X at %08x\n", je16_to_cpu(node
.u
.nodetype
), ref_offset(ref
));
427 jffs2_mark_node_obsolete(c
, ref
);
432 spin_lock(&c
->erase_completion_lock
);
435 spin_unlock(&c
->erase_completion_lock
);
442 jffs2_free_tmp_dnode_info_list(ret_tn
);
443 jffs2_free_full_dirent_list(ret_fd
);
447 void jffs2_set_inocache_state(struct jffs2_sb_info
*c
, struct jffs2_inode_cache
*ic
, int state
)
449 spin_lock(&c
->inocache_lock
);
451 wake_up(&c
->inocache_wq
);
452 spin_unlock(&c
->inocache_lock
);
455 /* During mount, this needs no locking. During normal operation, its
456 callers want to do other stuff while still holding the inocache_lock.
457 Rather than introducing special case get_ino_cache functions or
458 callbacks, we just let the caller do the locking itself. */
460 struct jffs2_inode_cache
*jffs2_get_ino_cache(struct jffs2_sb_info
*c
, uint32_t ino
)
462 struct jffs2_inode_cache
*ret
;
464 D2(printk(KERN_DEBUG
"jffs2_get_ino_cache(): ino %u\n", ino
));
466 ret
= c
->inocache_list
[ino
% INOCACHE_HASHSIZE
];
467 while (ret
&& ret
->ino
< ino
) {
471 if (ret
&& ret
->ino
!= ino
)
474 D2(printk(KERN_DEBUG
"jffs2_get_ino_cache found %p for ino %u\n", ret
, ino
));
478 void jffs2_add_ino_cache (struct jffs2_sb_info
*c
, struct jffs2_inode_cache
*new)
480 struct jffs2_inode_cache
**prev
;
481 D2(printk(KERN_DEBUG
"jffs2_add_ino_cache: Add %p (ino #%u)\n", new, new->ino
));
482 spin_lock(&c
->inocache_lock
);
484 prev
= &c
->inocache_list
[new->ino
% INOCACHE_HASHSIZE
];
486 while ((*prev
) && (*prev
)->ino
< new->ino
) {
487 prev
= &(*prev
)->next
;
492 spin_unlock(&c
->inocache_lock
);
495 void jffs2_del_ino_cache(struct jffs2_sb_info
*c
, struct jffs2_inode_cache
*old
)
497 struct jffs2_inode_cache
**prev
;
498 D2(printk(KERN_DEBUG
"jffs2_del_ino_cache: Del %p (ino #%u)\n", old
, old
->ino
));
499 spin_lock(&c
->inocache_lock
);
501 prev
= &c
->inocache_list
[old
->ino
% INOCACHE_HASHSIZE
];
503 while ((*prev
) && (*prev
)->ino
< old
->ino
) {
504 prev
= &(*prev
)->next
;
506 if ((*prev
) == old
) {
510 spin_unlock(&c
->inocache_lock
);
513 void jffs2_free_ino_caches(struct jffs2_sb_info
*c
)
516 struct jffs2_inode_cache
*this, *next
;
518 for (i
=0; i
<INOCACHE_HASHSIZE
; i
++) {
519 this = c
->inocache_list
[i
];
522 D2(printk(KERN_DEBUG
"jffs2_free_ino_caches: Freeing ino #%u at %p\n", this->ino
, this));
523 jffs2_free_inode_cache(this);
526 c
->inocache_list
[i
] = NULL
;
530 void jffs2_free_raw_node_refs(struct jffs2_sb_info
*c
)
533 struct jffs2_raw_node_ref
*this, *next
;
535 for (i
=0; i
<c
->nr_blocks
; i
++) {
536 this = c
->blocks
[i
].first_node
;
538 next
= this->next_phys
;
539 jffs2_free_raw_node_ref(this);
542 c
->blocks
[i
].first_node
= c
->blocks
[i
].last_node
= NULL
;
546 struct jffs2_node_frag
*jffs2_lookup_node_frag(struct rb_root
*fragtree
, uint32_t offset
)
548 /* The common case in lookup is that there will be a node
549 which precisely matches. So we go looking for that first */
550 struct rb_node
*next
;
551 struct jffs2_node_frag
*prev
= NULL
;
552 struct jffs2_node_frag
*frag
= NULL
;
554 D2(printk(KERN_DEBUG
"jffs2_lookup_node_frag(%p, %d)\n", fragtree
, offset
));
556 next
= fragtree
->rb_node
;
559 frag
= rb_entry(next
, struct jffs2_node_frag
, rb
);
561 D2(printk(KERN_DEBUG
"Considering frag %d-%d (%p). left %p, right %p\n",
562 frag
->ofs
, frag
->ofs
+frag
->size
, frag
, frag
->rb
.rb_left
, frag
->rb
.rb_right
));
563 if (frag
->ofs
+ frag
->size
<= offset
) {
564 D2(printk(KERN_DEBUG
"Going right from frag %d-%d, before the region we care about\n",
565 frag
->ofs
, frag
->ofs
+frag
->size
));
566 /* Remember the closest smaller match on the way down */
567 if (!prev
|| frag
->ofs
> prev
->ofs
)
569 next
= frag
->rb
.rb_right
;
570 } else if (frag
->ofs
> offset
) {
571 D2(printk(KERN_DEBUG
"Going left from frag %d-%d, after the region we care about\n",
572 frag
->ofs
, frag
->ofs
+frag
->size
));
573 next
= frag
->rb
.rb_left
;
575 D2(printk(KERN_DEBUG
"Returning frag %d,%d, matched\n",
576 frag
->ofs
, frag
->ofs
+frag
->size
));
581 /* Exact match not found. Go back up looking at each parent,
582 and return the closest smaller one */
585 D2(printk(KERN_DEBUG
"No match. Returning frag %d,%d, closest previous\n",
586 prev
->ofs
, prev
->ofs
+prev
->size
));
588 D2(printk(KERN_DEBUG
"Returning NULL, empty fragtree\n"));
593 /* Pass 'c' argument to indicate that nodes should be marked obsolete as
595 void jffs2_kill_fragtree(struct rb_root
*root
, struct jffs2_sb_info
*c
)
597 struct jffs2_node_frag
*frag
;
598 struct jffs2_node_frag
*parent
;
603 frag
= (rb_entry(root
->rb_node
, struct jffs2_node_frag
, rb
));
606 if (frag
->rb
.rb_left
) {
607 D2(printk(KERN_DEBUG
"Going left from frag (%p) %d-%d\n",
608 frag
, frag
->ofs
, frag
->ofs
+frag
->size
));
609 frag
= frag_left(frag
);
612 if (frag
->rb
.rb_right
) {
613 D2(printk(KERN_DEBUG
"Going right from frag (%p) %d-%d\n",
614 frag
, frag
->ofs
, frag
->ofs
+frag
->size
));
615 frag
= frag_right(frag
);
619 D2(printk(KERN_DEBUG
"jffs2_kill_fragtree: frag at 0x%x-0x%x: node %p, frags %d--\n",
620 frag
->ofs
, frag
->ofs
+frag
->size
, frag
->node
,
621 frag
->node
?frag
->node
->frags
:0));
623 if (frag
->node
&& !(--frag
->node
->frags
)) {
624 /* Not a hole, and it's the final remaining frag
625 of this node. Free the node */
627 jffs2_mark_node_obsolete(c
, frag
->node
->raw
);
629 jffs2_free_full_dnode(frag
->node
);
631 parent
= frag_parent(frag
);
633 if (frag_left(parent
) == frag
)
634 parent
->rb
.rb_left
= NULL
;
636 parent
->rb
.rb_right
= NULL
;
639 jffs2_free_node_frag(frag
);
646 void jffs2_fragtree_insert(struct jffs2_node_frag
*newfrag
, struct jffs2_node_frag
*base
)
648 struct rb_node
*parent
= &base
->rb
;
649 struct rb_node
**link
= &parent
;
651 D2(printk(KERN_DEBUG
"jffs2_fragtree_insert(%p; %d-%d, %p)\n", newfrag
,
652 newfrag
->ofs
, newfrag
->ofs
+newfrag
->size
, base
));
656 base
= rb_entry(parent
, struct jffs2_node_frag
, rb
);
658 D2(printk(KERN_DEBUG
"fragtree_insert considering frag at 0x%x\n", base
->ofs
));
659 if (newfrag
->ofs
> base
->ofs
)
660 link
= &base
->rb
.rb_right
;
661 else if (newfrag
->ofs
< base
->ofs
)
662 link
= &base
->rb
.rb_left
;
664 printk(KERN_CRIT
"Duplicate frag at %08x (%p,%p)\n", newfrag
->ofs
, newfrag
, base
);
669 rb_link_node(&newfrag
->rb
, &base
->rb
, link
);