To ensure the uniquness of the inode-number, manage it by IDR. Also it tries using the lowest unused inode-number, so the value will usually be smaller. Cc: Eric Dumazet <edumazet@xxxxxxxxxx> Cc: Hugh Dickins <hughd@xxxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxx> Cc: Andreas Dilger <adilger@xxxxxxxxx> Cc: Jan Kara <jack@xxxxxxx> Signed-off-by: J. R. Okajima <hooanon05g@xxxxxxxxx> --- include/linux/shmem_fs.h | 2 ++ mm/shmem.c | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 4d1771c..30c75f0 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -24,6 +24,8 @@ struct shmem_inode_info { }; struct shmem_sb_info { + struct mutex idr_lock; + struct idr idr; /* manages inode-number */ unsigned long max_blocks; /* How many blocks are allowed */ struct percpu_counter used_blocks; /* How many are allocated */ unsigned long max_inodes; /* How many inodes are allowed */ diff --git a/mm/shmem.c b/mm/shmem.c index 368f314..440db70 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -569,6 +569,7 @@ static int shmem_setattr(struct dentry *dentry, struct iattr *attr) static void shmem_evict_inode(struct inode *inode) { struct shmem_inode_info *info = SHMEM_I(inode); + struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); if (inode->i_mapping->a_ops == &shmem_aops) { shmem_unacct_size(info->flags, inode->i_size); @@ -584,6 +585,9 @@ static void shmem_evict_inode(struct inode *inode) simple_xattrs_free(&info->xattrs); WARN_ON(inode->i_blocks); + mutex_lock(&sbinfo->idr_lock); + idr_remove(&sbinfo->idr, inode->i_ino); + mutex_unlock(&sbinfo->idr_lock); shmem_free_inode(inode->i_sb); clear_inode(inode); } @@ -1315,13 +1319,13 @@ 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); + long long ino; /* signed to detect an error */ if (shmem_reserve_inode(sb)) return NULL; inode = new_inode(sb); if (inode) { - inode->i_ino = get_next_ino(); inode_init_owner(inode, dir, mode); inode->i_blocks = 0; inode->i_mapping->backing_dev_info = &shmem_backing_dev_info; @@ -1362,6 +1366,17 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode mpol_shared_policy_init(&info->policy, NULL); break; } + + /* inum 0 and 1 are unused */ + mutex_lock(&sbinfo->idr_lock); + ino = idr_alloc(&sbinfo->idr, inode, 2, UINT_MAX, GFP_NOFS); + if (ino > 0) + inode->i_ino = ino; + mutex_unlock(&sbinfo->idr_lock); + if (unlikely(ino < 0)) { + iput(inode); /* shmem_free_inode() will be called */ + inode = NULL; + } } else shmem_free_inode(sb); return inode; @@ -2504,6 +2519,7 @@ static void shmem_put_super(struct super_block *sb) { struct shmem_sb_info *sbinfo = SHMEM_SB(sb); + idr_destroy(&sbinfo->idr); percpu_counter_destroy(&sbinfo->used_blocks); mpol_put(sbinfo->mpol); kfree(sbinfo); @@ -2522,6 +2538,8 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent) if (!sbinfo) return -ENOMEM; + mutex_init(&sbinfo->idr_lock); + idr_init(&sbinfo->idr); sbinfo->mode = S_IRWXUGO | S_ISVTX; sbinfo->uid = current_fsuid(); sbinfo->gid = current_fsgid(); -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html