The patch itself looks good to me.

On 6/29/22 4:15 PM, Hongnan Li wrote:
> erofs_readdir update ctx->pos after filling a batch of dentries
> and it may cause dir/files duplication for NFS readdirplus which
> depends on ctx->pos to fill dir correctly. So update ctx->pos for
> every emitted dirent in erofs_fill_dentries to fix it.
> 
> Fixes: 3e917cc305c6 ("erofs: make filesystem exportable")
> Signed-off-by: Hongnan Li <[email protected]>
> ---
>  fs/erofs/dir.c | 16 +++++++---------
>  1 file changed, 7 insertions(+), 9 deletions(-)
> 
> diff --git a/fs/erofs/dir.c b/fs/erofs/dir.c
> index 18e59821c597..6fc325052853 100644
> --- a/fs/erofs/dir.c
> +++ b/fs/erofs/dir.c
> @@ -22,10 +22,9 @@ static void debug_one_dentry(unsigned char d_type, const 
> char *de_name,
>  }
>  
>  static int erofs_fill_dentries(struct inode *dir, struct dir_context *ctx,
> -                            void *dentry_blk, unsigned int *ofs,
> +                            void *dentry_blk, struct erofs_dirent *de,
>                              unsigned int nameoff, unsigned int maxsize)
>  {
> -     struct erofs_dirent *de = dentry_blk + *ofs;
>       const struct erofs_dirent *end = dentry_blk + nameoff;
>  
>       while (de < end) {
> @@ -59,9 +58,8 @@ static int erofs_fill_dentries(struct inode *dir, struct 
> dir_context *ctx,
>                       /* stopped by some reason */
>                       return 1;
>               ++de;
> -             *ofs += sizeof(struct erofs_dirent);
> +             ctx->pos += sizeof(struct erofs_dirent);
>       }
> -     *ofs = maxsize;
>       return 0;
>  }
>  
> @@ -95,7 +93,7 @@ static int erofs_readdir(struct file *f, struct dir_context 
> *ctx)
>                                 "invalid de[0].nameoff %u @ nid %llu",
>                                 nameoff, EROFS_I(dir)->nid);
>                       err = -EFSCORRUPTED;
> -                     goto skip_this;
> +                     break;
>               }
>  
>               maxsize = min_t(unsigned int,
> @@ -106,17 +104,17 @@ static int erofs_readdir(struct file *f, struct 
> dir_context *ctx)
>                       initial = false;
>  
>                       ofs = roundup(ofs, sizeof(struct erofs_dirent));
> +                     ctx->pos = blknr_to_addr(i) + ofs;
>                       if (ofs >= nameoff)
>                               goto skip_this;

Besides, I thinks there's another issue with erofs_readdir() here
(though unrelated to the issue this patch wants to fix).

We need to update ctx->pos correctly if the initial file position has
exceeded nameoff. ctx->pos needs to be updated to the end of
EROFS_BLKSIZ or directory's i_size, surpassing the remaining name string
in the current EROFS block.

>               }
>  
> -             err = erofs_fill_dentries(dir, ctx, de, &ofs,
> +             err = erofs_fill_dentries(dir, ctx, de, (void *)de + ofs,
>                                         nameoff, maxsize);
> -skip_this:
> -             ctx->pos = blknr_to_addr(i) + ofs;
> -
>               if (err)
>                       break;

> +             ctx->pos = blknr_to_addr(i) + maxsize;

It's quite easy to fix the above issue. We only need to move this line
beneath skip_this label.

> +skip_this:>                  ++i;
>               ofs = 0;
>       }

like:

        skip_this:
                ctx->pos = blknr_to_addr(i) + maxsize;
                ++i;
                ofs = 0;

Thus we'd better fold this simple fix into this patch.

-- 
Thanks,
Jeffle

Reply via email to