- 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


Reply via email to