Skip to content

Commit

Permalink
jffs2: Dynamically choose inocache hash size
Browse files Browse the repository at this point in the history
When JFFS2 is used for large volumes, the mount times are quite long.
Increasing the hash size provides a significant speed boost on the OLPC
XO-1 laptop.

Add logic that dynamically selects a hash size based on the size of
the medium. A 64mb medium will result in a hash size of 128, and a 512mb
medium will result in a hash size of 1024.

Signed-off-by: Daniel Drake <[email protected]>
Signed-off-by: David Woodhouse <[email protected]>
  • Loading branch information
Daniel Drake authored and David Woodhouse committed Oct 24, 2010
1 parent b46daf7 commit 65e5a0e
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 7 deletions.
2 changes: 1 addition & 1 deletion fs/jffs2/build.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *,
static inline struct jffs2_inode_cache *
first_inode_chain(int *i, struct jffs2_sb_info *c)
{
for (; *i < INOCACHE_HASHSIZE; (*i)++) {
for (; *i < c->inocache_hashsize; (*i)++) {
if (c->inocache_list[*i])
return c->inocache_list[*i];
}
Expand Down
22 changes: 21 additions & 1 deletion fs/jffs2/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,25 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
return inode;
}

static int calculate_inocache_hashsize(uint32_t flash_size)
{
/*
* Pick a inocache hash size based on the size of the medium.
* Count how many megabytes we're dealing with, apply a hashsize twice
* that size, but rounding down to the usual big powers of 2. And keep
* to sensible bounds.
*/

int size_mb = flash_size / 1024 / 1024;
int hashsize = (size_mb * 2) & ~0x3f;

if (hashsize < INOCACHE_HASHSIZE_MIN)
return INOCACHE_HASHSIZE_MIN;
if (hashsize > INOCACHE_HASHSIZE_MAX)
return INOCACHE_HASHSIZE_MAX;

return hashsize;
}

int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
{
Expand Down Expand Up @@ -524,7 +543,8 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
if (ret)
return ret;

c->inocache_list = kcalloc(INOCACHE_HASHSIZE, sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
c->inocache_hashsize = calculate_inocache_hashsize(c->flash_size);
c->inocache_list = kcalloc(c->inocache_hashsize, sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
if (!c->inocache_list) {
ret = -ENOMEM;
goto out_wbuf;
Expand Down
1 change: 1 addition & 0 deletions fs/jffs2/jffs2_fs_sb.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ struct jffs2_sb_info {
wait_queue_head_t erase_wait; /* For waiting for erases to complete */

wait_queue_head_t inocache_wq;
int inocache_hashsize;
struct jffs2_inode_cache **inocache_list;
spinlock_t inocache_lock;

Expand Down
8 changes: 4 additions & 4 deletions fs/jffs2/nodelist.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t
{
struct jffs2_inode_cache *ret;

ret = c->inocache_list[ino % INOCACHE_HASHSIZE];
ret = c->inocache_list[ino % c->inocache_hashsize];
while (ret && ret->ino < ino) {
ret = ret->next;
}
Expand All @@ -441,7 +441,7 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new

dbg_inocache("add %p (ino #%u)\n", new, new->ino);

prev = &c->inocache_list[new->ino % INOCACHE_HASHSIZE];
prev = &c->inocache_list[new->ino % c->inocache_hashsize];

while ((*prev) && (*prev)->ino < new->ino) {
prev = &(*prev)->next;
Expand All @@ -462,7 +462,7 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
dbg_inocache("del %p (ino #%u)\n", old, old->ino);
spin_lock(&c->inocache_lock);

prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE];
prev = &c->inocache_list[old->ino % c->inocache_hashsize];

while ((*prev) && (*prev)->ino < old->ino) {
prev = &(*prev)->next;
Expand All @@ -487,7 +487,7 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c)
int i;
struct jffs2_inode_cache *this, *next;

for (i=0; i<INOCACHE_HASHSIZE; i++) {
for (i=0; i < c->inocache_hashsize; i++) {
this = c->inocache_list[i];
while (this) {
next = this->next;
Expand Down
3 changes: 2 additions & 1 deletion fs/jffs2/nodelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ struct jffs2_inode_cache {
#define RAWNODE_CLASS_XATTR_DATUM 1
#define RAWNODE_CLASS_XATTR_REF 2

#define INOCACHE_HASHSIZE 128
#define INOCACHE_HASHSIZE_MIN 128
#define INOCACHE_HASHSIZE_MAX 1024

#define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size)

Expand Down

0 comments on commit 65e5a0e

Please sign in to comment.