diff options
| -rw-r--r-- | fs/jffs2/nodelist.c | 18 | ||||
| -rw-r--r-- | fs/jffs2/nodelist.h | 2 | ||||
| -rw-r--r-- | fs/jffs2/readinode.c | 9 |
3 files changed, 20 insertions, 9 deletions
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index ac2a4c422e32..4bf86088b3ae 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c | |||
| @@ -52,7 +52,7 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new | |||
| 52 | *prev = new; | 52 | *prev = new; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) | 55 | uint32_t jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) |
| 56 | { | 56 | { |
| 57 | struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); | 57 | struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); |
| 58 | 58 | ||
| @@ -74,18 +74,24 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint | |||
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | if (size == 0) | 76 | if (size == 0) |
| 77 | return; | 77 | return 0; |
| 78 | 78 | ||
| 79 | /* | ||
| 80 | * If the last fragment starts at the RAM page boundary, it is | ||
| 81 | * REF_PRISTINE irrespective of its size. | ||
| 82 | */ | ||
| 83 | frag = frag_last(list); | 79 | frag = frag_last(list); |
| 80 | |||
| 81 | /* Sanity check for truncation to longer than we started with... */ | ||
| 82 | if (!frag) | ||
| 83 | return 0; | ||
| 84 | if (frag->ofs + frag->size < size) | ||
| 85 | return frag->ofs + frag->size; | ||
| 86 | |||
| 87 | /* If the last fragment starts at the RAM page boundary, it is | ||
| 88 | * REF_PRISTINE irrespective of its size. */ | ||
| 84 | if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) { | 89 | if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) { |
| 85 | dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", | 90 | dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", |
| 86 | frag->ofs, frag->ofs + frag->size); | 91 | frag->ofs, frag->ofs + frag->size); |
| 87 | frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE; | 92 | frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE; |
| 88 | } | 93 | } |
| 94 | return size; | ||
| 89 | } | 95 | } |
| 90 | 96 | ||
| 91 | static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, | 97 | static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, |
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index cb34cac5d0f8..25126a062cae 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h | |||
| @@ -362,7 +362,7 @@ struct rb_node *rb_next(struct rb_node *); | |||
| 362 | struct rb_node *rb_prev(struct rb_node *); | 362 | struct rb_node *rb_prev(struct rb_node *); |
| 363 | void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); | 363 | void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); |
| 364 | int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); | 364 | int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); |
| 365 | void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); | 365 | uint32_t jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); |
| 366 | struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c, | 366 | struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c, |
| 367 | struct jffs2_eraseblock *jeb, | 367 | struct jffs2_eraseblock *jeb, |
| 368 | uint32_t ofs, uint32_t len, | 368 | uint32_t ofs, uint32_t len, |
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index a42ffba2ed17..6aff38930b50 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c | |||
| @@ -1132,7 +1132,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
| 1132 | struct jffs2_raw_inode *latest_node) | 1132 | struct jffs2_raw_inode *latest_node) |
| 1133 | { | 1133 | { |
| 1134 | struct jffs2_readinode_info rii; | 1134 | struct jffs2_readinode_info rii; |
| 1135 | uint32_t crc; | 1135 | uint32_t crc, new_size; |
| 1136 | size_t retlen; | 1136 | size_t retlen; |
| 1137 | int ret; | 1137 | int ret; |
| 1138 | 1138 | ||
| @@ -1233,7 +1233,12 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
| 1233 | 1233 | ||
| 1234 | case S_IFREG: | 1234 | case S_IFREG: |
| 1235 | /* 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 */ |
| 1236 | 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 | } | ||
| 1237 | break; | 1242 | break; |
| 1238 | 1243 | ||
| 1239 | case S_IFLNK: | 1244 | case S_IFLNK: |
