Commit 33801147a8fda6b04d7e9afe1d42f1c01d3d6837
1 parent
913a70fc17
Exists in
master
and in
7 other branches
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>
Showing 6 changed files with 44 additions and 20 deletions Side-by-side Diff
fs/nfs/inode.c
... | ... | @@ -785,7 +785,8 @@ |
785 | 785 | else |
786 | 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 | 790 | inode->i_atime = fattr->atime; |
790 | 791 | inode->i_mtime = fattr->mtime; |
791 | 792 | inode->i_ctime = fattr->ctime; |
792 | 793 | |
793 | 794 | |
... | ... | @@ -1120,14 +1121,15 @@ |
1120 | 1121 | goto out; |
1121 | 1122 | } |
1122 | 1123 | |
1124 | + spin_lock(&inode->i_lock); | |
1123 | 1125 | status = nfs_update_inode(inode, &fattr, verifier); |
1124 | 1126 | if (status) { |
1127 | + spin_unlock(&inode->i_lock); | |
1125 | 1128 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", |
1126 | 1129 | inode->i_sb->s_id, |
1127 | 1130 | (long long)NFS_FILEID(inode), status); |
1128 | 1131 | goto out; |
1129 | 1132 | } |
1130 | - spin_lock(&inode->i_lock); | |
1131 | 1133 | cache_validity = nfsi->cache_validity; |
1132 | 1134 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; |
1133 | 1135 | |
... | ... | @@ -1247,7 +1249,7 @@ |
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 | 1253 | * @inode - pointer to inode |
1252 | 1254 | * @fattr - updated attributes |
1253 | 1255 | * |
1254 | 1256 | |
... | ... | @@ -1255,13 +1257,12 @@ |
1255 | 1257 | * so that fattr carries weak cache consistency data, then it may |
1256 | 1258 | * also update the ctime/mtime/change_attribute. |
1257 | 1259 | */ |
1258 | -int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |
1260 | +static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fattr) | |
1259 | 1261 | { |
1260 | 1262 | struct nfs_inode *nfsi = NFS_I(inode); |
1261 | 1263 | loff_t cur_size, new_isize; |
1262 | 1264 | int data_unstable; |
1263 | 1265 | |
1264 | - spin_lock(&inode->i_lock); | |
1265 | 1266 | |
1266 | 1267 | /* Are we in the process of updating data on the server? */ |
1267 | 1268 | data_unstable = nfs_caches_unstable(inode); |
1268 | 1269 | |
... | ... | @@ -1325,11 +1326,40 @@ |
1325 | 1326 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) |
1326 | 1327 | nfsi->cache_validity |= NFS_INO_INVALID_ATIME; |
1327 | 1328 | |
1328 | - nfsi->read_cache_jiffies = fattr->timestamp; | |
1329 | - spin_unlock(&inode->i_lock); | |
1329 | + nfsi->read_cache_jiffies = fattr->time_start; | |
1330 | 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 | + */ | |
1343 | +int 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 | 1364 | * Many nfs protocol calls return the new file attributes after |
1335 | 1365 | * an operation. Here we update the inode to reflect the state |
1336 | 1366 | |
1337 | 1367 | |
1338 | 1368 | |
... | ... | @@ -1365,20 +1395,17 @@ |
1365 | 1395 | goto out_err; |
1366 | 1396 | } |
1367 | 1397 | |
1368 | - spin_lock(&inode->i_lock); | |
1369 | - | |
1370 | 1398 | /* |
1371 | 1399 | * Make sure the inode's type hasn't changed. |
1372 | 1400 | */ |
1373 | - if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { | |
1374 | - spin_unlock(&inode->i_lock); | |
1401 | + if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) | |
1375 | 1402 | goto out_changed; |
1376 | - } | |
1377 | 1403 | |
1378 | 1404 | /* |
1379 | 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 | 1410 | /* Are we racing with known updates of the metadata on the server? */ |
1384 | 1411 | data_unstable = ! (nfs_verify_change_attribute(inode, verifier) || |
... | ... | @@ -1467,7 +1494,6 @@ |
1467 | 1494 | if (!nfs_have_delegation(inode, FMODE_READ)) |
1468 | 1495 | nfsi->cache_validity |= invalid; |
1469 | 1496 | |
1470 | - spin_unlock(&inode->i_lock); | |
1471 | 1497 | return 0; |
1472 | 1498 | out_changed: |
1473 | 1499 | /* |
fs/nfs/nfs2xdr.c
fs/nfs/nfs3xdr.c
fs/nfs/nfs4xdr.c
... | ... | @@ -2799,10 +2799,8 @@ |
2799 | 2799 | goto xdr_error; |
2800 | 2800 | if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0) |
2801 | 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 | 2803 | fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4; |
2804 | - fattr->timestamp = jiffies; | |
2805 | - } | |
2806 | 2804 | xdr_error: |
2807 | 2805 | if (status != 0) |
2808 | 2806 | printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status); |
include/linux/nfs_fs.h
... | ... | @@ -141,6 +141,7 @@ |
141 | 141 | unsigned long attrtimeo_timestamp; |
142 | 142 | __u64 change_attr; /* v4 only */ |
143 | 143 | |
144 | + unsigned long last_updated; | |
144 | 145 | /* "Generation counter" for the attribute cache. This is |
145 | 146 | * bumped whenever we update the metadata on the |
146 | 147 | * server. |
... | ... | @@ -319,6 +320,7 @@ |
319 | 320 | static inline void nfs_fattr_init(struct nfs_fattr *fattr) |
320 | 321 | { |
321 | 322 | fattr->valid = 0; |
323 | + fattr->time_start = jiffies; | |
322 | 324 | } |
323 | 325 | |
324 | 326 | /* |
include/linux/nfs_xdr.h
... | ... | @@ -41,7 +41,7 @@ |
41 | 41 | __u32 bitmap[2]; /* NFSv4 returned attribute bitmap */ |
42 | 42 | __u64 change_attr; /* NFSv4 change attribute */ |
43 | 43 | __u64 pre_change_attr;/* pre-op NFSv4 change attribute */ |
44 | - unsigned long timestamp; | |
44 | + unsigned long time_start; | |
45 | 45 | }; |
46 | 46 | |
47 | 47 | #define NFS_ATTR_WCC 0x0001 /* pre-op WCC data */ |