From: Nick Piggin <npiggin@xxxxxxx> Before removing the inode_lock, the iunique counter needs to be made independent of the inode_lock. Add a new lock to protect the iunique counter and nest it inside the inode_lock to provide the same protection that the inode_lock currently provides. Signed-off-by: Nick Piggin <npiggin@xxxxxxx> Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx> Reviewed-by: Christoph Hellwig <hch@xxxxxx> --- fs/inode.c | 35 ++++++++++++++++++++++++++++------- 1 files changed, 28 insertions(+), 7 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index e65a01d..434a49b 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1053,6 +1053,30 @@ static struct inode *get_new_inode_fast(struct super_block *sb, return inode; } +/* + * search the inode cache for a matching inode number. + * If we find one, then the inode number we are trying to + * allocate is not unique and so we should not use it. + * + * Returns 1 if the inode number is unique, 0 if it is not. + */ +static int test_inode_iunique(struct super_block * sb, unsigned long ino) +{ + struct hlist_bl_head *b = inode_hashtable + hash(sb, ino); + struct hlist_bl_node *node; + struct inode *inode; + + hlist_bl_lock(b); + hlist_bl_for_each_entry(inode, node, b, i_hash) { + if (inode->i_ino == ino && inode->i_sb == sb) { + hlist_bl_unlock(b); + return 0; + } + } + hlist_bl_unlock(b); + return 1; +} + /** * iunique - get a unique inode number * @sb: superblock @@ -1074,20 +1098,17 @@ ino_t iunique(struct super_block *sb, ino_t max_reserved) * error if st_ino won't fit in target struct field. Use 32bit counter * here to attempt to avoid that. */ + static DEFINE_SPINLOCK(iunique_lock); static unsigned int counter; - struct inode *inode; - struct hlist_bl_head *b; ino_t res; - spin_lock(&inode_lock); + spin_lock(&iunique_lock); do { if (counter <= max_reserved) counter = max_reserved + 1; res = counter++; - b = inode_hashtable + hash(sb, res); - inode = find_inode_fast(sb, b, res); - } while (inode != NULL); - spin_unlock(&inode_lock); + } while (!test_inode_iunique(sb, res)); + spin_unlock(&iunique_lock); return res; } -- 1.7.1 -- 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