[PATCH] tmpfs: use ida to get inode number

From: zhengbin
Date: Wed Nov 20 2019 - 09:16:08 EST


Use a script to test tmpfs, after 10 days, there will be files share the
same inode number, thus bug happens.
The script is as follows:
while(1) {
create a file
dlopen it
...
remove it
}

I have tried to change last_ino type to unsigned long, while this was
rejected, see details on https://patchwork.kernel.org/patch/11023915.

Use ida to get inode number, from the fs_mark test, performance impact
is small.

CPU core: 128 memory: 8G
Use fs_mark to create ten million files first in tmpfs.

Then test performance in the following command(test five times):
rm -rf /tmp/fsmark_test
sync
echo 3 > /proc/sys/vm/drop_caches
sleep 10
fs_mark -t 20 -s 0 -n 102400 -D 64 -N 1600 -L 3 -d /tmp/fsmark_test

result is file creation speed(Files/sec).
get_next_ino | use ida
439506.7 | 423219.0
441453.0 | 406832.7
439868.0 | 441283.3
445642.3 | 428221.3
441776.7 | 438129.0
average:
441649.34 | 427537.06

Signed-off-by: zhengbin <zhengbin13@xxxxxxxxxx>
---
mm/shmem.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index 5b93877..6b5e01b 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -258,6 +258,7 @@ static const struct inode_operations shmem_dir_inode_operations;
static const struct inode_operations shmem_special_inode_operations;
static const struct vm_operations_struct shmem_vm_ops;
static struct file_system_type shmem_fs_type;
+static DEFINE_IDA(shmem_inode_ida);

bool vma_is_shmem(struct vm_area_struct *vma)
{
@@ -1138,6 +1139,7 @@ static void shmem_evict_inode(struct inode *inode)

simple_xattrs_free(&info->xattrs);
WARN_ON(inode->i_blocks);
+ ida_simple_remove(&shmem_inode_ida, inode->i_ino);
shmem_free_inode(inode->i_sb);
clear_inode(inode);
}
@@ -2213,13 +2215,20 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode
struct inode *inode;
struct shmem_inode_info *info;
struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
+ int i_ino;

if (shmem_reserve_inode(sb))
return NULL;

+ i_ino = ida_simple_get(&shmem_inode_ida, 0, 0, GFP_KERNEL);
+ if (i_ino < 0) {
+ shmem_free_inode(sb);
+ return NULL;
+ }
+
inode = new_inode(sb);
if (inode) {
- inode->i_ino = get_next_ino();
+ inode->i_ino = i_ino;
inode_init_owner(inode, dir, mode);
inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
@@ -2263,8 +2272,11 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode
}

lockdep_annotate_inode_mutex_key(inode);
- } else
+ } else {
+ ida_simple_remove(&shmem_inode_ida, i_ino);
shmem_free_inode(sb);
+ }
+
return inode;
}

--
2.7.4