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: |