Re: [PATCH] generic/676: Unstable d_type handling for NFS READDIR

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]



On Thu, Feb 02, 2023 at 09:48:04AM -0500, Benjamin Coddington wrote:
> The NFS client may send READDIR or READDIRPLUS to populate the dentry
> cache, and switch between them to optimize for least RPC calls based on the
> process' behavior.  When using READDIR, dentries will have d_type =
> DT_UNKNOWN but with READDIRPLUS d_type will be set from the mode.
> 
> This heuristic will cause generic/676 to fail when comparing dentries
> cached from one or the other call, since we compare d_type directly. Fix
> this by bypassing the comparison of d_type if any entry is loaded with
> DT_UNKNOWN.
> 
> Signed-off-by: Benjamin Coddington <bcodding@xxxxxxxxxx>
> ---

OK, thanks for this fix from nfs side. I think it doesn't affect other fs
testing, then I'd like to merge it if it's helpful for nfs side. If anyone
has objection, please tell us.

Reviewed-by: Zorro Lang <zlang@xxxxxxxxxx>

Thanks,
Zorro

>  src/t_readdir_3.c | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/src/t_readdir_3.c b/src/t_readdir_3.c
> index e5179ab27c51..8f9bb326dccb 100644
> --- a/src/t_readdir_3.c
> +++ b/src/t_readdir_3.c
> @@ -27,6 +27,7 @@ struct linux_dirent64 {
>  static DIR *dir;
>  static int dfd;
>  static int ignore_error;
> +static int ignore_dtype = 0;
>  
>  struct dir_ops {
>  	loff_t (*getpos)(void);
> @@ -61,6 +62,10 @@ static void libc_getentry(struct dirent *entry)
>  		exit(1);
>  	}
>  	memcpy(entry, ret, sizeof(struct dirent));
> +
> +	/* NFS may or may not set d_type, depending on READDIRPLUS */
> +	if (!ignore_dtype && entry->d_type == DT_UNKNOWN)
> +		ignore_dtype = 1;
>  }
>  
>  static off64_t kernel_getpos(void)
> @@ -95,6 +100,10 @@ static void kernel_getentry(struct dirent *entry)
>  	entry->d_reclen = lentry->d_reclen;
>  	entry->d_type = lentry->d_type;
>  	strcpy(entry->d_name, lentry->d_name);
> +
> +	/* NFS may or may not set d_type, depending on READDIRPLUS */
> +	if (!ignore_dtype && entry->d_type == DT_UNKNOWN)
> +		ignore_dtype = 1;
>  }
>  
>  struct dir_ops libc_ops = {
> @@ -168,8 +177,9 @@ static void test(int count, struct dir_ops *ops)
>  		pos = random() % count;
>  		ops->setpos(pbuf[pos]);
>  		ops->getentry(&entry);
> +
>  		if (dbuf[pos].d_ino != entry.d_ino ||
> -		    dbuf[pos].d_type != entry.d_type ||
> +		    (!ignore_dtype && dbuf[pos].d_type != entry.d_type) ||
>  		    strcmp(dbuf[pos].d_name, entry.d_name)) {
>  			fprintf(stderr,
>  				"Mismatch in dir entry %u at pos %llu\n", pos,
> -- 
> 2.31.1
> 




[Index of Archives]     [Linux Filesystems Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux