NFS: Separate metadata and page cache revalidation mechanisms
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Thu, 25 May 2006 05:40:59 +0000 (01:40 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 9 Jun 2006 13:34:09 +0000 (09:34 -0400)
Separate out the function of revalidating the inode metadata, and
revalidating the mapping. The former may be called by lookup(),
and only really needs to check that permissions, ctime, etc haven't changed
whereas the latter needs only done when we want to read data from the page
cache, and may need to sync and then invalidate the mapping.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/symlink.c
include/linux/nfs_fs.h

index cae74dd4c7f51f6bd674c5e61bad36c415cb4460..1d3d8922a66393fd1f9af82afe66154ec1fc22fb 100644 (file)
@@ -528,7 +528,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
        lock_kernel();
 
-       res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+       res = nfs_revalidate_mapping(inode, filp->f_mapping);
        if (res < 0) {
                unlock_kernel();
                return res;
index fade02c15e6ef11a8575e6381b6f10445a1de375..63154070145af23d61414ade14f4964c4b37a676 100644 (file)
@@ -126,23 +126,6 @@ nfs_file_release(struct inode *inode, struct file *filp)
        return NFS_PROTO(inode)->file_release(inode, filp);
 }
 
-/**
- * nfs_revalidate_file - Revalidate the page cache & related metadata
- * @inode - pointer to inode struct
- * @file - pointer to file
- */
-static int nfs_revalidate_file(struct inode *inode, struct file *filp)
-{
-       struct nfs_inode *nfsi = NFS_I(inode);
-       int retval = 0;
-
-       if ((nfsi->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATTR))
-                       || nfs_attribute_timeout(inode))
-               retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
-       nfs_revalidate_mapping(inode, filp->f_mapping);
-       return 0;
-}
-
 /**
  * nfs_revalidate_size - Revalidate the file size
  * @inode - pointer to inode struct
@@ -228,7 +211,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
                dentry->d_parent->d_name.name, dentry->d_name.name,
                (unsigned long) count, (unsigned long) pos);
 
-       result = nfs_revalidate_file(inode, iocb->ki_filp);
+       result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
        nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, count);
        if (!result)
                result = generic_file_aio_read(iocb, buf, count, pos);
@@ -247,7 +230,7 @@ nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
                dentry->d_parent->d_name.name, dentry->d_name.name,
                (unsigned long) count, (unsigned long long) *ppos);
 
-       res = nfs_revalidate_file(inode, filp);
+       res = nfs_revalidate_mapping(inode, filp->f_mapping);
        if (!res)
                res = generic_file_sendfile(filp, ppos, count, actor, target);
        return res;
@@ -263,7 +246,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
        dfprintk(VFS, "nfs: mmap(%s/%s)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name);
 
-       status = nfs_revalidate_file(inode, file);
+       status = nfs_revalidate_mapping(inode, file->f_mapping);
        if (!status)
                status = generic_file_mmap(file, vma);
        return status;
@@ -373,7 +356,6 @@ nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t
                if (result)
                        goto out;
        }
-       nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
 
        result = count;
        if (!count)
index eddd0e982d2391195212cbe8ffb517a12ba4764b..69036ef39866079a84650588dd047f16cf505dad 100644 (file)
@@ -1220,7 +1220,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
                status = -ESTALE;
                /* Do we trust the cached ESTALE? */
                if (NFS_ATTRTIMEO(inode) != 0) {
-                       if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME)) {
+                       if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME)) {
                                /* no */
                        } else
                                goto out;
@@ -1251,8 +1251,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
        }
        spin_unlock(&inode->i_lock);
 
-       nfs_revalidate_mapping(inode, inode->i_mapping);
-
        if (nfsi->cache_validity & NFS_INO_INVALID_ACL)
                nfs_zap_acl_cache(inode);
 
@@ -1287,7 +1285,7 @@ int nfs_attribute_timeout(struct inode *inode)
 int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 {
        nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE);
-       if (!(NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
+       if (!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR)
                        && !nfs_attribute_timeout(inode))
                return NFS_STALE(inode) ? -ESTALE : 0;
        return __nfs_revalidate_inode(server, inode);
@@ -1298,9 +1296,16 @@ int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
  * @inode - pointer to host inode
  * @mapping - pointer to mapping
  */
-void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
+int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
+       int ret = 0;
+
+       if (NFS_STALE(inode))
+               ret = -ESTALE;
+       if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)
+                       || nfs_attribute_timeout(inode))
+               ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
 
        if (nfsi->cache_validity & NFS_INO_INVALID_DATA) {
                nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE);
@@ -1321,6 +1326,7 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
                                inode->i_sb->s_id,
                                (long long)NFS_FILEID(inode));
        }
+       return ret;
 }
 
 /**
index 18dc95b0b64638695a9dfa9b6db1983875d9a757..636c479995bcdc35d9d3fb1437d1ff72fd124e92 100644 (file)
@@ -52,7 +52,7 @@ static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
        struct page *page;
-       void *err = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode));
+       void *err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
        if (err)
                goto read_failed;
        page = read_cache_page(&inode->i_data, 0,
index 1d81e7d82970da5acd3f4a3686db10618deb3d68..1b524b9f982a0965e25d18bebd2bddb9727a5625 100644 (file)
@@ -301,7 +301,7 @@ extern int nfs_release(struct inode *, struct file *);
 extern int nfs_attribute_timeout(struct inode *inode);
 extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
 extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
-extern void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
+extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
 extern int nfs_setattr(struct dentry *, struct iattr *);
 extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
 extern void nfs_begin_attr_update(struct inode *);