diff -u --recursive --new-file linux-2.4.6-cto/fs/nfs/dir.c linux-2.4.6-rdplus/fs/nfs/dir.c --- linux-2.4.6-cto/fs/nfs/dir.c Fri Jun 22 19:44:24 2001 +++ linux-2.4.6-rdplus/fs/nfs/dir.c Fri Jun 22 19:45:19 2001 @@ -129,13 +129,17 @@ error = NFS_PROTO(inode)->readdir(inode, cred, desc->entry->cookie, buffer, NFS_SERVER(inode)->dtsize, desc->plus); /* We requested READDIRPLUS, but the server doesn't grok it */ - if (desc->plus && error == -ENOTSUPP) { - NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS; - desc->plus = 0; - goto again; - } - if (error < 0) + if (error < 0) { + if (error == -ENOTSUPP && desc->plus) { + NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS; + NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS; + desc->plus = 0; + goto again; + } goto error; + } + if (desc->plus) + NFS_FLAGS(inode) |= NFS_INO_ADVISE_RDPLUS; SetPageUptodate(page); kunmap(page); /* Ensure consistent page alignment of the data. @@ -216,7 +220,6 @@ dfprintk(VFS, "NFS: find_dirent_page() searching directory page %ld\n", desc->page_index); - desc->plus = NFS_USE_READDIRPLUS(inode); page = read_cache_page(&inode->i_data, desc->page_index, (filler_t *)nfs_readdir_filler, desc); if (IS_ERR(page)) { @@ -268,6 +271,29 @@ return res; } +static struct { + unsigned int nfstype; + unsigned int dtype; +} nfs_type2dtype[] = { + { NFNON, DT_UNKNOWN }, + { NFREG, DT_REG }, + { NFDIR, DT_DIR }, + { NFBLK, DT_BLK }, + { NFCHR, DT_CHR }, + { NFLNK, DT_LNK }, + { NFSOCK, DT_SOCK }, + { NFBAD, DT_UNKNOWN }, + { NFFIFO, DT_FIFO }, +}; + +static inline +unsigned nfs_type_to_d_type(unsigned type) +{ + if (type < 8) + return nfs_type2dtype[type].dtype; + return DT_UNKNOWN; +} + /* * Once we've found the start of the dirent within a page: fill 'er up... */ @@ -284,11 +310,17 @@ dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)desc->target); for(;;) { + unsigned d_type = DT_UNKNOWN; /* Note: entry->prev_cookie contains the cookie for * retrieving the current dirent on the server */ fileid = nfs_fileid_to_ino_t(entry->ino); + + /* Use readdirplus info */ + if (desc->plus && (entry->fattr.valid & NFS_ATTR_FATTR)) + d_type = nfs_type_to_d_type(entry->fattr.type); + res = filldir(dirent, entry->name, entry->len, - entry->prev_cookie, fileid, DT_UNKNOWN); + entry->prev_cookie, fileid, d_type); if (res < 0) break; file->f_pos = desc->target = entry->cookie; @@ -393,6 +425,7 @@ desc->target = filp->f_pos; desc->entry = &my_entry; desc->decode = NFS_PROTO(inode)->decode_dirent; + desc->plus = NFS_USE_READDIRPLUS(inode); while(!desc->entry->eof) { res = readdir_search_pagecache(desc); diff -u --recursive --new-file linux-2.4.6-cto/fs/nfs/inode.c linux-2.4.6-rdplus/fs/nfs/inode.c --- linux-2.4.6-cto/fs/nfs/inode.c Fri Jun 22 19:11:22 2001 +++ linux-2.4.6-rdplus/fs/nfs/inode.c Fri Jun 22 19:12:46 2001 @@ -300,6 +300,7 @@ if (!server->hostname) goto out_unlock; strcpy(server->hostname, data->hostname); + server->caps = 0; nfsv3_try_again: /* Check NFS protocol revision and initialize RPC op vector @@ -308,6 +309,7 @@ #ifdef CONFIG_NFS_V3 server->rpc_ops = &nfs_v3_clientops; version = 3; + server->caps |= NFS_CAP_READDIRPLUS; if (data->version < 4) { printk(KERN_NOTICE "NFS: NFSv3 not supported by mount program.\n"); goto out_unlock; diff -u --recursive --new-file linux-2.4.6-cto/fs/nfs/nfs3xdr.c linux-2.4.6-rdplus/fs/nfs/nfs3xdr.c --- linux-2.4.6-cto/fs/nfs/nfs3xdr.c Fri Jun 22 19:10:02 2001 +++ linux-2.4.6-rdplus/fs/nfs/nfs3xdr.c Fri Jun 22 19:12:46 2001 @@ -660,6 +660,7 @@ entry->cookie = nfs_transform_cookie64(cookie); if (plus) { + entry->fattr.valid = 0; p = xdr_decode_post_op_attr(p, &entry->fattr); /* In fact, a post_op_fh3: */ if (*p++) { @@ -670,11 +671,8 @@ *entry = old; return ERR_PTR(-EAGAIN); } - } else { - /* If we don't get a file handle, the attrs - * aren't worth a lot. */ - entry->fattr.valid = 0; - } + } else + memset((u8*)(&entry->fh), 0, sizeof(entry->fh)); } entry->eof = !p[0] && p[1]; diff -u --recursive --new-file linux-2.4.6-cto/include/linux/nfs_fs.h linux-2.4.6-rdplus/include/linux/nfs_fs.h --- linux-2.4.6-cto/include/linux/nfs_fs.h Fri Jun 22 19:05:20 2001 +++ linux-2.4.6-rdplus/include/linux/nfs_fs.h Fri Jun 22 23:41:48 2001 @@ -102,8 +102,19 @@ #define NFS_FILEID(inode) (NFS_I(inode)->fileid) #define NFS_FSID(inode) (NFS_I(inode)->fsid) -/* Inode Flags */ -#define NFS_USE_READDIRPLUS(inode) ((NFS_FLAGS(inode) & NFS_INO_ADVISE_RDPLUS) ? 1 : 0) +static inline int nfs_server_caps(struct inode *inode) +{ + return NFS_SERVER(inode)->caps; +} + +static inline int NFS_USE_READDIRPLUS(struct inode *inode) +{ + if (nfs_server_caps(inode) & NFS_CAP_READDIRPLUS) + return 1; + if (NFS_FLAGS(inode) & NFS_INO_ADVISE_RDPLUS) + return 1; + return 0; +} /* * These are the default flags for swap requests diff -u --recursive --new-file linux-2.4.6-cto/include/linux/nfs_fs_sb.h linux-2.4.6-rdplus/include/linux/nfs_fs_sb.h --- linux-2.4.6-cto/include/linux/nfs_fs_sb.h Wed Apr 26 02:28:56 2000 +++ linux-2.4.6-rdplus/include/linux/nfs_fs_sb.h Fri Jun 22 19:12:46 2001 @@ -8,6 +8,7 @@ struct rpc_clnt * client; /* RPC client handle */ struct nfs_rpc_ops * rpc_ops; /* NFS protocol vector */ int flags; /* various flags */ + unsigned int caps; /* server capabilities */ unsigned int rsize; /* read size */ unsigned int rpages; /* read size (in pages) */ unsigned int wsize; /* write size */ @@ -29,5 +30,9 @@ struct nfs_sb_info { struct nfs_server s_server; }; + +/* Server capabilities */ +#define NFS_CAP_READDIRPLUS 1 + #endif