if ((*prev)->nhash == new->nhash && !strcmp((*prev)->name, new->name)) {
/* Duplicate. Free one */
if (new->version < (*prev)->version) {
- dbg_dentlist("Eep! Marking new dirent node is obsolete, old is \"%s\", ino #%u\n",
+ dbg_dentlist("Eep! Marking new dirent node obsolete, old is \"%s\", ino #%u\n",
(*prev)->name, (*prev)->ino);
jffs2_mark_node_obsolete(c, new->raw);
jffs2_free_full_dirent(new);
} else {
- dbg_dentlist("marking old dirent \"%s\", ino #%u bsolete\n",
+ dbg_dentlist("marking old dirent \"%s\", ino #%u obsolete\n",
(*prev)->name, (*prev)->ino);
new->next = (*prev)->next;
- jffs2_mark_node_obsolete(c, ((*prev)->raw));
+ /* It may have been a 'placeholder' deletion dirent,
+ if jffs2_can_mark_obsolete() (see jffs2_do_unlink()) */
+ if ((*prev)->raw)
+ jffs2_mark_node_obsolete(c, ((*prev)->raw));
jffs2_free_full_dirent(*prev);
*prev = new;
}
*prev = new;
}
-void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint32_t size)
+uint32_t jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint32_t size)
{
struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size);
}
if (size == 0)
- return;
+ return 0;
- /*
- * If the last fragment starts at the RAM page boundary, it is
- * REF_PRISTINE irrespective of its size.
- */
frag = frag_last(list);
+
+ /* Sanity check for truncation to longer than we started with... */
+ if (!frag)
+ return 0;
+ if (frag->ofs + frag->size < size)
+ return frag->ofs + frag->size;
+
+ /* If the last fragment starts at the RAM page boundary, it is
+ * REF_PRISTINE irrespective of its size. */
if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) {
dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n",
frag->ofs, frag->ofs + frag->size);
frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE;
}
+ return size;
}
static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c,