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: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
3020093f57
commit
0b26a0bf6f
@ -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)
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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)
|
|||||||
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
|
|||||||
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
|
|||||||
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,
|
|||||||
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 {
|
|||||||
int eof;
|
int eof;
|
||||||
struct nfs_fh * fh;
|
struct nfs_fh * fh;
|
||||||
struct nfs_fattr * fattr;
|
struct nfs_fattr * fattr;
|
||||||
|
unsigned char d_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user