| From 28235dd3e8170633e5d125cab717d962973c6c68 Mon Sep 17 00:00:00 2001 |
| From: Tejun Heo <tj@kernel.org> |
| Date: Mon, 4 Nov 2019 15:54:29 -0800 |
| Subject: [PATCH] kernfs: fix ino wrap-around detection |
| |
| commit e23f568aa63f64cd6b355094224cc9356c0f696b upstream. |
| |
| When the 32bit ino wraps around, kernfs increments the generation |
| number to distinguish reused ino instances. The wrap-around detection |
| tests whether the allocated ino is lower than what the cursor but the |
| cursor is pointing to the next ino to allocate so the condition never |
| triggers. |
| |
| Fix it by remembering the last ino and comparing against that. |
| |
| Signed-off-by: Tejun Heo <tj@kernel.org> |
| Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Fixes: 4a3ef68acacf ("kernfs: implement i_generation") |
| Cc: Namhyung Kim <namhyung@kernel.org> |
| Cc: stable@vger.kernel.org # v4.14+ |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c |
| index a387534c9577..a5a65de50318 100644 |
| --- a/fs/kernfs/dir.c |
| +++ b/fs/kernfs/dir.c |
| @@ -621,7 +621,6 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root, |
| { |
| struct kernfs_node *kn; |
| u32 gen; |
| - int cursor; |
| int ret; |
| |
| name = kstrdup_const(name, GFP_KERNEL); |
| @@ -634,11 +633,11 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root, |
| |
| idr_preload(GFP_KERNEL); |
| spin_lock(&kernfs_idr_lock); |
| - cursor = idr_get_cursor(&root->ino_idr); |
| ret = idr_alloc_cyclic(&root->ino_idr, kn, 1, 0, GFP_ATOMIC); |
| - if (ret >= 0 && ret < cursor) |
| + if (ret >= 0 && ret < root->last_ino) |
| root->next_generation++; |
| gen = root->next_generation; |
| + root->last_ino = ret; |
| spin_unlock(&kernfs_idr_lock); |
| idr_preload_end(); |
| if (ret < 0) |
| diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h |
| index 936b61bd504e..f797ccc650e7 100644 |
| --- a/include/linux/kernfs.h |
| +++ b/include/linux/kernfs.h |
| @@ -187,6 +187,7 @@ struct kernfs_root { |
| |
| /* private fields, do not use outside kernfs proper */ |
| struct idr ino_idr; |
| + u32 last_ino; |
| u32 next_generation; |
| struct kernfs_syscall_ops *syscall_ops; |
| |
| -- |
| 2.7.4 |
| |