diff options
Diffstat (limited to 'fs/jffs2/readinode.c')
| -rw-r--r-- | fs/jffs2/readinode.c | 851 |
1 files changed, 640 insertions, 211 deletions
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 717a48cf7df2..6aff38930b50 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c | |||
| @@ -1,14 +1,12 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2001-2003 Red Hat, Inc. | 4 | * Copyright © 2001-2007 Red Hat, Inc. |
| 5 | * | 5 | * |
| 6 | * Created by David Woodhouse <dwmw2@infradead.org> | 6 | * Created by David Woodhouse <dwmw2@infradead.org> |
| 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: readinode.c,v 1.143 2005/11/07 11:14:41 gleixner Exp $ | ||
| 11 | * | ||
| 12 | */ | 10 | */ |
| 13 | 11 | ||
| 14 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| @@ -22,30 +20,510 @@ | |||
| 22 | #include "nodelist.h" | 20 | #include "nodelist.h" |
| 23 | 21 | ||
| 24 | /* | 22 | /* |
| 25 | * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in | 23 | * Check the data CRC of the node. |
| 26 | * order of increasing version. | 24 | * |
| 25 | * Returns: 0 if the data CRC is correct; | ||
| 26 | * 1 - if incorrect; | ||
| 27 | * error code if an error occured. | ||
| 27 | */ | 28 | */ |
| 28 | static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list) | 29 | static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) |
| 29 | { | 30 | { |
| 30 | struct rb_node **p = &list->rb_node; | 31 | struct jffs2_raw_node_ref *ref = tn->fn->raw; |
| 31 | struct rb_node * parent = NULL; | 32 | int err = 0, pointed = 0; |
| 32 | struct jffs2_tmp_dnode_info *this; | 33 | struct jffs2_eraseblock *jeb; |
| 33 | 34 | unsigned char *buffer; | |
| 34 | while (*p) { | 35 | uint32_t crc, ofs, len; |
| 35 | parent = *p; | 36 | size_t retlen; |
| 36 | this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); | 37 | |
| 37 | 38 | BUG_ON(tn->csize == 0); | |
| 38 | /* There may actually be a collision here, but it doesn't | 39 | |
| 39 | actually matter. As long as the two nodes with the same | 40 | if (!jffs2_is_writebuffered(c)) |
| 40 | version are together, it's all fine. */ | 41 | goto adj_acc; |
| 41 | if (tn->version > this->version) | 42 | |
| 42 | p = &(*p)->rb_left; | 43 | /* Calculate how many bytes were already checked */ |
| 44 | ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); | ||
| 45 | len = ofs % c->wbuf_pagesize; | ||
| 46 | if (likely(len)) | ||
| 47 | len = c->wbuf_pagesize - len; | ||
| 48 | |||
| 49 | if (len >= tn->csize) { | ||
| 50 | dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", | ||
| 51 | ref_offset(ref), tn->csize, ofs); | ||
| 52 | goto adj_acc; | ||
| 53 | } | ||
| 54 | |||
| 55 | ofs += len; | ||
| 56 | len = tn->csize - len; | ||
| 57 | |||
| 58 | dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", | ||
| 59 | ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len); | ||
| 60 | |||
| 61 | #ifndef __ECOS | ||
| 62 | /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(), | ||
| 63 | * adding and jffs2_flash_read_end() interface. */ | ||
| 64 | if (c->mtd->point) { | ||
| 65 | err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer); | ||
| 66 | if (!err && retlen < tn->csize) { | ||
| 67 | JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize); | ||
| 68 | c->mtd->unpoint(c->mtd, buffer, ofs, len); | ||
| 69 | } else if (err) | ||
| 70 | JFFS2_WARNING("MTD point failed: error code %d.\n", err); | ||
| 43 | else | 71 | else |
| 44 | p = &(*p)->rb_right; | 72 | pointed = 1; /* succefully pointed to device */ |
| 73 | } | ||
| 74 | #endif | ||
| 75 | |||
| 76 | if (!pointed) { | ||
| 77 | buffer = kmalloc(len, GFP_KERNEL); | ||
| 78 | if (unlikely(!buffer)) | ||
| 79 | return -ENOMEM; | ||
| 80 | |||
| 81 | /* TODO: this is very frequent pattern, make it a separate | ||
| 82 | * routine */ | ||
| 83 | err = jffs2_flash_read(c, ofs, len, &retlen, buffer); | ||
| 84 | if (err) { | ||
| 85 | JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err); | ||
| 86 | goto free_out; | ||
| 87 | } | ||
| 88 | |||
| 89 | if (retlen != len) { | ||
| 90 | JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len); | ||
| 91 | err = -EIO; | ||
| 92 | goto free_out; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | /* Continue calculating CRC */ | ||
| 97 | crc = crc32(tn->partial_crc, buffer, len); | ||
| 98 | if(!pointed) | ||
| 99 | kfree(buffer); | ||
| 100 | #ifndef __ECOS | ||
| 101 | else | ||
| 102 | c->mtd->unpoint(c->mtd, buffer, ofs, len); | ||
| 103 | #endif | ||
| 104 | |||
| 105 | if (crc != tn->data_crc) { | ||
| 106 | JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n", | ||
| 107 | ofs, tn->data_crc, crc); | ||
| 108 | return 1; | ||
| 45 | } | 109 | } |
| 46 | 110 | ||
| 47 | rb_link_node(&tn->rb, parent, p); | 111 | adj_acc: |
| 48 | rb_insert_color(&tn->rb, list); | 112 | jeb = &c->blocks[ref->flash_offset / c->sector_size]; |
| 113 | len = ref_totlen(c, jeb, ref); | ||
| 114 | /* If it should be REF_NORMAL, it'll get marked as such when | ||
| 115 | we build the fragtree, shortly. No need to worry about GC | ||
| 116 | moving it while it's marked REF_PRISTINE -- GC won't happen | ||
| 117 | till we've finished checking every inode anyway. */ | ||
| 118 | ref->flash_offset |= REF_PRISTINE; | ||
| 119 | /* | ||
| 120 | * Mark the node as having been checked and fix the | ||
| 121 | * accounting accordingly. | ||
| 122 | */ | ||
| 123 | spin_lock(&c->erase_completion_lock); | ||
| 124 | jeb->used_size += len; | ||
| 125 | jeb->unchecked_size -= len; | ||
| 126 | c->used_size += len; | ||
| 127 | c->unchecked_size -= len; | ||
| 128 | jffs2_dbg_acct_paranoia_check_nolock(c, jeb); | ||
| 129 | spin_unlock(&c->erase_completion_lock); | ||
| 130 | |||
| 131 | return 0; | ||
| 132 | |||
| 133 | free_out: | ||
| 134 | if(!pointed) | ||
| 135 | kfree(buffer); | ||
| 136 | #ifndef __ECOS | ||
| 137 | else | ||
| 138 | c->mtd->unpoint(c->mtd, buffer, ofs, len); | ||
| 139 | #endif | ||
| 140 | return err; | ||
| 141 | } | ||
| 142 | |||
| 143 | /* | ||
| 144 | * Helper function for jffs2_add_older_frag_to_fragtree(). | ||
| 145 | * | ||
| 146 | * Checks the node if we are in the checking stage. | ||
| 147 | */ | ||
| 148 | static int check_tn_node(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) | ||
| 149 | { | ||
| 150 | int ret; | ||
| 151 | |||
| 152 | BUG_ON(ref_obsolete(tn->fn->raw)); | ||
| 153 | |||
| 154 | /* We only check the data CRC of unchecked nodes */ | ||
| 155 | if (ref_flags(tn->fn->raw) != REF_UNCHECKED) | ||
| 156 | return 0; | ||
| 157 | |||
| 158 | dbg_readinode("check node %#04x-%#04x, phys offs %#08x\n", | ||
| 159 | tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw)); | ||
| 160 | |||
| 161 | ret = check_node_data(c, tn); | ||
| 162 | if (unlikely(ret < 0)) { | ||
| 163 | JFFS2_ERROR("check_node_data() returned error: %d.\n", | ||
| 164 | ret); | ||
| 165 | } else if (unlikely(ret > 0)) { | ||
| 166 | dbg_readinode("CRC error, mark it obsolete.\n"); | ||
| 167 | jffs2_mark_node_obsolete(c, tn->fn->raw); | ||
| 168 | } | ||
| 169 | |||
| 170 | return ret; | ||
| 171 | } | ||
| 172 | |||
| 173 | static struct jffs2_tmp_dnode_info *jffs2_lookup_tn(struct rb_root *tn_root, uint32_t offset) | ||
| 174 | { | ||
| 175 | struct rb_node *next; | ||
| 176 | struct jffs2_tmp_dnode_info *tn = NULL; | ||
| 177 | |||
| 178 | dbg_readinode("root %p, offset %d\n", tn_root, offset); | ||
| 179 | |||
| 180 | next = tn_root->rb_node; | ||
| 181 | |||
| 182 | while (next) { | ||
| 183 | tn = rb_entry(next, struct jffs2_tmp_dnode_info, rb); | ||
| 184 | |||
| 185 | if (tn->fn->ofs < offset) | ||
| 186 | next = tn->rb.rb_right; | ||
| 187 | else if (tn->fn->ofs >= offset) | ||
| 188 | next = tn->rb.rb_left; | ||
| 189 | else | ||
| 190 | break; | ||
| 191 | } | ||
| 192 | |||
| 193 | return tn; | ||
| 194 | } | ||
| 195 | |||
| 196 | |||
| 197 | static void jffs2_kill_tn(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) | ||
| 198 | { | ||
| 199 | jffs2_mark_node_obsolete(c, tn->fn->raw); | ||
| 200 | jffs2_free_full_dnode(tn->fn); | ||
| 201 | jffs2_free_tmp_dnode_info(tn); | ||
| 202 | } | ||
| 203 | /* | ||
| 204 | * This function is used when we read an inode. Data nodes arrive in | ||
| 205 | * arbitrary order -- they may be older or newer than the nodes which | ||
| 206 | * are already in the tree. Where overlaps occur, the older node can | ||
| 207 | * be discarded as long as the newer passes the CRC check. We don't | ||
| 208 | * bother to keep track of holes in this rbtree, and neither do we deal | ||
| 209 | * with frags -- we can have multiple entries starting at the same | ||
| 210 | * offset, and the one with the smallest length will come first in the | ||
| 211 | * ordering. | ||
| 212 | * | ||
| 213 | * Returns 0 if the node was inserted | ||
| 214 | * 1 if the node is obsolete (because we can't mark it so yet) | ||
| 215 | * < 0 an if error occurred | ||
| 216 | */ | ||
| 217 | static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | ||
| 218 | struct jffs2_readinode_info *rii, | ||
| 219 | struct jffs2_tmp_dnode_info *tn) | ||
| 220 | { | ||
| 221 | uint32_t fn_end = tn->fn->ofs + tn->fn->size; | ||
| 222 | struct jffs2_tmp_dnode_info *insert_point = NULL, *this; | ||
| 223 | |||
| 224 | dbg_readinode("insert fragment %#04x-%#04x, ver %u\n", tn->fn->ofs, fn_end, tn->version); | ||
| 225 | |||
| 226 | /* If a node has zero dsize, we only have to keep if it if it might be the | ||
| 227 | node with highest version -- i.e. the one which will end up as f->metadata. | ||
| 228 | Note that such nodes won't be REF_UNCHECKED since there are no data to | ||
| 229 | check anyway. */ | ||
| 230 | if (!tn->fn->size) { | ||
| 231 | if (rii->mdata_tn) { | ||
| 232 | /* We had a candidate mdata node already */ | ||
| 233 | dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version); | ||
| 234 | jffs2_kill_tn(c, rii->mdata_tn); | ||
| 235 | } | ||
| 236 | rii->mdata_tn = tn; | ||
| 237 | dbg_readinode("keep new mdata with ver %d\n", tn->version); | ||
| 238 | return 0; | ||
| 239 | } | ||
| 240 | |||
| 241 | /* Find the earliest node which _may_ be relevant to this one */ | ||
| 242 | this = jffs2_lookup_tn(&rii->tn_root, tn->fn->ofs); | ||
| 243 | if (!this) { | ||
| 244 | /* First addition to empty tree. $DEITY how I love the easy cases */ | ||
| 245 | rb_link_node(&tn->rb, NULL, &rii->tn_root.rb_node); | ||
| 246 | rb_insert_color(&tn->rb, &rii->tn_root); | ||
| 247 | dbg_readinode("keep new frag\n"); | ||
| 248 | return 0; | ||
| 249 | } | ||
| 250 | |||
| 251 | /* If we add a new node it'll be somewhere under here. */ | ||
| 252 | insert_point = this; | ||
| 253 | |||
| 254 | /* If the node is coincident with another at a lower address, | ||
| 255 | back up until the other node is found. It may be relevant */ | ||
| 256 | while (tn->overlapped) | ||
| 257 | tn = tn_prev(tn); | ||
| 258 | |||
| 259 | dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole"); | ||
| 260 | |||
| 261 | while (this) { | ||
| 262 | if (this->fn->ofs > fn_end) | ||
| 263 | break; | ||
| 264 | dbg_readinode("Ponder this ver %d, 0x%x-0x%x\n", | ||
| 265 | this->version, this->fn->ofs, this->fn->size); | ||
| 266 | |||
| 267 | if (this->version == tn->version) { | ||
| 268 | /* Version number collision means REF_PRISTINE GC. Accept either of them | ||
| 269 | as long as the CRC is correct. Check the one we have already... */ | ||
| 270 | if (!check_tn_node(c, this)) { | ||
| 271 | /* The one we already had was OK. Keep it and throw away the new one */ | ||
| 272 | dbg_readinode("Like old node. Throw away new\n"); | ||
| 273 | jffs2_kill_tn(c, tn); | ||
| 274 | return 0; | ||
| 275 | } else { | ||
| 276 | /* Who cares if the new one is good; keep it for now anyway. */ | ||
| 277 | rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); | ||
| 278 | /* Same overlapping from in front and behind */ | ||
| 279 | tn->overlapped = this->overlapped; | ||
| 280 | jffs2_kill_tn(c, this); | ||
| 281 | dbg_readinode("Like new node. Throw away old\n"); | ||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | } | ||
| 285 | if (this->version < tn->version && | ||
| 286 | this->fn->ofs >= tn->fn->ofs && | ||
| 287 | this->fn->ofs + this->fn->size <= fn_end) { | ||
| 288 | /* New node entirely overlaps 'this' */ | ||
| 289 | if (check_tn_node(c, tn)) { | ||
| 290 | dbg_readinode("new node bad CRC\n"); | ||
| 291 | jffs2_kill_tn(c, tn); | ||
| 292 | return 0; | ||
| 293 | } | ||
| 294 | /* ... and is good. Kill 'this'... */ | ||
| 295 | rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); | ||
| 296 | tn->overlapped = this->overlapped; | ||
| 297 | jffs2_kill_tn(c, this); | ||
| 298 | /* ... and any subsequent nodes which are also overlapped */ | ||
| 299 | this = tn_next(tn); | ||
| 300 | while (this && this->fn->ofs + this->fn->size < fn_end) { | ||
| 301 | struct jffs2_tmp_dnode_info *next = tn_next(this); | ||
| 302 | if (this->version < tn->version) { | ||
| 303 | tn_erase(this, &rii->tn_root); | ||
| 304 | dbg_readinode("Kill overlapped ver %d, 0x%x-0x%x\n", | ||
| 305 | this->version, this->fn->ofs, | ||
| 306 | this->fn->ofs+this->fn->size); | ||
| 307 | jffs2_kill_tn(c, this); | ||
| 308 | } | ||
| 309 | this = next; | ||
| 310 | } | ||
| 311 | dbg_readinode("Done inserting new\n"); | ||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | if (this->version > tn->version && | ||
| 315 | this->fn->ofs <= tn->fn->ofs && | ||
| 316 | this->fn->ofs+this->fn->size >= fn_end) { | ||
| 317 | /* New node entirely overlapped by 'this' */ | ||
| 318 | if (!check_tn_node(c, this)) { | ||
| 319 | dbg_readinode("Good CRC on old node. Kill new\n"); | ||
| 320 | jffs2_kill_tn(c, tn); | ||
| 321 | return 0; | ||
| 322 | } | ||
| 323 | /* ... but 'this' was bad. Replace it... */ | ||
| 324 | rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); | ||
| 325 | dbg_readinode("Bad CRC on old overlapping node. Kill it\n"); | ||
| 326 | jffs2_kill_tn(c, this); | ||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | /* We want to be inserted under the last node which is | ||
| 330 | either at a lower offset _or_ has a smaller range */ | ||
| 331 | if (this->fn->ofs < tn->fn->ofs || | ||
| 332 | (this->fn->ofs == tn->fn->ofs && | ||
| 333 | this->fn->size <= tn->fn->size)) | ||
| 334 | insert_point = this; | ||
| 335 | |||
| 336 | this = tn_next(this); | ||
| 337 | } | ||
| 338 | dbg_readinode("insert_point %p, ver %d, 0x%x-0x%x, ov %d\n", | ||
| 339 | insert_point, insert_point->version, insert_point->fn->ofs, | ||
| 340 | insert_point->fn->ofs+insert_point->fn->size, | ||
| 341 | insert_point->overlapped); | ||
| 342 | /* We neither completely obsoleted nor were completely | ||
| 343 | obsoleted by an earlier node. Insert under insert_point */ | ||
| 344 | { | ||
| 345 | struct rb_node *parent = &insert_point->rb; | ||
| 346 | struct rb_node **link = &parent; | ||
| 347 | |||
| 348 | while (*link) { | ||
| 349 | parent = *link; | ||
| 350 | insert_point = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); | ||
| 351 | if (tn->fn->ofs > insert_point->fn->ofs) | ||
| 352 | link = &insert_point->rb.rb_right; | ||
| 353 | else if (tn->fn->ofs < insert_point->fn->ofs || | ||
| 354 | tn->fn->size < insert_point->fn->size) | ||
| 355 | link = &insert_point->rb.rb_left; | ||
| 356 | else | ||
| 357 | link = &insert_point->rb.rb_right; | ||
| 358 | } | ||
| 359 | rb_link_node(&tn->rb, &insert_point->rb, link); | ||
| 360 | rb_insert_color(&tn->rb, &rii->tn_root); | ||
| 361 | } | ||
| 362 | /* If there's anything behind that overlaps us, note it */ | ||
| 363 | this = tn_prev(tn); | ||
| 364 | if (this) { | ||
| 365 | while (1) { | ||
| 366 | if (this->fn->ofs + this->fn->size > tn->fn->ofs) { | ||
| 367 | dbg_readinode("Node is overlapped by %p (v %d, 0x%x-0x%x)\n", | ||
| 368 | this, this->version, this->fn->ofs, | ||
| 369 | this->fn->ofs+this->fn->size); | ||
| 370 | tn->overlapped = 1; | ||
| 371 | break; | ||
| 372 | } | ||
| 373 | if (!this->overlapped) | ||
| 374 | break; | ||
| 375 | this = tn_prev(this); | ||
| 376 | } | ||
| 377 | } | ||
| 378 | |||
| 379 | /* If the new node overlaps anything ahead, note it */ | ||
| 380 | this = tn_next(tn); | ||
| 381 | while (this && this->fn->ofs < fn_end) { | ||
| 382 | this->overlapped = 1; | ||
| 383 | dbg_readinode("Node ver %d, 0x%x-0x%x is overlapped\n", | ||
| 384 | this->version, this->fn->ofs, | ||
| 385 | this->fn->ofs+this->fn->size); | ||
| 386 | this = tn_next(this); | ||
| 387 | } | ||
| 388 | return 0; | ||
| 389 | } | ||
| 390 | |||
| 391 | /* Trivial function to remove the last node in the tree. Which by definition | ||
| 392 | has no right-hand -- so can be removed just by making its only child (if | ||
| 393 | any) take its place under its parent. */ | ||
| 394 | static void eat_last(struct rb_root *root, struct rb_node *node) | ||
| 395 | { | ||
| 396 | struct rb_node *parent = rb_parent(node); | ||
| 397 | struct rb_node **link; | ||
| 398 | |||
| 399 | /* LAST! */ | ||
| 400 | BUG_ON(node->rb_right); | ||
| 401 | |||
| 402 | if (!parent) | ||
| 403 | link = &root->rb_node; | ||
| 404 | else if (node == parent->rb_left) | ||
| 405 | link = &parent->rb_left; | ||
| 406 | else | ||
| 407 | link = &parent->rb_right; | ||
| 408 | |||
| 409 | *link = node->rb_left; | ||
| 410 | /* Colour doesn't matter now. Only the parent pointer. */ | ||
| 411 | if (node->rb_left) | ||
| 412 | node->rb_left->rb_parent_color = node->rb_parent_color; | ||
| 413 | } | ||
| 414 | |||
| 415 | /* We put this in reverse order, so we can just use eat_last */ | ||
| 416 | static void ver_insert(struct rb_root *ver_root, struct jffs2_tmp_dnode_info *tn) | ||
| 417 | { | ||
| 418 | struct rb_node **link = &ver_root->rb_node; | ||
| 419 | struct rb_node *parent = NULL; | ||
| 420 | struct jffs2_tmp_dnode_info *this_tn; | ||
| 421 | |||
| 422 | while (*link) { | ||
| 423 | parent = *link; | ||
| 424 | this_tn = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); | ||
| 425 | |||
| 426 | if (tn->version > this_tn->version) | ||
| 427 | link = &parent->rb_left; | ||
| 428 | else | ||
| 429 | link = &parent->rb_right; | ||
| 430 | } | ||
| 431 | dbg_readinode("Link new node at %p (root is %p)\n", link, ver_root); | ||
| 432 | rb_link_node(&tn->rb, parent, link); | ||
| 433 | rb_insert_color(&tn->rb, ver_root); | ||
| 434 | } | ||
| 435 | |||
| 436 | /* Build final, normal fragtree from tn tree. It doesn't matter which order | ||
| 437 | we add nodes to the real fragtree, as long as they don't overlap. And | ||
| 438 | having thrown away the majority of overlapped nodes as we went, there | ||
| 439 | really shouldn't be many sets of nodes which do overlap. If we start at | ||
| 440 | the end, we can use the overlap markers -- we can just eat nodes which | ||
| 441 | aren't overlapped, and when we encounter nodes which _do_ overlap we | ||
| 442 | sort them all into a temporary tree in version order before replaying them. */ | ||
| 443 | static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c, | ||
| 444 | struct jffs2_inode_info *f, | ||
| 445 | struct jffs2_readinode_info *rii) | ||
| 446 | { | ||
| 447 | struct jffs2_tmp_dnode_info *pen, *last, *this; | ||
| 448 | struct rb_root ver_root = RB_ROOT; | ||
| 449 | uint32_t high_ver = 0; | ||
| 450 | |||
| 451 | if (rii->mdata_tn) { | ||
| 452 | dbg_readinode("potential mdata is ver %d at %p\n", rii->mdata_tn->version, rii->mdata_tn); | ||
| 453 | high_ver = rii->mdata_tn->version; | ||
| 454 | rii->latest_ref = rii->mdata_tn->fn->raw; | ||
| 455 | } | ||
| 456 | #ifdef JFFS2_DBG_READINODE_MESSAGES | ||
| 457 | this = tn_last(&rii->tn_root); | ||
| 458 | while (this) { | ||
| 459 | dbg_readinode("tn %p ver %d range 0x%x-0x%x ov %d\n", this, this->version, this->fn->ofs, | ||
| 460 | this->fn->ofs+this->fn->size, this->overlapped); | ||
| 461 | this = tn_prev(this); | ||
| 462 | } | ||
| 463 | #endif | ||
| 464 | pen = tn_last(&rii->tn_root); | ||
| 465 | while ((last = pen)) { | ||
| 466 | pen = tn_prev(last); | ||
| 467 | |||
| 468 | eat_last(&rii->tn_root, &last->rb); | ||
| 469 | ver_insert(&ver_root, last); | ||
| 470 | |||
| 471 | if (unlikely(last->overlapped)) | ||
| 472 | continue; | ||
| 473 | |||
| 474 | /* Now we have a bunch of nodes in reverse version | ||
| 475 | order, in the tree at ver_root. Most of the time, | ||
| 476 | there'll actually be only one node in the 'tree', | ||
| 477 | in fact. */ | ||
| 478 | this = tn_last(&ver_root); | ||
| 479 | |||
| 480 | while (this) { | ||
| 481 | struct jffs2_tmp_dnode_info *vers_next; | ||
| 482 | int ret; | ||
| 483 | vers_next = tn_prev(this); | ||
| 484 | eat_last(&ver_root, &this->rb); | ||
| 485 | if (check_tn_node(c, this)) { | ||
| 486 | dbg_readinode("node ver %x, 0x%x-0x%x failed CRC\n", | ||
| 487 | this->version, this->fn->ofs, | ||
| 488 | this->fn->ofs+this->fn->size); | ||
| 489 | jffs2_kill_tn(c, this); | ||
| 490 | } else { | ||
| 491 | if (this->version > high_ver) { | ||
| 492 | /* Note that this is different from the other | ||
| 493 | highest_version, because this one is only | ||
| 494 | counting _valid_ nodes which could give the | ||
| 495 | latest inode metadata */ | ||
| 496 | high_ver = this->version; | ||
| 497 | rii->latest_ref = this->fn->raw; | ||
| 498 | } | ||
| 499 | dbg_readinode("Add %p (v %x, 0x%x-0x%x, ov %d) to fragtree\n", | ||
| 500 | this, this->version, this->fn->ofs, | ||
| 501 | this->fn->ofs+this->fn->size, this->overlapped); | ||
| 502 | |||
| 503 | ret = jffs2_add_full_dnode_to_inode(c, f, this->fn); | ||
| 504 | if (ret) { | ||
| 505 | /* Free the nodes in vers_root; let the caller | ||
| 506 | deal with the rest */ | ||
| 507 | JFFS2_ERROR("Add node to tree failed %d\n", ret); | ||
| 508 | while (1) { | ||
| 509 | vers_next = tn_prev(this); | ||
| 510 | if (check_tn_node(c, this)) | ||
| 511 | jffs2_mark_node_obsolete(c, this->fn->raw); | ||
| 512 | jffs2_free_full_dnode(this->fn); | ||
| 513 | jffs2_free_tmp_dnode_info(this); | ||
| 514 | this = vers_next; | ||
| 515 | if (!this) | ||
| 516 | break; | ||
| 517 | eat_last(&ver_root, &vers_next->rb); | ||
| 518 | } | ||
| 519 | return ret; | ||
| 520 | } | ||
| 521 | jffs2_free_tmp_dnode_info(this); | ||
| 522 | } | ||
| 523 | this = vers_next; | ||
| 524 | } | ||
| 525 | } | ||
| 526 | return 0; | ||
| 49 | } | 527 | } |
| 50 | 528 | ||
| 51 | static void jffs2_free_tmp_dnode_info_list(struct rb_root *list) | 529 | static void jffs2_free_tmp_dnode_info_list(struct rb_root *list) |
| @@ -112,8 +590,8 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r | |||
| 112 | * negative error code on failure. | 590 | * negative error code on failure. |
| 113 | */ | 591 | */ |
| 114 | static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, | 592 | static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, |
| 115 | struct jffs2_raw_dirent *rd, size_t read, struct jffs2_full_dirent **fdp, | 593 | struct jffs2_raw_dirent *rd, size_t read, |
| 116 | uint32_t *latest_mctime, uint32_t *mctime_ver) | 594 | struct jffs2_readinode_info *rii) |
| 117 | { | 595 | { |
| 118 | struct jffs2_full_dirent *fd; | 596 | struct jffs2_full_dirent *fd; |
| 119 | uint32_t crc; | 597 | uint32_t crc; |
| @@ -125,7 +603,8 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r | |||
| 125 | if (unlikely(crc != je32_to_cpu(rd->node_crc))) { | 603 | if (unlikely(crc != je32_to_cpu(rd->node_crc))) { |
| 126 | JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n", | 604 | JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n", |
| 127 | ref_offset(ref), je32_to_cpu(rd->node_crc), crc); | 605 | ref_offset(ref), je32_to_cpu(rd->node_crc), crc); |
| 128 | return 1; | 606 | jffs2_mark_node_obsolete(c, ref); |
| 607 | return 0; | ||
| 129 | } | 608 | } |
| 130 | 609 | ||
| 131 | /* If we've never checked the CRCs on this node, check them now */ | 610 | /* If we've never checked the CRCs on this node, check them now */ |
| @@ -137,7 +616,8 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r | |||
| 137 | if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { | 616 | if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { |
| 138 | JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", | 617 | JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", |
| 139 | ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); | 618 | ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); |
| 140 | return 1; | 619 | jffs2_mark_node_obsolete(c, ref); |
| 620 | return 0; | ||
| 141 | } | 621 | } |
| 142 | 622 | ||
| 143 | jeb = &c->blocks[ref->flash_offset / c->sector_size]; | 623 | jeb = &c->blocks[ref->flash_offset / c->sector_size]; |
| @@ -161,10 +641,13 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r | |||
| 161 | fd->ino = je32_to_cpu(rd->ino); | 641 | fd->ino = je32_to_cpu(rd->ino); |
| 162 | fd->type = rd->type; | 642 | fd->type = rd->type; |
| 163 | 643 | ||
| 644 | if (fd->version > rii->highest_version) | ||
| 645 | rii->highest_version = fd->version; | ||
| 646 | |||
| 164 | /* Pick out the mctime of the latest dirent */ | 647 | /* Pick out the mctime of the latest dirent */ |
| 165 | if(fd->version > *mctime_ver && je32_to_cpu(rd->mctime)) { | 648 | if(fd->version > rii->mctime_ver && je32_to_cpu(rd->mctime)) { |
| 166 | *mctime_ver = fd->version; | 649 | rii->mctime_ver = fd->version; |
| 167 | *latest_mctime = je32_to_cpu(rd->mctime); | 650 | rii->latest_mctime = je32_to_cpu(rd->mctime); |
| 168 | } | 651 | } |
| 169 | 652 | ||
| 170 | /* | 653 | /* |
| @@ -201,7 +684,7 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r | |||
| 201 | * Wheee. We now have a complete jffs2_full_dirent structure, with | 684 | * Wheee. We now have a complete jffs2_full_dirent structure, with |
| 202 | * the name in it and everything. Link it into the list | 685 | * the name in it and everything. Link it into the list |
| 203 | */ | 686 | */ |
| 204 | jffs2_add_fd_to_list(c, fd, fdp); | 687 | jffs2_add_fd_to_list(c, fd, &rii->fds); |
| 205 | 688 | ||
| 206 | return 0; | 689 | return 0; |
| 207 | } | 690 | } |
| @@ -210,13 +693,13 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r | |||
| 210 | * Helper function for jffs2_get_inode_nodes(). | 693 | * Helper function for jffs2_get_inode_nodes(). |
| 211 | * It is called every time an inode node is found. | 694 | * It is called every time an inode node is found. |
| 212 | * | 695 | * |
| 213 | * Returns: 0 on succes; | 696 | * Returns: 0 on success; |
| 214 | * 1 if the node should be marked obsolete; | 697 | * 1 if the node should be marked obsolete; |
| 215 | * negative error code on failure. | 698 | * negative error code on failure. |
| 216 | */ | 699 | */ |
| 217 | static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, | 700 | static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, |
| 218 | struct jffs2_raw_inode *rd, struct rb_root *tnp, int rdlen, | 701 | struct jffs2_raw_inode *rd, int rdlen, |
| 219 | uint32_t *latest_mctime, uint32_t *mctime_ver) | 702 | struct jffs2_readinode_info *rii) |
| 220 | { | 703 | { |
| 221 | struct jffs2_tmp_dnode_info *tn; | 704 | struct jffs2_tmp_dnode_info *tn; |
| 222 | uint32_t len, csize; | 705 | uint32_t len, csize; |
| @@ -230,7 +713,8 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
| 230 | if (unlikely(crc != je32_to_cpu(rd->node_crc))) { | 713 | if (unlikely(crc != je32_to_cpu(rd->node_crc))) { |
| 231 | JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n", | 714 | JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n", |
| 232 | ref_offset(ref), je32_to_cpu(rd->node_crc), crc); | 715 | ref_offset(ref), je32_to_cpu(rd->node_crc), crc); |
| 233 | return 1; | 716 | jffs2_mark_node_obsolete(c, ref); |
| 717 | return 0; | ||
| 234 | } | 718 | } |
| 235 | 719 | ||
| 236 | tn = jffs2_alloc_tmp_dnode_info(); | 720 | tn = jffs2_alloc_tmp_dnode_info(); |
| @@ -342,6 +826,10 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
| 342 | tn->data_crc = je32_to_cpu(rd->data_crc); | 826 | tn->data_crc = je32_to_cpu(rd->data_crc); |
| 343 | tn->csize = csize; | 827 | tn->csize = csize; |
| 344 | tn->fn->raw = ref; | 828 | tn->fn->raw = ref; |
| 829 | tn->overlapped = 0; | ||
| 830 | |||
| 831 | if (tn->version > rii->highest_version) | ||
| 832 | rii->highest_version = tn->version; | ||
| 345 | 833 | ||
| 346 | /* There was a bug where we wrote hole nodes out with | 834 | /* There was a bug where we wrote hole nodes out with |
| 347 | csize/dsize swapped. Deal with it */ | 835 | csize/dsize swapped. Deal with it */ |
| @@ -353,13 +841,25 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
| 353 | dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", | 841 | dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", |
| 354 | ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); | 842 | ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); |
| 355 | 843 | ||
| 356 | jffs2_add_tn_to_tree(tn, tnp); | 844 | ret = jffs2_add_tn_to_tree(c, rii, tn); |
| 357 | 845 | ||
| 846 | if (ret) { | ||
| 847 | jffs2_free_full_dnode(tn->fn); | ||
| 848 | free_out: | ||
| 849 | jffs2_free_tmp_dnode_info(tn); | ||
| 850 | return ret; | ||
| 851 | } | ||
| 852 | #ifdef JFFS2_DBG_READINODE_MESSAGES | ||
| 853 | dbg_readinode("After adding ver %d:\n", tn->version); | ||
| 854 | tn = tn_first(&rii->tn_root); | ||
| 855 | while (tn) { | ||
| 856 | dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n", | ||
| 857 | tn, tn->version, tn->fn->ofs, | ||
| 858 | tn->fn->ofs+tn->fn->size, tn->overlapped); | ||
| 859 | tn = tn_next(tn); | ||
| 860 | } | ||
| 861 | #endif | ||
| 358 | return 0; | 862 | return 0; |
| 359 | |||
| 360 | free_out: | ||
| 361 | jffs2_free_tmp_dnode_info(tn); | ||
| 362 | return ret; | ||
| 363 | } | 863 | } |
| 364 | 864 | ||
| 365 | /* | 865 | /* |
| @@ -379,7 +879,8 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re | |||
| 379 | JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n", | 879 | JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n", |
| 380 | je16_to_cpu(un->magic), je16_to_cpu(un->nodetype), | 880 | je16_to_cpu(un->magic), je16_to_cpu(un->nodetype), |
| 381 | je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc)); | 881 | je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc)); |
| 382 | return 1; | 882 | jffs2_mark_node_obsolete(c, ref); |
| 883 | return 0; | ||
| 383 | } | 884 | } |
| 384 | 885 | ||
| 385 | un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); | 886 | un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); |
| @@ -407,7 +908,8 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re | |||
| 407 | case JFFS2_FEATURE_RWCOMPAT_DELETE: | 908 | case JFFS2_FEATURE_RWCOMPAT_DELETE: |
| 408 | JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", | 909 | JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", |
| 409 | je16_to_cpu(un->nodetype), ref_offset(ref)); | 910 | je16_to_cpu(un->nodetype), ref_offset(ref)); |
| 410 | return 1; | 911 | jffs2_mark_node_obsolete(c, ref); |
| 912 | return 0; | ||
| 411 | } | 913 | } |
| 412 | 914 | ||
| 413 | return 0; | 915 | return 0; |
| @@ -421,92 +923,62 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re | |||
| 421 | * negative error code on failure. | 923 | * negative error code on failure. |
| 422 | */ | 924 | */ |
| 423 | static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, | 925 | static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, |
| 424 | int right_size, int *rdlen, unsigned char *buf, unsigned char *bufstart) | 926 | int needed_len, int *rdlen, unsigned char *buf) |
| 425 | { | 927 | { |
| 426 | int right_len, err, len; | 928 | int err, to_read = needed_len - *rdlen; |
| 427 | size_t retlen; | 929 | size_t retlen; |
| 428 | uint32_t offs; | 930 | uint32_t offs; |
| 429 | 931 | ||
| 430 | if (jffs2_is_writebuffered(c)) { | 932 | if (jffs2_is_writebuffered(c)) { |
| 431 | right_len = c->wbuf_pagesize - (bufstart - buf); | 933 | int rem = to_read % c->wbuf_pagesize; |
| 432 | if (right_size + (int)(bufstart - buf) > c->wbuf_pagesize) | ||
| 433 | right_len += c->wbuf_pagesize; | ||
| 434 | } else | ||
| 435 | right_len = right_size; | ||
| 436 | 934 | ||
| 437 | if (*rdlen == right_len) | 935 | if (rem) |
| 438 | return 0; | 936 | to_read += c->wbuf_pagesize - rem; |
| 937 | } | ||
| 439 | 938 | ||
| 440 | /* We need to read more data */ | 939 | /* We need to read more data */ |
| 441 | offs = ref_offset(ref) + *rdlen; | 940 | offs = ref_offset(ref) + *rdlen; |
| 442 | if (jffs2_is_writebuffered(c)) { | ||
| 443 | bufstart = buf + c->wbuf_pagesize; | ||
| 444 | len = c->wbuf_pagesize; | ||
| 445 | } else { | ||
| 446 | bufstart = buf + *rdlen; | ||
| 447 | len = right_size - *rdlen; | ||
| 448 | } | ||
| 449 | 941 | ||
| 450 | dbg_readinode("read more %d bytes\n", len); | 942 | dbg_readinode("read more %d bytes\n", to_read); |
| 451 | 943 | ||
| 452 | err = jffs2_flash_read(c, offs, len, &retlen, bufstart); | 944 | err = jffs2_flash_read(c, offs, to_read, &retlen, buf + *rdlen); |
| 453 | if (err) { | 945 | if (err) { |
| 454 | JFFS2_ERROR("can not read %d bytes from 0x%08x, " | 946 | JFFS2_ERROR("can not read %d bytes from 0x%08x, " |
| 455 | "error code: %d.\n", len, offs, err); | 947 | "error code: %d.\n", to_read, offs, err); |
| 456 | return err; | 948 | return err; |
| 457 | } | 949 | } |
| 458 | 950 | ||
| 459 | if (retlen < len) { | 951 | if (retlen < to_read) { |
| 460 | JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", | 952 | JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", |
| 461 | offs, retlen, len); | 953 | offs, retlen, to_read); |
| 462 | return -EIO; | 954 | return -EIO; |
| 463 | } | 955 | } |
| 464 | 956 | ||
| 465 | *rdlen = right_len; | 957 | *rdlen += to_read; |
| 466 | |||
| 467 | return 0; | 958 | return 0; |
| 468 | } | 959 | } |
| 469 | 960 | ||
| 470 | /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated | 961 | /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated |
| 471 | with this ino, returning the former in order of version */ | 962 | with this ino. Perform a preliminary ordering on data nodes, throwing away |
| 963 | those which are completely obsoleted by newer ones. The naïve approach we | ||
| 964 | use to take of just returning them _all_ in version order will cause us to | ||
| 965 | run out of memory in certain degenerate cases. */ | ||
| 472 | static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | 966 | static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, |
| 473 | struct rb_root *tnp, struct jffs2_full_dirent **fdp, | 967 | struct jffs2_readinode_info *rii) |
| 474 | uint32_t *highest_version, uint32_t *latest_mctime, | ||
| 475 | uint32_t *mctime_ver) | ||
| 476 | { | 968 | { |
| 477 | struct jffs2_raw_node_ref *ref, *valid_ref; | 969 | struct jffs2_raw_node_ref *ref, *valid_ref; |
| 478 | struct rb_root ret_tn = RB_ROOT; | ||
| 479 | struct jffs2_full_dirent *ret_fd = NULL; | ||
| 480 | unsigned char *buf = NULL; | 970 | unsigned char *buf = NULL; |
| 481 | union jffs2_node_union *node; | 971 | union jffs2_node_union *node; |
| 482 | size_t retlen; | 972 | size_t retlen; |
| 483 | int len, err; | 973 | int len, err; |
| 484 | 974 | ||
| 485 | *mctime_ver = 0; | 975 | rii->mctime_ver = 0; |
| 486 | 976 | ||
| 487 | dbg_readinode("ino #%u\n", f->inocache->ino); | 977 | dbg_readinode("ino #%u\n", f->inocache->ino); |
| 488 | 978 | ||
| 489 | if (jffs2_is_writebuffered(c)) { | ||
| 490 | /* | ||
| 491 | * If we have the write buffer, we assume the minimal I/O unit | ||
| 492 | * is c->wbuf_pagesize. We implement some optimizations which in | ||
| 493 | * this case and we need a temporary buffer of size = | ||
| 494 | * 2*c->wbuf_pagesize bytes (see comments in read_dnode()). | ||
| 495 | * Basically, we want to read not only the node header, but the | ||
| 496 | * whole wbuf (NAND page in case of NAND) or 2, if the node | ||
| 497 | * header overlaps the border between the 2 wbufs. | ||
| 498 | */ | ||
| 499 | len = 2*c->wbuf_pagesize; | ||
| 500 | } else { | ||
| 501 | /* | ||
| 502 | * When there is no write buffer, the size of the temporary | ||
| 503 | * buffer is the size of the larges node header. | ||
| 504 | */ | ||
| 505 | len = sizeof(union jffs2_node_union); | ||
| 506 | } | ||
| 507 | |||
| 508 | /* FIXME: in case of NOR and available ->point() this | 979 | /* FIXME: in case of NOR and available ->point() this |
| 509 | * needs to be fixed. */ | 980 | * needs to be fixed. */ |
| 981 | len = sizeof(union jffs2_node_union) + c->wbuf_pagesize; | ||
| 510 | buf = kmalloc(len, GFP_KERNEL); | 982 | buf = kmalloc(len, GFP_KERNEL); |
| 511 | if (!buf) | 983 | if (!buf) |
| 512 | return -ENOMEM; | 984 | return -ENOMEM; |
| @@ -516,8 +988,6 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf | |||
| 516 | if (!valid_ref && f->inocache->ino != 1) | 988 | if (!valid_ref && f->inocache->ino != 1) |
| 517 | JFFS2_WARNING("Eep. No valid nodes for ino #%u.\n", f->inocache->ino); | 989 | JFFS2_WARNING("Eep. No valid nodes for ino #%u.\n", f->inocache->ino); |
| 518 | while (valid_ref) { | 990 | while (valid_ref) { |
| 519 | unsigned char *bufstart; | ||
| 520 | |||
| 521 | /* We can hold a pointer to a non-obsolete node without the spinlock, | 991 | /* We can hold a pointer to a non-obsolete node without the spinlock, |
| 522 | but _obsolete_ nodes may disappear at any time, if the block | 992 | but _obsolete_ nodes may disappear at any time, if the block |
| 523 | they're in gets erased. So if we mark 'ref' obsolete while we're | 993 | they're in gets erased. So if we mark 'ref' obsolete while we're |
| @@ -533,32 +1003,31 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf | |||
| 533 | /* | 1003 | /* |
| 534 | * At this point we don't know the type of the node we're going | 1004 | * At this point we don't know the type of the node we're going |
| 535 | * to read, so we do not know the size of its header. In order | 1005 | * to read, so we do not know the size of its header. In order |
| 536 | * to minimize the amount of flash IO we assume the node has | 1006 | * to minimize the amount of flash IO we assume the header is |
| 537 | * size = JFFS2_MIN_NODE_HEADER. | 1007 | * of size = JFFS2_MIN_NODE_HEADER. |
| 538 | */ | 1008 | */ |
| 1009 | len = JFFS2_MIN_NODE_HEADER; | ||
| 539 | if (jffs2_is_writebuffered(c)) { | 1010 | if (jffs2_is_writebuffered(c)) { |
| 1011 | int end, rem; | ||
| 1012 | |||
| 540 | /* | 1013 | /* |
| 541 | * We treat 'buf' as 2 adjacent wbufs. We want to | 1014 | * We are about to read JFFS2_MIN_NODE_HEADER bytes, |
| 542 | * adjust bufstart such as it points to the | 1015 | * but this flash has some minimal I/O unit. It is |
| 543 | * beginning of the node within this wbuf. | 1016 | * possible that we'll need to read more soon, so read |
| 1017 | * up to the next min. I/O unit, in order not to | ||
| 1018 | * re-read the same min. I/O unit twice. | ||
| 544 | */ | 1019 | */ |
| 545 | bufstart = buf + (ref_offset(ref) % c->wbuf_pagesize); | 1020 | end = ref_offset(ref) + len; |
| 546 | /* We will read either one wbuf or 2 wbufs. */ | 1021 | rem = end % c->wbuf_pagesize; |
| 547 | len = c->wbuf_pagesize - (bufstart - buf); | 1022 | if (rem) |
| 548 | if (JFFS2_MIN_NODE_HEADER + (int)(bufstart - buf) > c->wbuf_pagesize) { | 1023 | end += c->wbuf_pagesize - rem; |
| 549 | /* The header spans the border of the first wbuf */ | 1024 | len = end - ref_offset(ref); |
| 550 | len += c->wbuf_pagesize; | ||
| 551 | } | ||
| 552 | } else { | ||
| 553 | bufstart = buf; | ||
| 554 | len = JFFS2_MIN_NODE_HEADER; | ||
| 555 | } | 1025 | } |
| 556 | 1026 | ||
| 557 | dbg_readinode("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref)); | 1027 | dbg_readinode("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref)); |
| 558 | 1028 | ||
| 559 | /* FIXME: point() */ | 1029 | /* FIXME: point() */ |
| 560 | err = jffs2_flash_read(c, ref_offset(ref), len, | 1030 | err = jffs2_flash_read(c, ref_offset(ref), len, &retlen, buf); |
| 561 | &retlen, bufstart); | ||
| 562 | if (err) { | 1031 | if (err) { |
| 563 | JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err); | 1032 | JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err); |
| 564 | goto free_out; | 1033 | goto free_out; |
| @@ -570,7 +1039,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf | |||
| 570 | goto free_out; | 1039 | goto free_out; |
| 571 | } | 1040 | } |
| 572 | 1041 | ||
| 573 | node = (union jffs2_node_union *)bufstart; | 1042 | node = (union jffs2_node_union *)buf; |
| 574 | 1043 | ||
| 575 | /* No need to mask in the valid bit; it shouldn't be invalid */ | 1044 | /* No need to mask in the valid bit; it shouldn't be invalid */ |
| 576 | if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) { | 1045 | if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) { |
| @@ -583,10 +1052,10 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf | |||
| 583 | jffs2_mark_node_obsolete(c, ref); | 1052 | jffs2_mark_node_obsolete(c, ref); |
| 584 | goto cont; | 1053 | goto cont; |
| 585 | } | 1054 | } |
| 586 | /* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */ | 1055 | if (je16_to_cpu(node->u.magic) != JFFS2_MAGIC_BITMASK) { |
| 587 | if (!je32_to_cpu(node->u.hdr_crc) && !je16_to_cpu(node->u.nodetype) && | 1056 | /* Not a JFFS2 node, whinge and move on */ |
| 588 | !je16_to_cpu(node->u.magic) && !je32_to_cpu(node->u.totlen)) { | 1057 | JFFS2_NOTICE("Wrong magic bitmask 0x%04x in node header at %#08x.\n", |
| 589 | JFFS2_NOTICE("All zero node header at %#08x.\n", ref_offset(ref)); | 1058 | je16_to_cpu(node->u.magic), ref_offset(ref)); |
| 590 | jffs2_mark_node_obsolete(c, ref); | 1059 | jffs2_mark_node_obsolete(c, ref); |
| 591 | goto cont; | 1060 | goto cont; |
| 592 | } | 1061 | } |
| @@ -596,46 +1065,34 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf | |||
| 596 | case JFFS2_NODETYPE_DIRENT: | 1065 | case JFFS2_NODETYPE_DIRENT: |
| 597 | 1066 | ||
| 598 | if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) { | 1067 | if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) { |
| 599 | err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf, bufstart); | 1068 | err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf); |
| 600 | if (unlikely(err)) | 1069 | if (unlikely(err)) |
| 601 | goto free_out; | 1070 | goto free_out; |
| 602 | } | 1071 | } |
| 603 | 1072 | ||
| 604 | err = read_direntry(c, ref, &node->d, retlen, &ret_fd, latest_mctime, mctime_ver); | 1073 | err = read_direntry(c, ref, &node->d, retlen, rii); |
| 605 | if (err == 1) { | 1074 | if (unlikely(err)) |
| 606 | jffs2_mark_node_obsolete(c, ref); | ||
| 607 | break; | ||
| 608 | } else if (unlikely(err)) | ||
| 609 | goto free_out; | 1075 | goto free_out; |
| 610 | 1076 | ||
| 611 | if (je32_to_cpu(node->d.version) > *highest_version) | ||
| 612 | *highest_version = je32_to_cpu(node->d.version); | ||
| 613 | |||
| 614 | break; | 1077 | break; |
| 615 | 1078 | ||
| 616 | case JFFS2_NODETYPE_INODE: | 1079 | case JFFS2_NODETYPE_INODE: |
| 617 | 1080 | ||
| 618 | if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) { | 1081 | if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) { |
| 619 | err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf, bufstart); | 1082 | err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf); |
| 620 | if (unlikely(err)) | 1083 | if (unlikely(err)) |
| 621 | goto free_out; | 1084 | goto free_out; |
| 622 | } | 1085 | } |
| 623 | 1086 | ||
| 624 | err = read_dnode(c, ref, &node->i, &ret_tn, len, latest_mctime, mctime_ver); | 1087 | err = read_dnode(c, ref, &node->i, len, rii); |
| 625 | if (err == 1) { | 1088 | if (unlikely(err)) |
| 626 | jffs2_mark_node_obsolete(c, ref); | ||
| 627 | break; | ||
| 628 | } else if (unlikely(err)) | ||
| 629 | goto free_out; | 1089 | goto free_out; |
| 630 | 1090 | ||
| 631 | if (je32_to_cpu(node->i.version) > *highest_version) | ||
| 632 | *highest_version = je32_to_cpu(node->i.version); | ||
| 633 | |||
| 634 | break; | 1091 | break; |
| 635 | 1092 | ||
| 636 | default: | 1093 | default: |
| 637 | if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node)) { | 1094 | if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node)) { |
| 638 | err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf, bufstart); | 1095 | err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf); |
| 639 | if (unlikely(err)) | 1096 | if (unlikely(err)) |
| 640 | goto free_out; | 1097 | goto free_out; |
| 641 | } | 1098 | } |
| @@ -653,17 +1110,19 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf | |||
| 653 | } | 1110 | } |
| 654 | 1111 | ||
| 655 | spin_unlock(&c->erase_completion_lock); | 1112 | spin_unlock(&c->erase_completion_lock); |
| 656 | *tnp = ret_tn; | ||
| 657 | *fdp = ret_fd; | ||
| 658 | kfree(buf); | 1113 | kfree(buf); |
| 659 | 1114 | ||
| 1115 | f->highest_version = rii->highest_version; | ||
| 1116 | |||
| 660 | dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n", | 1117 | dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n", |
| 661 | f->inocache->ino, *highest_version, *latest_mctime, *mctime_ver); | 1118 | f->inocache->ino, rii->highest_version, rii->latest_mctime, |
| 1119 | rii->mctime_ver); | ||
| 662 | return 0; | 1120 | return 0; |
| 663 | 1121 | ||
| 664 | free_out: | 1122 | free_out: |
| 665 | jffs2_free_tmp_dnode_info_list(&ret_tn); | 1123 | jffs2_free_tmp_dnode_info_list(&rii->tn_root); |
| 666 | jffs2_free_full_dirent_list(ret_fd); | 1124 | jffs2_free_full_dirent_list(rii->fds); |
| 1125 | rii->fds = NULL; | ||
| 667 | kfree(buf); | 1126 | kfree(buf); |
| 668 | return err; | 1127 | return err; |
| 669 | } | 1128 | } |
| @@ -672,20 +1131,17 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
| 672 | struct jffs2_inode_info *f, | 1131 | struct jffs2_inode_info *f, |
| 673 | struct jffs2_raw_inode *latest_node) | 1132 | struct jffs2_raw_inode *latest_node) |
| 674 | { | 1133 | { |
| 675 | struct jffs2_tmp_dnode_info *tn; | 1134 | struct jffs2_readinode_info rii; |
| 676 | struct rb_root tn_list; | 1135 | uint32_t crc, new_size; |
| 677 | struct rb_node *rb, *repl_rb; | ||
| 678 | struct jffs2_full_dirent *fd_list; | ||
| 679 | struct jffs2_full_dnode *fn, *first_fn = NULL; | ||
| 680 | uint32_t crc; | ||
| 681 | uint32_t latest_mctime, mctime_ver; | ||
| 682 | size_t retlen; | 1136 | size_t retlen; |
| 683 | int ret; | 1137 | int ret; |
| 684 | 1138 | ||
| 685 | dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); | 1139 | dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); |
| 686 | 1140 | ||
| 1141 | memset(&rii, 0, sizeof(rii)); | ||
| 1142 | |||
| 687 | /* Grab all nodes relevant to this ino */ | 1143 | /* Grab all nodes relevant to this ino */ |
| 688 | ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); | 1144 | ret = jffs2_get_inode_nodes(c, f, &rii); |
| 689 | 1145 | ||
| 690 | if (ret) { | 1146 | if (ret) { |
| 691 | JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret); | 1147 | JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret); |
| @@ -693,74 +1149,42 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
| 693 | jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); | 1149 | jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); |
| 694 | return ret; | 1150 | return ret; |
| 695 | } | 1151 | } |
| 696 | f->dents = fd_list; | ||
| 697 | |||
| 698 | rb = rb_first(&tn_list); | ||
| 699 | 1152 | ||
| 700 | while (rb) { | 1153 | ret = jffs2_build_inode_fragtree(c, f, &rii); |
| 701 | cond_resched(); | 1154 | if (ret) { |
| 702 | tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb); | 1155 | JFFS2_ERROR("Failed to build final fragtree for inode #%u: error %d\n", |
| 703 | fn = tn->fn; | 1156 | f->inocache->ino, ret); |
| 704 | ret = 1; | 1157 | if (f->inocache->state == INO_STATE_READING) |
| 705 | dbg_readinode("consider node ver %u, phys offset " | 1158 | jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); |
| 706 | "%#08x(%d), range %u-%u.\n", tn->version, | 1159 | jffs2_free_tmp_dnode_info_list(&rii.tn_root); |
| 707 | ref_offset(fn->raw), ref_flags(fn->raw), | 1160 | /* FIXME: We could at least crc-check them all */ |
| 708 | fn->ofs, fn->ofs + fn->size); | 1161 | if (rii.mdata_tn) { |
| 709 | 1162 | jffs2_free_full_dnode(rii.mdata_tn->fn); | |
| 710 | if (fn->size) { | 1163 | jffs2_free_tmp_dnode_info(rii.mdata_tn); |
| 711 | ret = jffs2_add_older_frag_to_fragtree(c, f, tn); | 1164 | rii.mdata_tn = NULL; |
| 712 | /* TODO: the error code isn't checked, check it */ | 1165 | } |
| 713 | jffs2_dbg_fragtree_paranoia_check_nolock(f); | 1166 | return ret; |
| 714 | BUG_ON(ret < 0); | 1167 | } |
| 715 | if (!first_fn && ret == 0) | ||
| 716 | first_fn = fn; | ||
| 717 | } else if (!first_fn) { | ||
| 718 | first_fn = fn; | ||
| 719 | f->metadata = fn; | ||
| 720 | ret = 0; /* Prevent freeing the metadata update node */ | ||
| 721 | } else | ||
| 722 | jffs2_mark_node_obsolete(c, fn->raw); | ||
| 723 | |||
| 724 | BUG_ON(rb->rb_left); | ||
| 725 | if (rb_parent(rb) && rb_parent(rb)->rb_left == rb) { | ||
| 726 | /* We were then left-hand child of our parent. We need | ||
| 727 | * to move our own right-hand child into our place. */ | ||
| 728 | repl_rb = rb->rb_right; | ||
| 729 | if (repl_rb) | ||
| 730 | rb_set_parent(repl_rb, rb_parent(rb)); | ||
| 731 | } else | ||
| 732 | repl_rb = NULL; | ||
| 733 | |||
| 734 | rb = rb_next(rb); | ||
| 735 | |||
| 736 | /* Remove the spent tn from the tree; don't bother rebalancing | ||
| 737 | * but put our right-hand child in our own place. */ | ||
| 738 | if (rb_parent(&tn->rb)) { | ||
| 739 | if (rb_parent(&tn->rb)->rb_left == &tn->rb) | ||
| 740 | rb_parent(&tn->rb)->rb_left = repl_rb; | ||
| 741 | else if (rb_parent(&tn->rb)->rb_right == &tn->rb) | ||
| 742 | rb_parent(&tn->rb)->rb_right = repl_rb; | ||
| 743 | else BUG(); | ||
| 744 | } else if (tn->rb.rb_right) | ||
| 745 | rb_set_parent(tn->rb.rb_right, NULL); | ||
| 746 | 1168 | ||
| 747 | jffs2_free_tmp_dnode_info(tn); | 1169 | if (rii.mdata_tn) { |
| 748 | if (ret) { | 1170 | if (rii.mdata_tn->fn->raw == rii.latest_ref) { |
| 749 | dbg_readinode("delete dnode %u-%u.\n", | 1171 | f->metadata = rii.mdata_tn->fn; |
| 750 | fn->ofs, fn->ofs + fn->size); | 1172 | jffs2_free_tmp_dnode_info(rii.mdata_tn); |
| 751 | jffs2_free_full_dnode(fn); | 1173 | } else { |
| 1174 | jffs2_kill_tn(c, rii.mdata_tn); | ||
| 752 | } | 1175 | } |
| 1176 | rii.mdata_tn = NULL; | ||
| 753 | } | 1177 | } |
| 754 | jffs2_dbg_fragtree_paranoia_check_nolock(f); | ||
| 755 | 1178 | ||
| 756 | BUG_ON(first_fn && ref_obsolete(first_fn->raw)); | 1179 | f->dents = rii.fds; |
| 757 | 1180 | ||
| 758 | fn = first_fn; | 1181 | jffs2_dbg_fragtree_paranoia_check_nolock(f); |
| 759 | if (unlikely(!first_fn)) { | 1182 | |
| 1183 | if (unlikely(!rii.latest_ref)) { | ||
| 760 | /* No data nodes for this inode. */ | 1184 | /* No data nodes for this inode. */ |
| 761 | if (f->inocache->ino != 1) { | 1185 | if (f->inocache->ino != 1) { |
| 762 | JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino); | 1186 | JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino); |
| 763 | if (!fd_list) { | 1187 | if (!rii.fds) { |
| 764 | if (f->inocache->state == INO_STATE_READING) | 1188 | if (f->inocache->state == INO_STATE_READING) |
| 765 | jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); | 1189 | jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); |
| 766 | return -EIO; | 1190 | return -EIO; |
| @@ -778,7 +1202,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
| 778 | return 0; | 1202 | return 0; |
| 779 | } | 1203 | } |
| 780 | 1204 | ||
| 781 | ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node); | 1205 | ret = jffs2_flash_read(c, ref_offset(rii.latest_ref), sizeof(*latest_node), &retlen, (void *)latest_node); |
| 782 | if (ret || retlen != sizeof(*latest_node)) { | 1206 | if (ret || retlen != sizeof(*latest_node)) { |
| 783 | JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n", | 1207 | JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n", |
| 784 | ret, retlen, sizeof(*latest_node)); | 1208 | ret, retlen, sizeof(*latest_node)); |
| @@ -791,7 +1215,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
| 791 | crc = crc32(0, latest_node, sizeof(*latest_node)-8); | 1215 | crc = crc32(0, latest_node, sizeof(*latest_node)-8); |
| 792 | if (crc != je32_to_cpu(latest_node->node_crc)) { | 1216 | if (crc != je32_to_cpu(latest_node->node_crc)) { |
| 793 | JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n", | 1217 | JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n", |
| 794 | f->inocache->ino, ref_offset(fn->raw)); | 1218 | f->inocache->ino, ref_offset(rii.latest_ref)); |
| 795 | up(&f->sem); | 1219 | up(&f->sem); |
| 796 | jffs2_do_clear_inode(c, f); | 1220 | jffs2_do_clear_inode(c, f); |
| 797 | return -EIO; | 1221 | return -EIO; |
| @@ -799,17 +1223,22 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
| 799 | 1223 | ||
| 800 | switch(jemode_to_cpu(latest_node->mode) & S_IFMT) { | 1224 | switch(jemode_to_cpu(latest_node->mode) & S_IFMT) { |
| 801 | case S_IFDIR: | 1225 | case S_IFDIR: |
| 802 | if (mctime_ver > je32_to_cpu(latest_node->version)) { | 1226 | if (rii.mctime_ver > je32_to_cpu(latest_node->version)) { |
| 803 | /* The times in the latest_node are actually older than | 1227 | /* The times in the latest_node are actually older than |
| 804 | mctime in the latest dirent. Cheat. */ | 1228 | mctime in the latest dirent. Cheat. */ |
| 805 | latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime); | 1229 | latest_node->ctime = latest_node->mtime = cpu_to_je32(rii.latest_mctime); |
| 806 | } | 1230 | } |
| 807 | break; | 1231 | break; |
| 808 | 1232 | ||
| 809 | 1233 | ||
| 810 | case S_IFREG: | 1234 | case S_IFREG: |
| 811 | /* If it was a regular file, truncate it to the latest node's isize */ | 1235 | /* If it was a regular file, truncate it to the latest node's isize */ |
| 812 | jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); | 1236 | new_size = jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); |
| 1237 | if (new_size != je32_to_cpu(latest_node->isize)) { | ||
| 1238 | JFFS2_WARNING("Truncating ino #%u to %d bytes failed because it only had %d bytes to start with!\n", | ||
| 1239 | f->inocache->ino, je32_to_cpu(latest_node->isize), new_size); | ||
| 1240 | latest_node->isize = cpu_to_je32(new_size); | ||
| 1241 | } | ||
| 813 | break; | 1242 | break; |
| 814 | 1243 | ||
| 815 | case S_IFLNK: | 1244 | case S_IFLNK: |
| @@ -832,7 +1261,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
| 832 | return -ENOMEM; | 1261 | return -ENOMEM; |
| 833 | } | 1262 | } |
| 834 | 1263 | ||
| 835 | ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), | 1264 | ret = jffs2_flash_read(c, ref_offset(rii.latest_ref) + sizeof(*latest_node), |
| 836 | je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); | 1265 | je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); |
| 837 | 1266 | ||
| 838 | if (ret || retlen != je32_to_cpu(latest_node->csize)) { | 1267 | if (ret || retlen != je32_to_cpu(latest_node->csize)) { |
