Message ID | 42d3218724fbe3758005f984ad85934a50c33611.1675348307.git.bcodding@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | generic/676: Unstable d_type handling for NFS READDIR | expand |
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 >
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,
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(-)