Skip to content

Commit 2f78540

Browse files
committed
[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 <[email protected]>
1 parent 4cbb9b8 commit 2f78540

File tree

12 files changed

+204
-349
lines changed

12 files changed

+204
-349
lines changed

fs/jffs2/erase.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *
296296
jffs2_remove_node_refs_from_ino_list(c, ref, jeb);
297297
/* else it was a non-inode node or already removed, so don't bother */
298298

299-
jffs2_free_raw_node_ref(ref);
299+
__jffs2_free_raw_node_ref(ref);
300300
}
301301
jeb->last_node = NULL;
302302
}
@@ -351,7 +351,6 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
351351

352352
static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
353353
{
354-
struct jffs2_raw_node_ref *marker_ref = NULL;
355354
size_t retlen;
356355
int ret;
357356
uint32_t bad_offset;
@@ -384,11 +383,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
384383
.totlen = cpu_to_je32(c->cleanmarker_size)
385384
};
386385

387-
marker_ref = jffs2_alloc_raw_node_ref();
388-
if (!marker_ref) {
389-
printk(KERN_WARNING "Failed to allocate raw node ref for clean marker. Refiling\n");
390-
goto refile;
391-
}
386+
jffs2_prealloc_raw_node_refs(c, 1);
392387

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

@@ -404,16 +399,13 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
404399
printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n",
405400
jeb->offset, sizeof(marker), retlen);
406401

407-
jffs2_free_raw_node_ref(marker_ref);
408402
goto filebad;
409403
}
410404

411405
/* Everything else got zeroed before the erase */
412406
jeb->free_size = c->sector_size;
413-
414-
marker_ref->flash_offset = jeb->offset | REF_NORMAL;
415-
416-
jffs2_link_node_ref(c, jeb, marker_ref, c->cleanmarker_size, NULL);
407+
/* FIXME Special case for cleanmarker in empty block */
408+
jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
417409
}
418410

419411
spin_lock(&c->erase_completion_lock);

fs/jffs2/gc.c

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,6 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
528528
struct jffs2_raw_node_ref *raw)
529529
{
530530
union jffs2_node_union *node;
531-
struct jffs2_raw_node_ref *nraw;
532531
size_t retlen;
533532
int ret;
534533
uint32_t phys_ofs, alloclen;
@@ -618,30 +617,21 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
618617
}
619618
}
620619

621-
nraw = jffs2_alloc_raw_node_ref();
622-
if (!nraw) {
623-
ret = -ENOMEM;
624-
goto out_node;
625-
}
626-
627620
/* OK, all the CRCs are good; this node can just be copied as-is. */
628621
retry:
629-
nraw->flash_offset = phys_ofs = write_ofs(c);
622+
phys_ofs = write_ofs(c);
630623

631624
ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node);
632625

633626
if (ret || (retlen != rawlen)) {
634627
printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n",
635-
rawlen, nraw->flash_offset, ret, retlen);
628+
rawlen, phys_ofs, ret, retlen);
636629
if (retlen) {
637-
nraw->flash_offset |= REF_OBSOLETE;
638-
jffs2_add_physical_node_ref(c, nraw, rawlen, NULL);
639-
jffs2_mark_node_obsolete(c, nraw);
630+
jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
640631
} else {
641-
printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset);
642-
jffs2_free_raw_node_ref(nraw);
632+
printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", phys_ofs);
643633
}
644-
if (!retried && (nraw = jffs2_alloc_raw_node_ref())) {
634+
if (!retried) {
645635
/* Try to reallocate space and retry */
646636
uint32_t dummy;
647637
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,
666656
goto retry;
667657
}
668658
D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
669-
jffs2_free_raw_node_ref(nraw);
670659
}
671660

672-
jffs2_free_raw_node_ref(nraw);
673661
if (!ret)
674662
ret = -EIO;
675663
goto out_node;
676664
}
677-
nraw->flash_offset |= REF_PRISTINE;
678-
jffs2_add_physical_node_ref(c, nraw, rawlen, ic);
665+
jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, rawlen, ic);
679666

680667
jffs2_mark_node_obsolete(c, raw);
681668
D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw)));

fs/jffs2/jffs2_fs_sb.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ struct jffs2_inodirty;
2626
struct jffs2_sb_info {
2727
struct mtd_info *mtd;
2828

29+
struct jffs2_raw_node_ref *refs;
30+
int reserved_refs;
31+
2932
uint32_t highest_ino;
3033
uint32_t checked_ino;
3134

fs/jffs2/malloc.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,15 +190,37 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x)
190190
kmem_cache_free(tmp_dnode_info_slab, x);
191191
}
192192

193-
struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void)
193+
int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, int nr)
194+
{
195+
struct jffs2_raw_node_ref *p = c->refs;
196+
197+
dbg_memalloc("%d\n", nr);
198+
199+
while (nr && p) {
200+
p = p->next_in_ino;
201+
nr--;
202+
}
203+
while (nr) {
204+
p = __jffs2_alloc_raw_node_ref();
205+
if (!p)
206+
return -ENOMEM;
207+
p->next_in_ino = c->refs;
208+
c->refs = p;
209+
nr--;
210+
}
211+
c->reserved_refs = nr;
212+
return 0;
213+
}
214+
215+
struct jffs2_raw_node_ref *__jffs2_alloc_raw_node_ref(void)
194216
{
195217
struct jffs2_raw_node_ref *ret;
196218
ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL);
197219
dbg_memalloc("%p\n", ret);
198220
return ret;
199221
}
200222

201-
void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x)
223+
void __jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x)
202224
{
203225
dbg_memalloc("%p\n", x);
204226
kmem_cache_free(raw_node_ref_slab, x);

fs/jffs2/nodelist.c

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -953,13 +953,19 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c)
953953

954954
for (i=0; i<c->nr_blocks; i++) {
955955
this = c->blocks[i].first_node;
956-
while(this) {
956+
while (this) {
957957
next = this->next_phys;
958-
jffs2_free_raw_node_ref(this);
958+
__jffs2_free_raw_node_ref(this);
959959
this = next;
960960
}
961961
c->blocks[i].first_node = c->blocks[i].last_node = NULL;
962962
}
963+
this = c->refs;
964+
while (this) {
965+
next = this->next_in_ino;
966+
__jffs2_free_raw_node_ref(this);
967+
this = next;
968+
}
963969
}
964970

965971
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)
10471053
}
10481054
}
10491055

1050-
void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
1051-
struct jffs2_raw_node_ref *ref, uint32_t len,
1052-
struct jffs2_inode_cache *ic)
1056+
struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
1057+
struct jffs2_eraseblock *jeb,
1058+
uint32_t ofs, uint32_t len,
1059+
struct jffs2_inode_cache *ic)
10531060
{
1061+
struct jffs2_raw_node_ref *ref;
1062+
1063+
/* These will be preallocated _very_ shortly. */
1064+
ref = c->refs;
1065+
if (!c->refs) {
1066+
JFFS2_WARNING("Using non-preallocated refs!\n");
1067+
ref = __jffs2_alloc_raw_node_ref();
1068+
BUG_ON(!ref);
1069+
WARN_ON(1);
1070+
} else {
1071+
c->refs = ref->next_in_ino;
1072+
}
1073+
1074+
ref->next_phys = NULL;
1075+
ref->flash_offset = ofs;
1076+
10541077
if (!jeb->first_node)
10551078
jeb->first_node = ref;
10561079
if (jeb->last_node) {
@@ -1093,15 +1116,15 @@ void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
10931116
c->free_size -= len;
10941117
jeb->free_size -= len;
10951118

1096-
ref->next_phys = NULL;
10971119
#ifdef TEST_TOTLEN
10981120
/* Set (and test) __totlen field... for now */
10991121
ref->__totlen = len;
11001122
ref_totlen(c, jeb, ref);
11011123
#endif
1124+
return ref;
11021125
}
11031126

1104-
/* No locking. Do not use on a live file system */
1127+
/* No locking, no reservation of 'ref'. Do not use on a live file system */
11051128
int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
11061129
uint32_t size)
11071130
{
@@ -1121,18 +1144,10 @@ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
11211144
jeb->dirty_size += size;
11221145
jeb->free_size -= size;
11231146
} else {
1124-
struct jffs2_raw_node_ref *ref;
1125-
ref = jffs2_alloc_raw_node_ref();
1126-
if (!ref)
1127-
return -ENOMEM;
1128-
1129-
ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size;
1130-
ref->flash_offset |= REF_OBSOLETE;
1131-
#ifdef TEST_TOTLEN
1132-
ref->__totlen = size;
1133-
#endif
1147+
uint32_t ofs = jeb->offset + c->sector_size - jeb->free_size;
1148+
ofs |= REF_OBSOLETE;
11341149

1135-
jffs2_link_node_ref(c, jeb, ref, size, NULL);
1150+
jffs2_link_node_ref(c, jeb, ofs, size, NULL);
11361151
}
11371152

11381153
return 0;

fs/jffs2/nodelist.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,10 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t
318318
int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn);
319319
void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size);
320320
int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn);
321-
void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
322-
struct jffs2_raw_node_ref *ref, uint32_t len,
323-
struct jffs2_inode_cache *ic);
321+
struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
322+
struct jffs2_eraseblock *jeb,
323+
uint32_t ofs, uint32_t len,
324+
struct jffs2_inode_cache *ic);
324325
extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c,
325326
struct jffs2_eraseblock *jeb,
326327
struct jffs2_raw_node_ref *ref);
@@ -331,10 +332,9 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
331332
uint32_t *len, int prio, uint32_t sumsize);
332333
int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
333334
uint32_t *len, uint32_t sumsize);
334-
int jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
335-
struct jffs2_raw_node_ref *new,
336-
uint32_t len,
337-
struct jffs2_inode_cache *ic);
335+
struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
336+
uint32_t ofs, uint32_t len,
337+
struct jffs2_inode_cache *ic);
338338
void jffs2_complete_reservation(struct jffs2_sb_info *c);
339339
void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw);
340340

@@ -378,8 +378,9 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void);
378378
void jffs2_free_raw_inode(struct jffs2_raw_inode *);
379379
struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void);
380380
void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *);
381-
struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void);
382-
void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *);
381+
int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, int nr);
382+
struct jffs2_raw_node_ref *__jffs2_alloc_raw_node_ref(void);
383+
void __jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *);
383384
struct jffs2_node_frag *jffs2_alloc_node_frag(void);
384385
void jffs2_free_node_frag(struct jffs2_node_frag *);
385386
struct jffs2_inode_cache *jffs2_alloc_inode_cache(void);

fs/jffs2/nodemgmt.c

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
137137
}
138138
}
139139
spin_unlock(&c->erase_completion_lock);
140+
if (!ret)
141+
ret = jffs2_prealloc_raw_node_refs(c, 1);
140142
if (ret)
141143
up(&c->alloc_sem);
142144
return ret;
@@ -158,6 +160,9 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
158160
}
159161
}
160162
spin_unlock(&c->erase_completion_lock);
163+
if (!ret)
164+
ret = jffs2_prealloc_raw_node_refs(c, 1);
165+
161166
return ret;
162167
}
163168

@@ -381,30 +386,30 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
381386
* Must be called with the alloc_sem held.
382387
*/
383388

384-
int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new,
385-
uint32_t len, struct jffs2_inode_cache *ic)
389+
struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
390+
uint32_t ofs, uint32_t len,
391+
struct jffs2_inode_cache *ic)
386392
{
387393
struct jffs2_eraseblock *jeb;
394+
struct jffs2_raw_node_ref *new;
388395

389-
jeb = &c->blocks[new->flash_offset / c->sector_size];
390-
#ifdef TEST_TOTLEN
391-
new->__totlen = len;
392-
#endif
396+
jeb = &c->blocks[ofs / c->sector_size];
393397

394-
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));
398+
D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n",
399+
ofs & ~3, ofs & 3, len));
395400
#if 1
396-
/* we could get some obsolete nodes after nextblock was refiled
397-
in wbuf.c */
398-
if ((c->nextblock || !ref_obsolete(new))
399-
&&(jeb != c->nextblock || ref_offset(new) != jeb->offset + (c->sector_size - jeb->free_size))) {
401+
/* Allow non-obsolete nodes only to be added at the end of c->nextblock,
402+
if c->nextblock is set. Note that wbuf.c will file obsolete nodes
403+
even after refiling c->nextblock */
404+
if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
405+
&& (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
400406
printk(KERN_WARNING "argh. node added in wrong place\n");
401-
jffs2_free_raw_node_ref(new);
402-
return -EINVAL;
407+
return ERR_PTR(-EINVAL);
403408
}
404409
#endif
405410
spin_lock(&c->erase_completion_lock);
406411

407-
jffs2_link_node_ref(c, jeb, new, len, ic);
412+
new = jffs2_link_node_ref(c, jeb, ofs, len, ic);
408413

409414
if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) {
410415
/* 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
425430

426431
spin_unlock(&c->erase_completion_lock);
427432

428-
return 0;
433+
return new;
429434
}
430435

431436

@@ -697,7 +702,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
697702
}
698703
spin_unlock(&c->erase_completion_lock);
699704

700-
jffs2_free_raw_node_ref(n);
705+
__jffs2_free_raw_node_ref(n);
701706
}
702707

703708
/* 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
722727
jeb->gc_node=p;
723728
}
724729
p->next_phys = ref->next_phys;
725-
jffs2_free_raw_node_ref(ref);
730+
__jffs2_free_raw_node_ref(ref);
726731
}
727732
spin_unlock(&c->erase_completion_lock);
728733
}

0 commit comments

Comments
 (0)