]> git.hungrycats.org Git - linux/commitdiff
NFSv4: More aggressive caching if we have a delegation.
authorTrond Myklebust <trond.myklebust@fys.uio.no>
Mon, 23 Aug 2004 16:00:15 +0000 (12:00 -0400)
committerTrond Myklebust <trond.myklebust@fys.uio.no>
Mon, 23 Aug 2004 16:00:15 +0000 (12:00 -0400)
Signed-off-by: Trond Myklebust <trond.myklebust@fys.uio.no>
fs/nfs/delegation.c
fs/nfs/delegation.h
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/write.c
include/linux/nfs_fs.h

index 2d8863790451f923ff74d041d3695ee8c095c153..cb510fb292ee0c4cc62e34a60f6bbb89a31a0cff 100644 (file)
@@ -70,6 +70,8 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st
        put_rpccred(cred);
        delegation->cred = get_rpccred(cred);
        delegation->flags &= ~NFS_DELEGATION_NEED_RECLAIM;
+       NFS_I(inode)->delegation_state = delegation->type;
+       smp_wmb();
 }
 
 /*
@@ -96,6 +98,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
        if (nfsi->delegation == NULL) {
                list_add(&delegation->super_list, &clp->cl_delegations);
                nfsi->delegation = delegation;
+               nfsi->delegation_state = delegation->type;
                delegation = NULL;
        } else {
                if (memcmp(&delegation->stateid, &nfsi->delegation->stateid,
@@ -150,6 +153,7 @@ int nfs_inode_return_delegation(struct inode *inode)
        if (delegation != NULL) {
                list_del_init(&delegation->super_list);
                nfsi->delegation = NULL;
+               nfsi->delegation_state = 0;
        }
        spin_unlock(&clp->cl_lock);
        nfs_delegation_claim_opens(inode);
@@ -218,6 +222,7 @@ static int recall_thread(void *data)
                                sizeof(delegation->stateid.data)) == 0) {
                list_del_init(&delegation->super_list);
                nfsi->delegation = NULL;
+               nfsi->delegation_state = 0;
                args->result = 0;
        } else {
                delegation = NULL;
@@ -302,6 +307,7 @@ void nfs_delegation_reap_unclaimed(struct nfs4_client *clp)
                        continue;
                list_move(&delegation->super_list, &head);
                NFS_I(delegation->inode)->delegation = NULL;
+               NFS_I(delegation->inode)->delegation_state = 0;
        }
        spin_unlock(&clp->cl_lock);
        while(!list_empty(&head)) {
index be76feacb2f76e4b60c5319eca49f4ba95b423f8..2be2f32abb9a386f51d3895d3db90601a284e19a 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef FS_NFS_DELEGATION_H
 #define FS_NFS_DELEGATION_H
 
+#if defined(CONFIG_NFS_V4)
 /*
  * NFSv4 delegation
  */
@@ -37,4 +38,19 @@ void nfs_delegation_reap_unclaimed(struct nfs4_client *clp);
 int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
 int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state);
 
+static inline int nfs_have_delegation(struct inode *inode, int flags)
+{
+       flags &= FMODE_READ|FMODE_WRITE;
+       smp_rmb();
+       if ((NFS_I(inode)->delegation_state & flags) == flags)
+               return 1;
+       return 0;
+}
+#else
+static inline int nfs_have_delegation(struct inode *inode, int flags)
+{
+       return 0;
+}
+#endif
+
 #endif
index 840af1a237006e918aea15dc1d48339e5783c734..86c5eda70a803bd03912aca9301245702c067c88 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/smp_lock.h>
 #include <linux/namei.h>
 
+#include "delegation.h"
+
 #define NFS_PARANOIA 1
 /* #define NFS_DEBUG_VERBOSE 1 */
 
@@ -887,6 +889,8 @@ out:
        return ret;
 no_open:
        dput(parent);
+       if (inode != NULL && nfs_have_delegation(inode, FMODE_READ))
+               return 1;
        return nfs_lookup_revalidate(dentry, nd);
 }
 #endif /* CONFIG_NFSV4 */
index 0bd5913f690bad28169b16b5f329bc2a6d691722..21071ddd466277f0bb585f375ad6010d513109eb 100644 (file)
@@ -31,6 +31,8 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+#include "delegation.h"
+
 #define NFSDBG_FACILITY                NFSDBG_FILE
 
 static int nfs_file_open(struct inode *, struct file *);
@@ -127,7 +129,7 @@ nfs_file_flush(struct file *file)
        if (!status) {
                status = ctx->error;
                ctx->error = 0;
-               if (!status)
+               if (!status && !nfs_have_delegation(inode, FMODE_READ))
                        __nfs_revalidate_inode(NFS_SERVER(inode), inode);
        }
        unlock_kernel();
index 607f3d97c280b5a8d0c27cd3f7b10e5a62e5448c..243b5750287ae648c5b804985b127cec798a639f 100644 (file)
@@ -39,6 +39,8 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
+#include "delegation.h"
+
 #define NFSDBG_FACILITY                NFSDBG_VFS
 #define NFS_PARANOIA 1
 
@@ -1017,6 +1019,30 @@ out:
        return status;
 }
 
+int nfs_attribute_timeout(struct inode *inode)
+{
+       struct nfs_inode *nfsi = NFS_I(inode);
+
+       if (nfs_have_delegation(inode, FMODE_READ))
+               return 0;
+       return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo);
+}
+
+/**
+ * nfs_revalidate_inode - Revalidate the inode attributes
+ * @server - pointer to nfs_server struct
+ * @inode - pointer to inode struct
+ *
+ * Updates inode attribute information by retrieving the data from the server.
+ */
+int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+{
+       if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
+                       && !nfs_attribute_timeout(inode))
+               return NFS_STALE(inode) ? -ESTALE : 0;
+       return __nfs_revalidate_inode(server, inode);
+}
+
 /**
  * nfs_begin_data_update
  * @inode - pointer to inode
@@ -1038,11 +1064,13 @@ void nfs_end_data_update(struct inode *inode)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
 
-       /* Mark the attribute cache for revalidation */
-       nfsi->flags |= NFS_INO_INVALID_ATTR;
-       /* Directories and symlinks: invalidate page cache too */
-       if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
-               nfsi->flags |= NFS_INO_INVALID_DATA;
+       if (!nfs_have_delegation(inode, FMODE_READ)) {
+               /* Mark the attribute cache for revalidation */
+               nfsi->flags |= NFS_INO_INVALID_ATTR;
+               /* Directories and symlinks: invalidate page cache too */
+               if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+                       nfsi->flags |= NFS_INO_INVALID_DATA;
+       }
        nfsi->cache_change_attribute ++;
        atomic_dec(&nfsi->data_updates);
 }
@@ -1083,6 +1111,10 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
        loff_t cur_size, new_isize;
        int data_unstable;
 
+       /* Do we hold a delegation? */
+       if (nfs_have_delegation(inode, FMODE_READ))
+               return 0;
+
        /* Are we in the process of updating data on the server? */
        data_unstable = nfs_caches_unstable(inode);
 
@@ -1280,7 +1312,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
        if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
                                || S_ISLNK(inode->i_mode)))
                invalid &= ~NFS_INO_INVALID_DATA;
-       nfsi->flags |= invalid;
+       if (!nfs_have_delegation(inode, FMODE_READ))
+               nfsi->flags |= invalid;
 
        return 0;
  out_changed:
@@ -1437,8 +1470,6 @@ static struct file_system_type nfs_fs_type = {
 
 #ifdef CONFIG_NFS_V4
 
-#include "delegation.h"
-
 static void nfs4_clear_inode(struct inode *);
 
 
@@ -1767,6 +1798,7 @@ static struct file_system_type nfs4_fs_type = {
        do { \
                INIT_LIST_HEAD(&(nfsi)->open_states); \
                nfsi->delegation = NULL; \
+               nfsi->delegation_state = 0; \
                init_rwsem(&nfsi->rwsem); \
        } while(0)
 #define register_nfs4fs() register_filesystem(&nfs4_fs_type)
index daea97848193b3c51b5e0ac01d04c29bc91d3cc8..847b77d4c7aedd099f8a2abe0f0971713cdcccab 100644 (file)
@@ -63,6 +63,8 @@
 #include <linux/smp_lock.h>
 #include <linux/mempool.h>
 
+#include "delegation.h"
+
 #define NFSDBG_FACILITY                NFSDBG_PAGECACHE
 
 #define MIN_POOL_WRITE         (32)
@@ -382,8 +384,7 @@ out:
 /*
  * Insert a write request into an inode
  */
-static inline int
-nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
+static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
        int error;
@@ -395,6 +396,8 @@ nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
        if (!nfsi->npages) {
                igrab(inode);
                nfs_begin_data_update(inode);
+               if (nfs_have_delegation(inode, FMODE_WRITE))
+                       nfsi->change_attr++;
        }
        nfsi->npages++;
        atomic_inc(&req->wb_count);
index c186bdae70762a2b2e0e357f0bbe6c7ad329757a..0ccc263aacf540f56303dbddc8bb70def232412d 100644 (file)
@@ -185,6 +185,7 @@ struct nfs_inode {
         /* NFSv4 state */
        struct list_head        open_states;
        struct nfs_delegation   *delegation;
+       int                      delegation_state;
        struct rw_semaphore     rwsem;
 #endif /* CONFIG_NFS_V4*/
 
@@ -294,6 +295,8 @@ extern int nfs_access_get_cached(struct inode *, struct rpc_cred *, struct nfs_a
 extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *);
 extern int nfs_open(struct inode *, struct file *);
 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 int nfs_setattr(struct dentry *, struct iattr *);
 extern void nfs_begin_attr_update(struct inode *);
@@ -446,28 +449,6 @@ extern int  nfsroot_mount(struct sockaddr_in *, char *, struct nfs_fh *,
  * inline functions
  */
 
-static inline int nfs_attribute_timeout(struct inode *inode)
-{
-       struct nfs_inode *nfsi = NFS_I(inode);
-
-       return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo);
-}
-
-/**
- * nfs_revalidate_inode - Revalidate the inode attributes
- * @server - pointer to nfs_server struct
- * @inode - pointer to inode struct
- *
- * Updates inode attribute information by retrieving the data from the server.
- */
-static inline int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
-{
-       if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
-                       && !nfs_attribute_timeout(inode))
-               return NFS_STALE(inode) ? -ESTALE : 0;
-       return __nfs_revalidate_inode(server, inode);
-}
-
 static inline loff_t
 nfs_size_to_loff_t(__u64 size)
 {