[PATCH 2/2] erofs-utils: lib: refine the inode hash table
Gao Xiang
hsiangkao at linux.alibaba.com
Wed Jun 18 19:58:26 AEST 2025
- Increase the hash table entries to 65536;
- Protect the hash table with `erofs_rwsem`.
Signed-off-by: Gao Xiang <hsiangkao at 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 <xiang at 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
More information about the Linux-erofs
mailing list