diff options
author | David Woodhouse <dwmw2@infradead.org> | 2007-04-25 12:04:23 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2007-04-25 12:04:23 -0400 |
commit | 61c4b23770d1b0cef7c06a23378ab544eb0c64b4 (patch) | |
tree | b4cf1e784621d2f60a3494ded1d5852934107c22 /fs/jffs2/nodelist.c | |
parent | c00c310eac04a28d2143368ae988716792ed53ce (diff) |
[JFFS2] Handle inodes with only a single metadata node with non-zero isize
This should never happen unless there's corruption on the medium and the
actual data nodes go missing. But the failure mode (an oops when we assume
the fragtree isn't empty and go looking for its last node) isn't useful.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'fs/jffs2/nodelist.c')
-rw-r--r-- | fs/jffs2/nodelist.c | 18 |
1 files changed, 12 insertions, 6 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, |