[PATCH] Enhancement to current 1:1 mapping handling in JFFS2
zhao forrest
zhao_fusheng at hotmail.com
Mon Sep 26 04:32:20 EDT 2005
> >
> > This patch gave a possible method to improve the current 1:1
> > mapping handling in JFFS2.
> >
> > Data structure:
> > 1 A slab cache for struct jffs2_eraseblock; is created, so
> > struc jffs2_eraseblock is allocated from this slab cache.
> > 2 A pointer array is created by kmalloc(), and the pointer
> > point to the struct jffs2_eraseblock allocated from slab cache.
> >
> > By storing pointers instead of "struct jffs2_eraseblock"s into
> > continuous memory space, we reduce the pressure of continuous
> > memory space requirement.
> >
> > On a 32-bit system, 128K continuous memory allocated by kmalloc()
> > can hold 32K pointers.
> > So if the eraseblock size is 4K, it can support 128M flash memory.
> > if the eraseblock size is 8K, it can support 256M flash memory.
> >
> > I think this patch can support most of flashes now. If there's
> > size limitation report in the future, we can add another level of
> > pointers to meet the requirement.
>
>This could become a limit already. Block devices going through a
>translation usually have 4k as erase size. Any USB key above 128KiB
>will be a problem.
>
>Not sure what we want to do about this.
I agree with you that my patch is not a perfect solution to the
problem. But at least it's a further step of current 1:1 mapping
handling in JFFS2. I think someone can give better patch if he
meets the limit in the future. Does it make sense to you? Or
do you agree to check in this patch after I finish revising it?
>
> > diff -auNrp ./mtd_EBH_EBS/fs/jffs2/build.c
./mtd_EBH_EBS_1on1/fs/jffs2/build.c
> > --- ./mtd_EBH_EBS/fs/jffs2/build.c 2005-09-22 13:13:51.000000000 +0800
> > +++ ./mtd_EBH_EBS_1on1/fs/jffs2/build.c 2005-09-22 15:01:40.000000000
+0800
> > @@ -305,34 +305,51 @@ static void jffs2_calc_trigger_levels(st
> > c->nospc_dirty_size);
> > }
> >
> > +void jffs2_free_eraseblocks(struct jffs2_sb_info *c, uint32_t number)
> > +{
> > + uint32_t i;
> > +
> > + for(i=0; i<number; i++) {
> > + jffs2_free_eraseblock(c->blocks[i]);
> > + }
> > + return;
> > +}
>
>Is there a reason why this function doesn't encapsulate everything to
>free all objects?
>
>void jffs2_free_eraseblocks(struct jffs2_sb_info *c)
>{
> u32 i = c->nr_blocks - 1;
>
> for (; i>=0; i--)
> jffs2_free_eraseblock(c->blocks[i]);
> kfree(c->blocks);
>}
>
>Should be safe from all contexts. Failure case is a slow path anyway,
>so iterating through the full array shouldn't matter too much.
>
OK. I'll modify the patch accordingly.
> > int jffs2_do_mount_fs(struct jffs2_sb_info *c)
> > {
> > int ret;
> > - int i;
> > + uint32_t i, number = 0;
> >
> > c->free_size = c->flash_size;
> > c->nr_blocks = c->flash_size / c->sector_size;
> > -#ifndef __ECOS
> > - if (jffs2_blocks_use_vmalloc(c))
> > - c->blocks = vmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks);
> > - else
> > -#endif
> > - c->blocks = kmalloc(sizeof(struct jffs2_eraseblock) * c->nr_blocks,
GFP_KERNEL);
> > +
> > + c->blocks = kmalloc(sizeof(char *) * c->nr_blocks, GFP_KERNEL);
> > if (!c->blocks)
> > return -ENOMEM;
> > +
> > + for (i=0; i<c->nr_blocks; i++) {
> > + c->blocks[i] = jffs2_alloc_eraseblock();
> > + if (!c->blocks[i]) {
> > + ret = -ENOMEM;
> > + number = i;
> > + goto failed;
> > + }
> > + }
> > + number = c->nr_blocks;
>
>This could be moved into a function, analog to the above.
>
OK.
>static int jffs2_alloc_eraseblocks(struct jffs2_sb_info *c)
>{
> int i = c->nr_blocks - 1;
>
> c->blocks = kzalloc(sizeof(char *) * c->nr_blocks, GFP_KERNEL);
> if (!c->blocks)
> return -ENOMEM;
>
> for (; i>=0; i--) {
> c->blocks[i] = jffs2_alloc_eraseblock();
> if (!c->blocks[i]) {
> jffs2_free_eraseblocks(c);
> return -ENOMEM;
> }
> }
> return 0;
>}
>
> > for (i=0; i<c->nr_blocks; i++) {
> > - INIT_LIST_HEAD(&c->blocks[i].list);
> > - c->blocks[i].offset = i * c->sector_size;
> > - c->blocks[i].free_size = c->sector_size;
> > - c->blocks[i].dirty_size = 0;
> > - c->blocks[i].wasted_size = 0;
> > - c->blocks[i].unchecked_size = 0;
> > - c->blocks[i].used_size = 0;
> > - c->blocks[i].first_node = NULL;
> > - c->blocks[i].last_node = NULL;
> > - c->blocks[i].bad_count = 0;
> > - c->blocks[i].has_eraseblock_header = 0;
> > - c->blocks[i].erase_count = 0;
> > + INIT_LIST_HEAD(&c->blocks[i]->list);
> > + c->blocks[i]->offset = i * c->sector_size;
> > + c->blocks[i]->free_size = c->sector_size;
> > + c->blocks[i]->dirty_size = 0;
> > + c->blocks[i]->wasted_size = 0;
> > + c->blocks[i]->unchecked_size = 0;
> > + c->blocks[i]->used_size = 0;
> > + c->blocks[i]->first_node = NULL;
> > + c->blocks[i]->last_node = NULL;
> > + c->blocks[i]->bad_count = 0;
> > + c->blocks[i]->has_eraseblock_header = 0;
> > + c->blocks[i]->erase_count = 0;
> > }
>
>Most of those fields are initialized to 0 or NULL. Maybe we should
>just kzalloc() or memset() the complete object, then initialize the
>few fields that are non-zero. If that reduces the text size, it'd be
>worth it.
>
OK.
> > INIT_LIST_HEAD(&c->clean_list);
> > @@ -351,22 +368,22 @@ int jffs2_do_mount_fs(struct jffs2_sb_in
> >
> > ret = jffs2_sum_init(c);
> > if (ret)
> > - return ret;
> > + goto failed;
> >
> > if (jffs2_build_filesystem(c)) {
> > dbg_fsbuild("build_fs failed\n");
> > - jffs2_free_ino_caches(c);
> > - jffs2_free_raw_node_refs(c);
> > -#ifndef __ECOS
> > - if (jffs2_blocks_use_vmalloc(c))
> > - vfree(c->blocks);
> > - else
> > -#endif
> > - kfree(c->blocks);
> > -
> > - return -EIO;
> > - }
> > + ret = -EIO;
> > + } else
> > + goto out;
> > +
> > +failed:
> > + jffs2_free_ino_caches(c);
> > + jffs2_free_raw_node_refs(c);
> > + jffs2_free_eraseblocks(c, number);
> > + kfree(jffs2_free_eraseblocks);
> > + return ret;
>
>This logic would be a bit simpler if allocation is moved into a
>function.
OK
I'll send out the revised patch soon.
Thanks,
Forrest
More information about the linux-mtd
mailing list