Commit 33801147a8fda6b04d7e9afe1d42f1c01d3d6837

Authored by Trond Myklebust
1 parent 913a70fc17

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

... ... @@ -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 /*
... ... @@ -143,7 +143,6 @@
143 143 fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
144 144 fattr->rdev = 0;
145 145 }
146   - fattr->timestamp = jiffies;
147 146 return p;
148 147 }
149 148  
... ... @@ -174,7 +174,6 @@
174 174  
175 175 /* Update the mode bits */
176 176 fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
177   - fattr->timestamp = jiffies;
178 177 return p;
179 178 }
180 179  
... ... @@ -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 */