summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2023-07-25 14:31:04 -0400
committerChristian Brauner <brauner@kernel.org>2023-08-09 09:15:41 +0200
commit2be4f05af71bb2a9958c5680c19e5a489636ff42 (patch)
tree422fc12ee546561b1ccf87b66842201799e43f69
parentbbaef7973dd017954419718ab2df526ae1f66e93 (diff)
libfs: Remove parent dentry locking in offset_iterate_dir()
Since offset_iterate_dir() does not walk the parent's d_subdir list nor does it manipulate the parent's d_child, there doesn't seem to be a reason to hold the parent's d_lock. The offset_ctx's xarray can be sufficiently protected with just the RCU read lock. Flame graph data captured during the git regression run shows a 20% reduction in CPU cycles consumed in offset_find_next(). Reported-by: kernel test robot <oliver.sang@intel.com> Closes: https://lore.kernel.org/oe-lkp/202307171640.e299f8d5-oliver.sang@intel.com Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Message-Id: <169030957098.157536.9938425508695693348.stgit@manet.1015granger.net> Signed-off-by: Christian Brauner <brauner@kernel.org>
-rw-r--r--fs/libfs.c11
1 files changed, 4 insertions, 7 deletions
diff --git a/fs/libfs.c b/fs/libfs.c
index 3495f071093e..c78a48654a94 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -407,7 +407,7 @@ static struct dentry *offset_find_next(struct xa_state *xas)
child = xas_next_entry(xas, U32_MAX);
if (!child)
goto out;
- spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
+ spin_lock(&child->d_lock);
if (simple_positive(child))
found = dget_dlock(child);
spin_unlock(&child->d_lock);
@@ -425,17 +425,14 @@ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry)
inode->i_ino, fs_umode_to_dtype(inode->i_mode));
}
-static void offset_iterate_dir(struct dentry *dir, struct dir_context *ctx)
+static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
{
- struct inode *inode = d_inode(dir);
struct offset_ctx *so_ctx = inode->i_op->get_offset_ctx(inode);
XA_STATE(xas, &so_ctx->xa, ctx->pos);
struct dentry *dentry;
while (true) {
- spin_lock(&dir->d_lock);
dentry = offset_find_next(&xas);
- spin_unlock(&dir->d_lock);
if (!dentry)
break;
@@ -465,7 +462,7 @@ static void offset_iterate_dir(struct dentry *dir, struct dir_context *ctx)
* output buffer.
*
* On return, @ctx->pos contains an offset that will read the next entry
- * in this directory when shmem_readdir() is called again with @ctx.
+ * in this directory when offset_readdir() is called again with @ctx.
*
* Return values:
* %0 - Complete
@@ -479,7 +476,7 @@ static int offset_readdir(struct file *file, struct dir_context *ctx)
if (!dir_emit_dots(file, ctx))
return 0;
- offset_iterate_dir(dir, ctx);
+ offset_iterate_dir(d_inode(dir), ctx);
return 0;
}