aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/nodelist.c
diff options
context:
space:
mode:
authorArtem B. Bityutskiy <dedekind@infradead.org>2005-07-27 10:46:14 -0400
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-11-06 11:50:45 -0500
commitf97117d15361b3a6aeaf9e347a287ef3f54b58f9 (patch)
tree614ff5f6fa693e1e475430eff9687e40b96b8555 /fs/jffs2/nodelist.c
parentf538c96ba2a3fdf7744ecf9fdffac14b1ec4be32 (diff)
[JFFS2] Move scattered function into related files
Move functions to read inodes into readinode.c Move functions to handle fragtree and dentry lists into nodelist.[ch] Signed-off-by: Artem B. Bityutskiy <dedekind@infradead.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'fs/jffs2/nodelist.c')
-rw-r--r--fs/jffs2/nodelist.c717
1 files changed, 230 insertions, 487 deletions
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index 9d08d3388186..8373d312b195 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.100 2005/07/22 10:32:08 dedekind Exp $ 10 * $Id: nodelist.c,v 1.101 2005/07/27 14:46:11 dedekind Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -55,515 +55,284 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new
55 }); 55 });
56} 56}
57 57
58/* 58void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this)
59 * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in
60 * order of increasing version.
61 */
62static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list)
63{ 59{
64 struct rb_node **p = &list->rb_node; 60 if (this->node) {
65 struct rb_node * parent = NULL; 61 this->node->frags--;
66 struct jffs2_tmp_dnode_info *this; 62 if (!this->node->frags) {
67 63 /* The node has no valid frags left. It's totally obsoleted */
68 while (*p) { 64 D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) obsolete\n",
69 parent = *p; 65 ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size));
70 this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); 66 jffs2_mark_node_obsolete(c, this->node->raw);
71 67 jffs2_free_full_dnode(this->node);
72 /* There may actually be a collision here, but it doesn't 68 } else {
73 actually matter. As long as the two nodes with the same 69 D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n",
74 version are together, it's all fine. */ 70 ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size,
75 if (tn->version < this->version) 71 this->node->frags));
76 p = &(*p)->rb_left; 72 mark_ref_normal(this->node->raw);
77 else 73 }
78 p = &(*p)->rb_right; 74
79 } 75 }
80 76 jffs2_free_node_frag(this);
81 rb_link_node(&tn->rb, parent, p);
82 rb_insert_color(&tn->rb, list);
83} 77}
84 78
85static void jffs2_free_tmp_dnode_info_list(struct rb_root *list) 79static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base)
86{ 80{
87 struct rb_node *this; 81 struct rb_node *parent = &base->rb;
88 struct jffs2_tmp_dnode_info *tn; 82 struct rb_node **link = &parent;
89 83
90 this = list->rb_node; 84 D2(printk(KERN_DEBUG "jffs2_fragtree_insert(%p; %d-%d, %p)\n", newfrag,
85 newfrag->ofs, newfrag->ofs+newfrag->size, base));
91 86
92 /* Now at bottom of tree */ 87 while (*link) {
93 while (this) { 88 parent = *link;
94 if (this->rb_left) 89 base = rb_entry(parent, struct jffs2_node_frag, rb);
95 this = this->rb_left; 90
96 else if (this->rb_right) 91 D2(printk(KERN_DEBUG "fragtree_insert considering frag at 0x%x\n", base->ofs));
97 this = this->rb_right; 92 if (newfrag->ofs > base->ofs)
93 link = &base->rb.rb_right;
94 else if (newfrag->ofs < base->ofs)
95 link = &base->rb.rb_left;
98 else { 96 else {
99 tn = rb_entry(this, struct jffs2_tmp_dnode_info, rb); 97 printk(KERN_CRIT "Duplicate frag at %08x (%p,%p)\n", newfrag->ofs, newfrag, base);
100 jffs2_free_full_dnode(tn->fn); 98 BUG();
101 jffs2_free_tmp_dnode_info(tn);
102
103 this = this->rb_parent;
104 if (!this)
105 break;
106
107 if (this->rb_left == &tn->rb)
108 this->rb_left = NULL;
109 else if (this->rb_right == &tn->rb)
110 this->rb_right = NULL;
111 else BUG();
112 } 99 }
113 } 100 }
114 list->rb_node = NULL; 101
102 rb_link_node(&newfrag->rb, &base->rb, link);
115} 103}
116 104
117static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd) 105/* Doesn't set inode->i_size */
106static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag)
118{ 107{
119 struct jffs2_full_dirent *next; 108 struct jffs2_node_frag *this;
109 uint32_t lastend;
120 110
121 while (fd) { 111 /* Skip all the nodes which are completed before this one starts */
122 next = fd->next; 112 this = jffs2_lookup_node_frag(list, newfrag->node->ofs);
123 jffs2_free_full_dirent(fd);
124 fd = next;
125 }
126}
127 113
128/* Returns first valid node after 'ref'. May return 'ref' */ 114 if (this) {
129static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_ref *ref) 115 D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n",
130{ 116 this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this));
131 while (ref && ref->next_in_ino) { 117 lastend = this->ofs + this->size;
132 if (!ref_obsolete(ref)) 118 } else {
133 return ref; 119 D2(printk(KERN_DEBUG "j_a_f_d_t_f: Lookup gave no frag\n"));
134 D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref))); 120 lastend = 0;
135 ref = ref->next_in_ino;
136 } 121 }
137 return NULL; 122
138} 123 /* See if we ran off the end of the list */
124 if (lastend <= newfrag->ofs) {
125 /* We did */
126
127 /* Check if 'this' node was on the same page as the new node.
128 If so, both 'this' and the new node get marked REF_NORMAL so
129 the GC can take a look.
130 */
131 if (lastend && (lastend-1) >> PAGE_CACHE_SHIFT == newfrag->ofs >> PAGE_CACHE_SHIFT) {
132 if (this->node)
133 mark_ref_normal(this->node->raw);
134 mark_ref_normal(newfrag->node->raw);
135 }
139 136
140/* 137 if (lastend < newfrag->node->ofs) {
141 * Helper function for jffs2_get_inode_nodes(). 138 /* ... and we need to put a hole in before the new node */
142 * It is called every time an directory entry node is found. 139 struct jffs2_node_frag *holefrag = jffs2_alloc_node_frag();
143 * 140 if (!holefrag) {
144 * Returns: 0 on succes; 141 jffs2_free_node_frag(newfrag);
145 * 1 if the node should be marked obsolete; 142 return -ENOMEM;
146 * negative error code on failure. 143 }
147 */ 144 holefrag->ofs = lastend;
148static inline int 145 holefrag->size = newfrag->node->ofs - lastend;
149read_direntry(struct jffs2_sb_info *c, 146 holefrag->node = NULL;
150 struct jffs2_raw_node_ref *ref, 147 if (this) {
151 struct jffs2_raw_dirent *rd, 148 /* By definition, the 'this' node has no right-hand child,
152 uint32_t read, 149 because there are no frags with offset greater than it.
153 struct jffs2_full_dirent **fdp, 150 So that's where we want to put the hole */
154 int32_t *latest_mctime, 151 D2(printk(KERN_DEBUG "Adding hole frag (%p) on right of node at (%p)\n", holefrag, this));
155 uint32_t *mctime_ver) 152 rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right);
156{ 153 } else {
157 struct jffs2_full_dirent *fd; 154 D2(printk(KERN_DEBUG "Adding hole frag (%p) at root of tree\n", holefrag));
158 155 rb_link_node(&holefrag->rb, NULL, &list->rb_node);
159 /* The direntry nodes are checked during the flash scanning */ 156 }
160 BUG_ON(ref_flags(ref) == REF_UNCHECKED); 157 rb_insert_color(&holefrag->rb, list);
161 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ 158 this = holefrag;
162 BUG_ON(ref_obsolete(ref)); 159 }
163 160 if (this) {
164 /* Sanity check */ 161 /* By definition, the 'this' node has no right-hand child,
165 if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { 162 because there are no frags with offset greater than it.
166 printk(KERN_ERR "Error! Illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", 163 So that's where we want to put new fragment */
167 ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); 164 D2(printk(KERN_DEBUG "Adding new frag (%p) on right of node at (%p)\n", newfrag, this));
168 return 1; 165 rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right);
166 } else {
167 D2(printk(KERN_DEBUG "Adding new frag (%p) at root of tree\n", newfrag));
168 rb_link_node(&newfrag->rb, NULL, &list->rb_node);
169 }
170 rb_insert_color(&newfrag->rb, list);
171 return 0;
169 } 172 }
170
171 fd = jffs2_alloc_full_dirent(rd->nsize + 1);
172 if (unlikely(!fd))
173 return -ENOMEM;
174
175 fd->raw = ref;
176 fd->version = je32_to_cpu(rd->version);
177 fd->ino = je32_to_cpu(rd->ino);
178 fd->type = rd->type;
179 173
180 /* Pick out the mctime of the latest dirent */ 174 D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n",
181 if(fd->version > *mctime_ver) { 175 this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this));
182 *mctime_ver = fd->version;
183 *latest_mctime = je32_to_cpu(rd->mctime);
184 }
185 176
186 /* 177 /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes,
187 * Copy as much of the name as possible from the raw 178 * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs
188 * dirent we've already read from the flash.
189 */ 179 */
190 if (read > sizeof(*rd)) 180 if (newfrag->ofs > this->ofs) {
191 memcpy(&fd->name[0], &rd->name[0], 181 /* This node isn't completely obsoleted. The start of it remains valid */
192 min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) )); 182
193 183 /* Mark the new node and the partially covered node REF_NORMAL -- let
194 /* Do we need to copy any more of the name directly from the flash? */ 184 the GC take a look at them */
195 if (rd->nsize + sizeof(*rd) > read) { 185 mark_ref_normal(newfrag->node->raw);
196 /* FIXME: point() */ 186 if (this->node)
197 int err; 187 mark_ref_normal(this->node->raw);
198 int already = read - sizeof(*rd); 188
189 if (this->ofs + this->size > newfrag->ofs + newfrag->size) {
190 /* The new node splits 'this' frag into two */
191 struct jffs2_node_frag *newfrag2 = jffs2_alloc_node_frag();
192 if (!newfrag2) {
193 jffs2_free_node_frag(newfrag);
194 return -ENOMEM;
195 }
196 D2(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size);
197 if (this->node)
198 printk("phys 0x%08x\n", ref_offset(this->node->raw));
199 else
200 printk("hole\n");
201 )
202
203 /* New second frag pointing to this's node */
204 newfrag2->ofs = newfrag->ofs + newfrag->size;
205 newfrag2->size = (this->ofs+this->size) - newfrag2->ofs;
206 newfrag2->node = this->node;
207 if (this->node)
208 this->node->frags++;
209
210 /* Adjust size of original 'this' */
211 this->size = newfrag->ofs - this->ofs;
212
213 /* Now, we know there's no node with offset
214 greater than this->ofs but smaller than
215 newfrag2->ofs or newfrag->ofs, for obvious
216 reasons. So we can do a tree insert from
217 'this' to insert newfrag, and a tree insert
218 from newfrag to insert newfrag2. */
219 jffs2_fragtree_insert(newfrag, this);
220 rb_insert_color(&newfrag->rb, list);
199 221
200 err = jffs2_flash_read(c, (ref_offset(ref)) + read, 222 jffs2_fragtree_insert(newfrag2, newfrag);
201 rd->nsize - already, &read, &fd->name[already]); 223 rb_insert_color(&newfrag2->rb, list);
202 if (unlikely(read != rd->nsize - already) && likely(!err))
203 return -EIO;
204 224
205 if (unlikely(err)) { 225 return 0;
206 printk(KERN_WARNING "Read remainder of name: error %d\n", err);
207 jffs2_free_full_dirent(fd);
208 return -EIO;
209 } 226 }
210 } 227 /* New node just reduces 'this' frag in size, doesn't split it */
211 228 this->size = newfrag->ofs - this->ofs;
212 fd->nhash = full_name_hash(fd->name, rd->nsize);
213 fd->next = NULL;
214 fd->name[rd->nsize] = '\0';
215
216 /*
217 * Wheee. We now have a complete jffs2_full_dirent structure, with
218 * the name in it and everything. Link it into the list
219 */
220 D1(printk(KERN_DEBUG "Adding fd \"%s\", ino #%u\n", fd->name, fd->ino));
221
222 jffs2_add_fd_to_list(c, fd, fdp);
223 229
224 return 0; 230 /* Again, we know it lives down here in the tree */
225} 231 jffs2_fragtree_insert(newfrag, this);
226 232 rb_insert_color(&newfrag->rb, list);
227/* 233 } else {
228 * Helper function for jffs2_get_inode_nodes(). 234 /* New frag starts at the same point as 'this' used to. Replace
229 * It is called every time an inode node is found. 235 it in the tree without doing a delete and insertion */
230 * 236 D2(printk(KERN_DEBUG "Inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n",
231 * Returns: 0 on succes; 237 newfrag, newfrag->ofs, newfrag->ofs+newfrag->size,
232 * 1 if the node should be marked obsolete; 238 this, this->ofs, this->ofs+this->size));
233 * negative error code on failure.
234 */
235static inline int
236read_dnode(struct jffs2_sb_info *c,
237 struct jffs2_raw_node_ref *ref,
238 struct jffs2_raw_inode *rd,
239 uint32_t read,
240 struct rb_root *tnp,
241 int32_t *latest_mctime,
242 uint32_t *mctime_ver)
243{
244 struct jffs2_eraseblock *jeb;
245 struct jffs2_tmp_dnode_info *tn;
246 239
247 /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ 240 rb_replace_node(&this->rb, &newfrag->rb, list);
248 BUG_ON(ref_obsolete(ref));
249
250 /* If we've never checked the CRCs on this node, check them now */
251 if (ref_flags(ref) == REF_UNCHECKED) {
252 uint32_t crc, len;
253
254 crc = crc32(0, rd, sizeof(*rd) - 8);
255 if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
256 printk(KERN_WARNING "Header CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
257 ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
258 return 1;
259 }
260 241
261 /* Sanity checks */ 242 if (newfrag->ofs + newfrag->size >= this->ofs+this->size) {
262 if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || 243 D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size));
263 unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { 244 jffs2_obsolete_node_frag(c, this);
264 printk(KERN_WARNING "Inode corrupted at %#08x, totlen %d, #ino %d, version %d, "
265 "isize %d, csize %d, dsize %d \n",
266 ref_offset(ref), je32_to_cpu(rd->totlen), je32_to_cpu(rd->ino),
267 je32_to_cpu(rd->version), je32_to_cpu(rd->isize),
268 je32_to_cpu(rd->csize), je32_to_cpu(rd->dsize));
269 return 1;
270 }
271
272 if (rd->compr != JFFS2_COMPR_ZERO && je32_to_cpu(rd->csize)) {
273 unsigned char *buf = NULL;
274 uint32_t pointed = 0;
275 int err;
276#ifndef __ECOS
277 if (c->mtd->point) {
278 err = c->mtd->point (c->mtd, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize),
279 &read, &buf);
280 if (unlikely(read < je32_to_cpu(rd->csize)) && likely(!err)) {
281 D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", read));
282 c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd),
283 je32_to_cpu(rd->csize));
284 } else if (unlikely(err)){
285 D1(printk(KERN_DEBUG "MTD point failed %d\n", err));
286 } else
287 pointed = 1; /* succefully pointed to device */
288 }
289#endif
290 if(!pointed){
291 buf = kmalloc(je32_to_cpu(rd->csize), GFP_KERNEL);
292 if (!buf)
293 return -ENOMEM;
294
295 err = jffs2_flash_read(c, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize),
296 &read, buf);
297 if (unlikely(read != je32_to_cpu(rd->csize)) && likely(!err))
298 err = -EIO;
299 if (err) {
300 kfree(buf);
301 return err;
302 }
303 }
304 crc = crc32(0, buf, je32_to_cpu(rd->csize));
305 if(!pointed)
306 kfree(buf);
307#ifndef __ECOS
308 else
309 c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize));
310#endif
311
312 if (crc != je32_to_cpu(rd->data_crc)) {
313 printk(KERN_NOTICE "Data CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
314 ref_offset(ref), je32_to_cpu(rd->data_crc), crc);
315 return 1;
316 }
317
318 }
319
320 /* Mark the node as having been checked and fix the accounting accordingly */
321 jeb = &c->blocks[ref->flash_offset / c->sector_size];
322 len = ref_totlen(c, jeb, ref);
323
324 spin_lock(&c->erase_completion_lock);
325 jeb->used_size += len;
326 jeb->unchecked_size -= len;
327 c->used_size += len;
328 c->unchecked_size -= len;
329
330 /* If node covers at least a whole page, or if it starts at the
331 beginning of a page and runs to the end of the file, or if
332 it's a hole node, mark it REF_PRISTINE, else REF_NORMAL.
333
334 If it's actually overlapped, it'll get made NORMAL (or OBSOLETE)
335 when the overlapping node(s) get added to the tree anyway.
336 */
337 if ((je32_to_cpu(rd->dsize) >= PAGE_CACHE_SIZE) ||
338 ( ((je32_to_cpu(rd->offset) & (PAGE_CACHE_SIZE-1))==0) &&
339 (je32_to_cpu(rd->dsize) + je32_to_cpu(rd->offset) == je32_to_cpu(rd->isize)))) {
340 D1(printk(KERN_DEBUG "Marking node at %#08x REF_PRISTINE\n", ref_offset(ref)));
341 ref->flash_offset = ref_offset(ref) | REF_PRISTINE;
342 } else { 245 } else {
343 D1(printk(KERN_DEBUG "Marking node at %#08x REF_NORMAL\n", ref_offset(ref))); 246 this->ofs += newfrag->size;
344 ref->flash_offset = ref_offset(ref) | REF_NORMAL; 247 this->size -= newfrag->size;
248
249 jffs2_fragtree_insert(this, newfrag);
250 rb_insert_color(&this->rb, list);
251 return 0;
345 } 252 }
346 spin_unlock(&c->erase_completion_lock);
347 } 253 }
348 254 /* OK, now we have newfrag added in the correct place in the tree, but
349 tn = jffs2_alloc_tmp_dnode_info(); 255 frag_next(newfrag) may be a fragment which is overlapped by it
350 if (!tn) { 256 */
351 D1(printk(KERN_DEBUG "alloc tn failed\n")); 257 while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) {
352 return -ENOMEM; 258 /* 'this' frag is obsoleted completely. */
259 D2(printk(KERN_DEBUG "Obsoleting node frag %p (%x-%x) and removing from tree\n", this, this->ofs, this->ofs+this->size));
260 rb_erase(&this->rb, list);
261 jffs2_obsolete_node_frag(c, this);
353 } 262 }
263 /* Now we're pointing at the first frag which isn't totally obsoleted by
264 the new frag */
354 265
355 tn->fn = jffs2_alloc_full_dnode(); 266 if (!this || newfrag->ofs + newfrag->size == this->ofs) {
356 if (!tn->fn) { 267 return 0;
357 D1(printk(KERN_DEBUG "alloc fn failed\n"));
358 jffs2_free_tmp_dnode_info(tn);
359 return -ENOMEM;
360 } 268 }
361 269 /* Still some overlap but we don't need to move it in the tree */
362 tn->version = je32_to_cpu(rd->version); 270 this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size);
363 tn->fn->ofs = je32_to_cpu(rd->offset); 271 this->ofs = newfrag->ofs + newfrag->size;
364 tn->fn->raw = ref; 272
365 273 /* And mark them REF_NORMAL so the GC takes a look at them */
366 /* There was a bug where we wrote hole nodes out with 274 if (this->node)
367 csize/dsize swapped. Deal with it */ 275 mark_ref_normal(this->node->raw);
368 if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && je32_to_cpu(rd->csize)) 276 mark_ref_normal(newfrag->node->raw);
369 tn->fn->size = je32_to_cpu(rd->csize);
370 else // normal case...
371 tn->fn->size = je32_to_cpu(rd->dsize);
372
373 D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %#04x, dsize %#04x\n",
374 ref_offset(ref), je32_to_cpu(rd->version),
375 je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize)));
376
377 jffs2_add_tn_to_tree(tn, tnp);
378 277
379 return 0; 278 return 0;
380} 279}
381 280
382/* 281/* Given an inode, probably with existing list of fragments, add the new node
383 * Helper function for jffs2_get_inode_nodes(). 282 * to the fragment list.
384 * It is called every time an unknown node is found.
385 *
386 * Returns: 0 on succes;
387 * 1 if the node should be marked obsolete;
388 * negative error code on failure.
389 */ 283 */
390static inline int 284int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn)
391read_unknown(struct jffs2_sb_info *c,
392 struct jffs2_raw_node_ref *ref,
393 struct jffs2_unknown_node *un,
394 uint32_t read)
395{ 285{
396 /* We don't mark unknown nodes as REF_UNCHECKED */ 286 int ret;
397 BUG_ON(ref_flags(ref) == REF_UNCHECKED); 287 struct jffs2_node_frag *newfrag;
398
399 un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
400 288
401 if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { 289 D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn));
402 290
403 /* Hmmm. This should have been caught at scan time. */ 291 if (unlikely(!fn->size))
404 printk(KERN_WARNING "Warning! Node header CRC failed at %#08x. " 292 return 0;
405 "But it must have been OK earlier.\n", ref_offset(ref));
406 D1(printk(KERN_DEBUG "Node was: { %#04x, %#04x, %#08x, %#08x }\n",
407 je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
408 je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc)));
409 return 1;
410 } else {
411 switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
412 293
413 case JFFS2_FEATURE_INCOMPAT: 294 newfrag = jffs2_alloc_node_frag();
414 printk(KERN_NOTICE "Unknown INCOMPAT nodetype %#04X at %#08x\n", 295 if (unlikely(!newfrag))
415 je16_to_cpu(un->nodetype), ref_offset(ref)); 296 return -ENOMEM;
416 /* EEP */
417 BUG();
418 break;
419
420 case JFFS2_FEATURE_ROCOMPAT:
421 printk(KERN_NOTICE "Unknown ROCOMPAT nodetype %#04X at %#08x\n",
422 je16_to_cpu(un->nodetype), ref_offset(ref));
423 BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
424 break;
425
426 case JFFS2_FEATURE_RWCOMPAT_COPY:
427 printk(KERN_NOTICE "Unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
428 je16_to_cpu(un->nodetype), ref_offset(ref));
429 break;
430
431 case JFFS2_FEATURE_RWCOMPAT_DELETE:
432 printk(KERN_NOTICE "Unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
433 je16_to_cpu(un->nodetype), ref_offset(ref));
434 return 1;
435 }
436 }
437
438 return 0;
439}
440
441/* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
442 with this ino, returning the former in order of version */
443 297
444int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 298 D2(printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n",
445 struct rb_root *tnp, struct jffs2_full_dirent **fdp, 299 fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag));
446 uint32_t *highest_version, uint32_t *latest_mctime,
447 uint32_t *mctime_ver)
448{
449 struct jffs2_raw_node_ref *ref, *valid_ref;
450 struct rb_root ret_tn = RB_ROOT;
451 struct jffs2_full_dirent *ret_fd = NULL;
452 union jffs2_node_union node;
453 size_t retlen;
454 int err;
455
456 *mctime_ver = 0;
457 300
458 D1(printk(KERN_DEBUG "jffs2_get_inode_nodes(): ino #%u\n", f->inocache->ino)); 301 newfrag->ofs = fn->ofs;
459 302 newfrag->size = fn->size;
460 spin_lock(&c->erase_completion_lock); 303 newfrag->node = fn;
461 304 newfrag->node->frags = 1;
462 valid_ref = jffs2_first_valid_node(f->inocache->nodes); 305
463 306 ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag);
464 if (!valid_ref && (f->inocache->ino != 1)) 307 if (unlikely(ret))
465 printk(KERN_WARNING "Eep. No valid nodes for ino #%u\n", f->inocache->ino); 308 return ret;
466 309
467 while (valid_ref) { 310 /* If we now share a page with other nodes, mark either previous
468 /* We can hold a pointer to a non-obsolete node without the spinlock, 311 or next node REF_NORMAL, as appropriate. */
469 but _obsolete_ nodes may disappear at any time, if the block 312 if (newfrag->ofs & (PAGE_CACHE_SIZE-1)) {
470 they're in gets erased. So if we mark 'ref' obsolete while we're 313 struct jffs2_node_frag *prev = frag_prev(newfrag);
471 not holding the lock, it can go away immediately. For that reason, 314
472 we find the next valid node first, before processing 'ref'. 315 mark_ref_normal(fn->raw);
473 */ 316 /* If we don't start at zero there's _always_ a previous */
474 ref = valid_ref; 317 if (prev->node)
475 valid_ref = jffs2_first_valid_node(ref->next_in_ino); 318 mark_ref_normal(prev->node->raw);
476 spin_unlock(&c->erase_completion_lock); 319 }
477
478 cond_resched();
479
480 /* FIXME: point() */
481 err = jffs2_flash_read(c, (ref_offset(ref)),
482 min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node)),
483 &retlen, (void *)&node);
484 if (err) {
485 printk(KERN_WARNING "error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref));
486 goto free_out;
487 }
488
489 switch (je16_to_cpu(node.u.nodetype)) {
490
491 case JFFS2_NODETYPE_DIRENT:
492 D1(printk(KERN_DEBUG "Node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref)));
493
494 if (retlen < sizeof(node.d)) {
495 printk(KERN_WARNING "Warning! Short read dirent at %#08x\n", ref_offset(ref));
496 err = -EIO;
497 goto free_out;
498 }
499
500 err = read_direntry(c, ref, &node.d, retlen, &ret_fd, latest_mctime, mctime_ver);
501 if (err == 1) {
502 jffs2_mark_node_obsolete(c, ref);
503 break;
504 } else if (unlikely(err))
505 goto free_out;
506
507 if (je32_to_cpu(node.d.version) > *highest_version)
508 *highest_version = je32_to_cpu(node.d.version);
509
510 break;
511
512 case JFFS2_NODETYPE_INODE:
513 D1(printk(KERN_DEBUG "Node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref)));
514
515 if (retlen < sizeof(node.i)) {
516 printk(KERN_WARNING "Warning! Short read dnode at %#08x\n", ref_offset(ref));
517 err = -EIO;
518 goto free_out;
519 }
520
521 err = read_dnode(c, ref, &node.i, retlen, &ret_tn, latest_mctime, mctime_ver);
522 if (err == 1) {
523 jffs2_mark_node_obsolete(c, ref);
524 break;
525 } else if (unlikely(err))
526 goto free_out;
527
528 if (je32_to_cpu(node.i.version) > *highest_version)
529 *highest_version = je32_to_cpu(node.i.version);
530
531 D1(printk(KERN_DEBUG "version %d, highest_version now %d\n",
532 je32_to_cpu(node.i.version), *highest_version));
533
534 break;
535
536 default:
537 /* Check we've managed to read at least the common node header */
538 if (retlen < sizeof(struct jffs2_unknown_node)) {
539 printk(KERN_WARNING "Warning! Short read unknown node at %#08x\n",
540 ref_offset(ref));
541 return -EIO;
542 }
543
544 err = read_unknown(c, ref, &node.u, retlen);
545 if (err == 1) {
546 jffs2_mark_node_obsolete(c, ref);
547 break;
548 } else if (unlikely(err))
549 goto free_out;
550 320
321 if ((newfrag->ofs+newfrag->size) & (PAGE_CACHE_SIZE-1)) {
322 struct jffs2_node_frag *next = frag_next(newfrag);
323
324 if (next) {
325 mark_ref_normal(fn->raw);
326 if (next->node)
327 mark_ref_normal(next->node->raw);
551 } 328 }
552 spin_lock(&c->erase_completion_lock);
553
554 } 329 }
555 spin_unlock(&c->erase_completion_lock); 330 jffs2_dbg_fragtree_paranoia_check_nolock(f);
556 *tnp = ret_tn; 331 jffs2_dbg_dump_fragtree_nolock(f);
557 *fdp = ret_fd;
558
559 return 0; 332 return 0;
560
561 free_out:
562 jffs2_free_tmp_dnode_info_list(&ret_tn);
563 jffs2_free_full_dirent_list(ret_fd);
564 return err;
565} 333}
566 334
335
567void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state) 336void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state)
568{ 337{
569 spin_lock(&c->inocache_lock); 338 spin_lock(&c->inocache_lock);
@@ -773,29 +542,3 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c)
773 cond_resched(); 542 cond_resched();
774 } 543 }
775} 544}
776
777void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base)
778{
779 struct rb_node *parent = &base->rb;
780 struct rb_node **link = &parent;
781
782 D2(printk(KERN_DEBUG "jffs2_fragtree_insert(%p; %d-%d, %p)\n", newfrag,
783 newfrag->ofs, newfrag->ofs+newfrag->size, base));
784
785 while (*link) {
786 parent = *link;
787 base = rb_entry(parent, struct jffs2_node_frag, rb);
788
789 D2(printk(KERN_DEBUG "fragtree_insert considering frag at 0x%x\n", base->ofs));
790 if (newfrag->ofs > base->ofs)
791 link = &base->rb.rb_right;
792 else if (newfrag->ofs < base->ofs)
793 link = &base->rb.rb_left;
794 else {
795 printk(KERN_CRIT "Duplicate frag at %08x (%p,%p)\n", newfrag->ofs, newfrag, base);
796 BUG();
797 }
798 }
799
800 rb_link_node(&newfrag->rb, &base->rb, link);
801}