[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: David Woodhouse <dwmw2@infradead.org>
This commit is contained in:
David Woodhouse 2006-05-24 02:04:45 +01:00
parent 4cbb9b80e1
commit 2f785402f3
12 changed files with 205 additions and 350 deletions

View File

@ -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:
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
.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
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);

View File

@ -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,
} }
} }
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,
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)));

View File

@ -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;

View File

@ -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)
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);

View File

@ -955,11 +955,17 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c)
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)
} }
} }
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,
uint32_t ofs, uint32_t len,
struct jffs2_inode_cache *ic) 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,
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
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; jffs2_link_node_ref(c, jeb, ofs, size, NULL);
ref->flash_offset |= REF_OBSOLETE;
#ifdef TEST_TOTLEN
ref->__totlen = size;
#endif
jffs2_link_node_ref(c, jeb, ref, size, NULL);
} }
return 0; return 0;

View File

@ -318,8 +318,9 @@ 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,
uint32_t ofs, uint32_t len,
struct jffs2_inode_cache *ic); 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,
@ -331,9 +332,8 @@ 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);
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);

View File

@ -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,
} }
} }
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,
* 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
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
} }
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
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);
} }

View File

@ -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
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
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; xd->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL);
/* FIXME */ xd->node->next_in_ino = (void *)xd;
jffs2_link_node_ref(c, jeb, raw, totlen, NULL);
/* FIXME */ raw->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
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
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
* 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:
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:
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:
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
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
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
/* 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
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
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);

View File

@ -369,22 +369,18 @@ no_mem:
return -ENOMEM; return -ENOMEM;
} }
static struct jffs2_raw_node_ref *alloc_ref_at(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, static struct jffs2_raw_node_ref *sum_link_node_ref(struct jffs2_sb_info *c,
uint32_t offset) struct jffs2_eraseblock *jeb,
uint32_t ofs, uint32_t len,
struct jffs2_inode_cache *ic)
{ {
struct jffs2_raw_node_ref *ref;
/* If there was a gap, mark it dirty */ /* If there was a gap, mark it dirty */
if (offset > c->sector_size - jeb->free_size) { if ((ofs & ~3) > c->sector_size - jeb->free_size) {
int ret = jffs2_scan_dirty_space(c, jeb, offset - (c->sector_size - jeb->free_size)); /* Ew. Summary doesn't actually tell us explicitly about dirty space */
if (ret) jffs2_scan_dirty_space(c, jeb, (ofs & ~3) - (c->sector_size - jeb->free_size));
return NULL;
} }
ref = jffs2_alloc_raw_node_ref();
if (!ref)
return NULL;
ref->flash_offset = jeb->offset + offset; return jffs2_link_node_ref(c, jeb, jeb->offset + ofs, len, ic);
return ref;
} }
/* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */
@ -392,7 +388,6 @@ static struct jffs2_raw_node_ref *alloc_ref_at(struct jffs2_sb_info *c, struct j
static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
struct jffs2_raw_summary *summary, uint32_t *pseudo_random) struct jffs2_raw_summary *summary, uint32_t *pseudo_random)
{ {
struct jffs2_raw_node_ref *raw;
struct jffs2_inode_cache *ic; struct jffs2_inode_cache *ic;
struct jffs2_full_dirent *fd; struct jffs2_full_dirent *fd;
void *sp; void *sp;
@ -404,6 +399,11 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
for (i=0; i<je32_to_cpu(summary->sum_num); i++) { for (i=0; i<je32_to_cpu(summary->sum_num); i++) {
dbg_summary("processing summary index %d\n", i); dbg_summary("processing summary index %d\n", i);
/* Make sure there's a spare ref for dirty space */
err = jffs2_prealloc_raw_node_refs(c, 2);
if (err)
return err;
switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) {
case JFFS2_NODETYPE_INODE: { case JFFS2_NODETYPE_INODE: {
struct jffs2_sum_inode_flash *spi; struct jffs2_sum_inode_flash *spi;
@ -415,22 +415,14 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
jeb->offset + je32_to_cpu(spi->offset), jeb->offset + je32_to_cpu(spi->offset),
jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spu->totlen)); jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spu->totlen));
raw = alloc_ref_at(c, jeb, je32_to_cpu(spi->offset));
if (!raw) {
JFFS2_NOTICE("allocation of node reference failed\n");
return -ENOMEM;
}
ic = jffs2_scan_make_ino_cache(c, ino); ic = jffs2_scan_make_ino_cache(c, ino);
if (!ic) { if (!ic) {
JFFS2_NOTICE("scan_make_ino_cache failed\n"); JFFS2_NOTICE("scan_make_ino_cache failed\n");
jffs2_free_raw_node_ref(raw);
return -ENOMEM; return -ENOMEM;
} }
raw->flash_offset |= REF_UNCHECKED; sum_link_node_ref(c, jeb, je32_to_cpu(spi->offset) | REF_UNCHECKED,
PAD(je32_to_cpu(spi->totlen)), ic);
jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spi->totlen)), ic);
*pseudo_random += je32_to_cpu(spi->version); *pseudo_random += je32_to_cpu(spi->version);
@ -455,24 +447,15 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
memcpy(&fd->name, spd->name, spd->nsize); memcpy(&fd->name, spd->name, spd->nsize);
fd->name[spd->nsize] = 0; fd->name[spd->nsize] = 0;
raw = alloc_ref_at(c, jeb, je32_to_cpu(spd->offset));
if (!raw) {
jffs2_free_full_dirent(fd);
JFFS2_NOTICE("allocation of node reference failed\n");
return -ENOMEM;
}
ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->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 |= REF_PRISTINE; fd->raw = sum_link_node_ref(c, jeb, je32_to_cpu(spd->offset) | REF_PRISTINE,
jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spd->totlen)), ic); PAD(je32_to_cpu(spd->totlen)), ic);
fd->raw = raw;
fd->next = NULL; fd->next = NULL;
fd->version = je32_to_cpu(spd->version); fd->version = je32_to_cpu(spd->version);
fd->ino = je32_to_cpu(spd->ino); fd->ino = je32_to_cpu(spd->ino);
@ -497,15 +480,10 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
jeb->offset + je32_to_cpu(spx->offset), jeb->offset + je32_to_cpu(spx->offset),
jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen), jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen),
je32_to_cpu(spx->xid), je32_to_cpu(spx->version)); je32_to_cpu(spx->xid), je32_to_cpu(spx->version));
raw = alloc_ref_at(c, jeb, je32_to_cpu(spx->offset));
if (!raw) {
JFFS2_NOTICE("allocation of node reference failed\n");
return -ENOMEM;
}
xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid), xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
je32_to_cpu(spx->version)); je32_to_cpu(spx->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) {
/* a newer version of xd exists */ /* a newer version of xd exists */
if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen)))) if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen))))
@ -516,12 +494,10 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
JFFS2_NOTICE("allocation of xattr_datum failed\n"); JFFS2_NOTICE("allocation of xattr_datum failed\n");
return PTR_ERR(xd); return PTR_ERR(xd);
} }
xd->node = raw;
raw->flash_offset |= REF_UNCHECKED; xd->node = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
PAD(je32_to_cpu(spx->totlen)), NULL);
jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spx->totlen)), NULL); /* FIXME */ xd->node->next_in_ino = (void *)xd;
/* FIXME */ raw->next_in_ino = (void *)xd;
*pseudo_random += je32_to_cpu(spx->xid); *pseudo_random += je32_to_cpu(spx->xid);
sp += JFFS2_SUMMARY_XATTR_SIZE; sp += JFFS2_SUMMARY_XATTR_SIZE;
@ -537,29 +513,21 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
jeb->offset + je32_to_cpu(spr->offset), jeb->offset + je32_to_cpu(spr->offset),
jeb->offset + je32_to_cpu(spr->offset) + PAD(sizeof(struct jffs2_raw_xref))); jeb->offset + je32_to_cpu(spr->offset) + PAD(sizeof(struct jffs2_raw_xref)));
raw = alloc_ref_at(c, jeb, je32_to_cpu(spr->offset));
if (!raw) {
JFFS2_NOTICE("allocation of node reference failed\n");
return -ENOMEM;
}
ref = jffs2_alloc_xattr_ref(); ref = jffs2_alloc_xattr_ref();
if (!ref) { if (!ref) {
JFFS2_NOTICE("allocation of xattr_datum failed\n"); JFFS2_NOTICE("allocation of xattr_datum failed\n");
jffs2_free_raw_node_ref(raw);
return -ENOMEM; return -ENOMEM;
} }
ref->ino = 0xfffffffe; ref->ino = 0xfffffffe;
ref->xid = 0xfffffffd; ref->xid = 0xfffffffd;
ref->node = raw;
ref->next = c->xref_temp; ref->next = c->xref_temp;
c->xref_temp = ref; c->xref_temp = ref;
raw->flash_offset |= REF_UNCHECKED; ref->node = sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED,
PAD(sizeof(struct jffs2_raw_xref)), NULL);
/* FIXME */ ref->node->next_in_ino = (void *)ref;
jffs2_link_node_ref(c, jeb, raw, PAD(sizeof(struct jffs2_raw_xref)), NULL); *pseudo_random += ref->node->flash_offset;
/* FIXME */ raw->next_in_ino = (void *)ref;
*pseudo_random += raw->flash_offset;
sp += JFFS2_SUMMARY_XREF_SIZE; sp += JFFS2_SUMMARY_XREF_SIZE;
break; break;
@ -584,7 +552,6 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
} }
} }
} }
return 0; return 0;
} }
@ -594,7 +561,6 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
uint32_t *pseudo_random) uint32_t *pseudo_random)
{ {
struct jffs2_unknown_node crcnode; struct jffs2_unknown_node crcnode;
struct jffs2_raw_node_ref *cache_ref;
int ret, ofs; int ret, ofs;
uint32_t crc; uint32_t crc;
int err; int err;
@ -650,16 +616,8 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr))))) if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
return err; return err;
} else { } else {
struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL,
je32_to_cpu(summary->cln_mkr), NULL);
if (!marker_ref) {
JFFS2_NOTICE("Failed to allocate node ref for clean marker\n");
return -ENOMEM;
}
marker_ref->flash_offset = jeb->offset | REF_NORMAL;
jffs2_link_node_ref(c, jeb, marker_ref, je32_to_cpu(summary->cln_mkr), NULL);
} }
} }
@ -672,16 +630,11 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
return ret; /* real error */ return ret; /* real error */
/* for PARANOIA_CHECK */ /* for PARANOIA_CHECK */
cache_ref = alloc_ref_at(c, jeb, ofs); ret = jffs2_prealloc_raw_node_refs(c, 1);
if (ret)
return ret;
if (!cache_ref) { jffs2_link_node_ref(c, jeb, (jeb->offset + ofs) | REF_NORMAL, sumsize, NULL);
JFFS2_NOTICE("Failed to allocate node ref for cache\n");
return -ENOMEM;
}
cache_ref->flash_offset |= REF_NORMAL;
jffs2_link_node_ref(c, jeb, cache_ref, sumsize, NULL);
if (unlikely(jeb->free_size)) { if (unlikely(jeb->free_size)) {
JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n", JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n",
@ -709,6 +662,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
union jffs2_sum_mem *temp; union jffs2_sum_mem *temp;
struct jffs2_sum_marker *sm; struct jffs2_sum_marker *sm;
struct kvec vecs[2]; struct kvec vecs[2];
uint32_t sum_ofs;
void *wpage; void *wpage;
int ret; int ret;
size_t retlen; size_t retlen;
@ -821,36 +775,31 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
vecs[1].iov_base = c->summary->sum_buf; vecs[1].iov_base = c->summary->sum_buf;
vecs[1].iov_len = datasize; vecs[1].iov_len = datasize;
dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n", sum_ofs = jeb->offset + c->sector_size - jeb->free_size;
jeb->offset + c->sector_size - jeb->free_size);
spin_unlock(&c->erase_completion_lock); dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n",
ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size - sum_ofs);
jeb->free_size, &retlen, 0);
ret = jffs2_flash_writev(c, vecs, 2, sum_ofs, &retlen, 0);
if (ret || (retlen != infosize)) { if (ret || (retlen != infosize)) {
struct jffs2_raw_node_ref *ref;
JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n", JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n",
infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen); infosize, sum_ofs, ret, retlen);
/* Waste remaining space */ /* Waste remaining space */
ref = jffs2_alloc_raw_node_ref();
if (ref) {
spin_lock(&c->erase_completion_lock); spin_lock(&c->erase_completion_lock);
jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL);
ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size; spin_unlock(&c->erase_completion_lock);
ref->flash_offset |= REF_OBSOLETE;
jffs2_link_node_ref(c, jeb, ref, c->sector_size - jeb->free_size, NULL);
}
c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
return 1; return 0;
} }
spin_lock(&c->erase_completion_lock); spin_lock(&c->erase_completion_lock);
jffs2_link_node_ref(c, jeb, sum_ofs | REF_NORMAL, infosize, NULL);
spin_unlock(&c->erase_completion_lock);
return 0; return 0;
} }
@ -859,12 +808,15 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
{ {
struct jffs2_raw_node_ref *summary_ref; int datasize, infosize, padsize;
int datasize, infosize, padsize, ret;
struct jffs2_eraseblock *jeb; struct jffs2_eraseblock *jeb;
int ret;
dbg_summary("called\n"); dbg_summary("called\n");
spin_unlock(&c->erase_completion_lock);
jffs2_prealloc_raw_node_refs(c, 1);
jeb = c->nextblock; jeb = c->nextblock;
if (!c->summary->sum_num || !c->summary->sum_list_head) { if (!c->summary->sum_num || !c->summary->sum_list_head) {
@ -888,22 +840,6 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
} }
ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize);
if (ret)
return 0; /* can't write out summary, block is marked as NOSUM_SIZE */
/* for ACCT_PARANOIA_CHECK */
spin_unlock(&c->erase_completion_lock);
summary_ref = jffs2_alloc_raw_node_ref();
if (!summary_ref) {
JFFS2_NOTICE("Failed to allocate node ref for summary\n");
return -ENOMEM;
}
summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL;
spin_lock(&c->erase_completion_lock); spin_lock(&c->erase_completion_lock);
jffs2_link_node_ref(c, jeb, summary_ref, infosize, NULL); return ret;
return 0;
} }

View File

@ -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)
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)
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)
/* 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)
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;

View File

@ -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
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
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
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
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
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
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
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
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
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);

View File

@ -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
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
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)
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)
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);