NFSv4: Always ask for type with READDIR
authorBenjamin Coddington <bcodding@redhat.com>
Wed, 6 Dec 2023 13:10:22 +0000 (08:10 -0500)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Thu, 4 Jan 2024 15:47:56 +0000 (10:47 -0500)
Again we have claimed regressions for walking a directory tree, this time
with the "find" utility which always tries to optimize away asking for any
attributes until it has a complete list of entries.  This behavior makes
the readdir plus heuristic do the wrong thing, which causes a storm of
GETATTRs to determine each entry's type in order to continue the walk.

For v4 add the type attribute to each READDIR request to include it no
matter the heuristic.  This allows a simple `find` command to proceed
quickly through a directory tree.

Suggested-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/nfs4xdr.c

index deec76cf5afeaffe5af3a0e8330fb33e71c97f31..69406e60f391e274c83a215bdbd72fc36c8ad78e 100644 (file)
@@ -1602,7 +1602,8 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_pgio_args *args
 static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr)
 {
        uint32_t attrs[3] = {
-               FATTR4_WORD0_RDATTR_ERROR,
+               FATTR4_WORD0_TYPE
+               | FATTR4_WORD0_RDATTR_ERROR,
                FATTR4_WORD1_MOUNTED_ON_FILEID,
        };
        uint32_t dircount = readdir->count;
@@ -1612,12 +1613,20 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
        unsigned int i;
 
        if (readdir->plus) {
-               attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE|
-                       FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE|FATTR4_WORD0_FILEID;
-               attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER|
-                       FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV|
-                       FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS|
-                       FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
+               attrs[0] |= FATTR4_WORD0_CHANGE
+                       | FATTR4_WORD0_SIZE
+                       | FATTR4_WORD0_FSID
+                       | FATTR4_WORD0_FILEHANDLE
+                       | FATTR4_WORD0_FILEID;
+               attrs[1] |= FATTR4_WORD1_MODE
+                       | FATTR4_WORD1_NUMLINKS
+                       | FATTR4_WORD1_OWNER
+                       | FATTR4_WORD1_OWNER_GROUP
+                       | FATTR4_WORD1_RAWDEV
+                       | FATTR4_WORD1_SPACE_USED
+                       | FATTR4_WORD1_TIME_ACCESS
+                       | FATTR4_WORD1_TIME_METADATA
+                       | FATTR4_WORD1_TIME_MODIFY;
                attrs[2] |= FATTR4_WORD2_SECURITY_LABEL;
        }
        /* Use mounted_on_fileid only if the server supports it */