From: Trond Myklebust Date: Wed, 15 Aug 2007 12:15:37 -0400 NFS: Optimise nfs_revalidate_inode() Instead of serialising calls to nfs_revalidate_inode, we should just be attempting to ensure that we've updated the attributes. Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 88 +++++++++++++------------------------------------------- 1 files changed, 21 insertions(+), 67 deletions(-) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e062b8f..082b3dd 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -420,41 +420,6 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) } } -static int nfs_wait_schedule(void *word) -{ - if (signal_pending(current)) - return -ERESTARTSYS; - schedule(); - return 0; -} - -/* - * Wait for the inode to get unlocked. - */ -static int nfs_wait_on_inode(struct inode *inode) -{ - struct rpc_clnt *clnt = NFS_CLIENT(inode); - struct nfs_inode *nfsi = NFS_I(inode); - sigset_t oldmask; - int error; - - rpc_clnt_sigmask(clnt, &oldmask); - error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING, - nfs_wait_schedule, TASK_INTERRUPTIBLE); - rpc_clnt_sigunmask(clnt, &oldmask); - - return error; -} - -static void nfs_wake_up_inode(struct inode *inode) -{ - struct nfs_inode *nfsi = NFS_I(inode); - - clear_bit(NFS_INO_REVALIDATING, &nfsi->flags); - smp_mb__after_clear_bit(); - wake_up_bit(&nfsi->flags, NFS_INO_REVALIDATING); -} - int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { struct inode *inode = dentry->d_inode; @@ -673,42 +638,34 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); lock_kernel(); - if (is_bad_inode(inode)) - goto out_nowait; - if (NFS_STALE(inode)) - goto out_nowait; - - status = nfs_wait_on_inode(inode); - if (status < 0) - goto out; - status = -ESTALE; if (NFS_STALE(inode)) goto out; - status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); - if (status != 0) { - dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", - inode->i_sb->s_id, - (long long)NFS_FILEID(inode), status); - if (status == -ESTALE) { - nfs_zap_caches(inode); - if (!S_ISDIR(inode->i_mode)) - set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); + for(;;) { + status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); + if (status != 0) { + dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", + inode->i_sb->s_id, + (long long)NFS_FILEID(inode), status); + if (status == -ESTALE) { + nfs_zap_caches(inode); + if (!S_ISDIR(inode->i_mode)) + set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); + } + goto out; } - goto out; - } - spin_lock(&inode->i_lock); - status = nfs_update_inode(inode, &fattr); - if (status) { - spin_unlock(&inode->i_lock); - dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", - inode->i_sb->s_id, - (long long)NFS_FILEID(inode), status); - goto out; + status = nfs_refresh_inode(inode, &fattr); + if (status) { + dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", + inode->i_sb->s_id, + (long long)NFS_FILEID(inode), status); + break; + } + if (!(nfsi->cache_validity & NFS_INO_INVALID_ATTR)) + break; } - spin_unlock(&inode->i_lock); if (nfsi->cache_validity & NFS_INO_INVALID_ACL) nfs_zap_acl_cache(inode); @@ -718,9 +675,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) (long long)NFS_FILEID(inode)); out: - nfs_wake_up_inode(inode); - - out_nowait: unlock_kernel(); return status; }