Commit 33801147 authored by Trond Myklebust's avatar Trond Myklebust

NFS: Optimise inode attribute cache updates

 Allow nfs_refresh_inode() also to update attributes on the inode if the
 RPC call was sent after the last call to nfs_update_inode().
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 913a70fc
...@@ -785,7 +785,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) ...@@ -785,7 +785,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
else else
init_special_inode(inode, inode->i_mode, fattr->rdev); init_special_inode(inode, inode->i_mode, fattr->rdev);
nfsi->read_cache_jiffies = fattr->timestamp; nfsi->read_cache_jiffies = fattr->time_start;
nfsi->last_updated = jiffies;
inode->i_atime = fattr->atime; inode->i_atime = fattr->atime;
inode->i_mtime = fattr->mtime; inode->i_mtime = fattr->mtime;
inode->i_ctime = fattr->ctime; inode->i_ctime = fattr->ctime;
...@@ -1120,14 +1121,15 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) ...@@ -1120,14 +1121,15 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
goto out; goto out;
} }
spin_lock(&inode->i_lock);
status = nfs_update_inode(inode, &fattr, verifier); status = nfs_update_inode(inode, &fattr, verifier);
if (status) { if (status) {
spin_unlock(&inode->i_lock);
dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",
inode->i_sb->s_id, inode->i_sb->s_id,
(long long)NFS_FILEID(inode), status); (long long)NFS_FILEID(inode), status);
goto out; goto out;
} }
spin_lock(&inode->i_lock);
cache_validity = nfsi->cache_validity; cache_validity = nfsi->cache_validity;
nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
...@@ -1247,7 +1249,7 @@ void nfs_end_data_update(struct inode *inode) ...@@ -1247,7 +1249,7 @@ void nfs_end_data_update(struct inode *inode)
} }
/** /**
* nfs_refresh_inode - verify consistency of the inode attribute cache * nfs_check_inode_attributes - verify consistency of the inode attribute cache
* @inode - pointer to inode * @inode - pointer to inode
* @fattr - updated attributes * @fattr - updated attributes
* *
...@@ -1255,13 +1257,12 @@ void nfs_end_data_update(struct inode *inode) ...@@ -1255,13 +1257,12 @@ void nfs_end_data_update(struct inode *inode)
* so that fattr carries weak cache consistency data, then it may * so that fattr carries weak cache consistency data, then it may
* also update the ctime/mtime/change_attribute. * also update the ctime/mtime/change_attribute.
*/ */
int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fattr)
{ {
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
loff_t cur_size, new_isize; loff_t cur_size, new_isize;
int data_unstable; int data_unstable;
spin_lock(&inode->i_lock);
/* Are we in the process of updating data on the server? */ /* Are we in the process of updating data on the server? */
data_unstable = nfs_caches_unstable(inode); data_unstable = nfs_caches_unstable(inode);
...@@ -1325,11 +1326,40 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) ...@@ -1325,11 +1326,40 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
if (!timespec_equal(&inode->i_atime, &fattr->atime)) if (!timespec_equal(&inode->i_atime, &fattr->atime))
nfsi->cache_validity |= NFS_INO_INVALID_ATIME; nfsi->cache_validity |= NFS_INO_INVALID_ATIME;
nfsi->read_cache_jiffies = fattr->timestamp; nfsi->read_cache_jiffies = fattr->time_start;
spin_unlock(&inode->i_lock);
return 0; return 0;
} }
/**
* nfs_refresh_inode - try to update the inode attribute cache
* @inode - pointer to inode
* @fattr - updated attributes
*
* Check that an RPC call that returned attributes has not overlapped with
* other recent updates of the inode metadata, then decide whether it is
* safe to do a full update of the inode attributes, or whether just to
* call nfs_check_inode_attributes.
*/
int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
{
struct nfs_inode *nfsi = NFS_I(inode);
int status;
if ((fattr->valid & NFS_ATTR_FATTR) == 0)
return 0;
spin_lock(&inode->i_lock);
nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
if (nfs_verify_change_attribute(inode, fattr->time_start))
nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
if (time_after(fattr->time_start, nfsi->last_updated))
status = nfs_update_inode(inode, fattr, fattr->time_start);
else
status = nfs_check_inode_attributes(inode, fattr);
spin_unlock(&inode->i_lock);
return status;
}
/* /*
* Many nfs protocol calls return the new file attributes after * Many nfs protocol calls return the new file attributes after
* an operation. Here we update the inode to reflect the state * an operation. Here we update the inode to reflect the state
...@@ -1365,20 +1395,17 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign ...@@ -1365,20 +1395,17 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
goto out_err; goto out_err;
} }
spin_lock(&inode->i_lock);
/* /*
* Make sure the inode's type hasn't changed. * Make sure the inode's type hasn't changed.
*/ */
if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
spin_unlock(&inode->i_lock);
goto out_changed; goto out_changed;
}
/* /*
* Update the read time so we don't revalidate too often. * Update the read time so we don't revalidate too often.
*/ */
nfsi->read_cache_jiffies = fattr->timestamp; nfsi->read_cache_jiffies = fattr->time_start;
nfsi->last_updated = jiffies;
/* Are we racing with known updates of the metadata on the server? */ /* Are we racing with known updates of the metadata on the server? */
data_unstable = ! (nfs_verify_change_attribute(inode, verifier) || data_unstable = ! (nfs_verify_change_attribute(inode, verifier) ||
...@@ -1467,7 +1494,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign ...@@ -1467,7 +1494,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
if (!nfs_have_delegation(inode, FMODE_READ)) if (!nfs_have_delegation(inode, FMODE_READ))
nfsi->cache_validity |= invalid; nfsi->cache_validity |= invalid;
spin_unlock(&inode->i_lock);
return 0; return 0;
out_changed: out_changed:
/* /*
......
...@@ -143,7 +143,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) ...@@ -143,7 +143,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
fattr->rdev = 0; fattr->rdev = 0;
} }
fattr->timestamp = jiffies;
return p; return p;
} }
......
...@@ -174,7 +174,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) ...@@ -174,7 +174,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
/* Update the mode bits */ /* Update the mode bits */
fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3); fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
fattr->timestamp = jiffies;
return p; return p;
} }
......
...@@ -2799,10 +2799,8 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons ...@@ -2799,10 +2799,8 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons
goto xdr_error; goto xdr_error;
if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0) if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0)
goto xdr_error; goto xdr_error;
if ((status = verify_attr_len(xdr, savep, attrlen)) == 0) { if ((status = verify_attr_len(xdr, savep, attrlen)) == 0)
fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4; fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4;
fattr->timestamp = jiffies;
}
xdr_error: xdr_error:
if (status != 0) if (status != 0)
printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status); printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
......
...@@ -141,6 +141,7 @@ struct nfs_inode { ...@@ -141,6 +141,7 @@ struct nfs_inode {
unsigned long attrtimeo_timestamp; unsigned long attrtimeo_timestamp;
__u64 change_attr; /* v4 only */ __u64 change_attr; /* v4 only */
unsigned long last_updated;
/* "Generation counter" for the attribute cache. This is /* "Generation counter" for the attribute cache. This is
* bumped whenever we update the metadata on the * bumped whenever we update the metadata on the
* server. * server.
...@@ -319,6 +320,7 @@ extern u32 root_nfs_parse_addr(char *name); /*__init*/ ...@@ -319,6 +320,7 @@ extern u32 root_nfs_parse_addr(char *name); /*__init*/
static inline void nfs_fattr_init(struct nfs_fattr *fattr) static inline void nfs_fattr_init(struct nfs_fattr *fattr)
{ {
fattr->valid = 0; fattr->valid = 0;
fattr->time_start = jiffies;
} }
/* /*
......
...@@ -41,7 +41,7 @@ struct nfs_fattr { ...@@ -41,7 +41,7 @@ struct nfs_fattr {
__u32 bitmap[2]; /* NFSv4 returned attribute bitmap */ __u32 bitmap[2]; /* NFSv4 returned attribute bitmap */
__u64 change_attr; /* NFSv4 change attribute */ __u64 change_attr; /* NFSv4 change attribute */
__u64 pre_change_attr;/* pre-op NFSv4 change attribute */ __u64 pre_change_attr;/* pre-op NFSv4 change attribute */
unsigned long timestamp; unsigned long time_start;
}; };
#define NFS_ATTR_WCC 0x0001 /* pre-op WCC data */ #define NFS_ATTR_WCC 0x0001 /* pre-op WCC data */
......
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