aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-27 22:12:39 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-10-27 22:12:39 -0400
commit33801147a8fda6b04d7e9afe1d42f1c01d3d6837 (patch)
tree5311fb4714f0a24b7d7666b04250205025e18d15
parent913a70fc170530f7e1ff0693595155457cc6d0ca (diff)
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: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/inode.c54
-rw-r--r--fs/nfs/nfs2xdr.c1
-rw-r--r--fs/nfs/nfs3xdr.c1
-rw-r--r--fs/nfs/nfs4xdr.c4
-rw-r--r--include/linux/nfs_fs.h2
-rw-r--r--include/linux/nfs_xdr.h2
6 files changed, 44 insertions, 20 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 449df8c8aa31..b7d4f8f13ac2 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -785,7 +785,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
785 else 785 else
786 init_special_inode(inode, inode->i_mode, fattr->rdev); 786 init_special_inode(inode, inode->i_mode, fattr->rdev);
787 787
788 nfsi->read_cache_jiffies = fattr->timestamp; 788 nfsi->read_cache_jiffies = fattr->time_start;
789 nfsi->last_updated = jiffies;
789 inode->i_atime = fattr->atime; 790 inode->i_atime = fattr->atime;
790 inode->i_mtime = fattr->mtime; 791 inode->i_mtime = fattr->mtime;
791 inode->i_ctime = fattr->ctime; 792 inode->i_ctime = fattr->ctime;
@@ -1120,14 +1121,15 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
1120 goto out; 1121 goto out;
1121 } 1122 }
1122 1123
1124 spin_lock(&inode->i_lock);
1123 status = nfs_update_inode(inode, &fattr, verifier); 1125 status = nfs_update_inode(inode, &fattr, verifier);
1124 if (status) { 1126 if (status) {
1127 spin_unlock(&inode->i_lock);
1125 dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", 1128 dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",
1126 inode->i_sb->s_id, 1129 inode->i_sb->s_id,
1127 (long long)NFS_FILEID(inode), status); 1130 (long long)NFS_FILEID(inode), status);
1128 goto out; 1131 goto out;
1129 } 1132 }
1130 spin_lock(&inode->i_lock);
1131 cache_validity = nfsi->cache_validity; 1133 cache_validity = nfsi->cache_validity;
1132 nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; 1134 nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
1133 1135
@@ -1247,7 +1249,7 @@ void nfs_end_data_update(struct inode *inode)
1247} 1249}
1248 1250
1249/** 1251/**
1250 * nfs_refresh_inode - verify consistency of the inode attribute cache 1252 * nfs_check_inode_attributes - verify consistency of the inode attribute cache
1251 * @inode - pointer to inode 1253 * @inode - pointer to inode
1252 * @fattr - updated attributes 1254 * @fattr - updated attributes
1253 * 1255 *
@@ -1255,13 +1257,12 @@ void nfs_end_data_update(struct inode *inode)
1255 * so that fattr carries weak cache consistency data, then it may 1257 * so that fattr carries weak cache consistency data, then it may
1256 * also update the ctime/mtime/change_attribute. 1258 * also update the ctime/mtime/change_attribute.
1257 */ 1259 */
1258int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) 1260static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fattr)
1259{ 1261{
1260 struct nfs_inode *nfsi = NFS_I(inode); 1262 struct nfs_inode *nfsi = NFS_I(inode);
1261 loff_t cur_size, new_isize; 1263 loff_t cur_size, new_isize;
1262 int data_unstable; 1264 int data_unstable;
1263 1265
1264 spin_lock(&inode->i_lock);
1265 1266
1266 /* Are we in the process of updating data on the server? */ 1267 /* Are we in the process of updating data on the server? */
1267 data_unstable = nfs_caches_unstable(inode); 1268 data_unstable = nfs_caches_unstable(inode);
@@ -1325,11 +1326,40 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
1325 if (!timespec_equal(&inode->i_atime, &fattr->atime)) 1326 if (!timespec_equal(&inode->i_atime, &fattr->atime))
1326 nfsi->cache_validity |= NFS_INO_INVALID_ATIME; 1327 nfsi->cache_validity |= NFS_INO_INVALID_ATIME;
1327 1328
1328 nfsi->read_cache_jiffies = fattr->timestamp; 1329 nfsi->read_cache_jiffies = fattr->time_start;
1329 spin_unlock(&inode->i_lock);
1330 return 0; 1330 return 0;
1331} 1331}
1332 1332
1333/**
1334 * nfs_refresh_inode - try to update the inode attribute cache
1335 * @inode - pointer to inode
1336 * @fattr - updated attributes
1337 *
1338 * Check that an RPC call that returned attributes has not overlapped with
1339 * other recent updates of the inode metadata, then decide whether it is
1340 * safe to do a full update of the inode attributes, or whether just to
1341 * call nfs_check_inode_attributes.
1342 */
1343int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
1344{
1345 struct nfs_inode *nfsi = NFS_I(inode);
1346 int status;
1347
1348 if ((fattr->valid & NFS_ATTR_FATTR) == 0)
1349 return 0;
1350 spin_lock(&inode->i_lock);
1351 nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
1352 if (nfs_verify_change_attribute(inode, fattr->time_start))
1353 nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
1354 if (time_after(fattr->time_start, nfsi->last_updated))
1355 status = nfs_update_inode(inode, fattr, fattr->time_start);
1356 else
1357 status = nfs_check_inode_attributes(inode, fattr);
1358
1359 spin_unlock(&inode->i_lock);
1360 return status;
1361}
1362
1333/* 1363/*
1334 * Many nfs protocol calls return the new file attributes after 1364 * Many nfs protocol calls return the new file attributes after
1335 * an operation. Here we update the inode to reflect the state 1365 * 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 goto out_err; 1395 goto out_err;
1366 } 1396 }
1367 1397
1368 spin_lock(&inode->i_lock);
1369
1370 /* 1398 /*
1371 * Make sure the inode's type hasn't changed. 1399 * Make sure the inode's type hasn't changed.
1372 */ 1400 */
1373 if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { 1401 if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
1374 spin_unlock(&inode->i_lock);
1375 goto out_changed; 1402 goto out_changed;
1376 }
1377 1403
1378 /* 1404 /*
1379 * Update the read time so we don't revalidate too often. 1405 * Update the read time so we don't revalidate too often.
1380 */ 1406 */
1381 nfsi->read_cache_jiffies = fattr->timestamp; 1407 nfsi->read_cache_jiffies = fattr->time_start;
1408 nfsi->last_updated = jiffies;
1382 1409
1383 /* Are we racing with known updates of the metadata on the server? */ 1410 /* Are we racing with known updates of the metadata on the server? */
1384 data_unstable = ! (nfs_verify_change_attribute(inode, verifier) || 1411 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 if (!nfs_have_delegation(inode, FMODE_READ)) 1494 if (!nfs_have_delegation(inode, FMODE_READ))
1468 nfsi->cache_validity |= invalid; 1495 nfsi->cache_validity |= invalid;
1469 1496
1470 spin_unlock(&inode->i_lock);
1471 return 0; 1497 return 0;
1472 out_changed: 1498 out_changed:
1473 /* 1499 /*
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index d91b69044a4d..59049e864ca7 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -143,7 +143,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
143 fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; 143 fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
144 fattr->rdev = 0; 144 fattr->rdev = 0;
145 } 145 }
146 fattr->timestamp = jiffies;
147 return p; 146 return p;
148} 147}
149 148
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index db4a904810a4..0498bd36602c 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -174,7 +174,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
174 174
175 /* Update the mode bits */ 175 /* Update the mode bits */
176 fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3); 176 fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
177 fattr->timestamp = jiffies;
178 return p; 177 return p;
179} 178}
180 179
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index cd762648fa9a..8b21de8a06fa 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -2799,10 +2799,8 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons
2799 goto xdr_error; 2799 goto xdr_error;
2800 if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0) 2800 if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0)
2801 goto xdr_error; 2801 goto xdr_error;
2802 if ((status = verify_attr_len(xdr, savep, attrlen)) == 0) { 2802 if ((status = verify_attr_len(xdr, savep, attrlen)) == 0)
2803 fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4; 2803 fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4;
2804 fattr->timestamp = jiffies;
2805 }
2806xdr_error: 2804xdr_error:
2807 if (status != 0) 2805 if (status != 0)
2808 printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status); 2806 printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index abf890f5fbfb..faeaad666ca8 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -141,6 +141,7 @@ struct nfs_inode {
141 unsigned long attrtimeo_timestamp; 141 unsigned long attrtimeo_timestamp;
142 __u64 change_attr; /* v4 only */ 142 __u64 change_attr; /* v4 only */
143 143
144 unsigned long last_updated;
144 /* "Generation counter" for the attribute cache. This is 145 /* "Generation counter" for the attribute cache. This is
145 * bumped whenever we update the metadata on the 146 * bumped whenever we update the metadata on the
146 * server. 147 * server.
@@ -319,6 +320,7 @@ extern u32 root_nfs_parse_addr(char *name); /*__init*/
319static inline void nfs_fattr_init(struct nfs_fattr *fattr) 320static inline void nfs_fattr_init(struct nfs_fattr *fattr)
320{ 321{
321 fattr->valid = 0; 322 fattr->valid = 0;
323 fattr->time_start = jiffies;
322} 324}
323 325
324/* 326/*
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 60086dac11d5..aeaee7e7c51d 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -41,7 +41,7 @@ struct nfs_fattr {
41 __u32 bitmap[2]; /* NFSv4 returned attribute bitmap */ 41 __u32 bitmap[2]; /* NFSv4 returned attribute bitmap */
42 __u64 change_attr; /* NFSv4 change attribute */ 42 __u64 change_attr; /* NFSv4 change attribute */
43 __u64 pre_change_attr;/* pre-op NFSv4 change attribute */ 43 __u64 pre_change_attr;/* pre-op NFSv4 change attribute */
44 unsigned long timestamp; 44 unsigned long time_start;
45}; 45};
46 46
47#define NFS_ATTR_WCC 0x0001 /* pre-op WCC data */ 47#define NFS_ATTR_WCC 0x0001 /* pre-op WCC data */