Commit b42a8a16 authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: More aggressive caching if we have a delegation.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@fys.uio.no>
parent 7129dfe5
......@@ -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)) {
......
......@@ -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
......@@ -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 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
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 */
......
......@@ -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();
......
......@@ -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 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
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)
......
......@@ -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 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
/*
* 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);
......
......@@ -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)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment