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>

+22 -3
+4 -3
fs/nfs/dir.c
··· 162 162 u64 cookie; 163 163 u64 ino; 164 164 struct qstr string; 165 + unsigned char d_type; 165 166 }; 166 167 167 168 struct nfs_cache_array { ··· 266 265 267 266 cache_entry->cookie = entry->prev_cookie; 268 267 cache_entry->ino = entry->ino; 268 + cache_entry->d_type = entry->d_type; 269 269 ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len); 270 270 if (ret) 271 271 goto out; ··· 703 701 int i = 0; 704 702 int res = 0; 705 703 struct nfs_cache_array *array = NULL; 706 - unsigned int d_type = DT_UNKNOWN; 707 704 708 705 array = nfs_readdir_get_array(desc->page); 709 706 if (IS_ERR(array)) { ··· 712 711 713 712 for (i = desc->cache_entry_index; i < array->size; i++) { 714 713 struct nfs_cache_array_entry *ent; 715 - d_type = DT_UNKNOWN; 716 714 717 715 ent = &array->array[i]; 718 716 if (filldir(dirent, ent->string.name, ent->string.len, 719 - file->f_pos, nfs_compat_user_ino64(ent->ino), d_type) < 0) { 717 + file->f_pos, nfs_compat_user_ino64(ent->ino), 718 + ent->d_type) < 0) { 720 719 desc->eof = 1; 721 720 break; 722 721 }
+9
fs/nfs/internal.h
··· 362 362 } 363 363 364 364 /* 365 + * Convert a umode to a dirent->d_type 366 + */ 367 + static inline 368 + unsigned char nfs_umode_to_dtype(umode_t mode) 369 + { 370 + return (mode >> 12) & 15; 371 + } 372 + 373 + /* 365 374 * Determine the number of pages in an array of length 'len' and 366 375 * with a base offset of 'base' 367 376 */
+2
fs/nfs/nfs2xdr.c
··· 485 485 entry->prev_cookie = entry->cookie; 486 486 entry->cookie = ntohl(*p++); 487 487 488 + entry->d_type = DT_UNKNOWN; 489 + 488 490 p = xdr_inline_peek(xdr, 8); 489 491 if (p != NULL) 490 492 entry->eof = !p[0] && p[1];
+2
fs/nfs/nfs3xdr.c
··· 622 622 entry->prev_cookie = entry->cookie; 623 623 p = xdr_decode_hyper(p, &entry->cookie); 624 624 625 + entry->d_type = DT_UNKNOWN; 625 626 if (plus) { 626 627 entry->fattr->valid = 0; 627 628 p = xdr_decode_post_op_attr_stream(xdr, entry->fattr); 628 629 if (IS_ERR(p)) 629 630 goto out_overflow_exit; 631 + entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); 630 632 /* In fact, a post_op_fh3: */ 631 633 p = xdr_inline_decode(xdr, 4); 632 634 if (unlikely(!p))
+4
fs/nfs/nfs4xdr.c
··· 6208 6208 if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) 6209 6209 entry->ino = entry->fattr->fileid; 6210 6210 6211 + entry->d_type = DT_UNKNOWN; 6212 + if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE) 6213 + entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); 6214 + 6211 6215 if (verify_attr_len(xdr, p, len) < 0) 6212 6216 goto out_overflow; 6213 6217
+1
include/linux/nfs_xdr.h
··· 483 483 int eof; 484 484 struct nfs_fh * fh; 485 485 struct nfs_fattr * fattr; 486 + unsigned char d_type; 486 487 }; 487 488 488 489 /*