fstests.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] generic/676: Unstable d_type handling for NFS READDIR
@ 2023-02-02 14:48 Benjamin Coddington
  2023-02-09 14:54 ` Zorro Lang
  0 siblings, 1 reply; 2+ messages in thread
From: Benjamin Coddington @ 2023-02-02 14:48 UTC (permalink / raw)
  To: Eryu Guan, Jan Kara, fstests; +Cc: Benjamin Coddington

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@redhat.com>
---
 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


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] generic/676: Unstable d_type handling for NFS READDIR
  2023-02-02 14:48 [PATCH] generic/676: Unstable d_type handling for NFS READDIR Benjamin Coddington
@ 2023-02-09 14:54 ` Zorro Lang
  0 siblings, 0 replies; 2+ messages in thread
From: Zorro Lang @ 2023-02-09 14:54 UTC (permalink / raw)
  To: Benjamin Coddington; +Cc: fstests

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@redhat.com>
> ---

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@redhat.com>

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
> 


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-02-09 14:55 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-02 14:48 [PATCH] generic/676: Unstable d_type handling for NFS READDIR Benjamin Coddington
2023-02-09 14:54 ` Zorro Lang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).