mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-07-07 22:35:42 +02:00
libfs: getdents() should return 0 after reaching EOD
The new directory offset helpers don't conform with the convention
of getdents() returning no more entries once a directory file
descriptor has reached the current end-of-directory.
To address this, copy the logic from dcache_readdir() to mark the
open directory file descriptor once EOD has been reached. Seeking
resets the mark.
Reported-by: Tavian Barnes <tavianator@tavianator.com>
Closes: https://lore.kernel.org/linux-fsdevel/20231113180616.2831430-1-tavianator@tavianator.com/
Fixes: 6faddda69f
("libfs: Add directory operations for stable offsets")
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Link: https://lore.kernel.org/r/170043792492.4628.15646203084646716134.stgit@bazille.1015granger.net
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
9c04138414
commit
796432efab
14
fs/libfs.c
14
fs/libfs.c
|
@ -399,6 +399,8 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* In this case, ->private_data is protected by f_pos_lock */
|
||||
file->private_data = NULL;
|
||||
return vfs_setpos(file, offset, U32_MAX);
|
||||
}
|
||||
|
||||
|
@ -428,7 +430,7 @@ 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 inode *inode, struct dir_context *ctx)
|
||||
static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
|
||||
{
|
||||
struct offset_ctx *so_ctx = inode->i_op->get_offset_ctx(inode);
|
||||
XA_STATE(xas, &so_ctx->xa, ctx->pos);
|
||||
|
@ -437,7 +439,7 @@ static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
|
|||
while (true) {
|
||||
dentry = offset_find_next(&xas);
|
||||
if (!dentry)
|
||||
break;
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
if (!offset_dir_emit(ctx, dentry)) {
|
||||
dput(dentry);
|
||||
|
@ -447,6 +449,7 @@ static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
|
|||
dput(dentry);
|
||||
ctx->pos = xas.xa_index + 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -479,7 +482,12 @@ static int offset_readdir(struct file *file, struct dir_context *ctx)
|
|||
if (!dir_emit_dots(file, ctx))
|
||||
return 0;
|
||||
|
||||
offset_iterate_dir(d_inode(dir), ctx);
|
||||
/* In this case, ->private_data is protected by f_pos_lock */
|
||||
if (ctx->pos == 2)
|
||||
file->private_data = NULL;
|
||||
else if (file->private_data == ERR_PTR(-ENOENT))
|
||||
return 0;
|
||||
file->private_data = offset_iterate_dir(d_inode(dir), ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user