}
  
  /*
 - * Decode PATHCONF reply
 + * 3.3.12  REMOVE3res
 + *
 + *    struct REMOVE3resok {
 + *            wcc_data    dir_wcc;
 + *    };
 + *
 + *    struct REMOVE3resfail {
 + *            wcc_data    dir_wcc;
 + *    };
 + *
 + *    union REMOVE3res switch (nfsstat3 status) {
 + *    case NFS3_OK:
 + *            REMOVE3resok   resok;
 + *    default:
 + *            REMOVE3resfail resfail;
 + *    };
   */
 -static int
 -nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
 +static int nfs3_xdr_dec_remove3res(struct rpc_rqst *req,
 +                                 struct xdr_stream *xdr,
 +                                 struct nfs_removeres *result)
  {
 -      int             status;
 +      enum nfs_stat status;
 +      int error;
 +
 +      error = decode_nfsstat3(xdr, &status);
 +      if (unlikely(error))
 +              goto out;
 +      error = decode_wcc_data(xdr, result->dir_attr);
 +      if (unlikely(error))
 +              goto out;
 +      if (status != NFS3_OK)
 +              goto out_status;
 +out:
 +      return error;
 +out_status:
 +      return nfs_stat_to_errno(status);
 +}
  
 -      status = ntohl(*p++);
 +/*
 + * 3.3.14  RENAME3res
 + *
 + *    struct RENAME3resok {
 + *            wcc_data        fromdir_wcc;
 + *            wcc_data        todir_wcc;
 + *    };
 + *
 + *    struct RENAME3resfail {
 + *            wcc_data        fromdir_wcc;
 + *            wcc_data        todir_wcc;
 + *    };
 + *
 + *    union RENAME3res switch (nfsstat3 status) {
 + *    case NFS3_OK:
 + *            RENAME3resok   resok;
 + *    default:
 + *            RENAME3resfail resfail;
 + *    };
 + */
 +static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req,
 +                                 struct xdr_stream *xdr,
 +                                 struct nfs_renameres *result)
 +{
 +      enum nfs_stat status;
 +      int error;
 +
 +      error = decode_nfsstat3(xdr, &status);
 +      if (unlikely(error))
 +              goto out;
 +      error = decode_wcc_data(xdr, result->old_fattr);
 +      if (unlikely(error))
 +              goto out;
 +      error = decode_wcc_data(xdr, result->new_fattr);
 +      if (unlikely(error))
 +              goto out;
 +      if (status != NFS3_OK)
 +              goto out_status;
 +out:
 +      return error;
 +out_status:
 +      return nfs_stat_to_errno(status);
 +}
  
 -      p = xdr_decode_post_op_attr(p, res->fattr);
 -      if (status != 0)
 -              return nfs_stat_to_errno(status);
 -      res->max_link = ntohl(*p++);
 -      res->max_namelen = ntohl(*p++);
 +/*
 + * 3.3.15  LINK3res
 + *
 + *    struct LINK3resok {
 + *            post_op_attr    file_attributes;
 + *            wcc_data        linkdir_wcc;
 + *    };
 + *
 + *    struct LINK3resfail {
 + *            post_op_attr    file_attributes;
 + *            wcc_data        linkdir_wcc;
 + *    };
 + *
 + *    union LINK3res switch (nfsstat3 status) {
 + *    case NFS3_OK:
 + *            LINK3resok      resok;
 + *    default:
 + *            LINK3resfail    resfail;
 + *    };
 + */
 +static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, struct xdr_stream *xdr,
 +                               struct nfs3_linkres *result)
 +{
 +      enum nfs_stat status;
 +      int error;
 +
 +      error = decode_nfsstat3(xdr, &status);
 +      if (unlikely(error))
 +              goto out;
 +      error = decode_post_op_attr(xdr, result->fattr);
 +      if (unlikely(error))
 +              goto out;
 +      error = decode_wcc_data(xdr, result->dir_attr);
 +      if (unlikely(error))
 +              goto out;
 +      if (status != NFS3_OK)
 +              goto out_status;
 +out:
 +      return error;
 +out_status:
 +      return nfs_stat_to_errno(status);
 +}
 +
 +/**
 + * nfs3_decode_dirent - Decode a single NFSv3 directory entry stored in
 + *                    the local page cache
 + * @xdr: XDR stream where entry resides
 + * @entry: buffer to fill in with entry data
 + * @plus: boolean indicating whether this should be a readdirplus entry
 + *
 + * Returns zero if successful, otherwise a negative errno value is
 + * returned.
 + *
 + * This function is not invoked during READDIR reply decoding, but
 + * rather whenever an application invokes the getdents(2) system call
 + * on a directory already in our cache.
 + *
 + * 3.3.16  entry3
 + *
 + *    struct entry3 {
 + *            fileid3         fileid;
 + *            filename3       name;
 + *            cookie3         cookie;
 + *            fhandle3        filehandle;
 + *            post_op_attr3   attributes;
 + *            entry3          *nextentry;
 + *    };
 + *
 + * 3.3.17  entryplus3
 + *    struct entryplus3 {
 + *            fileid3         fileid;
 + *            filename3       name;
 + *            cookie3         cookie;
 + *            post_op_attr    name_attributes;
 + *            post_op_fh3     name_handle;
 + *            entryplus3      *nextentry;
 + *    };
 + */
 +int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
 +                     int plus)
 +{
 +      struct nfs_entry old = *entry;
 +      __be32 *p;
 +      int error;
 +
 +      p = xdr_inline_decode(xdr, 4);
 +      if (unlikely(p == NULL))
 +              goto out_overflow;
 +      if (*p == xdr_zero) {
 +              p = xdr_inline_decode(xdr, 4);
 +              if (unlikely(p == NULL))
 +                      goto out_overflow;
 +              if (*p == xdr_zero)
 +                      return -EAGAIN;
 +              entry->eof = 1;
 +              return -EBADCOOKIE;
 +      }
 +
 +      error = decode_fileid3(xdr, &entry->ino);
 +      if (unlikely(error))
 +              return error;
 +
 +      error = decode_inline_filename3(xdr, &entry->name, &entry->len);
 +      if (unlikely(error))
 +              return error;
 +
 +      entry->prev_cookie = entry->cookie;
 +      error = decode_cookie3(xdr, &entry->cookie);
 +      if (unlikely(error))
 +              return error;
 +
 +      entry->d_type = DT_UNKNOWN;
 +
 +      if (plus) {
 +              entry->fattr->valid = 0;
 +              error = decode_post_op_attr(xdr, entry->fattr);
 +              if (unlikely(error))
 +                      return error;
 +              if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
 +                      entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
 +
 +              /* In fact, a post_op_fh3: */
 +              p = xdr_inline_decode(xdr, 4);
 +              if (unlikely(p == NULL))
 +                      goto out_overflow;
 +              if (*p != xdr_zero) {
 +                      error = decode_nfs_fh3(xdr, entry->fh);
 +                      if (unlikely(error)) {
 +                              if (error == -E2BIG)
 +                                      goto out_truncated;
 +                              return error;
 +                      }
 +              } else
 +                      zero_nfs_fh3(entry->fh);
 +      }
  
-       /* Peek at the next entry to see if we're at EOD */
-       p = xdr_inline_peek(xdr, 4 + 4);
-       entry->eof = 0;
-       if (p != NULL)
-               entry->eof = (p[0] == xdr_zero) && (p[1] != xdr_zero);
 -      /* ignore remaining fields */
        return 0;
 +
 +out_overflow:
 +      print_overflow_msg(__func__, xdr);
 +      return -EAGAIN;
 +out_truncated:
 +      dprintk("NFS: directory entry contains invalid file handle\n");
 +      *entry = old;
 +      return -EAGAIN;
  }
  
  /*