Skip to content

Commit

Permalink
[JFFS2] Reduce visibility of raw_node_ref to upper layers of JFFS2 code.
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
dwmw2 committed May 24, 2006
1 parent 4cbb9b8 commit 2f78540
Show file tree
Hide file tree
Showing 12 changed files with 204 additions and 349 deletions.
16 changes: 4 additions & 12 deletions fs/jffs2/erase.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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));

Expand All @@ -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);
Expand Down
25 changes: 6 additions & 19 deletions fs/jffs2/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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];
Expand All @@ -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)));
Expand Down
3 changes: 3 additions & 0 deletions fs/jffs2/jffs2_fs_sb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
26 changes: 24 additions & 2 deletions fs/jffs2/malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,37 @@ 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);
dbg_memalloc("%p\n", 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);
kmem_cache_free(raw_node_ref_slab, x);
Expand Down
51 changes: 33 additions & 18 deletions fs/jffs2/nodelist.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
{
Expand All @@ -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;
Expand Down
19 changes: 10 additions & 9 deletions fs/jffs2/nodelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);

Expand Down Expand Up @@ -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);
Expand Down
39 changes: 22 additions & 17 deletions fs/jffs2/nodemgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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 */
Expand All @@ -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;
}


Expand Down Expand Up @@ -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
Expand All @@ -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);
}
Expand Down
Loading

0 comments on commit 2f78540

Please sign in to comment.