aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/nodelist.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2/nodelist.c')
-rw-r--r--fs/jffs2/nodelist.c93
1 files changed, 69 insertions, 24 deletions
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index cd6a8bd13e0b..c7bbdeec93a6 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: nodelist.c,v 1.90 2004/12/08 17:59:20 dwmw2 Exp $ 10 * $Id: nodelist.c,v 1.97 2005/07/06 15:18:41 dwmw2 Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -58,27 +58,60 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new
58/* Put a new tmp_dnode_info into the list, keeping the list in 58/* Put a new tmp_dnode_info into the list, keeping the list in
59 order of increasing version 59 order of increasing version
60*/ 60*/
61static void jffs2_add_tn_to_list(struct jffs2_tmp_dnode_info *tn, struct jffs2_tmp_dnode_info **list) 61
62static void jffs2_add_tn_to_list(struct jffs2_tmp_dnode_info *tn, struct rb_root *list)
62{ 63{
63 struct jffs2_tmp_dnode_info **prev = list; 64 struct rb_node **p = &list->rb_node;
64 65 struct rb_node * parent = NULL;
65 while ((*prev) && (*prev)->version < tn->version) { 66 struct jffs2_tmp_dnode_info *this;
66 prev = &((*prev)->next); 67
67 } 68 while (*p) {
68 tn->next = (*prev); 69 parent = *p;
69 *prev = tn; 70 this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
71
72 /* There may actually be a collision here, but it doesn't
73 actually matter. As long as the two nodes with the same
74 version are together, it's all fine. */
75 if (tn->version < this->version)
76 p = &(*p)->rb_left;
77 else
78 p = &(*p)->rb_right;
79 }
80
81 rb_link_node(&tn->rb, parent, p);
82 rb_insert_color(&tn->rb, list);
70} 83}
71 84
72static void jffs2_free_tmp_dnode_info_list(struct jffs2_tmp_dnode_info *tn) 85static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
73{ 86{
74 struct jffs2_tmp_dnode_info *next; 87 struct rb_node *this;
88 struct jffs2_tmp_dnode_info *tn;
89
90 this = list->rb_node;
91
92 /* Now at bottom of tree */
93 while (this) {
94 if (this->rb_left)
95 this = this->rb_left;
96 else if (this->rb_right)
97 this = this->rb_right;
98 else {
99 tn = rb_entry(this, struct jffs2_tmp_dnode_info, rb);
100 jffs2_free_full_dnode(tn->fn);
101 jffs2_free_tmp_dnode_info(tn);
102
103 this = this->rb_parent;
104 if (!this)
105 break;
75 106
76 while (tn) { 107 if (this->rb_left == &tn->rb)
77 next = tn; 108 this->rb_left = NULL;
78 tn = tn->next; 109 else if (this->rb_right == &tn->rb)
79 jffs2_free_full_dnode(next->fn); 110 this->rb_right = NULL;
80 jffs2_free_tmp_dnode_info(next); 111 else BUG();
112 }
81 } 113 }
114 list->rb_node = NULL;
82} 115}
83 116
84static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd) 117static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd)
@@ -108,12 +141,13 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r
108 with this ino, returning the former in order of version */ 141 with this ino, returning the former in order of version */
109 142
110int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 143int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
111 struct jffs2_tmp_dnode_info **tnp, struct jffs2_full_dirent **fdp, 144 struct rb_root *tnp, struct jffs2_full_dirent **fdp,
112 uint32_t *highest_version, uint32_t *latest_mctime, 145 uint32_t *highest_version, uint32_t *latest_mctime,
113 uint32_t *mctime_ver) 146 uint32_t *mctime_ver)
114{ 147{
115 struct jffs2_raw_node_ref *ref, *valid_ref; 148 struct jffs2_raw_node_ref *ref, *valid_ref;
116 struct jffs2_tmp_dnode_info *tn, *ret_tn = NULL; 149 struct jffs2_tmp_dnode_info *tn;
150 struct rb_root ret_tn = RB_ROOT;
117 struct jffs2_full_dirent *fd, *ret_fd = NULL; 151 struct jffs2_full_dirent *fd, *ret_fd = NULL;
118 union jffs2_node_union node; 152 union jffs2_node_union node;
119 size_t retlen; 153 size_t retlen;
@@ -127,7 +161,7 @@ int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
127 161
128 valid_ref = jffs2_first_valid_node(f->inocache->nodes); 162 valid_ref = jffs2_first_valid_node(f->inocache->nodes);
129 163
130 if (!valid_ref) 164 if (!valid_ref && (f->inocache->ino != 1))
131 printk(KERN_WARNING "Eep. No valid nodes for ino #%u\n", f->inocache->ino); 165 printk(KERN_WARNING "Eep. No valid nodes for ino #%u\n", f->inocache->ino);
132 166
133 while (valid_ref) { 167 while (valid_ref) {
@@ -450,7 +484,7 @@ int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
450 return 0; 484 return 0;
451 485
452 free_out: 486 free_out:
453 jffs2_free_tmp_dnode_info_list(ret_tn); 487 jffs2_free_tmp_dnode_info_list(&ret_tn);
454 jffs2_free_full_dirent_list(ret_fd); 488 jffs2_free_full_dirent_list(ret_fd);
455 return err; 489 return err;
456} 490}
@@ -489,9 +523,13 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t
489void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new) 523void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new)
490{ 524{
491 struct jffs2_inode_cache **prev; 525 struct jffs2_inode_cache **prev;
492 D2(printk(KERN_DEBUG "jffs2_add_ino_cache: Add %p (ino #%u)\n", new, new->ino)); 526
493 spin_lock(&c->inocache_lock); 527 spin_lock(&c->inocache_lock);
494 528 if (!new->ino)
529 new->ino = ++c->highest_ino;
530
531 D2(printk(KERN_DEBUG "jffs2_add_ino_cache: Add %p (ino #%u)\n", new, new->ino));
532
495 prev = &c->inocache_list[new->ino % INOCACHE_HASHSIZE]; 533 prev = &c->inocache_list[new->ino % INOCACHE_HASHSIZE];
496 534
497 while ((*prev) && (*prev)->ino < new->ino) { 535 while ((*prev) && (*prev)->ino < new->ino) {
@@ -506,7 +544,7 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new
506void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) 544void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
507{ 545{
508 struct jffs2_inode_cache **prev; 546 struct jffs2_inode_cache **prev;
509 D2(printk(KERN_DEBUG "jffs2_del_ino_cache: Del %p (ino #%u)\n", old, old->ino)); 547 D1(printk(KERN_DEBUG "jffs2_del_ino_cache: Del %p (ino #%u)\n", old, old->ino));
510 spin_lock(&c->inocache_lock); 548 spin_lock(&c->inocache_lock);
511 549
512 prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE]; 550 prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE];
@@ -518,6 +556,14 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
518 *prev = old->next; 556 *prev = old->next;
519 } 557 }
520 558
559 /* Free it now unless it's in READING or CLEARING state, which
560 are the transitions upon read_inode() and clear_inode(). The
561 rest of the time we know nobody else is looking at it, and
562 if it's held by read_inode() or clear_inode() they'll free it
563 for themselves. */
564 if (old->state != INO_STATE_READING && old->state != INO_STATE_CLEARING)
565 jffs2_free_inode_cache(old);
566
521 spin_unlock(&c->inocache_lock); 567 spin_unlock(&c->inocache_lock);
522} 568}
523 569
@@ -530,7 +576,6 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c)
530 this = c->inocache_list[i]; 576 this = c->inocache_list[i];
531 while (this) { 577 while (this) {
532 next = this->next; 578 next = this->next;
533 D2(printk(KERN_DEBUG "jffs2_free_ino_caches: Freeing ino #%u at %p\n", this->ino, this));
534 jffs2_free_inode_cache(this); 579 jffs2_free_inode_cache(this);
535 this = next; 580 this = next;
536 } 581 }