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 >