}
spin_unlock(&c->erase_completion_lock);
if (!ret)
- ret = jffs2_prealloc_raw_node_refs(c, 1);
+ ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
if (ret)
up(&c->alloc_sem);
return ret;
}
spin_unlock(&c->erase_completion_lock);
if (!ret)
- ret = jffs2_prealloc_raw_node_refs(c, 1);
+ ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
return ret;
}
}
} else {
if (jeb && minsize > jeb->free_size) {
+ uint32_t waste;
+
/* Skip the end of this block and file it as having some dirty space */
/* If there's a pending write to it, flush now */
goto restart;
}
- c->wasted_size += jeb->free_size;
- c->free_size -= jeb->free_size;
- jeb->wasted_size += jeb->free_size;
- jeb->free_size = 0;
+ spin_unlock(&c->erase_completion_lock);
+
+ ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
+ if (ret)
+ return ret;
+ /* Just lock it again and continue. Nothing much can change because
+ we hold c->alloc_sem anyway. In fact, it's not entirely clear why
+ we hold c->erase_completion_lock in the majority of this function...
+ but that's a question for another (more caffeine-rich) day. */
+ spin_lock(&c->erase_completion_lock);
+
+ waste = jeb->free_size;
+ jffs2_link_node_ref(c, jeb,
+ (jeb->offset + c->sector_size - waste) | REF_OBSOLETE,
+ waste, NULL);
+ /* FIXME: that made it count as dirty. Convert to wasted */
+ jeb->dirty_size -= waste;
+ c->dirty_size -= waste;
+ jeb->wasted_size += waste;
+ c->wasted_size += waste;
jffs2_close_nextblock(c, jeb);
jeb = NULL;
void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref)
{
struct jffs2_eraseblock *jeb;
- struct jffs2_raw_node_ref *next_ref;
int blocknr;
struct jffs2_unknown_node n;
int ret, addedsize;
size_t retlen;
uint32_t freed_len;
- if(!ref) {
+ if(unlikely(!ref)) {
printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n");
return;
}
// Take care, that wasted size is taken into concern
if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + freed_len)) && jeb != c->nextblock) {
- D1(printk(KERN_DEBUG "Dirtying\n"));
+ D1(printk("Dirtying\n"));
addedsize = freed_len;
jeb->dirty_size += freed_len;
c->dirty_size += freed_len;
}
}
} else {
- D1(printk(KERN_DEBUG "Wasting\n"));
+ D1(printk("Wasting\n"));
addedsize = 0;
jeb->wasted_size += freed_len;
c->wasted_size += freed_len;
/* The erase_free_sem is locked, and has been since before we marked the node obsolete
and potentially put its eraseblock onto the erase_pending_list. Thus, we know that
the block hasn't _already_ been erased, and that 'ref' itself hasn't been freed yet
- by jffs2_free_all_node_refs() in erase.c. Which is nice. */
+ by jffs2_free_jeb_node_refs() in erase.c. Which is nice. */
D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref_offset(ref)));
ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n);
spin_unlock(&c->erase_completion_lock);
}
-
- /* Merge with the next node in the physical list, if there is one
- and if it's also obsolete and if it doesn't belong to any inode */
- next_ref = ref_next(ref);
-
- if (next_ref && ref_obsolete(next_ref) && !next_ref->next_in_ino) {
- spin_lock(&c->erase_completion_lock);
-
-#ifdef TEST_TOTLEN
- ref->__totlen += next_ref->__totlen;
-#endif
- ref->next_phys = ref_next(next_ref);
- if (jeb->last_node == next_ref) jeb->last_node = ref;
- if (jeb->gc_node == next_ref) {
- /* gc will be happy continuing gc on this node */
- jeb->gc_node=ref;
- }
- spin_unlock(&c->erase_completion_lock);
-
- __jffs2_free_raw_node_ref(next_ref);
- }
-
- /* Also merge with the previous node in the list, if there is one
- and that one is obsolete */
- if (ref != jeb->first_node ) {
- struct jffs2_raw_node_ref *p = jeb->first_node;
-
- spin_lock(&c->erase_completion_lock);
-
- while ((next_ref = ref_next(ref)) != ref)
- p = next_ref;
-
- if (ref_obsolete(p) && !ref->next_in_ino) {
-#ifdef TEST_TOTLEN
- p->__totlen += ref->__totlen;
-#endif
- if (jeb->last_node == ref) {
- jeb->last_node = p;
- }
- if (jeb->gc_node == ref) {
- /* gc will be happy continuing gc on this node */
- jeb->gc_node=p;
- }
- p->next_phys = ref_next(ref);
- __jffs2_free_raw_node_ref(ref);
- }
- spin_unlock(&c->erase_completion_lock);
- }
out_erase_sem:
up(&c->erase_free_sem);
}