Commit 2f785402 authored by David Woodhouse's avatar David Woodhouse

[JFFS2] Reduce visibility of raw_node_ref to upper layers of JFFS2 code.

As the first step towards eliminating the ref->next_phys member and saving
memory by using an _array_ of struct jffs2_raw_node_ref per eraseblock,
stop the write functions from allocating their own refs; have them just
_reserve_ the appropriate number instead. Then jffs2_link_node_ref() can
just fill them in.

Use a linked list of pre-allocated refs in the superblock, for now. Once
we switch to an array, it'll just be a case of extending that array.
Signed-off-by: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent 4cbb9b80
...@@ -296,7 +296,7 @@ void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock * ...@@ -296,7 +296,7 @@ void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *
jffs2_remove_node_refs_from_ino_list(c, ref, jeb); jffs2_remove_node_refs_from_ino_list(c, ref, jeb);
/* else it was a non-inode node or already removed, so don't bother */ /* else it was a non-inode node or already removed, so don't bother */
jffs2_free_raw_node_ref(ref); __jffs2_free_raw_node_ref(ref);
} }
jeb->last_node = NULL; jeb->last_node = NULL;
} }
...@@ -351,7 +351,6 @@ fail: ...@@ -351,7 +351,6 @@ fail:
static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
{ {
struct jffs2_raw_node_ref *marker_ref = NULL;
size_t retlen; size_t retlen;
int ret; int ret;
uint32_t bad_offset; uint32_t bad_offset;
...@@ -384,11 +383,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb ...@@ -384,11 +383,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
.totlen = cpu_to_je32(c->cleanmarker_size) .totlen = cpu_to_je32(c->cleanmarker_size)
}; };
marker_ref = jffs2_alloc_raw_node_ref(); jffs2_prealloc_raw_node_refs(c, 1);
if (!marker_ref) {
printk(KERN_WARNING "Failed to allocate raw node ref for clean marker. Refiling\n");
goto refile;
}
marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4));
...@@ -404,16 +399,13 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb ...@@ -404,16 +399,13 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n", printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n",
jeb->offset, sizeof(marker), retlen); jeb->offset, sizeof(marker), retlen);
jffs2_free_raw_node_ref(marker_ref);
goto filebad; goto filebad;
} }
/* Everything else got zeroed before the erase */ /* Everything else got zeroed before the erase */
jeb->free_size = c->sector_size; jeb->free_size = c->sector_size;
/* FIXME Special case for cleanmarker in empty block */
marker_ref->flash_offset = jeb->offset | REF_NORMAL; jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size, NULL);
} }
spin_lock(&c->erase_completion_lock); spin_lock(&c->erase_completion_lock);
......
...@@ -528,7 +528,6 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, ...@@ -528,7 +528,6 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
struct jffs2_raw_node_ref *raw) struct jffs2_raw_node_ref *raw)
{ {
union jffs2_node_union *node; union jffs2_node_union *node;
struct jffs2_raw_node_ref *nraw;
size_t retlen; size_t retlen;
int ret; int ret;
uint32_t phys_ofs, alloclen; uint32_t phys_ofs, alloclen;
...@@ -618,30 +617,21 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, ...@@ -618,30 +617,21 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
} }
} }
nraw = jffs2_alloc_raw_node_ref();
if (!nraw) {
ret = -ENOMEM;
goto out_node;
}
/* OK, all the CRCs are good; this node can just be copied as-is. */ /* OK, all the CRCs are good; this node can just be copied as-is. */
retry: retry:
nraw->flash_offset = phys_ofs = write_ofs(c); phys_ofs = write_ofs(c);
ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node); ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node);
if (ret || (retlen != rawlen)) { if (ret || (retlen != rawlen)) {
printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n",
rawlen, nraw->flash_offset, ret, retlen); rawlen, phys_ofs, ret, retlen);
if (retlen) { if (retlen) {
nraw->flash_offset |= REF_OBSOLETE; jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
jffs2_add_physical_node_ref(c, nraw, rawlen, NULL);
jffs2_mark_node_obsolete(c, nraw);
} else { } else {
printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset); printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", phys_ofs);
jffs2_free_raw_node_ref(nraw);
} }
if (!retried && (nraw = jffs2_alloc_raw_node_ref())) { if (!retried) {
/* Try to reallocate space and retry */ /* Try to reallocate space and retry */
uint32_t dummy; uint32_t dummy;
struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size]; struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size];
...@@ -666,16 +656,13 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, ...@@ -666,16 +656,13 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
goto retry; goto retry;
} }
D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
jffs2_free_raw_node_ref(nraw);
} }
jffs2_free_raw_node_ref(nraw);
if (!ret) if (!ret)
ret = -EIO; ret = -EIO;
goto out_node; goto out_node;
} }
nraw->flash_offset |= REF_PRISTINE; jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, rawlen, ic);
jffs2_add_physical_node_ref(c, nraw, rawlen, ic);
jffs2_mark_node_obsolete(c, raw); jffs2_mark_node_obsolete(c, raw);
D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw))); D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw)));
......
...@@ -26,6 +26,9 @@ struct jffs2_inodirty; ...@@ -26,6 +26,9 @@ struct jffs2_inodirty;
struct jffs2_sb_info { struct jffs2_sb_info {
struct mtd_info *mtd; struct mtd_info *mtd;
struct jffs2_raw_node_ref *refs;
int reserved_refs;
uint32_t highest_ino; uint32_t highest_ino;
uint32_t checked_ino; uint32_t checked_ino;
......
...@@ -190,7 +190,29 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x) ...@@ -190,7 +190,29 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x)
kmem_cache_free(tmp_dnode_info_slab, x); kmem_cache_free(tmp_dnode_info_slab, x);
} }
struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, int nr)
{
struct jffs2_raw_node_ref *p = c->refs;
dbg_memalloc("%d\n", nr);
while (nr && p) {
p = p->next_in_ino;
nr--;
}
while (nr) {
p = __jffs2_alloc_raw_node_ref();
if (!p)
return -ENOMEM;
p->next_in_ino = c->refs;
c->refs = p;
nr--;
}
c->reserved_refs = nr;
return 0;
}
struct jffs2_raw_node_ref *__jffs2_alloc_raw_node_ref(void)
{ {
struct jffs2_raw_node_ref *ret; struct jffs2_raw_node_ref *ret;
ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL);
...@@ -198,7 +220,7 @@ struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) ...@@ -198,7 +220,7 @@ struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void)
return ret; return ret;
} }
void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) void __jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x)
{ {
dbg_memalloc("%p\n", x); dbg_memalloc("%p\n", x);
kmem_cache_free(raw_node_ref_slab, x); kmem_cache_free(raw_node_ref_slab, x);
......
...@@ -953,13 +953,19 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c) ...@@ -953,13 +953,19 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c)
for (i=0; i<c->nr_blocks; i++) { for (i=0; i<c->nr_blocks; i++) {
this = c->blocks[i].first_node; this = c->blocks[i].first_node;
while(this) { while (this) {
next = this->next_phys; next = this->next_phys;
jffs2_free_raw_node_ref(this); __jffs2_free_raw_node_ref(this);
this = next; this = next;
} }
c->blocks[i].first_node = c->blocks[i].last_node = NULL; c->blocks[i].first_node = c->blocks[i].last_node = NULL;
} }
this = c->refs;
while (this) {
next = this->next_in_ino;
__jffs2_free_raw_node_ref(this);
this = next;
}
} }
struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset) struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset)
...@@ -1047,10 +1053,27 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) ...@@ -1047,10 +1053,27 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c)
} }
} }
void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
struct jffs2_raw_node_ref *ref, uint32_t len, struct jffs2_eraseblock *jeb,
struct jffs2_inode_cache *ic) uint32_t ofs, uint32_t len,
struct jffs2_inode_cache *ic)
{ {
struct jffs2_raw_node_ref *ref;
/* These will be preallocated _very_ shortly. */
ref = c->refs;
if (!c->refs) {
JFFS2_WARNING("Using non-preallocated refs!\n");
ref = __jffs2_alloc_raw_node_ref();
BUG_ON(!ref);
WARN_ON(1);
} else {
c->refs = ref->next_in_ino;
}
ref->next_phys = NULL;
ref->flash_offset = ofs;
if (!jeb->first_node) if (!jeb->first_node)
jeb->first_node = ref; jeb->first_node = ref;
if (jeb->last_node) { if (jeb->last_node) {
...@@ -1093,15 +1116,15 @@ void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, ...@@ -1093,15 +1116,15 @@ void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
c->free_size -= len; c->free_size -= len;
jeb->free_size -= len; jeb->free_size -= len;
ref->next_phys = NULL;
#ifdef TEST_TOTLEN #ifdef TEST_TOTLEN
/* Set (and test) __totlen field... for now */ /* Set (and test) __totlen field... for now */
ref->__totlen = len; ref->__totlen = len;
ref_totlen(c, jeb, ref); ref_totlen(c, jeb, ref);
#endif #endif
return ref;
} }
/* No locking. Do not use on a live file system */ /* No locking, no reservation of 'ref'. Do not use on a live file system */
int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
uint32_t size) uint32_t size)
{ {
...@@ -1121,18 +1144,10 @@ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb ...@@ -1121,18 +1144,10 @@ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
jeb->dirty_size += size; jeb->dirty_size += size;
jeb->free_size -= size; jeb->free_size -= size;
} else { } else {
struct jffs2_raw_node_ref *ref; uint32_t ofs = jeb->offset + c->sector_size - jeb->free_size;
ref = jffs2_alloc_raw_node_ref(); ofs |= REF_OBSOLETE;
if (!ref)
return -ENOMEM;
ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size;
ref->flash_offset |= REF_OBSOLETE;
#ifdef TEST_TOTLEN
ref->__totlen = size;
#endif
jffs2_link_node_ref(c, jeb, ref, size, NULL); jffs2_link_node_ref(c, jeb, ofs, size, NULL);
} }
return 0; return 0;
......
...@@ -318,9 +318,10 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t ...@@ -318,9 +318,10 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t
int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn);
void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size);
int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn);
void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
struct jffs2_raw_node_ref *ref, uint32_t len, struct jffs2_eraseblock *jeb,
struct jffs2_inode_cache *ic); uint32_t ofs, uint32_t len,
struct jffs2_inode_cache *ic);
extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c,
struct jffs2_eraseblock *jeb, struct jffs2_eraseblock *jeb,
struct jffs2_raw_node_ref *ref); struct jffs2_raw_node_ref *ref);
...@@ -331,10 +332,9 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, ...@@ -331,10 +332,9 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
uint32_t *len, int prio, uint32_t sumsize); uint32_t *len, int prio, uint32_t sumsize);
int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
uint32_t *len, uint32_t sumsize); uint32_t *len, uint32_t sumsize);
int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
struct jffs2_raw_node_ref *new, uint32_t ofs, uint32_t len,
uint32_t len, struct jffs2_inode_cache *ic);
struct jffs2_inode_cache *ic);
void jffs2_complete_reservation(struct jffs2_sb_info *c); void jffs2_complete_reservation(struct jffs2_sb_info *c);
void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw);
...@@ -378,8 +378,9 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void); ...@@ -378,8 +378,9 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void);
void jffs2_free_raw_inode(struct jffs2_raw_inode *); void jffs2_free_raw_inode(struct jffs2_raw_inode *);
struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void); struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void);
void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *); void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *);
struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void); int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, int nr);
void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *); struct jffs2_raw_node_ref *__jffs2_alloc_raw_node_ref(void);
void __jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *);
struct jffs2_node_frag *jffs2_alloc_node_frag(void); struct jffs2_node_frag *jffs2_alloc_node_frag(void);
void jffs2_free_node_frag(struct jffs2_node_frag *); void jffs2_free_node_frag(struct jffs2_node_frag *);
struct jffs2_inode_cache *jffs2_alloc_inode_cache(void); struct jffs2_inode_cache *jffs2_alloc_inode_cache(void);
......
...@@ -137,6 +137,8 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, ...@@ -137,6 +137,8 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
} }
} }
spin_unlock(&c->erase_completion_lock); spin_unlock(&c->erase_completion_lock);
if (!ret)
ret = jffs2_prealloc_raw_node_refs(c, 1);
if (ret) if (ret)
up(&c->alloc_sem); up(&c->alloc_sem);
return ret; return ret;
...@@ -158,6 +160,9 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, ...@@ -158,6 +160,9 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
} }
} }
spin_unlock(&c->erase_completion_lock); spin_unlock(&c->erase_completion_lock);
if (!ret)
ret = jffs2_prealloc_raw_node_refs(c, 1);
return ret; return ret;
} }
...@@ -381,30 +386,30 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, ...@@ -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. * 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, struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
uint32_t len, struct jffs2_inode_cache *ic) uint32_t ofs, uint32_t len,
struct jffs2_inode_cache *ic)
{ {
struct jffs2_eraseblock *jeb; struct jffs2_eraseblock *jeb;
struct jffs2_raw_node_ref *new;
jeb = &c->blocks[new->flash_offset / c->sector_size]; jeb = &c->blocks[ofs / c->sector_size];
#ifdef TEST_TOTLEN
new->__totlen = len;
#endif
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 #if 1
/* we could get some obsolete nodes after nextblock was refiled /* Allow non-obsolete nodes only to be added at the end of c->nextblock,
in wbuf.c */ if c->nextblock is set. Note that wbuf.c will file obsolete nodes
if ((c->nextblock || !ref_obsolete(new)) even after refiling c->nextblock */
&&(jeb != c->nextblock || ref_offset(new) != jeb->offset + (c->sector_size - jeb->free_size))) { 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"); printk(KERN_WARNING "argh. node added in wrong place\n");
jffs2_free_raw_node_ref(new); return ERR_PTR(-EINVAL);
return -EINVAL;
} }
#endif #endif
spin_lock(&c->erase_completion_lock); 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 (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) {
/* If it lives on the dirty_list, jffs2_reserve_space will put it there */ /* 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 ...@@ -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); spin_unlock(&c->erase_completion_lock);
return 0; return new;
} }
...@@ -697,7 +702,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ...@@ -697,7 +702,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
} }
spin_unlock(&c->erase_completion_lock); spin_unlock(&c->erase_completion_lock);
jffs2_free_raw_node_ref(n); __jffs2_free_raw_node_ref(n);
} }
/* Also merge with the previous node in the list, if there is one /* Also merge with the previous node in the list, if there is one
...@@ -722,7 +727,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ...@@ -722,7 +727,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
jeb->gc_node=p; jeb->gc_node=p;
} }
p->next_phys = ref->next_phys; p->next_phys = ref->next_phys;
jffs2_free_raw_node_ref(ref); __jffs2_free_raw_node_ref(ref);
} }
spin_unlock(&c->erase_completion_lock); spin_unlock(&c->erase_completion_lock);
} }
......
...@@ -317,7 +317,6 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc ...@@ -317,7 +317,6 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
struct jffs2_summary *s) struct jffs2_summary *s)
{ {
struct jffs2_xattr_datum *xd; struct jffs2_xattr_datum *xd;
struct jffs2_raw_node_ref *raw;
uint32_t totlen, crc; uint32_t totlen, crc;
int err; int err;
...@@ -340,13 +339,8 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc ...@@ -340,13 +339,8 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
return 0; return 0;
} }
raw = jffs2_alloc_raw_node_ref();
if (!raw)
return -ENOMEM;
xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version)); xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version));
if (IS_ERR(xd)) { if (IS_ERR(xd)) {
jffs2_free_raw_node_ref(raw);
if (PTR_ERR(xd) == -EEXIST) { if (PTR_ERR(xd) == -EEXIST) {
if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rx->totlen))))) if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rx->totlen)))))
return err; return err;
...@@ -358,12 +352,9 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc ...@@ -358,12 +352,9 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
xd->name_len = rx->name_len; xd->name_len = rx->name_len;
xd->value_len = je16_to_cpu(rx->value_len); xd->value_len = je16_to_cpu(rx->value_len);
xd->data_crc = je32_to_cpu(rx->data_crc); xd->data_crc = je32_to_cpu(rx->data_crc);
xd->node = raw;
raw->flash_offset = ofs | REF_PRISTINE;
jffs2_link_node_ref(c, jeb, raw, totlen, NULL); xd->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL);
/* FIXME */ raw->next_in_ino = (void *)xd; /* FIXME */ xd->node->next_in_ino = (void *)xd;
if (jffs2_sum_active()) if (jffs2_sum_active())
jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset); jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
...@@ -377,7 +368,6 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock ...@@ -377,7 +368,6 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
struct jffs2_summary *s) struct jffs2_summary *s)
{ {
struct jffs2_xattr_ref *ref; struct jffs2_xattr_ref *ref;
struct jffs2_raw_node_ref *raw;
uint32_t crc; uint32_t crc;
int err; int err;
...@@ -404,12 +394,6 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock ...@@ -404,12 +394,6 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
if (!ref) if (!ref)
return -ENOMEM; return -ENOMEM;
raw = jffs2_alloc_raw_node_ref();
if (!raw) {
jffs2_free_xattr_ref(ref);
return -ENOMEM;
}
/* BEFORE jffs2_build_xattr_subsystem() called, /* BEFORE jffs2_build_xattr_subsystem() called,
* ref->xid is used to store 32bit xid, xd is not used * ref->xid is used to store 32bit xid, xd is not used
* ref->ino is used to store 32bit inode-number, ic is not used * ref->ino is used to store 32bit inode-number, ic is not used
...@@ -418,16 +402,13 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock ...@@ -418,16 +402,13 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
* used to chain all xattr_ref object. It's re-chained to * used to chain all xattr_ref object. It's re-chained to
* jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly. * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly.
*/ */
ref->node = raw;
ref->ino = je32_to_cpu(rr->ino); ref->ino = je32_to_cpu(rr->ino);
ref->xid = je32_to_cpu(rr->xid); ref->xid = je32_to_cpu(rr->xid);
ref->next = c->xref_temp; ref->next = c->xref_temp;
c->xref_temp = ref; c->xref_temp = ref;
raw->flash_offset = ofs | REF_PRISTINE; ref->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), NULL);
/* FIXME */ ref->node->next_in_ino = (void *)ref;
jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rr->totlen)), NULL);
/* FIXME */ raw->next_in_ino = (void *)ref;
if (jffs2_sum_active()) if (jffs2_sum_active())
jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset); jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
...@@ -597,6 +578,11 @@ scan_more: ...@@ -597,6 +578,11 @@ scan_more:
jffs2_dbg_acct_paranoia_check_nolock(c, jeb); jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
/* Make sure there are node refs available for use */
err = jffs2_prealloc_raw_node_refs(c, 2);
if (err)
return err;
cond_resched(); cond_resched();
if (ofs & 3) { if (ofs & 3) {
...@@ -839,14 +825,7 @@ scan_more: ...@@ -839,14 +825,7 @@ scan_more:
return err; return err;
ofs += PAD(sizeof(struct jffs2_unknown_node)); ofs += PAD(sizeof(struct jffs2_unknown_node));
} else { } else {
struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); jffs2_link_node_ref(c, jeb, ofs | REF_NORMAL, c->cleanmarker_size, NULL);
if (!marker_ref) {
printk(KERN_NOTICE "Failed to allocate node ref for clean marker\n");
return -ENOMEM;
}
marker_ref->flash_offset = ofs | REF_NORMAL;
jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size, NULL);
ofs += PAD(c->cleanmarker_size); ofs += PAD(c->cleanmarker_size);
} }
...@@ -884,14 +863,9 @@ scan_more: ...@@ -884,14 +863,9 @@ scan_more:
break; break;
case JFFS2_FEATURE_RWCOMPAT_COPY: { case JFFS2_FEATURE_RWCOMPAT_COPY: {
struct jffs2_raw_node_ref *ref;
D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
ref = jffs2_alloc_raw_node_ref(); jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(node->totlen)), NULL);
if (!ref)
return -ENOMEM;
ref->flash_offset = ofs | REF_PRISTINE;
jffs2_link_node_ref(c, jeb, ref, PAD(je32_to_cpu(node->totlen)), NULL);
/* We can't summarise nodes we don't grok */ /* We can't summarise nodes we don't grok */
jffs2_sum_disable_collecting(s); jffs2_sum_disable_collecting(s);
...@@ -953,7 +927,6 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin ...@@ -953,7 +927,6 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin
static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s)
{ {
struct jffs2_raw_node_ref *raw;
struct jffs2_inode_cache *ic; struct jffs2_inode_cache *ic;
uint32_t ino = je32_to_cpu(ri->ino); uint32_t ino = je32_to_cpu(ri->ino);
int err; int err;
...@@ -969,12 +942,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc ...@@ -969,12 +942,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
Which means that the _full_ amount of time to get to proper write mode with GC Which means that the _full_ amount of time to get to proper write mode with GC
operational may actually be _longer_ than before. Sucks to be me. */ operational may actually be _longer_ than before. Sucks to be me. */
raw = jffs2_alloc_raw_node_ref();
if (!raw) {
printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n");
return -ENOMEM;
}
ic = jffs2_get_ino_cache(c, ino); ic = jffs2_get_ino_cache(c, ino);
if (!ic) { if (!ic) {
/* Inocache get failed. Either we read a bogus ino# or it's just genuinely the /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the
...@@ -988,21 +955,15 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc ...@@ -988,21 +955,15 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
/* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen))))) if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen)))))
return err; return err;
jffs2_free_raw_node_ref(raw);
return 0; return 0;
} }
ic = jffs2_scan_make_ino_cache(c, ino); ic = jffs2_scan_make_ino_cache(c, ino);
if (!ic) { if (!ic)
jffs2_free_raw_node_ref(raw);
return -ENOMEM; return -ENOMEM;
}
} }
/* Wheee. It worked */ /* Wheee. It worked */
jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic);
raw->flash_offset = ofs | REF_UNCHECKED;
jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(ri->totlen)), ic);
D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n",
je32_to_cpu(ri->ino), je32_to_cpu(ri->version), je32_to_cpu(ri->ino), je32_to_cpu(ri->version),
...@@ -1021,7 +982,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc ...@@ -1021,7 +982,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s) struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s)
{ {
struct jffs2_raw_node_ref *raw;
struct jffs2_full_dirent *fd; struct jffs2_full_dirent *fd;
struct jffs2_inode_cache *ic; struct jffs2_inode_cache *ic;
uint32_t crc; uint32_t crc;
...@@ -1063,23 +1023,14 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo ...@@ -1063,23 +1023,14 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
return err; return err;
return 0; return 0;
} }
raw = jffs2_alloc_raw_node_ref();
if (!raw) {
jffs2_free_full_dirent(fd);
printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n");
return -ENOMEM;
}
ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino)); ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino));
if (!ic) { if (!ic) {
jffs2_free_full_dirent(fd); jffs2_free_full_dirent(fd);
jffs2_free_raw_node_ref(raw);
return -ENOMEM; return -ENOMEM;
} }
raw->flash_offset = ofs | REF_PRISTINE; fd->raw = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rd->totlen)), ic);
jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rd->totlen)), ic);
fd->raw = raw;
fd->next = NULL; fd->next = NULL;
fd->version = je32_to_cpu(rd->version); fd->version = je32_to_cpu(rd->version);
fd->ino = je32_to_cpu(rd->ino); fd->ino = je32_to_cpu(rd->ino);
......
This diff is collapsed.
...@@ -179,6 +179,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) ...@@ -179,6 +179,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
unsigned char *buf; unsigned char *buf;
uint32_t start, end, ofs, len; uint32_t start, end, ofs, len;
if (jffs2_prealloc_raw_node_refs(c, c->reserved_refs + 1))
return;
spin_lock(&c->erase_completion_lock); spin_lock(&c->erase_completion_lock);
jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
...@@ -306,17 +309,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) ...@@ -306,17 +309,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n"); printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
kfree(buf); kfree(buf);
if (retlen) { if (retlen)
struct jffs2_raw_node_ref *raw2; jffs2_add_physical_node_ref(c, ofs | REF_OBSOLETE, ref_totlen(c, jeb, *first_raw), NULL);
raw2 = jffs2_alloc_raw_node_ref();
if (!raw2)
return;
raw2->flash_offset = ofs | REF_OBSOLETE;
jffs2_add_physical_node_ref(c, raw2, ref_totlen(c, jeb, *first_raw), NULL);
}
return; return;
} }
printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs); printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs);
...@@ -428,6 +423,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) ...@@ -428,6 +423,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
if (!c->wbuf_len) /* already checked c->wbuf above */ if (!c->wbuf_len) /* already checked c->wbuf above */
return 0; return 0;
if (jffs2_prealloc_raw_node_refs(c, c->reserved_refs + 1))
return -ENOMEM;
/* claim remaining space on the page /* claim remaining space on the page
this happens, if we have a change to a new block, this happens, if we have a change to a new block,
or if fsync forces us to flush the writebuffer. or if fsync forces us to flush the writebuffer.
...@@ -485,7 +483,6 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) ...@@ -485,7 +483,6 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
/* Adjust free size of the block if we padded. */ /* Adjust free size of the block if we padded. */
if (pad) { if (pad) {
struct jffs2_eraseblock *jeb; struct jffs2_eraseblock *jeb;
struct jffs2_raw_node_ref *ref;
uint32_t waste = c->wbuf_pagesize - c->wbuf_len; uint32_t waste = c->wbuf_pagesize - c->wbuf_len;
jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
...@@ -503,15 +500,10 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) ...@@ -503,15 +500,10 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
jeb->offset, jeb->free_size); jeb->offset, jeb->free_size);
BUG(); BUG();
} }
ref = jffs2_alloc_raw_node_ref();
if (!ref)
return -ENOMEM;
ref->flash_offset = c->wbuf_ofs + c->wbuf_len;
ref->flash_offset |= REF_OBSOLETE;
spin_lock(&c->erase_completion_lock); spin_lock(&c->erase_completion_lock);
jffs2_link_node_ref(c, jeb, ref, waste, NULL); jffs2_link_node_ref(c, jeb, (c->wbuf_ofs + c->wbuf_len) | REF_OBSOLETE, waste, NULL);
/* FIXME: that made it count as dirty. Convert to wasted */ /* FIXME: that made it count as dirty. Convert to wasted */
jeb->dirty_size -= waste; jeb->dirty_size -= waste;
c->dirty_size -= waste; c->dirty_size -= waste;
......
...@@ -61,7 +61,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 ...@@ -61,7 +61,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
uint32_t datalen, int alloc_mode) uint32_t datalen, int alloc_mode)
{ {
struct jffs2_raw_node_ref *raw;
struct jffs2_full_dnode *fn; struct jffs2_full_dnode *fn;
size_t retlen; size_t retlen;
uint32_t flash_ofs; uint32_t flash_ofs;
...@@ -83,27 +82,16 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 ...@@ -83,27 +82,16 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) {
printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen);
} }
raw = jffs2_alloc_raw_node_ref();
if (!raw)
return ERR_PTR(-ENOMEM);
fn = jffs2_alloc_full_dnode(); fn = jffs2_alloc_full_dnode();
if (!fn) { if (!fn)
jffs2_free_raw_node_ref(raw);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
fn->ofs = je32_to_cpu(ri->offset);
fn->size = je32_to_cpu(ri->dsize);
fn->frags = 0;
/* check number of valid vecs */ /* check number of valid vecs */
if (!datalen || !data) if (!datalen || !data)
cnt = 1; cnt = 1;
retry: retry:
fn->raw = raw; flash_ofs = write_ofs(c);
raw->flash_offset = flash_ofs = write_ofs(c);
jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
...@@ -130,14 +118,11 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 ...@@ -130,14 +118,11 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
seem corrupted, in which case the scan would skip over seem corrupted, in which case the scan would skip over
any node we write before the original intended end of any node we write before the original intended end of
this node */ this node */
raw->flash_offset |= REF_OBSOLETE; jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*ri)+datalen), NULL);
jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), NULL);
jffs2_mark_node_obsolete(c, raw);
} else { } else {
printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs);
jffs2_free_raw_node_ref(raw);
} }
if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) { if (!retried && alloc_mode != ALLOC_NORETRY) {
/* Try to reallocate space and retry */ /* Try to reallocate space and retry */
uint32_t dummy; uint32_t dummy;
struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
...@@ -172,7 +157,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 ...@@ -172,7 +157,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
goto retry; goto retry;
} }
D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
jffs2_free_raw_node_ref(raw);
} }
/* Release the full_dnode which is now useless, and return */ /* Release the full_dnode which is now useless, and return */
jffs2_free_full_dnode(fn); jffs2_free_full_dnode(fn);
...@@ -186,14 +170,17 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 ...@@ -186,14 +170,17 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) ||
( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) &&
(je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) { (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) {
raw->flash_offset |= REF_PRISTINE; flash_ofs |= REF_PRISTINE;
} else { } else {
raw->flash_offset |= REF_NORMAL; flash_ofs |= REF_NORMAL;
} }
jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), f->inocache); fn->raw = jffs2_add_physical_node_ref(c, flash_ofs, PAD(sizeof(*ri)+datalen), f->inocache);
fn->ofs = je32_to_cpu(ri->offset);
fn->size = je32_to_cpu(ri->dsize);
fn->frags = 0;
D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n",
flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), flash_ofs & ~3, flash_ofs & 3, je32_to_cpu(ri->dsize),
je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc),
je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen)));
...@@ -208,11 +195,10 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff ...@@ -208,11 +195,10 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
struct jffs2_raw_dirent *rd, const unsigned char *name, struct jffs2_raw_dirent *rd, const unsigned char *name,
uint32_t namelen, int alloc_mode) uint32_t namelen, int alloc_mode)
{ {
struct jffs2_raw_node_ref *raw;
struct jffs2_full_dirent *fd; struct jffs2_full_dirent *fd;
size_t retlen; size_t retlen;
struct kvec vecs[2]; struct kvec vecs[2];
uint32_t flash_ofs = write_ofs(c); uint32_t flash_ofs;
int retried = 0; int retried = 0;
int ret; int ret;
...@@ -223,26 +209,16 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff ...@@ -223,26 +209,16 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) {
printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n");
BUG(); BUG();
} });
);
vecs[0].iov_base = rd; vecs[0].iov_base = rd;
vecs[0].iov_len = sizeof(*rd); vecs[0].iov_len = sizeof(*rd);
vecs[1].iov_base = (unsigned char *)name; vecs[1].iov_base = (unsigned char *)name;
vecs[1].iov_len = namelen; vecs[1].iov_len = namelen;
jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
raw = jffs2_alloc_raw_node_ref();
if (!raw)
return ERR_PTR(-ENOMEM);
fd = jffs2_alloc_full_dirent(namelen+1); fd = jffs2_alloc_full_dirent(namelen+1);
if (!fd) { if (!fd)
jffs2_free_raw_node_ref(raw);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
fd->version = je32_to_cpu(rd->version); fd->version = je32_to_cpu(rd->version);
fd->ino = je32_to_cpu(rd->ino); fd->ino = je32_to_cpu(rd->ino);
...@@ -252,9 +228,9 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff ...@@ -252,9 +228,9 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
fd->name[namelen]=0; fd->name[namelen]=0;
retry: retry:
fd->raw = raw; flash_ofs = write_ofs(c);
raw->flash_offset = flash_ofs; jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) { if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) {
BUG_ON(!retried); BUG_ON(!retried);
...@@ -273,14 +249,11 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff ...@@ -273,14 +249,11 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
sizeof(*rd)+namelen, flash_ofs, ret, retlen); sizeof(*rd)+namelen, flash_ofs, ret, retlen);
/* Mark the space as dirtied */ /* Mark the space as dirtied */
if (retlen) { if (retlen) {
raw->flash_offset |= REF_OBSOLETE; jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*rd)+namelen), NULL);
jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen), NULL);
jffs2_mark_node_obsolete(c, raw);
} else { } else {
printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs);
jffs2_free_raw_node_ref(raw);
} }
if (!retried && (raw = jffs2_alloc_raw_node_ref())) { if (!retried) {
/* Try to reallocate space and retry */ /* Try to reallocate space and retry */
uint32_t dummy; uint32_t dummy;
struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
...@@ -313,15 +286,13 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff ...@@ -313,15 +286,13 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
goto retry; goto retry;
} }
D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
jffs2_free_raw_node_ref(raw);
} }
/* Release the full_dnode which is now useless, and return */ /* Release the full_dnode which is now useless, and return */
jffs2_free_full_dirent(fd); jffs2_free_full_dirent(fd);
return ERR_PTR(ret?ret:-EIO); return ERR_PTR(ret?ret:-EIO);
} }
/* Mark the space used */ /* Mark the space used */
raw->flash_offset |= REF_PRISTINE; fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | REF_PRISTINE, PAD(sizeof(*rd)+namelen), f->inocache);
jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*rd)+namelen), f->inocache);
if (retried) { if (retried) {
jffs2_dbg_acct_sanity_check(c,NULL); jffs2_dbg_acct_sanity_check(c,NULL);
......
...@@ -304,8 +304,8 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x ...@@ -304,8 +304,8 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
{ {
/* must be called under down_write(xattr_sem) */ /* must be called under down_write(xattr_sem) */
struct jffs2_raw_xattr rx;
struct jffs2_raw_node_ref *raw; struct jffs2_raw_node_ref *raw;
struct jffs2_raw_xattr rx;
struct kvec vecs[2]; struct kvec vecs[2];
uint32_t length; uint32_t length;
int rc, totlen; int rc, totlen;
...@@ -319,11 +319,6 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x ...@@ -319,11 +319,6 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
vecs[1].iov_len = xd->name_len + 1 + xd->value_len; vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
totlen = vecs[0].iov_len + vecs[1].iov_len; totlen = vecs[0].iov_len + vecs[1].iov_len;
raw = jffs2_alloc_raw_node_ref();
if (!raw)
return -ENOMEM;
raw->flash_offset = phys_ofs;
/* Setup raw-xattr */ /* Setup raw-xattr */
rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR); rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
...@@ -343,19 +338,14 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x ...@@ -343,19 +338,14 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%u, at %#08x\n", JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%u, at %#08x\n",
rc, totlen, length, phys_ofs); rc, totlen, length, phys_ofs);
rc = rc ? rc : -EIO; rc = rc ? rc : -EIO;
if (length) { if (length)
raw->flash_offset |= REF_OBSOLETE; jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(totlen), NULL);
jffs2_add_physical_node_ref(c, raw, PAD(totlen), NULL);
jffs2_mark_node_obsolete(c, raw);
} else {
jffs2_free_raw_node_ref(raw);
}
return rc; return rc;
} }
/* success */ /* success */
raw->flash_offset |= REF_PRISTINE; raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), NULL);
jffs2_add_physical_node_ref(c, raw, PAD(totlen), NULL);
/* FIXME */ raw->next_in_ino = (void *)xd; /* FIXME */ raw->next_in_ino = (void *)xd;
if (xd->node) if (xd->node)
...@@ -563,11 +553,6 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) ...@@ -563,11 +553,6 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
uint32_t phys_ofs = write_ofs(c); uint32_t phys_ofs = write_ofs(c);
int ret; int ret;
raw = jffs2_alloc_raw_node_ref();
if (!raw)
return -ENOMEM;
raw->flash_offset = phys_ofs;
rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF); rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF);
rr.totlen = cpu_to_je32(PAD(sizeof(rr))); rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
...@@ -582,18 +567,13 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) ...@@ -582,18 +567,13 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
JFFS2_WARNING("jffs2_flash_write() returned %d, request=%u, retlen=%u, at %#08x\n", JFFS2_WARNING("jffs2_flash_write() returned %d, request=%u, retlen=%u, at %#08x\n",
ret, sizeof(rr), length, phys_ofs); ret, sizeof(rr), length, phys_ofs);
ret = ret ? ret : -EIO; ret = ret ? ret : -EIO;
if (length) { if (length)
raw->flash_offset |= REF_OBSOLETE; jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(sizeof(rr)), NULL);
jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr)), NULL);
jffs2_mark_node_obsolete(c, raw);
} else {
jffs2_free_raw_node_ref(raw);
}
return ret; return ret;
} }
raw->flash_offset |= REF_PRISTINE;
jffs2_add_physical_node_ref(c, raw, PAD(sizeof(rr)), NULL); raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), NULL);
/* FIXME */ raw->next_in_ino = (void *)ref; /* FIXME */ raw->next_in_ino = (void *)ref;
if (ref->node) if (ref->node)
delete_xattr_ref_node(c, ref); delete_xattr_ref_node(c, ref);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment