Messages in this thread Patch in this message | | | From | Minchan Kim <> | Subject | [RFC PATCH] kernfs: release kernfs_mutex before the inode allocation | Date | Tue, 16 Nov 2021 11:43:17 -0800 |
| |
The kernfs implementation has big lock granularity(kernfs_rwsem) so every kernfs-based(e.g., sysfs, cgroup, dmabuf) fs are able to compete the lock. Thus, if one of userspace goes the sleep under holding the lock for a long time, rest of them should wait it. A example is the holder goes direct reclaim with the lock since it needs memory allocation. Let's fix it at common technique that release the lock and then allocate the memory. Fortunately, kernfs looks like have an refcount so I hope it's fine.
Signed-off-by: Minchan Kim <minchan@kernel.org> --- fs/kernfs/dir.c | 14 +++++++++++--- fs/kernfs/inode.c | 2 +- fs/kernfs/kernfs-internal.h | 1 + 3 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index 8e0a1378a4b1..ecdb2975060d 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -1119,9 +1119,17 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir, up_read(&kernfs_rwsem); return NULL; } - inode = kernfs_get_inode(dir->i_sb, kn); - if (!inode) - inode = ERR_PTR(-ENOMEM); + kernfs_get(kn); + up_read(&kernfs_rwsem); + inode = iget_locked(dir->i_sb, kernfs_ino(kn)); + if (!inode) { + kernfs_put(kn); + return ERR_PTR(-ENOMEM); + } + down_read(&kernfs_rwsem); + if (inode->i_state & I_NEW) + kernfs_init_inode(kn, inode); + kernfs_put(kn); } /* * Needed for negative dentry validation. diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index c0eae1725435..6e2004010435 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c @@ -195,7 +195,7 @@ int kernfs_iop_getattr(struct user_namespace *mnt_userns, return 0; } -static void kernfs_init_inode(struct kernfs_node *kn, struct inode *inode) +void kernfs_init_inode(struct kernfs_node *kn, struct inode *inode) { kernfs_get(kn); inode->i_private = kn; diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index f9cc912c31e1..eef7656f7cd8 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -118,6 +118,7 @@ int kernfs_iop_getattr(struct user_namespace *mnt_userns, u32 request_mask, unsigned int query_flags); ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size); int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr); +void kernfs_init_inode(struct kernfs_node *kn, struct inode *inode); /* * dir.c -- 2.34.0.rc1.387.gb447b232ab-goog
| |