diff options
author | Dave Kleikamp <shaggy@austin.ibm.com> | 2005-07-13 09:57:38 -0400 |
---|---|---|
committer | Dave Kleikamp <shaggy@austin.ibm.com> | 2005-07-13 09:57:38 -0400 |
commit | f7f24758ac98a506770bc5910d33567610fa3403 (patch) | |
tree | ff7fad3d01bf9dc2e2e54b908f9fca4891e1ee72 /fs/jffs2/nodelist.c | |
parent | b38a3ab3d1bb0dc3288f73903d4dc4672b5cd2d0 (diff) | |
parent | c32511e2718618f0b53479eb36e07439aa363a74 (diff) |
Merge with /home/shaggy/git/linus-clean/
Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
Diffstat (limited to 'fs/jffs2/nodelist.c')
-rw-r--r-- | fs/jffs2/nodelist.c | 93 |
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 | */ |
61 | static void jffs2_add_tn_to_list(struct jffs2_tmp_dnode_info *tn, struct jffs2_tmp_dnode_info **list) | 61 | |
62 | static 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 | ||
72 | static void jffs2_free_tmp_dnode_info_list(struct jffs2_tmp_dnode_info *tn) | 85 | static 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 | ||
84 | static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd) | 117 | static 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 | ||
110 | int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | 143 | int 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 | |||
489 | void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new) | 523 | void 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 | |||
506 | void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) | 544 | void 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 | } |