On Wed, Jun 26, 2024 at 06:47:15AM +0900, OGAWA Hirofumi wrote: > Thadeu Lima de Souza Cascardo <cascardo@xxxxxxxxxx> writes: > > > Instead of only using dir_emit_dots for the root inode and explictily > > requiring the . and .. entries to emit them, use dir_emit_dots for all > > directories. > > > > That allows filesystems with directories without the . or .. entries to > > still show them. > > Unacceptable to change the correct behavior to broken format. And > unlikely break the userspace, however this still has the user visible > change of seek pos. > > Thanks. > I agree that if this breaks userspace with a good filesystem or regresses in a way that real applications would break, that this needs to be redone. However, I spent a few hours doing some extra testing (I had already run some xfstests that include directory testing) and I failed to find any issues with this fix. If this would break, it would have broken the root directory. In the case of a directory including the . and .. entries, the d_off for the .. entry will be set for the first non-dot-or-dotdot entry. For ., it will be set as 1, which, if used by telldir (or llseek), will emit the .. entry, as expected. For the case where both . and .. are absent, the first real entry will have d_off as 2, and it will just work. So everything seems to work as expected. Do you see any user visible change that would break any applications? Thanks. Cascardo. > > Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@xxxxxxxxxx> > > --- > > fs/fat/dir.c | 24 +++++++++--------------- > > 1 file changed, 9 insertions(+), 15 deletions(-) > > > > diff --git a/fs/fat/dir.c b/fs/fat/dir.c > > index 4e4a359a1ea3..e70781569de5 100644 > > --- a/fs/fat/dir.c > > +++ b/fs/fat/dir.c > > @@ -583,15 +583,14 @@ static int __fat_readdir(struct inode *inode, struct file *file, > > mutex_lock(&sbi->s_lock); > > > > cpos = ctx->pos; > > - /* Fake . and .. for the root directory. */ > > - if (inode->i_ino == MSDOS_ROOT_INO) { > > - if (!dir_emit_dots(file, ctx)) > > - goto out; > > - if (ctx->pos == 2) { > > - fake_offset = 1; > > - cpos = 0; > > - } > > + > > + if (!dir_emit_dots(file, ctx)) > > + goto out; > > + if (ctx->pos == 2) { > > + fake_offset = 1; > > + cpos = 0; > > } > > + > > if (cpos & (sizeof(struct msdos_dir_entry) - 1)) { > > ret = -ENOENT; > > goto out; > > @@ -671,13 +670,8 @@ static int __fat_readdir(struct inode *inode, struct file *file, > > if (fake_offset && ctx->pos < 2) > > ctx->pos = 2; > > > > - if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) { > > - if (!dir_emit_dot(file, ctx)) > > - goto fill_failed; > > - } else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) { > > - if (!dir_emit_dotdot(file, ctx)) > > - goto fill_failed; > > - } else { > > + if (memcmp(de->name, MSDOS_DOT, MSDOS_NAME) && > > + memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) { > > unsigned long inum; > > loff_t i_pos = fat_make_i_pos(sb, bh, de); > > struct inode *tmp = fat_iget(sb, i_pos); > > -- > OGAWA Hirofumi <hirofumi@xxxxxxxxxxxxxxxxxx>