diff options
-rw-r--r-- | fs/nfs/inode.c | 54 | ||||
-rw-r--r-- | fs/nfs/nfs2xdr.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs3xdr.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 4 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 2 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 2 |
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 | */ |
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 | 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 | */ | ||
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 | * 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 | } | ||
2806 | xdr_error: | 2804 | xdr_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*/ | |||
319 | static inline void nfs_fattr_init(struct nfs_fattr *fattr) | 320 | static 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 */ |