diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-29 10:43:51 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-29 10:43:51 -0700 |
commit | 53f2c4a8fd882009a2a75c5b72d6898c0808616e (patch) | |
tree | 922293a1056c0c2358203cdab832f0e0891e628a /fs/nfs/dir.c | |
parent | 8f6576ad476b2a22d05ddafd2ddaee102577a4ed (diff) | |
parent | cc0a98436820b161b595b8cc1d2329bcf7328107 (diff) |
Merge tag 'nfs-for-3.5-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust:
"New features include:
- Rewrite the O_DIRECT code so that it can share the same coalescing
and pNFS functionality as the page cache code.
- Allow the server to provide hints as to when we should use pNFS,
and when it is more efficient to read and write through the
metadata server.
- NFS cache consistency updates:
* Use the ctime to emulate a change attribute for NFSv2/v3 so that
all NFS versions can share the same cache management code.
* New cache management code will only look at the change attribute
and size attribute when deciding whether or not our cached data
is still valid or not.
* Don't request NFSv4 post-op attributes on writes in cases such as
O_DIRECT, where we don't care about data cache consistency, or
when we have a write delegation, and know that our cache is still
consistent.
* Don't request NFSv4 post-op attributes on operations such as
COMMIT, where there are no expected metadata updates.
* Don't request NFSv4 directory post-op attributes in cases where
the operations themselves already return change attribute
updates: i.e. operations such as OPEN, CREATE, REMOVE, LINK and
RENAME.
- Speed up 'ls' and friends by using READDIR rather than READDIRPLUS
if we detect no attempts to lookup filenames.
- Improve the code sharing between NFSv2/v3 and v4 mounts
- NFSv4.1 state management efficiency improvements
- More patches in preparation for NFSv4/v4.1 migration functionality."
Fix trivial conflict in fs/nfs/nfs4proc.c that was due to the dcache
qstr name initialization changes (that made the length/hash a 64-bit
union)
* tag 'nfs-for-3.5-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (146 commits)
NFSv4: Add debugging printks to state manager
NFSv4: Map NFS4ERR_SHARE_DENIED into an EACCES error instead of EIO
NFSv4: update_changeattr does not need to set NFS_INO_REVAL_PAGECACHE
NFSv4.1: nfs4_reset_session should use nfs4_handle_reclaim_lease_error
NFSv4.1: Handle other occurrences of NFS4ERR_CONN_NOT_BOUND_TO_SESSION
NFSv4.1: Handle NFS4ERR_CONN_NOT_BOUND_TO_SESSION in the state manager
NFSv4.1: Handle errors in nfs4_bind_conn_to_session
NFSv4.1: nfs4_bind_conn_to_session should drain the session
NFSv4.1: Don't clobber the seqid if exchange_id returns a confirmed clientid
NFSv4.1: Add DESTROY_CLIENTID
NFSv4.1: Ensure we use the correct credentials for bind_conn_to_session
NFSv4.1: Ensure we use the correct credentials for session create/destroy
NFSv4.1: Move NFSPROC4_CLNT_BIND_CONN_TO_SESSION to the end of the operations
NFSv4.1: Handle NFS4ERR_SEQ_MISORDERED when confirming the lease
NFSv4: When purging the lease, we must clear NFS4CLNT_LEASE_CONFIRM
NFSv4: Clean up the error handling for nfs4_reclaim_lease
NFSv4.1: Exchange ID must use GFP_NOFS allocation mode
nfs41: Use BIND_CONN_TO_SESSION for CB_PATH_DOWN*
nfs4.1: add BIND_CONN_TO_SESSION operation
NFSv4.1 test the mdsthreshold hint parameters
...
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index eedd24d0ad2e..0989a2099688 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -475,6 +475,29 @@ different: } static +bool nfs_use_readdirplus(struct inode *dir, struct file *filp) +{ + if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS)) + return false; + if (test_and_clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags)) + return true; + if (filp->f_pos == 0) + return true; + return false; +} + +/* + * This function is called by the lookup code to request the use of + * readdirplus to accelerate any future lookups in the same + * directory. + */ +static +void nfs_advise_use_readdirplus(struct inode *dir) +{ + set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags); +} + +static void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) { struct qstr filename = QSTR_INIT(entry->name, entry->len); @@ -871,7 +894,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) desc->file = filp; desc->dir_cookie = &dir_ctx->dir_cookie; desc->decode = NFS_PROTO(inode)->decode_dirent; - desc->plus = NFS_USE_READDIRPLUS(inode); + desc->plus = nfs_use_readdirplus(inode, filp) ? 1 : 0; nfs_block_sillyrename(dentry); res = nfs_revalidate_mapping(inode, filp->f_mapping); @@ -1111,7 +1134,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) if (!inode) { if (nfs_neg_need_reval(dir, dentry, nd)) goto out_bad; - goto out_valid; + goto out_valid_noent; } if (is_bad_inode(inode)) { @@ -1140,7 +1163,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) if (fhandle == NULL || fattr == NULL) goto out_error; - error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); + error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); if (error) goto out_bad; if (nfs_compare_fh(NFS_FH(inode), fhandle)) @@ -1153,6 +1176,9 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) out_set_verifier: nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); out_valid: + /* Success: notify readdir to use READDIRPLUS */ + nfs_advise_use_readdirplus(dir); + out_valid_noent: dput(parent); dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is valid\n", __func__, dentry->d_parent->d_name.name, @@ -1296,7 +1322,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru parent = dentry->d_parent; /* Protect against concurrent sillydeletes */ nfs_block_sillyrename(parent); - error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); + error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); if (error == -ENOENT) goto no_entry; if (error < 0) { @@ -1308,6 +1334,9 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru if (IS_ERR(res)) goto out_unblock_sillyrename; + /* Success: notify readdir to use READDIRPLUS */ + nfs_advise_use_readdirplus(dir); + no_entry: res = d_materialise_unique(dentry, inode); if (res != NULL) { @@ -1643,7 +1672,7 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, if (dentry->d_inode) goto out; if (fhandle->size == 0) { - error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); + error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); if (error) goto out_error; } |