- Increase the hash table entries to 65536; - Protect the hash table with `erofs_rwsem`.
Signed-off-by: Gao Xiang <hsiang...@linux.alibaba.com> --- include/erofs/inode.h | 2 +- lib/inode.c | 65 +++++++++++++++++++++++-------------------- lib/rebuild.c | 2 +- 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/include/erofs/inode.h b/include/erofs/inode.h index eb8f45b..fe86101 100644 --- a/include/erofs/inode.h +++ b/include/erofs/inode.h @@ -27,8 +27,8 @@ umode_t erofs_ftype_to_mode(unsigned int ftype, unsigned int perm); unsigned char erofs_ftype_to_dtype(unsigned int filetype); void erofs_inode_manager_init(void); void erofs_insert_ihash(struct erofs_inode *inode); +void erofs_remove_ihash(struct erofs_inode *inode); struct erofs_inode *erofs_iget(dev_t dev, ino_t ino); -struct erofs_inode *erofs_iget_by_nid(erofs_nid_t nid); unsigned int erofs_iput(struct erofs_inode *inode); erofs_nid_t erofs_lookupnid(struct erofs_inode *inode); int erofs_iflush(struct erofs_inode *inode); diff --git a/lib/inode.c b/lib/inode.c index 6b42fc9..a2ee522 100644 --- a/lib/inode.c +++ b/lib/inode.c @@ -6,9 +6,6 @@ * with heavy changes by Gao Xiang <xi...@kernel.org> */ #define _GNU_SOURCE -#ifdef EROFS_MT_ENABLED -#include <pthread.h> -#endif #include <string.h> #include <stdlib.h> #include <stdio.h> @@ -19,6 +16,7 @@ #endif #include <dirent.h> #include "erofs/print.h" +#include "erofs/lock.h" #include "erofs/diskbuf.h" #include "erofs/inode.h" #include "erofs/cache.h" @@ -85,48 +83,50 @@ unsigned char erofs_ftype_to_dtype(unsigned int filetype) return erofs_dtype_by_ftype[filetype]; } -#define NR_INODE_HASHTABLE 16384 - -struct list_head inode_hashtable[NR_INODE_HASHTABLE]; +static struct list_head erofs_ihash[65536]; +static erofs_rwsem_t erofs_ihashlock; void erofs_inode_manager_init(void) { unsigned int i; - for (i = 0; i < NR_INODE_HASHTABLE; ++i) - init_list_head(&inode_hashtable[i]); + for (i = 0; i < ARRAY_SIZE(erofs_ihash); ++i) + init_list_head(&erofs_ihash[i]); + erofs_init_rwsem(&erofs_ihashlock); } void erofs_insert_ihash(struct erofs_inode *inode) { - unsigned int nr = (inode->i_ino[1] ^ inode->dev) % NR_INODE_HASHTABLE; + u32 nr = (inode->i_ino[1] ^ inode->dev) % ARRAY_SIZE(erofs_ihash); - list_add(&inode->i_hash, &inode_hashtable[nr]); + erofs_down_write(&erofs_ihashlock); + list_add(&inode->i_hash, &erofs_ihash[nr]); + erofs_up_write(&erofs_ihashlock); } -/* get the inode from the (source) inode # */ -struct erofs_inode *erofs_iget(dev_t dev, ino_t ino) +void erofs_remove_ihash(struct erofs_inode *inode) { - struct list_head *head = - &inode_hashtable[(ino ^ dev) % NR_INODE_HASHTABLE]; - struct erofs_inode *inode; - - list_for_each_entry(inode, head, i_hash) - if (inode->i_ino[1] == ino && inode->dev == dev) - return erofs_igrab(inode); - return NULL; + erofs_down_write(&erofs_ihashlock); + list_del(&inode->i_hash); + erofs_up_write(&erofs_ihashlock); } -struct erofs_inode *erofs_iget_by_nid(erofs_nid_t nid) +/* get the inode from the (source) inode # */ +struct erofs_inode *erofs_iget(dev_t dev, ino_t ino) { - struct list_head *head = - &inode_hashtable[nid % NR_INODE_HASHTABLE]; - struct erofs_inode *inode; + u32 nr = (ino ^ dev) % ARRAY_SIZE(erofs_ihash); + struct list_head *head = &erofs_ihash[nr]; + struct erofs_inode *ret = NULL, *inode; - list_for_each_entry(inode, head, i_hash) - if (inode->nid == nid) - return erofs_igrab(inode); - return NULL; + erofs_down_read(&erofs_ihashlock); + list_for_each_entry(inode, head, i_hash) { + if (inode->i_ino[1] == ino && inode->dev == dev) { + ret = erofs_igrab(inode); + break; + } + } + erofs_up_read(&erofs_ihashlock); + return ret; } unsigned int erofs_iput(struct erofs_inode *inode) @@ -142,7 +142,7 @@ unsigned int erofs_iput(struct erofs_inode *inode) free(inode->compressmeta); free(inode->eof_tailraw); - list_del(&inode->i_hash); + erofs_remove_ihash(inode); free(inode->i_srcpath); if (inode->datasource == EROFS_INODE_DATA_SOURCE_DISKBUF) { @@ -1094,6 +1094,11 @@ struct erofs_inode *erofs_new_inode(struct erofs_sb_info *sbi) return ERR_PTR(-ENOMEM); inode->sbi = sbi; + /* + * By default, newly allocated in-memory inodes are associated with + * the target filesystem rather than any other foreign sources. + */ + inode->dev = sbi->dev; inode->i_count = 1; inode->datalayout = EROFS_INODE_FLAT_PLAIN; @@ -1707,7 +1712,7 @@ static int erofs_mkfs_dump_tree(struct erofs_inode *root, bool rebuild, if (incremental) { root->dev = root->sbi->dev; root->i_ino[1] = sbi->root_nid; - list_del(&root->i_hash); + erofs_remove_ihash(root); erofs_insert_ihash(root); } else if (cfg.c_root_xattr_isize) { if (cfg.c_root_xattr_isize > EROFS_XATTR_ALIGN( diff --git a/lib/rebuild.c b/lib/rebuild.c index 5787bb3..b61af15 100644 --- a/lib/rebuild.c +++ b/lib/rebuild.c @@ -481,7 +481,7 @@ static int erofs_rebuild_basedir_dirent_iter(struct erofs_dir_context *ctx) if (S_ISDIR(inode->i_mode) && (ctx->de_ftype == EROFS_FT_DIR || ctx->de_ftype == EROFS_FT_UNKNOWN)) { - list_del(&inode->i_hash); + erofs_remove_ihash(inode); inode->dev = dir->sbi->dev; inode->i_ino[1] = ctx->de_nid; erofs_insert_ihash(inode); -- 2.43.5