Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 27862
b: refs/heads/master
c: 9a57d47
h: refs/heads/master
v: v3
  • Loading branch information
Thomas Gleixner committed May 23, 2006
1 parent c68c48a commit 3d518fd
Show file tree
Hide file tree
Showing 15 changed files with 380 additions and 236 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 99988f7bbd16b861590dda4631c4db6cb17b5091
refs/heads/master: 9a57d470fd4a77b9732fee97bed29c565c730af0
14 changes: 7 additions & 7 deletions trunk/fs/jffs2/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,13 @@ __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
else
my_dirty_size += totlen;

if ((!ref_next(ref2)) != (ref2 == jeb->last_node)) {
JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
ref_offset(ref2), ref2, ref_offset(ref_next(ref2)), ref_next(ref2),
ref_offset(jeb->last_node), jeb->last_node);
if ((!ref2->next_phys) != (ref2 == jeb->last_node)) {
JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys,
ref_offset(jeb->last_node), jeb->last_node);
goto error;
}
ref2 = ref_next(ref2);
ref2 = ref2->next_phys;
}

if (my_used_size != jeb->used_size) {
Expand Down Expand Up @@ -268,9 +268,9 @@ __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
}

printk(JFFS2_DBG);
for (ref = jeb->first_node; ; ref = ref_next(ref)) {
for (ref = jeb->first_node; ; ref = ref->next_phys) {
printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
if (ref_next(ref))
if (ref->next_phys)
printk("->");
else
break;
Expand Down
16 changes: 12 additions & 4 deletions trunk/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,6 +351,7 @@ 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 @@ -383,7 +384,11 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
.totlen = cpu_to_je32(c->cleanmarker_size)
};

jffs2_prealloc_raw_node_refs(c, 1);
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;
}

marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4));

Expand All @@ -399,13 +404,16 @@ 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;
/* FIXME Special case for cleanmarker in empty block */
jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);

marker_ref->flash_offset = jeb->offset | REF_NORMAL;

jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size, NULL);
}

spin_lock(&c->erase_completion_lock);
Expand Down
27 changes: 20 additions & 7 deletions trunk/fs/jffs2/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)

while(ref_obsolete(raw)) {
D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw)));
raw = ref_next(raw);
raw = raw->next_phys;
if (unlikely(!raw)) {
printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n");
printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n",
Expand Down Expand Up @@ -528,6 +528,7 @@ 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 @@ -617,21 +618,30 @@ 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:
phys_ofs = write_ofs(c);
nraw->flash_offset = 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, phys_ofs, ret, retlen);
rawlen, nraw->flash_offset, ret, retlen);
if (retlen) {
jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
nraw->flash_offset |= REF_OBSOLETE;
jffs2_add_physical_node_ref(c, nraw, rawlen, NULL);
jffs2_mark_node_obsolete(c, nraw);
} else {
printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", phys_ofs);
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);
}
if (!retried) {
if (!retried && (nraw = jffs2_alloc_raw_node_ref())) {
/* Try to reallocate space and retry */
uint32_t dummy;
struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size];
Expand All @@ -656,13 +666,16 @@ 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;
}
jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, rawlen, ic);
nraw->flash_offset |= REF_PRISTINE;
jffs2_add_physical_node_ref(c, nraw, 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: 0 additions & 3 deletions trunk/fs/jffs2/jffs2_fs_sb.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ 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: 2 additions & 24 deletions trunk/fs/jffs2/malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,37 +190,15 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x)
kmem_cache_free(tmp_dnode_info_slab, x);
}

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 *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
64 changes: 24 additions & 40 deletions trunk/fs/jffs2/nodelist.c
Original file line number Diff line number Diff line change
Expand Up @@ -953,19 +953,13 @@ 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 @@ -1053,27 +1047,10 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c)
}
}

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)
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 *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 @@ -1116,15 +1093,15 @@ struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
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, no reservation of 'ref'. Do not use on a live file system */
/* No locking. 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 @@ -1144,10 +1121,18 @@ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
jeb->dirty_size += size;
jeb->free_size -= size;
} else {
uint32_t ofs = jeb->offset + c->sector_size - jeb->free_size;
ofs |= REF_OBSOLETE;
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

jffs2_link_node_ref(c, jeb, ofs, size, NULL);
jffs2_link_node_ref(c, jeb, ref, size, NULL);
}

return 0;
Expand All @@ -1159,10 +1144,9 @@ static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
struct jffs2_raw_node_ref *ref)
{
uint32_t ref_end;
struct jffs2_raw_node_ref *next_ref = ref_next(ref);

if (next_ref)
ref_end = ref_offset(next_ref);
if (ref->next_phys)
ref_end = ref_offset(ref->next_phys);
else {
if (!jeb)
jeb = &c->blocks[ref->flash_offset / c->sector_size];
Expand Down Expand Up @@ -1197,11 +1181,11 @@ uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *je
printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
ret, ref->__totlen);
if (ref_next(ref)) {
printk(KERN_CRIT "next %p (0x%08x-0x%08x)\n", ref_next(ref), ref_offset(ref_next(ref)),
ref_offset(ref_next(ref))+ref->__totlen);
if (ref->next_phys) {
printk(KERN_CRIT "next_phys %p (0x%08x-0x%08x)\n", ref->next_phys, ref_offset(ref->next_phys),
ref_offset(ref->next_phys)+ref->__totlen);
} else
printk(KERN_CRIT "No next ref. jeb->last_node is %p\n", jeb->last_node);
printk(KERN_CRIT "No next_phys. jeb->last_node is %p\n", jeb->last_node);

printk(KERN_CRIT "jeb->wasted_size %x, dirty_size %x, used_size %x, free_size %x\n", jeb->wasted_size, jeb->dirty_size, jeb->used_size, jeb->free_size);
ret = ref->__totlen;
Expand Down
25 changes: 12 additions & 13 deletions trunk/fs/jffs2/nodelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,18 @@ struct jffs2_raw_node_ref
#endif
};

#define ref_next(r) ((r)->next_phys)

static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw)
{
while(raw->next_in_ino)
while(raw->next_in_ino) {
raw = raw->next_in_ino;
}

/* NB. This can be a jffs2_xattr_datum or jffs2_xattr_ref and
not actually a jffs2_inode_cache. Check ->class */
return ((struct jffs2_inode_cache *)raw);
}


/* flash_offset & 3 always has to be zero, because nodes are
always aligned at 4 bytes. So we have a couple of extra bits
to play with, which indicate the node's status; see below: */
Expand Down Expand Up @@ -318,10 +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);
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);
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);
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);
extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c,
struct jffs2_eraseblock *jeb,
struct jffs2_raw_node_ref *ref);
Expand All @@ -332,9 +331,10 @@ 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);
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);
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);
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,9 +378,8 @@ 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 *);
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_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
Loading

0 comments on commit 3d518fd

Please sign in to comment.