2 * JFFS2 -- Journalling Flash File System, Version 2.
4 * Copyright (C) 2001-2003 Red Hat, Inc.
6 * Created by David Woodhouse <dwmw2@infradead.org>
8 * For licensing information, see the file 'LICENCE' in this directory.
10 * $Id: nodelist.c,v 1.95 2005/07/05 21:03:07 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
62 static void jffs2_add_tn_to_list(struct jffs2_tmp_dnode_info
*tn
, struct rb_root
*list
)
64 struct rb_node
**p
= &list
->rb_node
;
65 struct rb_node
* parent
= NULL
;
66 struct jffs2_tmp_dnode_info
*this;
70 this = rb_entry(parent
, struct jffs2_tmp_dnode_info
, rb
);
72 if (tn
->version
< this->version
)
74 else if (tn
->version
> this->version
)
82 rb_link_node(&tn
->rb
, parent
, p
);
83 rb_insert_color(&tn
->rb
, list
);
86 static void jffs2_free_tmp_dnode_info_list(struct rb_root
*list
)
89 struct jffs2_tmp_dnode_info
*tn
;
93 /* Now at bottom of tree */
97 else if (this->rb_right
)
98 this = this->rb_right
;
100 tn
= rb_entry(this, struct jffs2_tmp_dnode_info
, rb
);
101 jffs2_free_full_dnode(tn
->fn
);
102 jffs2_free_tmp_dnode_info(tn
);
104 this = this->rb_parent
;
108 if (this->rb_left
== &tn
->rb
)
109 this->rb_left
= NULL
;
110 else if (this->rb_right
== &tn
->rb
)
111 this->rb_right
= NULL
;
115 list
->rb_node
= NULL
;
118 static void jffs2_free_full_dirent_list(struct jffs2_full_dirent
*fd
)
120 struct jffs2_full_dirent
*next
;
124 jffs2_free_full_dirent(fd
);
129 /* Returns first valid node after 'ref'. May return 'ref' */
130 static struct jffs2_raw_node_ref
*jffs2_first_valid_node(struct jffs2_raw_node_ref
*ref
)
132 while (ref
&& ref
->next_in_ino
) {
133 if (!ref_obsolete(ref
))
135 D1(printk(KERN_DEBUG
"node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref
)));
136 ref
= ref
->next_in_ino
;
141 /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
142 with this ino, returning the former in order of version */
144 int jffs2_get_inode_nodes(struct jffs2_sb_info
*c
, struct jffs2_inode_info
*f
,
145 struct rb_root
*tnp
, struct jffs2_full_dirent
**fdp
,
146 uint32_t *highest_version
, uint32_t *latest_mctime
,
147 uint32_t *mctime_ver
)
149 struct jffs2_raw_node_ref
*ref
, *valid_ref
;
150 struct jffs2_tmp_dnode_info
*tn
;
151 struct rb_root ret_tn
= RB_ROOT
;
152 struct jffs2_full_dirent
*fd
, *ret_fd
= NULL
;
153 union jffs2_node_union node
;
159 D1(printk(KERN_DEBUG
"jffs2_get_inode_nodes(): ino #%u\n", f
->inocache
->ino
));
161 spin_lock(&c
->erase_completion_lock
);
163 valid_ref
= jffs2_first_valid_node(f
->inocache
->nodes
);
165 if (!valid_ref
&& (f
->inocache
->ino
!= 1))
166 printk(KERN_WARNING
"Eep. No valid nodes for ino #%u\n", f
->inocache
->ino
);
169 /* We can hold a pointer to a non-obsolete node without the spinlock,
170 but _obsolete_ nodes may disappear at any time, if the block
171 they're in gets erased. So if we mark 'ref' obsolete while we're
172 not holding the lock, it can go away immediately. For that reason,
173 we find the next valid node first, before processing 'ref'.
176 valid_ref
= jffs2_first_valid_node(ref
->next_in_ino
);
177 spin_unlock(&c
->erase_completion_lock
);
182 err
= jffs2_flash_read(c
, (ref_offset(ref
)),
183 min_t(uint32_t, ref_totlen(c
, NULL
, ref
), sizeof(node
)),
184 &retlen
, (void *)&node
);
186 printk(KERN_WARNING
"error %d reading node at 0x%08x in get_inode_nodes()\n", err
, ref_offset(ref
));
191 /* Check we've managed to read at least the common node header */
192 if (retlen
< min_t(uint32_t, ref_totlen(c
, NULL
, ref
), sizeof(node
.u
))) {
193 printk(KERN_WARNING
"short read in get_inode_nodes()\n");
198 switch (je16_to_cpu(node
.u
.nodetype
)) {
199 case JFFS2_NODETYPE_DIRENT
:
200 D1(printk(KERN_DEBUG
"Node at %08x (%d) is a dirent node\n", ref_offset(ref
), ref_flags(ref
)));
201 if (ref_flags(ref
) == REF_UNCHECKED
) {
202 printk(KERN_WARNING
"BUG: Dirent node at 0x%08x never got checked? How?\n", ref_offset(ref
));
205 if (retlen
< sizeof(node
.d
)) {
206 printk(KERN_WARNING
"short read in get_inode_nodes()\n");
211 if (PAD((node
.d
.nsize
+ sizeof (node
.d
))) != PAD(je32_to_cpu (node
.d
.totlen
))) {
212 printk(KERN_NOTICE
"jffs2_get_inode_nodes(): Illegal nsize in node at 0x%08x: nsize 0x%02x, totlen %04x\n",
213 ref_offset(ref
), node
.d
.nsize
, je32_to_cpu(node
.d
.totlen
));
214 jffs2_mark_node_obsolete(c
, ref
);
215 spin_lock(&c
->erase_completion_lock
);
218 if (je32_to_cpu(node
.d
.version
) > *highest_version
)
219 *highest_version
= je32_to_cpu(node
.d
.version
);
220 if (ref_obsolete(ref
)) {
221 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
222 printk(KERN_ERR
"Dirent node at 0x%08x became obsolete while we weren't looking\n",
227 fd
= jffs2_alloc_full_dirent(node
.d
.nsize
+1);
233 fd
->version
= je32_to_cpu(node
.d
.version
);
234 fd
->ino
= je32_to_cpu(node
.d
.ino
);
235 fd
->type
= node
.d
.type
;
237 /* Pick out the mctime of the latest dirent */
238 if(fd
->version
> *mctime_ver
) {
239 *mctime_ver
= fd
->version
;
240 *latest_mctime
= je32_to_cpu(node
.d
.mctime
);
243 /* memcpy as much of the name as possible from the raw
244 dirent we've already read from the flash
246 if (retlen
> sizeof(struct jffs2_raw_dirent
))
247 memcpy(&fd
->name
[0], &node
.d
.name
[0], min_t(uint32_t, node
.d
.nsize
, (retlen
-sizeof(struct jffs2_raw_dirent
))));
249 /* Do we need to copy any more of the name directly
252 if (node
.d
.nsize
+ sizeof(struct jffs2_raw_dirent
) > retlen
) {
254 int already
= retlen
- sizeof(struct jffs2_raw_dirent
);
256 err
= jffs2_flash_read(c
, (ref_offset(ref
)) + retlen
,
257 node
.d
.nsize
- already
, &retlen
, &fd
->name
[already
]);
258 if (!err
&& retlen
!= node
.d
.nsize
- already
)
262 printk(KERN_WARNING
"Read remainder of name in jffs2_get_inode_nodes(): error %d\n", err
);
263 jffs2_free_full_dirent(fd
);
267 fd
->nhash
= full_name_hash(fd
->name
, node
.d
.nsize
);
269 fd
->name
[node
.d
.nsize
] = '\0';
270 /* Wheee. We now have a complete jffs2_full_dirent structure, with
271 the name in it and everything. Link it into the list
273 D1(printk(KERN_DEBUG
"Adding fd \"%s\", ino #%u\n", fd
->name
, fd
->ino
));
274 jffs2_add_fd_to_list(c
, fd
, &ret_fd
);
277 case JFFS2_NODETYPE_INODE
:
278 D1(printk(KERN_DEBUG
"Node at %08x (%d) is a data node\n", ref_offset(ref
), ref_flags(ref
)));
279 if (retlen
< sizeof(node
.i
)) {
280 printk(KERN_WARNING
"read too short for dnode\n");
284 if (je32_to_cpu(node
.i
.version
) > *highest_version
)
285 *highest_version
= je32_to_cpu(node
.i
.version
);
286 D1(printk(KERN_DEBUG
"version %d, highest_version now %d\n", je32_to_cpu(node
.i
.version
), *highest_version
));
288 if (ref_obsolete(ref
)) {
289 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
290 printk(KERN_ERR
"Inode node at 0x%08x became obsolete while we weren't looking\n",
295 /* If we've never checked the CRCs on this node, check them now. */
296 if (ref_flags(ref
) == REF_UNCHECKED
) {
298 struct jffs2_eraseblock
*jeb
;
300 crc
= crc32(0, &node
, sizeof(node
.i
)-8);
301 if (crc
!= je32_to_cpu(node
.i
.node_crc
)) {
302 printk(KERN_NOTICE
"jffs2_get_inode_nodes(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
303 ref_offset(ref
), je32_to_cpu(node
.i
.node_crc
), crc
);
304 jffs2_mark_node_obsolete(c
, ref
);
305 spin_lock(&c
->erase_completion_lock
);
310 if ( je32_to_cpu(node
.i
.offset
) > je32_to_cpu(node
.i
.isize
) ||
311 PAD(je32_to_cpu(node
.i
.csize
) + sizeof (node
.i
)) != PAD(je32_to_cpu(node
.i
.totlen
))) {
312 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",
313 ref_offset(ref
), je32_to_cpu(node
.i
.totlen
), je32_to_cpu(node
.i
.ino
),
314 je32_to_cpu(node
.i
.version
), je32_to_cpu(node
.i
.isize
),
315 je32_to_cpu(node
.i
.csize
), je32_to_cpu(node
.i
.dsize
));
316 jffs2_mark_node_obsolete(c
, ref
);
317 spin_lock(&c
->erase_completion_lock
);
321 if (node
.i
.compr
!= JFFS2_COMPR_ZERO
&& je32_to_cpu(node
.i
.csize
)) {
322 unsigned char *buf
=NULL
;
323 uint32_t pointed
= 0;
326 err
= c
->mtd
->point (c
->mtd
, ref_offset(ref
) + sizeof(node
.i
), je32_to_cpu(node
.i
.csize
),
328 if (!err
&& retlen
< je32_to_cpu(node
.i
.csize
)) {
329 D1(printk(KERN_DEBUG
"MTD point returned len too short: 0x%zx\n", retlen
));
330 c
->mtd
->unpoint(c
->mtd
, buf
, ref_offset(ref
) + sizeof(node
.i
), je32_to_cpu(node
.i
.csize
));
332 D1(printk(KERN_DEBUG
"MTD point failed %d\n", err
));
334 pointed
= 1; /* succefully pointed to device */
338 buf
= kmalloc(je32_to_cpu(node
.i
.csize
), GFP_KERNEL
);
342 err
= jffs2_flash_read(c
, ref_offset(ref
) + sizeof(node
.i
), je32_to_cpu(node
.i
.csize
),
344 if (!err
&& retlen
!= je32_to_cpu(node
.i
.csize
))
351 crc
= crc32(0, buf
, je32_to_cpu(node
.i
.csize
));
356 c
->mtd
->unpoint(c
->mtd
, buf
, ref_offset(ref
) + sizeof(node
.i
), je32_to_cpu(node
.i
.csize
));
359 if (crc
!= je32_to_cpu(node
.i
.data_crc
)) {
360 printk(KERN_NOTICE
"jffs2_get_inode_nodes(): Data CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
361 ref_offset(ref
), je32_to_cpu(node
.i
.data_crc
), crc
);
362 jffs2_mark_node_obsolete(c
, ref
);
363 spin_lock(&c
->erase_completion_lock
);
369 /* Mark the node as having been checked and fix the accounting accordingly */
370 spin_lock(&c
->erase_completion_lock
);
371 jeb
= &c
->blocks
[ref
->flash_offset
/ c
->sector_size
];
372 len
= ref_totlen(c
, jeb
, ref
);
374 jeb
->used_size
+= len
;
375 jeb
->unchecked_size
-= len
;
377 c
->unchecked_size
-= len
;
379 /* If node covers at least a whole page, or if it starts at the
380 beginning of a page and runs to the end of the file, or if
381 it's a hole node, mark it REF_PRISTINE, else REF_NORMAL.
383 If it's actually overlapped, it'll get made NORMAL (or OBSOLETE)
384 when the overlapping node(s) get added to the tree anyway.
386 if ((je32_to_cpu(node
.i
.dsize
) >= PAGE_CACHE_SIZE
) ||
387 ( ((je32_to_cpu(node
.i
.offset
)&(PAGE_CACHE_SIZE
-1))==0) &&
388 (je32_to_cpu(node
.i
.dsize
)+je32_to_cpu(node
.i
.offset
) == je32_to_cpu(node
.i
.isize
)))) {
389 D1(printk(KERN_DEBUG
"Marking node at 0x%08x REF_PRISTINE\n", ref_offset(ref
)));
390 ref
->flash_offset
= ref_offset(ref
) | REF_PRISTINE
;
392 D1(printk(KERN_DEBUG
"Marking node at 0x%08x REF_NORMAL\n", ref_offset(ref
)));
393 ref
->flash_offset
= ref_offset(ref
) | REF_NORMAL
;
395 spin_unlock(&c
->erase_completion_lock
);
398 tn
= jffs2_alloc_tmp_dnode_info();
400 D1(printk(KERN_DEBUG
"alloc tn failed\n"));
405 tn
->fn
= jffs2_alloc_full_dnode();
407 D1(printk(KERN_DEBUG
"alloc fn failed\n"));
409 jffs2_free_tmp_dnode_info(tn
);
412 tn
->version
= je32_to_cpu(node
.i
.version
);
413 tn
->fn
->ofs
= je32_to_cpu(node
.i
.offset
);
414 /* There was a bug where we wrote hole nodes out with
415 csize/dsize swapped. Deal with it */
416 if (node
.i
.compr
== JFFS2_COMPR_ZERO
&& !je32_to_cpu(node
.i
.dsize
) && je32_to_cpu(node
.i
.csize
))
417 tn
->fn
->size
= je32_to_cpu(node
.i
.csize
);
418 else // normal case...
419 tn
->fn
->size
= je32_to_cpu(node
.i
.dsize
);
421 D1(printk(KERN_DEBUG
"dnode @%08x: ver %u, offset %04x, dsize %04x\n",
422 ref_offset(ref
), je32_to_cpu(node
.i
.version
),
423 je32_to_cpu(node
.i
.offset
), je32_to_cpu(node
.i
.dsize
)));
424 jffs2_add_tn_to_list(tn
, &ret_tn
);
428 if (ref_flags(ref
) == REF_UNCHECKED
) {
429 struct jffs2_eraseblock
*jeb
;
432 printk(KERN_ERR
"Eep. Unknown node type %04x at %08x was marked REF_UNCHECKED\n",
433 je16_to_cpu(node
.u
.nodetype
), ref_offset(ref
));
435 /* Mark the node as having been checked and fix the accounting accordingly */
436 spin_lock(&c
->erase_completion_lock
);
437 jeb
= &c
->blocks
[ref
->flash_offset
/ c
->sector_size
];
438 len
= ref_totlen(c
, jeb
, ref
);
440 jeb
->used_size
+= len
;
441 jeb
->unchecked_size
-= len
;
443 c
->unchecked_size
-= len
;
445 mark_ref_normal(ref
);
446 spin_unlock(&c
->erase_completion_lock
);
448 node
.u
.nodetype
= cpu_to_je16(JFFS2_NODE_ACCURATE
| je16_to_cpu(node
.u
.nodetype
));
449 if (crc32(0, &node
, sizeof(struct jffs2_unknown_node
)-4) != je32_to_cpu(node
.u
.hdr_crc
)) {
450 /* Hmmm. This should have been caught at scan time. */
451 printk(KERN_ERR
"Node header CRC failed at %08x. But it must have been OK earlier.\n",
453 printk(KERN_ERR
"Node was: { %04x, %04x, %08x, %08x }\n",
454 je16_to_cpu(node
.u
.magic
), je16_to_cpu(node
.u
.nodetype
), je32_to_cpu(node
.u
.totlen
),
455 je32_to_cpu(node
.u
.hdr_crc
));
456 jffs2_mark_node_obsolete(c
, ref
);
457 } else switch(je16_to_cpu(node
.u
.nodetype
) & JFFS2_COMPAT_MASK
) {
458 case JFFS2_FEATURE_INCOMPAT
:
459 printk(KERN_NOTICE
"Unknown INCOMPAT nodetype %04X at %08x\n", je16_to_cpu(node
.u
.nodetype
), ref_offset(ref
));
463 case JFFS2_FEATURE_ROCOMPAT
:
464 printk(KERN_NOTICE
"Unknown ROCOMPAT nodetype %04X at %08x\n", je16_to_cpu(node
.u
.nodetype
), ref_offset(ref
));
465 if (!(c
->flags
& JFFS2_SB_FLAG_RO
))
468 case JFFS2_FEATURE_RWCOMPAT_COPY
:
469 printk(KERN_NOTICE
"Unknown RWCOMPAT_COPY nodetype %04X at %08x\n", je16_to_cpu(node
.u
.nodetype
), ref_offset(ref
));
471 case JFFS2_FEATURE_RWCOMPAT_DELETE
:
472 printk(KERN_NOTICE
"Unknown RWCOMPAT_DELETE nodetype %04X at %08x\n", je16_to_cpu(node
.u
.nodetype
), ref_offset(ref
));
473 jffs2_mark_node_obsolete(c
, ref
);
478 spin_lock(&c
->erase_completion_lock
);
481 spin_unlock(&c
->erase_completion_lock
);
488 jffs2_free_tmp_dnode_info_list(&ret_tn
);
489 jffs2_free_full_dirent_list(ret_fd
);
493 void jffs2_set_inocache_state(struct jffs2_sb_info
*c
, struct jffs2_inode_cache
*ic
, int state
)
495 spin_lock(&c
->inocache_lock
);
497 wake_up(&c
->inocache_wq
);
498 spin_unlock(&c
->inocache_lock
);
501 /* During mount, this needs no locking. During normal operation, its
502 callers want to do other stuff while still holding the inocache_lock.
503 Rather than introducing special case get_ino_cache functions or
504 callbacks, we just let the caller do the locking itself. */
506 struct jffs2_inode_cache
*jffs2_get_ino_cache(struct jffs2_sb_info
*c
, uint32_t ino
)
508 struct jffs2_inode_cache
*ret
;
510 D2(printk(KERN_DEBUG
"jffs2_get_ino_cache(): ino %u\n", ino
));
512 ret
= c
->inocache_list
[ino
% INOCACHE_HASHSIZE
];
513 while (ret
&& ret
->ino
< ino
) {
517 if (ret
&& ret
->ino
!= ino
)
520 D2(printk(KERN_DEBUG
"jffs2_get_ino_cache found %p for ino %u\n", ret
, ino
));
524 void jffs2_add_ino_cache (struct jffs2_sb_info
*c
, struct jffs2_inode_cache
*new)
526 struct jffs2_inode_cache
**prev
;
528 spin_lock(&c
->inocache_lock
);
530 new->ino
= ++c
->highest_ino
;
532 D2(printk(KERN_DEBUG
"jffs2_add_ino_cache: Add %p (ino #%u)\n", new, new->ino
));
534 prev
= &c
->inocache_list
[new->ino
% INOCACHE_HASHSIZE
];
536 while ((*prev
) && (*prev
)->ino
< new->ino
) {
537 prev
= &(*prev
)->next
;
542 spin_unlock(&c
->inocache_lock
);
545 void jffs2_del_ino_cache(struct jffs2_sb_info
*c
, struct jffs2_inode_cache
*old
)
547 struct jffs2_inode_cache
**prev
;
548 D1(printk(KERN_DEBUG
"jffs2_del_ino_cache: Del %p (ino #%u)\n", old
, old
->ino
));
549 spin_lock(&c
->inocache_lock
);
551 prev
= &c
->inocache_list
[old
->ino
% INOCACHE_HASHSIZE
];
553 while ((*prev
) && (*prev
)->ino
< old
->ino
) {
554 prev
= &(*prev
)->next
;
556 if ((*prev
) == old
) {
560 /* Free it now unless it's in READING or CLEARING state, which
561 are the transitions upon read_inode() and clear_inode(). The
562 rest of the time we know nobody else is looking at it, and
563 if it's held by read_inode() or clear_inode() they'll free it
565 if (old
->state
!= INO_STATE_READING
&& old
->state
!= INO_STATE_CLEARING
)
566 jffs2_free_inode_cache(old
);
568 spin_unlock(&c
->inocache_lock
);
571 void jffs2_free_ino_caches(struct jffs2_sb_info
*c
)
574 struct jffs2_inode_cache
*this, *next
;
576 for (i
=0; i
<INOCACHE_HASHSIZE
; i
++) {
577 this = c
->inocache_list
[i
];
580 jffs2_free_inode_cache(this);
583 c
->inocache_list
[i
] = NULL
;
587 void jffs2_free_raw_node_refs(struct jffs2_sb_info
*c
)
590 struct jffs2_raw_node_ref
*this, *next
;
592 for (i
=0; i
<c
->nr_blocks
; i
++) {
593 this = c
->blocks
[i
].first_node
;
595 next
= this->next_phys
;
596 jffs2_free_raw_node_ref(this);
599 c
->blocks
[i
].first_node
= c
->blocks
[i
].last_node
= NULL
;
603 struct jffs2_node_frag
*jffs2_lookup_node_frag(struct rb_root
*fragtree
, uint32_t offset
)
605 /* The common case in lookup is that there will be a node
606 which precisely matches. So we go looking for that first */
607 struct rb_node
*next
;
608 struct jffs2_node_frag
*prev
= NULL
;
609 struct jffs2_node_frag
*frag
= NULL
;
611 D2(printk(KERN_DEBUG
"jffs2_lookup_node_frag(%p, %d)\n", fragtree
, offset
));
613 next
= fragtree
->rb_node
;
616 frag
= rb_entry(next
, struct jffs2_node_frag
, rb
);
618 D2(printk(KERN_DEBUG
"Considering frag %d-%d (%p). left %p, right %p\n",
619 frag
->ofs
, frag
->ofs
+frag
->size
, frag
, frag
->rb
.rb_left
, frag
->rb
.rb_right
));
620 if (frag
->ofs
+ frag
->size
<= offset
) {
621 D2(printk(KERN_DEBUG
"Going right from frag %d-%d, before the region we care about\n",
622 frag
->ofs
, frag
->ofs
+frag
->size
));
623 /* Remember the closest smaller match on the way down */
624 if (!prev
|| frag
->ofs
> prev
->ofs
)
626 next
= frag
->rb
.rb_right
;
627 } else if (frag
->ofs
> offset
) {
628 D2(printk(KERN_DEBUG
"Going left from frag %d-%d, after the region we care about\n",
629 frag
->ofs
, frag
->ofs
+frag
->size
));
630 next
= frag
->rb
.rb_left
;
632 D2(printk(KERN_DEBUG
"Returning frag %d,%d, matched\n",
633 frag
->ofs
, frag
->ofs
+frag
->size
));
638 /* Exact match not found. Go back up looking at each parent,
639 and return the closest smaller one */
642 D2(printk(KERN_DEBUG
"No match. Returning frag %d,%d, closest previous\n",
643 prev
->ofs
, prev
->ofs
+prev
->size
));
645 D2(printk(KERN_DEBUG
"Returning NULL, empty fragtree\n"));
650 /* Pass 'c' argument to indicate that nodes should be marked obsolete as
652 void jffs2_kill_fragtree(struct rb_root
*root
, struct jffs2_sb_info
*c
)
654 struct jffs2_node_frag
*frag
;
655 struct jffs2_node_frag
*parent
;
660 frag
= (rb_entry(root
->rb_node
, struct jffs2_node_frag
, rb
));
663 if (frag
->rb
.rb_left
) {
664 D2(printk(KERN_DEBUG
"Going left from frag (%p) %d-%d\n",
665 frag
, frag
->ofs
, frag
->ofs
+frag
->size
));
666 frag
= frag_left(frag
);
669 if (frag
->rb
.rb_right
) {
670 D2(printk(KERN_DEBUG
"Going right from frag (%p) %d-%d\n",
671 frag
, frag
->ofs
, frag
->ofs
+frag
->size
));
672 frag
= frag_right(frag
);
676 D2(printk(KERN_DEBUG
"jffs2_kill_fragtree: frag at 0x%x-0x%x: node %p, frags %d--\n",
677 frag
->ofs
, frag
->ofs
+frag
->size
, frag
->node
,
678 frag
->node
?frag
->node
->frags
:0));
680 if (frag
->node
&& !(--frag
->node
->frags
)) {
681 /* Not a hole, and it's the final remaining frag
682 of this node. Free the node */
684 jffs2_mark_node_obsolete(c
, frag
->node
->raw
);
686 jffs2_free_full_dnode(frag
->node
);
688 parent
= frag_parent(frag
);
690 if (frag_left(parent
) == frag
)
691 parent
->rb
.rb_left
= NULL
;
693 parent
->rb
.rb_right
= NULL
;
696 jffs2_free_node_frag(frag
);
703 void jffs2_fragtree_insert(struct jffs2_node_frag
*newfrag
, struct jffs2_node_frag
*base
)
705 struct rb_node
*parent
= &base
->rb
;
706 struct rb_node
**link
= &parent
;
708 D2(printk(KERN_DEBUG
"jffs2_fragtree_insert(%p; %d-%d, %p)\n", newfrag
,
709 newfrag
->ofs
, newfrag
->ofs
+newfrag
->size
, base
));
713 base
= rb_entry(parent
, struct jffs2_node_frag
, rb
);
715 D2(printk(KERN_DEBUG
"fragtree_insert considering frag at 0x%x\n", base
->ofs
));
716 if (newfrag
->ofs
> base
->ofs
)
717 link
= &base
->rb
.rb_right
;
718 else if (newfrag
->ofs
< base
->ofs
)
719 link
= &base
->rb
.rb_left
;
721 printk(KERN_CRIT
"Duplicate frag at %08x (%p,%p)\n", newfrag
->ofs
, newfrag
, base
);
726 rb_link_node(&newfrag
->rb
, &base
->rb
, link
);