Commit 9bfeb691 authored by David Woodhouse's avatar David Woodhouse

[JFFS2] Switch to using an array of jffs2_raw_node_refs instead of a list.

This allows us to drop another pointer from the struct jffs2_raw_node_ref,
shrinking it to 8 bytes on 32-bit machines (if the TEST_TOTLEN) paranoia
check is turned off, which will be committed soon).
Signed-off-by: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent f75e5097
...@@ -285,20 +285,25 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, ...@@ -285,20 +285,25 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
{ {
struct jffs2_raw_node_ref *ref; struct jffs2_raw_node_ref *block, *ref;
D1(printk(KERN_DEBUG "Freeing all node refs for eraseblock offset 0x%08x\n", jeb->offset)); D1(printk(KERN_DEBUG "Freeing all node refs for eraseblock offset 0x%08x\n", jeb->offset));
while(jeb->first_node) {
ref = jeb->first_node;
jeb->first_node = ref->next_phys;
/* Remove from the inode-list */ block = ref = jeb->first_node;
if (ref->next_in_ino)
while (ref) {
if (ref->flash_offset == REF_LINK_NODE) {
ref = ref->next_in_ino;
jffs2_free_refblock(block);
block = ref;
continue;
}
if (ref->flash_offset != REF_EMPTY_NODE && ref->next_in_ino)
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); ref++;
} }
jeb->last_node = NULL; jeb->first_node = jeb->last_node = NULL;
} }
static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *bad_offset) static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *bad_offset)
......
...@@ -26,9 +26,6 @@ struct jffs2_inodirty; ...@@ -26,9 +26,6 @@ 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;
......
...@@ -57,8 +57,8 @@ int __init jffs2_create_slab_caches(void) ...@@ -57,8 +57,8 @@ int __init jffs2_create_slab_caches(void)
if (!tmp_dnode_info_slab) if (!tmp_dnode_info_slab)
goto err; goto err;
raw_node_ref_slab = kmem_cache_create("jffs2_raw_node_ref", raw_node_ref_slab = kmem_cache_create("jffs2_refblock",
sizeof(struct jffs2_raw_node_ref), sizeof(struct jffs2_raw_node_ref) * (REFS_PER_BLOCK + 1),
0, 0, NULL, NULL); 0, 0, NULL, NULL);
if (!raw_node_ref_slab) if (!raw_node_ref_slab)
goto err; goto err;
...@@ -190,38 +190,65 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x) ...@@ -190,38 +190,65 @@ 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_refblock(void)
{
struct jffs2_raw_node_ref *ret;
ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL);
if (ret) {
int i = 0;
for (i=0; i < REFS_PER_BLOCK; i++) {
ret[i].flash_offset = REF_EMPTY_NODE;
ret[i].next_in_ino = NULL;
}
ret[i].flash_offset = REF_LINK_NODE;
ret[i].next_in_ino = NULL;
}
return ret;
}
int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
struct jffs2_eraseblock *jeb, int nr) struct jffs2_eraseblock *jeb, int nr)
{ {
struct jffs2_raw_node_ref *p = c->refs; struct jffs2_raw_node_ref **p, *ref;
int i = nr;
dbg_memalloc("%d\n", nr); dbg_memalloc("%d\n", nr);
while (nr && p) { p = &jeb->last_node;
p = p->next_in_ino; ref = *p;
nr--;
} dbg_memalloc("Reserving %d refs for block @0x%08x\n", nr, jeb->offset);
while (nr) {
p = __jffs2_alloc_raw_node_ref(); /* If jeb->last_node is really a valid node then skip over it */
if (!p) if (ref && ref->flash_offset != REF_EMPTY_NODE)
return -ENOMEM; ref++;
p->next_in_ino = c->refs;
c->refs = p; while (i) {
nr--; if (!ref) {
dbg_memalloc("Allocating new refblock linked from %p\n", p);
ref = *p = jffs2_alloc_refblock();
if (!ref)
return -ENOMEM;
}
if (ref->flash_offset == REF_LINK_NODE) {
p = &ref->next_in_ino;
ref = *p;
continue;
}
i--;
ref++;
} }
c->reserved_refs = nr; jeb->allocated_refs = nr;
return 0;
}
struct jffs2_raw_node_ref *__jffs2_alloc_raw_node_ref(void) dbg_memalloc("Reserved %d refs for block @0x%08x, last_node is %p (%08x,%p)\n",
{ nr, jeb->offset, jeb->last_node, jeb->last_node->flash_offset,
struct jffs2_raw_node_ref *ret; jeb->last_node->next_in_ino);
ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL);
dbg_memalloc("%p\n", ret); return 0;
return ret;
} }
void __jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) void jffs2_free_refblock(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);
......
...@@ -954,18 +954,16 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c) ...@@ -954,18 +954,16 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c)
for (i=0; i<c->nr_blocks; i++) { for (i=0; i<c->nr_blocks; i++) {
this = c->blocks[i].first_node; this = c->blocks[i].first_node;
while (this) { while (this) {
next = this->next_phys; if (this[REFS_PER_BLOCK].flash_offset == REF_LINK_NODE)
__jffs2_free_raw_node_ref(this); next = this[REFS_PER_BLOCK].next_in_ino;
else
next = NULL;
jffs2_free_refblock(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)
...@@ -1060,32 +1058,37 @@ struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c, ...@@ -1060,32 +1058,37 @@ struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
{ {
struct jffs2_raw_node_ref *ref; struct jffs2_raw_node_ref *ref;
/* These will be preallocated _very_ shortly. */ BUG_ON(!jeb->allocated_refs);
ref = c->refs; jeb->allocated_refs--;
if (!c->refs) {
JFFS2_WARNING("Using non-preallocated refs!\n"); ref = jeb->last_node;
ref = __jffs2_alloc_raw_node_ref();
BUG_ON(!ref); dbg_noderef("Last node at %p is (%08x,%p)\n", ref, ref->flash_offset,
WARN_ON(1); ref->next_in_ino);
} else {
c->refs = ref->next_in_ino; while (ref->flash_offset != REF_EMPTY_NODE) {
if (ref->flash_offset == REF_LINK_NODE)
ref = ref->next_in_ino;
else
ref++;
} }
ref->next_phys = NULL; dbg_noderef("New ref is %p (%08x becomes %08x,%p) len 0x%x\n", ref,
ref->flash_offset, ofs, ref->next_in_ino, len);
ref->flash_offset = ofs; ref->flash_offset = ofs;
if (!jeb->first_node) if (!jeb->first_node) {
jeb->first_node = ref; jeb->first_node = ref;
if (jeb->last_node) { BUG_ON(ref_offset(ref) != jeb->offset);
jeb->last_node->next_phys = ref; } else if (unlikely(ref_offset(ref) != jeb->offset + c->sector_size - jeb->free_size)) {
#ifdef TEST_TOTLEN uint32_t last_len = ref_totlen(c, jeb, jeb->last_node);
if (ref_offset(jeb->last_node) + jeb->last_node->__totlen != ref_offset(ref)) {
printk(KERN_CRIT "Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n", JFFS2_ERROR("Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n",
ref, ref_offset(ref), ref_offset(ref)+ref->__totlen, ref, ref_offset(ref), ref_offset(ref)+len,
ref_offset(jeb->last_node), ref_offset(jeb->last_node)+jeb->last_node->__totlen); ref_offset(jeb->last_node),
WARN_ON(1); ref_offset(jeb->last_node)+last_len);
} BUG();
#endif
} }
jeb->last_node = ref; jeb->last_node = ref;
...@@ -1130,12 +1133,13 @@ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb ...@@ -1130,12 +1133,13 @@ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
{ {
if (!size) if (!size)
return 0; return 0;
if (size > c->sector_size - jeb->used_size) { if (unlikely(size > jeb->free_size)) {
printk(KERN_CRIT "Dirty space 0x%x larger then used_size 0x%x (wasted 0x%x)\n", printk(KERN_CRIT "Dirty space 0x%x larger then free_size 0x%x (wasted 0x%x)\n",
size, jeb->used_size, jeb->wasted_size); size, jeb->free_size, jeb->wasted_size);
BUG(); BUG();
} }
if (jeb->last_node && ref_obsolete(jeb->last_node)) { /* REF_EMPTY_NODE is !obsolete, so that works OK */
if (ref_obsolete(jeb->last_node)) {
#ifdef TEST_TOTLEN #ifdef TEST_TOTLEN
jeb->last_node->__totlen += size; jeb->last_node->__totlen += size;
#endif #endif
...@@ -1168,7 +1172,7 @@ static inline uint32_t __ref_totlen(struct jffs2_sb_info *c, ...@@ -1168,7 +1172,7 @@ static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
jeb = &c->blocks[ref->flash_offset / c->sector_size]; jeb = &c->blocks[ref->flash_offset / c->sector_size];
/* Last node in block. Use free_space */ /* Last node in block. Use free_space */
if (ref != jeb->last_node) { if (unlikely(ref != jeb->last_node)) {
printk(KERN_CRIT "ref %p @0x%08x is not jeb->last_node (%p @0x%08x)\n", printk(KERN_CRIT "ref %p @0x%08x is not jeb->last_node (%p @0x%08x)\n",
ref, ref_offset(ref), jeb->last_node, jeb->last_node?ref_offset(jeb->last_node):0); ref, ref_offset(ref), jeb->last_node, jeb->last_node?ref_offset(jeb->last_node):0);
BUG(); BUG();
...@@ -1183,17 +1187,13 @@ uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *je ...@@ -1183,17 +1187,13 @@ uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *je
{ {
uint32_t ret; uint32_t ret;
#if CONFIG_JFFS2_FS_DEBUG > 0
if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) {
printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n",
jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref));
BUG();
}
#endif
ret = __ref_totlen(c, jeb, ref); ret = __ref_totlen(c, jeb, ref);
#ifdef TEST_TOTLEN #ifdef TEST_TOTLEN
if (ret != ref->__totlen) { if (unlikely(ret != ref->__totlen)) {
if (!jeb)
jeb = &c->blocks[ref->flash_offset / c->sector_size];
printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n", 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, ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
ret, ref->__totlen); ret, ref->__totlen);
...@@ -1204,13 +1204,14 @@ uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *je ...@@ -1204,13 +1204,14 @@ uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *je
printk(KERN_CRIT "No next ref. jeb->last_node is %p\n", jeb->last_node); printk(KERN_CRIT "No next ref. 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); 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;
if (!jeb)
jeb = &c->blocks[ref->flash_offset / c->sector_size];
#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS) #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
__jffs2_dbg_dump_node_refs_nolock(c, jeb); __jffs2_dbg_dump_node_refs_nolock(c, jeb);
#endif #endif
WARN_ON(1); WARN_ON(1);
ret = ref->__totlen;
} }
#endif /* TEST_TOTLEN */ #endif /* TEST_TOTLEN */
return ret; return ret;
......
...@@ -80,7 +80,6 @@ struct jffs2_raw_node_ref ...@@ -80,7 +80,6 @@ struct jffs2_raw_node_ref
for this object. If this _is_ the last, it points to the inode_cache, for this object. If this _is_ the last, it points to the inode_cache,
xattr_ref or xattr_datum instead. The common part of those structures xattr_ref or xattr_datum instead. The common part of those structures
has NULL in the first word. See jffs2_raw_ref_to_ic() below */ has NULL in the first word. See jffs2_raw_ref_to_ic() below */
struct jffs2_raw_node_ref *next_phys;
uint32_t flash_offset; uint32_t flash_offset;
#define TEST_TOTLEN #define TEST_TOTLEN
#ifdef TEST_TOTLEN #ifdef TEST_TOTLEN
...@@ -88,7 +87,29 @@ struct jffs2_raw_node_ref ...@@ -88,7 +87,29 @@ struct jffs2_raw_node_ref
#endif #endif
}; };
#define ref_next(r) ((r)->next_phys) #define REF_LINK_NODE ((int32_t)-1)
#define REF_EMPTY_NODE ((int32_t)-2)
/* Use blocks of about 256 bytes */
#define REFS_PER_BLOCK ((255/sizeof(struct jffs2_raw_node_ref))-1)
static inline struct jffs2_raw_node_ref *ref_next(struct jffs2_raw_node_ref *ref)
{
ref++;
/* Link to another block of refs */
if (ref->flash_offset == REF_LINK_NODE) {
ref = ref->next_in_ino;
if (!ref)
return ref;
}
/* End of chain */
if (ref->flash_offset == REF_EMPTY_NODE)
return NULL;
return ref;
}
static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw) static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw)
{ {
...@@ -234,6 +255,7 @@ struct jffs2_eraseblock ...@@ -234,6 +255,7 @@ struct jffs2_eraseblock
uint32_t wasted_size; uint32_t wasted_size;
uint32_t free_size; /* Note that sector_size - free_size uint32_t free_size; /* Note that sector_size - free_size
is the address of the first free space */ is the address of the first free space */
uint32_t allocated_refs;
struct jffs2_raw_node_ref *first_node; struct jffs2_raw_node_ref *first_node;
struct jffs2_raw_node_ref *last_node; struct jffs2_raw_node_ref *last_node;
...@@ -378,10 +400,9 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void); ...@@ -378,10 +400,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 *);
int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
struct jffs2_eraseblock *jeb, int nr); struct jffs2_eraseblock *jeb, int nr);
struct jffs2_raw_node_ref *__jffs2_alloc_raw_node_ref(void); void jffs2_free_refblock(struct jffs2_raw_node_ref *);
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);
......
...@@ -458,14 +458,13 @@ static inline int on_list(struct list_head *obj, struct list_head *head) ...@@ -458,14 +458,13 @@ static inline int on_list(struct list_head *obj, struct list_head *head)
void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref) void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref)
{ {
struct jffs2_eraseblock *jeb; struct jffs2_eraseblock *jeb;
struct jffs2_raw_node_ref *next_ref;
int blocknr; int blocknr;
struct jffs2_unknown_node n; struct jffs2_unknown_node n;
int ret, addedsize; int ret, addedsize;
size_t retlen; size_t retlen;
uint32_t freed_len; uint32_t freed_len;
if(!ref) { if(unlikely(!ref)) {
printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n"); printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n");
return; return;
} }
...@@ -683,54 +682,6 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ...@@ -683,54 +682,6 @@ 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);
} }
/* Merge with the next node in the physical list, if there is one
and if it's also obsolete and if it doesn't belong to any inode */
next_ref = ref_next(ref);
if (next_ref && ref_obsolete(next_ref) && !next_ref->next_in_ino) {
spin_lock(&c->erase_completion_lock);
#ifdef TEST_TOTLEN
ref->__totlen += next_ref->__totlen;
#endif
ref->next_phys = ref_next(next_ref);
if (jeb->last_node == next_ref) jeb->last_node = ref;
if (jeb->gc_node == next_ref) {
/* gc will be happy continuing gc on this node */
jeb->gc_node=ref;
}
spin_unlock(&c->erase_completion_lock);
__jffs2_free_raw_node_ref(next_ref);
}
/* Also merge with the previous node in the list, if there is one
and that one is obsolete */
if (ref != jeb->first_node ) {
struct jffs2_raw_node_ref *p = jeb->first_node;
spin_lock(&c->erase_completion_lock);
while ((next_ref = ref_next(ref)) != ref)
p = next_ref;
if (ref_obsolete(p) && !ref->next_in_ino) {
#ifdef TEST_TOTLEN
p->__totlen += ref->__totlen;
#endif
if (jeb->last_node == ref) {
jeb->last_node = p;
}
if (jeb->gc_node == ref) {
/* gc will be happy continuing gc on this node */
jeb->gc_node=p;
}
p->next_phys = ref_next(ref);
__jffs2_free_raw_node_ref(ref);
}
spin_unlock(&c->erase_completion_lock);
}
out_erase_sem: out_erase_sem:
up(&c->erase_free_sem); up(&c->erase_free_sem);
} }
......
...@@ -95,6 +95,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) ...@@ -95,6 +95,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
#define jffs2_dataflash(c) (0) #define jffs2_dataflash(c) (0)
#define jffs2_dataflash_setup(c) (0) #define jffs2_dataflash_setup(c) (0)
#define jffs2_dataflash_cleanup(c) do {} while (0) #define jffs2_dataflash_cleanup(c) do {} while (0)
#define jffs2_nor_wbuf_flash(c) (0)
#define jffs2_nor_wbuf_flash_setup(c) (0) #define jffs2_nor_wbuf_flash_setup(c) (0)
#define jffs2_nor_wbuf_flash_cleanup(c) do {} while (0) #define jffs2_nor_wbuf_flash_cleanup(c) do {} while (0)
......
...@@ -511,7 +511,8 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras ...@@ -511,7 +511,8 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
spr = (struct jffs2_sum_xref_flash *)sp; spr = (struct jffs2_sum_xref_flash *)sp;
dbg_summary("xref at %#08x-%#08x\n", dbg_summary("xref at %#08x-%#08x\n",
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) +
(uint32_t)PAD(sizeof(struct jffs2_raw_xref)));
ref = jffs2_alloc_xattr_ref(); ref = jffs2_alloc_xattr_ref();
if (!ref) { if (!ref) {
...@@ -787,10 +788,12 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock ...@@ -787,10 +788,12 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
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, sum_ofs, ret, retlen); infosize, sum_ofs, ret, retlen);
/* Waste remaining space */ if (retlen) {
spin_lock(&c->erase_completion_lock); /* Waste remaining space */
jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL); spin_lock(&c->erase_completion_lock);
spin_unlock(&c->erase_completion_lock); jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL);
spin_unlock(&c->erase_completion_lock);
}
c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
...@@ -836,6 +839,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) ...@@ -836,6 +839,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
jffs2_sum_disable_collecting(c->summary); jffs2_sum_disable_collecting(c->summary);
JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize); JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize);
spin_lock(&c->erase_completion_lock);
return 0; return 0;
} }
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment