Commit 0b26a0bf authored by Trond Myklebust's avatar Trond Myklebust

NFS: Ensure we return the dirent->d_type when it is known

Store the dirent->d_type in the struct nfs_cache_array_entry so that we
can use it in getdents() calls.

This fixes a regression with the new readdir code.
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 3020093f
...@@ -162,6 +162,7 @@ struct nfs_cache_array_entry { ...@@ -162,6 +162,7 @@ struct nfs_cache_array_entry {
u64 cookie; u64 cookie;
u64 ino; u64 ino;
struct qstr string; struct qstr string;
unsigned char d_type;
}; };
struct nfs_cache_array { struct nfs_cache_array {
...@@ -265,6 +266,7 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) ...@@ -265,6 +266,7 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
cache_entry->cookie = entry->prev_cookie; cache_entry->cookie = entry->prev_cookie;
cache_entry->ino = entry->ino; cache_entry->ino = entry->ino;
cache_entry->d_type = entry->d_type;
ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len); ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len);
if (ret) if (ret)
goto out; goto out;
...@@ -701,7 +703,6 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, ...@@ -701,7 +703,6 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
int i = 0; int i = 0;
int res = 0; int res = 0;
struct nfs_cache_array *array = NULL; struct nfs_cache_array *array = NULL;
unsigned int d_type = DT_UNKNOWN;
array = nfs_readdir_get_array(desc->page); array = nfs_readdir_get_array(desc->page);
if (IS_ERR(array)) { if (IS_ERR(array)) {
...@@ -711,11 +712,11 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, ...@@ -711,11 +712,11 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
for (i = desc->cache_entry_index; i < array->size; i++) { for (i = desc->cache_entry_index; i < array->size; i++) {
struct nfs_cache_array_entry *ent; struct nfs_cache_array_entry *ent;
d_type = DT_UNKNOWN;
ent = &array->array[i]; ent = &array->array[i];
if (filldir(dirent, ent->string.name, ent->string.len, if (filldir(dirent, ent->string.name, ent->string.len,
file->f_pos, nfs_compat_user_ino64(ent->ino), d_type) < 0) { file->f_pos, nfs_compat_user_ino64(ent->ino),
ent->d_type) < 0) {
desc->eof = 1; desc->eof = 1;
break; break;
} }
......
...@@ -361,6 +361,15 @@ unsigned int nfs_page_length(struct page *page) ...@@ -361,6 +361,15 @@ unsigned int nfs_page_length(struct page *page)
return 0; return 0;
} }
/*
* Convert a umode to a dirent->d_type
*/
static inline
unsigned char nfs_umode_to_dtype(umode_t mode)
{
return (mode >> 12) & 15;
}
/* /*
* Determine the number of pages in an array of length 'len' and * Determine the number of pages in an array of length 'len' and
* with a base offset of 'base' * with a base offset of 'base'
......
...@@ -485,6 +485,8 @@ nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_se ...@@ -485,6 +485,8 @@ nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_se
entry->prev_cookie = entry->cookie; entry->prev_cookie = entry->cookie;
entry->cookie = ntohl(*p++); entry->cookie = ntohl(*p++);
entry->d_type = DT_UNKNOWN;
p = xdr_inline_peek(xdr, 8); p = xdr_inline_peek(xdr, 8);
if (p != NULL) if (p != NULL)
entry->eof = !p[0] && p[1]; entry->eof = !p[0] && p[1];
......
...@@ -622,11 +622,13 @@ nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_s ...@@ -622,11 +622,13 @@ nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_s
entry->prev_cookie = entry->cookie; entry->prev_cookie = entry->cookie;
p = xdr_decode_hyper(p, &entry->cookie); p = xdr_decode_hyper(p, &entry->cookie);
entry->d_type = DT_UNKNOWN;
if (plus) { if (plus) {
entry->fattr->valid = 0; entry->fattr->valid = 0;
p = xdr_decode_post_op_attr_stream(xdr, entry->fattr); p = xdr_decode_post_op_attr_stream(xdr, entry->fattr);
if (IS_ERR(p)) if (IS_ERR(p))
goto out_overflow_exit; goto out_overflow_exit;
entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
/* In fact, a post_op_fh3: */ /* In fact, a post_op_fh3: */
p = xdr_inline_decode(xdr, 4); p = xdr_inline_decode(xdr, 4);
if (unlikely(!p)) if (unlikely(!p))
......
...@@ -6208,6 +6208,10 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, ...@@ -6208,6 +6208,10 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
entry->ino = entry->fattr->fileid; entry->ino = entry->fattr->fileid;
entry->d_type = DT_UNKNOWN;
if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE)
entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
if (verify_attr_len(xdr, p, len) < 0) if (verify_attr_len(xdr, p, len) < 0)
goto out_overflow; goto out_overflow;
......
...@@ -483,6 +483,7 @@ struct nfs_entry { ...@@ -483,6 +483,7 @@ struct nfs_entry {
int eof; int eof;
struct nfs_fh * fh; struct nfs_fh * fh;
struct nfs_fattr * fattr; struct nfs_fattr * fattr;
unsigned char d_type;
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment