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 *
jffs2_remove_node_refs_from_ino_list(c, ref, jeb);
/* 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;
}
......@@ -351,7 +351,6 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
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;
int ret;
uint32_t bad_offset;
......@@ -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)
};
marker_ref = jffs2_alloc_raw_node_ref();
if (!marker_ref) {
printk(KERN_WARNING "Failed to allocate raw node ref for clean marker. Refiling\n");
goto refile;
}
jffs2_prealloc_raw_node_refs(c, 1);
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
printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n",
jeb->offset, sizeof(marker), retlen);
jffs2_free_raw_node_ref(marker_ref);
goto filebad;
}
/* Everything else got zeroed before the erase */
jeb->free_size = c->sector_size;
marker_ref->flash_offset = jeb->offset | REF_NORMAL;
jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size, NULL);
/* FIXME Special case for cleanmarker in empty block */
jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
}
spin_lock(&c->erase_completion_lock);
......
......@@ -528,7 +528,6 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
struct jffs2_raw_node_ref *raw)
{
union jffs2_node_union *node;
struct jffs2_raw_node_ref *nraw;
size_t retlen;
int ret;
uint32_t phys_ofs, alloclen;
......@@ -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. */
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);
if (ret || (retlen != rawlen)) {
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) {
nraw->flash_offset |= REF_OBSOLETE;
jffs2_add_physical_node_ref(c, nraw, rawlen, NULL);
jffs2_mark_node_obsolete(c, nraw);
jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
} else {
printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset);
jffs2_free_raw_node_ref(nraw);
printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", phys_ofs);
}
if (!retried && (nraw = jffs2_alloc_raw_node_ref())) {
if (!retried) {
/* Try to reallocate space and retry */
uint32_t dummy;
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,
goto retry;
}
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)
ret = -EIO;
goto out_node;
}
nraw->flash_offset |= REF_PRISTINE;
jffs2_add_physical_node_ref(c, nraw, rawlen, ic);
jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, rawlen, ic);
jffs2_mark_node_obsolete(c, 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;
struct jffs2_sb_info {
struct mtd_info *mtd;
struct jffs2_raw_node_ref *refs;
int reserved_refs;
uint32_t highest_ino;
uint32_t checked_ino;
......
......@@ -190,7 +190,29 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *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;
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)
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);
kmem_cache_free(raw_node_ref_slab, x);
......
......@@ -953,13 +953,19 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c)
for (i=0; i<c->nr_blocks; i++) {
this = c->blocks[i].first_node;
while(this) {
while (this) {
next = this->next_phys;
jffs2_free_raw_node_ref(this);
__jffs2_free_raw_node_ref(this);
this = next;
}
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)
......@@ -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 *ref, uint32_t len,
struct jffs2_inode_cache *ic)
struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
struct jffs2_eraseblock *jeb,
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)
jeb->first_node = ref;
if (jeb->last_node) {
......@@ -1093,15 +1116,15 @@ void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
c->free_size -= len;
jeb->free_size -= len;
ref->next_phys = NULL;
#ifdef TEST_TOTLEN
/* Set (and test) __totlen field... for now */
ref->__totlen = len;
ref_totlen(c, jeb, ref);
#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,
uint32_t size)
{
......@@ -1121,18 +1144,10 @@ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
jeb->dirty_size += size;
jeb->free_size -= size;
} else {
struct jffs2_raw_node_ref *ref;
ref = jffs2_alloc_raw_node_ref();
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
uint32_t ofs = jeb->offset + c->sector_size - jeb->free_size;
ofs |= REF_OBSOLETE;
jffs2_link_node_ref(c, jeb, ref, size, NULL);
jffs2_link_node_ref(c, jeb, ofs, size, NULL);
}
return 0;
......
......@@ -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);
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);
void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
struct jffs2_raw_node_ref *ref, uint32_t len,
struct jffs2_inode_cache *ic);
struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
struct jffs2_eraseblock *jeb,
uint32_t ofs, uint32_t len,
struct jffs2_inode_cache *ic);
extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c,
struct jffs2_eraseblock *jeb,
struct jffs2_raw_node_ref *ref);
......@@ -331,10 +332,9 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
uint32_t *len, int prio, uint32_t sumsize);
int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
uint32_t *len, uint32_t sumsize);
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);
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);
......@@ -378,8 +378,9 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void);
void jffs2_free_raw_inode(struct jffs2_raw_inode *);
struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void);
void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *);
struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void);
void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *);
int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, int nr);
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);
void jffs2_free_node_frag(struct jffs2_node_frag *);
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,
}
}
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;
}
......@@ -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);
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
......@@ -722,7 +727,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
jeb->gc_node=p;
}
p->next_phys = ref->next_phys;
jffs2_free_raw_node_ref(ref);
__jffs2_free_raw_node_ref(ref);
}
spin_unlock(&c->erase_completion_lock);
}
......
......@@ -317,7 +317,6 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
struct jffs2_summary *s)
{
struct jffs2_xattr_datum *xd;
struct jffs2_raw_node_ref *raw;
uint32_t totlen, crc;
int err;
......@@ -340,13 +339,8 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
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));
if (IS_ERR(xd)) {
jffs2_free_raw_node_ref(raw);
if (PTR_ERR(xd) == -EEXIST) {
if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rx->totlen)))))
return err;
......@@ -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->value_len = je16_to_cpu(rx->value_len);
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);
/* FIXME */ raw->next_in_ino = (void *)xd;
xd->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL);
/* FIXME */ xd->node->next_in_ino = (void *)xd;
if (jffs2_sum_active())
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
struct jffs2_summary *s)
{
struct jffs2_xattr_ref *ref;
struct jffs2_raw_node_ref *raw;
uint32_t crc;
int err;
......@@ -404,12 +394,6 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock
if (!ref)
return -ENOMEM;
raw = jffs2_alloc_raw_node_ref();
if (!raw) {
jffs2_free_xattr_ref(ref);
return -ENOMEM;
}
/* BEFORE jffs2_build_xattr_subsystem() called,
* 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
......@@ -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
* jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly.
*/
ref->node = raw;
ref->ino = je32_to_cpu(rr->ino);
ref->xid = je32_to_cpu(rr->xid);
ref->next = c->xref_temp;
c->xref_temp = ref;
raw->flash_offset = ofs | REF_PRISTINE;
jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rr->totlen)), NULL);
/* FIXME */ raw->next_in_ino = (void *)ref;
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;
if (jffs2_sum_active())
jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
......@@ -597,6 +578,11 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
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();
if (ofs & 3) {
......@@ -839,14 +825,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
return err;
ofs += PAD(sizeof(struct jffs2_unknown_node));
} else {
struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref();
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);
jffs2_link_node_ref(c, jeb, ofs | REF_NORMAL, c->cleanmarker_size, NULL);
ofs += PAD(c->cleanmarker_size);
}
......@@ -884,14 +863,9 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
break;
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));
ref = jffs2_alloc_raw_node_ref();
if (!ref)
return -ENOMEM;
ref->flash_offset = ofs | REF_PRISTINE;
jffs2_link_node_ref(c, jeb, ref, PAD(je32_to_cpu(node->totlen)), NULL);
jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(node->totlen)), NULL);
/* We can't summarise nodes we don't grok */
jffs2_sum_disable_collecting(s);
......@@ -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,
struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s)
{
struct jffs2_raw_node_ref *raw;
struct jffs2_inode_cache *ic;
uint32_t ino = je32_to_cpu(ri->ino);
int err;
......@@ -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
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);
if (!ic) {
/* 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
/* 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)))))
return err;
jffs2_free_raw_node_ref(raw);
return 0;
}
ic = jffs2_scan_make_ino_cache(c, ino);
if (!ic) {
jffs2_free_raw_node_ref(raw);
if (!ic)
return -ENOMEM;
}
}
/* Wheee. It worked */
raw->flash_offset = ofs | REF_UNCHECKED;
jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(ri->totlen)), ic);
jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic);
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),
......@@ -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,
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_inode_cache *ic;
uint32_t crc;
......@@ -1063,23 +1023,14 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
return err;
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));
if (!ic) {
jffs2_free_full_dirent(fd);
jffs2_free_raw_node_ref(raw);
return -ENOMEM;
}
raw->flash_offset = ofs | REF_PRISTINE;
jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(rd->totlen)), ic);
fd->raw = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rd->totlen)), ic);
fd->raw = raw;
fd->next = NULL;
fd->version = je32_to_cpu(rd->version);
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)
unsigned char *buf;
uint32_t start, end, ofs, len;
if (jffs2_prealloc_raw_node_refs(c, c->reserved_refs + 1))
return;
spin_lock(&c->erase_completion_lock);
jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
......@@ -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");
kfree(buf);
if (retlen) {
struct jffs2_raw_node_ref *raw2;
raw2 = jffs2_alloc_raw_node_ref();
if (!raw2)
return;
raw2->flash_offset = ofs | REF_OBSOLETE;
if (retlen)
jffs2_add_physical_node_ref(c, ofs | REF_OBSOLETE, ref_totlen(c, jeb, *first_raw), NULL);
jffs2_add_physical_node_ref(c, raw2, ref_totlen(c, jeb, *first_raw), NULL);
}
return;
}
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)
if (!c->wbuf_len) /* already checked c->wbuf above */
return 0;
if (jffs2_prealloc_raw_node_refs(c, c->reserved_refs + 1))
return -ENOMEM;
/* claim remaining space on the page
this happens, if we have a change to a new block,
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)
/* Adjust free size of the block if we padded. */
if (pad) {
struct jffs2_eraseblock *jeb;
struct jffs2_raw_node_ref *ref;
uint32_t waste = c->wbuf_pagesize - c->wbuf_len;
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)
jeb->offset, jeb->free_size);
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);
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 */
jeb->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
uint32_t datalen, int alloc_mode)
{
struct jffs2_raw_node_ref *raw;
struct jffs2_full_dnode *fn;
size_t retlen;
uint32_t flash_ofs;
......@@ -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) {
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();
if (!fn) {
jffs2_free_raw_node_ref(raw);
if (!fn)
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 */
if (!datalen || !data)
cnt = 1;
retry:
fn->raw = raw;
raw->flash_offset = flash_ofs = write_ofs(c);
flash_ofs = write_ofs(c);
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
seem corrupted, in which case the scan would skip over
any node we write before the original intended end of
this node */
raw->flash_offset |= REF_OBSOLETE;
jffs2_add_physical_node_ref(c, raw, PAD(sizeof(*ri)+datalen), NULL);
jffs2_mark_node_obsolete(c, raw);
jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*ri)+datalen), NULL);
} else {
printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
jffs2_free_raw_node_ref(raw);
printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs);
}
if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) {
if (!retried && alloc_mode != ALLOC_NORETRY) {
/* Try to reallocate space and retry */
uint32_t dummy;
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
goto retry;
}
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 */
jffs2_free_full_dnode(fn);
......@@ -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) ||
( ((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)))) {
raw->flash_offset |= REF_PRISTINE;
flash_ofs |= REF_PRISTINE;
} 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",
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->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
struct jffs2_raw_dirent *rd, const unsigned char *name,
uint32_t namelen, int alloc_mode)
{
struct jffs2_raw_node_ref *raw;
struct jffs2_full_dirent *fd;
size_t retlen;
struct kvec vecs[2];
uint32_t flash_ofs = write_ofs(c);
uint32_t flash_ofs;
int retried = 0;
int ret