summaryrefslogtreecommitdiffstats
path: root/fs/jffs2/nodemgmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2/nodemgmt.c')
-rw-r--r--fs/jffs2/nodemgmt.c59
1 files changed, 32 insertions, 27 deletions
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 8feb8749bc75..f4649c275fbe 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -137,6 +137,8 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
}
}
spin_unlock(&c->erase_completion_lock);
+ if (!ret)
+ ret = jffs2_prealloc_raw_node_refs(c, 1);
if (ret)
up(&c->alloc_sem);
return ret;
@@ -158,6 +160,9 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
}
}
spin_unlock(&c->erase_completion_lock);
+ if (!ret)
+ ret = jffs2_prealloc_raw_node_refs(c, 1);
+
return ret;
}
@@ -381,30 +386,30 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
* Must be called with the alloc_sem held.
*/
-int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new,
- uint32_t len, struct jffs2_inode_cache *ic)
+struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
+ uint32_t ofs, uint32_t len,
+ struct jffs2_inode_cache *ic)
{
struct jffs2_eraseblock *jeb;
+ struct jffs2_raw_node_ref *new;
- jeb = &c->blocks[new->flash_offset / c->sector_size];
-#ifdef TEST_TOTLEN
- new->__totlen = len;
-#endif
+ jeb = &c->blocks[ofs / c->sector_size];
- D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len));
+ D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n",
+ ofs & ~3, ofs & 3, len));
#if 1
- /* we could get some obsolete nodes after nextblock was refiled
- in wbuf.c */
- if ((c->nextblock || !ref_obsolete(new))
- &&(jeb != c->nextblock || ref_offset(new) != jeb->offset + (c->sector_size - jeb->free_size))) {
+ /* Allow non-obsolete nodes only to be added at the end of c->nextblock,
+ if c->nextblock is set. Note that wbuf.c will file obsolete nodes
+ even after refiling c->nextblock */
+ if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
+ && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
printk(KERN_WARNING "argh. node added in wrong place\n");
- jffs2_free_raw_node_ref(new);
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
#endif
spin_lock(&c->erase_completion_lock);
- jffs2_link_node_ref(c, jeb, new, len, ic);
+ new = jffs2_link_node_ref(c, jeb, ofs, len, ic);
if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) {
/* If it lives on the dirty_list, jffs2_reserve_space will put it there */
@@ -425,7 +430,7 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_r
spin_unlock(&c->erase_completion_lock);
- return 0;
+ return new;
}
@@ -453,6 +458,7 @@ static inline int on_list(struct list_head *obj, struct list_head *head)
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;
@@ -680,24 +686,23 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
/* 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 */
- if (ref->next_phys && ref_obsolete(ref->next_phys) &&
- !ref->next_phys->next_in_ino) {
- struct jffs2_raw_node_ref *n = ref->next_phys;
+ 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 += n->__totlen;
+ ref->__totlen += next_ref->__totlen;
#endif
- ref->next_phys = n->next_phys;
- if (jeb->last_node == n) jeb->last_node = ref;
- if (jeb->gc_node == n) {
+ 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(n);
+ __jffs2_free_raw_node_ref(next_ref);
}
/* Also merge with the previous node in the list, if there is one
@@ -707,8 +712,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
spin_lock(&c->erase_completion_lock);
- while (p->next_phys != ref)
- p = p->next_phys;
+ while ((next_ref = ref_next(ref)) != ref)
+ p = next_ref;
if (ref_obsolete(p) && !ref->next_in_ino) {
#ifdef TEST_TOTLEN
@@ -721,8 +726,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
/* gc will be happy continuing gc on this node */
jeb->gc_node=p;
}
- p->next_phys = ref->next_phys;
- jffs2_free_raw_node_ref(ref);
+ p->next_phys = ref_next(ref);
+ __jffs2_free_raw_node_ref(ref);
}
spin_unlock(&c->erase_completion_lock);
}
OpenPOWER on IntegriCloud