diff options
Diffstat (limited to 'fs/nfs/inode.c')
| -rw-r--r-- | fs/nfs/inode.c | 111 |
1 files changed, 92 insertions, 19 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 83107be3dd01..d42dff6d5e98 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -556,6 +556,7 @@ EXPORT_SYMBOL_GPL(nfs_setattr); | |||
| 556 | * This is a copy of the common vmtruncate, but with the locking | 556 | * This is a copy of the common vmtruncate, but with the locking |
| 557 | * corrected to take into account the fact that NFS requires | 557 | * corrected to take into account the fact that NFS requires |
| 558 | * inode->i_size to be updated under the inode->i_lock. | 558 | * inode->i_size to be updated under the inode->i_lock. |
| 559 | * Note: must be called with inode->i_lock held! | ||
| 559 | */ | 560 | */ |
| 560 | static int nfs_vmtruncate(struct inode * inode, loff_t offset) | 561 | static int nfs_vmtruncate(struct inode * inode, loff_t offset) |
| 561 | { | 562 | { |
| @@ -565,14 +566,14 @@ static int nfs_vmtruncate(struct inode * inode, loff_t offset) | |||
| 565 | if (err) | 566 | if (err) |
| 566 | goto out; | 567 | goto out; |
| 567 | 568 | ||
| 568 | spin_lock(&inode->i_lock); | ||
| 569 | i_size_write(inode, offset); | 569 | i_size_write(inode, offset); |
| 570 | /* Optimisation */ | 570 | /* Optimisation */ |
| 571 | if (offset == 0) | 571 | if (offset == 0) |
| 572 | NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_DATA; | 572 | NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_DATA; |
| 573 | spin_unlock(&inode->i_lock); | ||
| 574 | 573 | ||
| 574 | spin_unlock(&inode->i_lock); | ||
| 575 | truncate_pagecache(inode, offset); | 575 | truncate_pagecache(inode, offset); |
| 576 | spin_lock(&inode->i_lock); | ||
| 576 | out: | 577 | out: |
| 577 | return err; | 578 | return err; |
| 578 | } | 579 | } |
| @@ -585,10 +586,15 @@ out: | |||
| 585 | * Note: we do this in the *proc.c in order to ensure that | 586 | * Note: we do this in the *proc.c in order to ensure that |
| 586 | * it works for things like exclusive creates too. | 587 | * it works for things like exclusive creates too. |
| 587 | */ | 588 | */ |
| 588 | void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | 589 | void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, |
| 590 | struct nfs_fattr *fattr) | ||
| 589 | { | 591 | { |
| 592 | /* Barrier: bump the attribute generation count. */ | ||
| 593 | nfs_fattr_set_barrier(fattr); | ||
| 594 | |||
| 595 | spin_lock(&inode->i_lock); | ||
| 596 | NFS_I(inode)->attr_gencount = fattr->gencount; | ||
| 590 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { | 597 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { |
| 591 | spin_lock(&inode->i_lock); | ||
| 592 | if ((attr->ia_valid & ATTR_MODE) != 0) { | 598 | if ((attr->ia_valid & ATTR_MODE) != 0) { |
| 593 | int mode = attr->ia_mode & S_IALLUGO; | 599 | int mode = attr->ia_mode & S_IALLUGO; |
| 594 | mode |= inode->i_mode & ~S_IALLUGO; | 600 | mode |= inode->i_mode & ~S_IALLUGO; |
| @@ -600,12 +606,13 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | |||
| 600 | inode->i_gid = attr->ia_gid; | 606 | inode->i_gid = attr->ia_gid; |
| 601 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ACCESS | 607 | nfs_set_cache_invalid(inode, NFS_INO_INVALID_ACCESS |
| 602 | | NFS_INO_INVALID_ACL); | 608 | | NFS_INO_INVALID_ACL); |
| 603 | spin_unlock(&inode->i_lock); | ||
| 604 | } | 609 | } |
| 605 | if ((attr->ia_valid & ATTR_SIZE) != 0) { | 610 | if ((attr->ia_valid & ATTR_SIZE) != 0) { |
| 606 | nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); | 611 | nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC); |
| 607 | nfs_vmtruncate(inode, attr->ia_size); | 612 | nfs_vmtruncate(inode, attr->ia_size); |
| 608 | } | 613 | } |
| 614 | nfs_update_inode(inode, fattr); | ||
| 615 | spin_unlock(&inode->i_lock); | ||
| 609 | } | 616 | } |
| 610 | EXPORT_SYMBOL_GPL(nfs_setattr_update_inode); | 617 | EXPORT_SYMBOL_GPL(nfs_setattr_update_inode); |
| 611 | 618 | ||
| @@ -1028,6 +1035,7 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map | |||
| 1028 | 1035 | ||
| 1029 | if (mapping->nrpages != 0) { | 1036 | if (mapping->nrpages != 0) { |
| 1030 | if (S_ISREG(inode->i_mode)) { | 1037 | if (S_ISREG(inode->i_mode)) { |
| 1038 | unmap_mapping_range(mapping, 0, 0, 0); | ||
| 1031 | ret = nfs_sync_mapping(mapping); | 1039 | ret = nfs_sync_mapping(mapping); |
| 1032 | if (ret < 0) | 1040 | if (ret < 0) |
| 1033 | return ret; | 1041 | return ret; |
| @@ -1060,11 +1068,14 @@ static bool nfs_mapping_need_revalidate_inode(struct inode *inode) | |||
| 1060 | } | 1068 | } |
| 1061 | 1069 | ||
| 1062 | /** | 1070 | /** |
| 1063 | * nfs_revalidate_mapping - Revalidate the pagecache | 1071 | * __nfs_revalidate_mapping - Revalidate the pagecache |
| 1064 | * @inode - pointer to host inode | 1072 | * @inode - pointer to host inode |
| 1065 | * @mapping - pointer to mapping | 1073 | * @mapping - pointer to mapping |
| 1074 | * @may_lock - take inode->i_mutex? | ||
| 1066 | */ | 1075 | */ |
| 1067 | int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | 1076 | static int __nfs_revalidate_mapping(struct inode *inode, |
| 1077 | struct address_space *mapping, | ||
| 1078 | bool may_lock) | ||
| 1068 | { | 1079 | { |
| 1069 | struct nfs_inode *nfsi = NFS_I(inode); | 1080 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1070 | unsigned long *bitlock = &nfsi->flags; | 1081 | unsigned long *bitlock = &nfsi->flags; |
| @@ -1113,7 +1124,12 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
| 1113 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; | 1124 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; |
| 1114 | spin_unlock(&inode->i_lock); | 1125 | spin_unlock(&inode->i_lock); |
| 1115 | trace_nfs_invalidate_mapping_enter(inode); | 1126 | trace_nfs_invalidate_mapping_enter(inode); |
| 1116 | ret = nfs_invalidate_mapping(inode, mapping); | 1127 | if (may_lock) { |
| 1128 | mutex_lock(&inode->i_mutex); | ||
| 1129 | ret = nfs_invalidate_mapping(inode, mapping); | ||
| 1130 | mutex_unlock(&inode->i_mutex); | ||
| 1131 | } else | ||
| 1132 | ret = nfs_invalidate_mapping(inode, mapping); | ||
| 1117 | trace_nfs_invalidate_mapping_exit(inode, ret); | 1133 | trace_nfs_invalidate_mapping_exit(inode, ret); |
| 1118 | 1134 | ||
| 1119 | clear_bit_unlock(NFS_INO_INVALIDATING, bitlock); | 1135 | clear_bit_unlock(NFS_INO_INVALIDATING, bitlock); |
| @@ -1123,6 +1139,29 @@ out: | |||
| 1123 | return ret; | 1139 | return ret; |
| 1124 | } | 1140 | } |
| 1125 | 1141 | ||
| 1142 | /** | ||
| 1143 | * nfs_revalidate_mapping - Revalidate the pagecache | ||
| 1144 | * @inode - pointer to host inode | ||
| 1145 | * @mapping - pointer to mapping | ||
| 1146 | */ | ||
| 1147 | int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | ||
| 1148 | { | ||
| 1149 | return __nfs_revalidate_mapping(inode, mapping, false); | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | /** | ||
| 1153 | * nfs_revalidate_mapping_protected - Revalidate the pagecache | ||
| 1154 | * @inode - pointer to host inode | ||
| 1155 | * @mapping - pointer to mapping | ||
| 1156 | * | ||
| 1157 | * Differs from nfs_revalidate_mapping() in that it grabs the inode->i_mutex | ||
| 1158 | * while invalidating the mapping. | ||
| 1159 | */ | ||
| 1160 | int nfs_revalidate_mapping_protected(struct inode *inode, struct address_space *mapping) | ||
| 1161 | { | ||
| 1162 | return __nfs_revalidate_mapping(inode, mapping, true); | ||
| 1163 | } | ||
| 1164 | |||
| 1126 | static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 1165 | static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
| 1127 | { | 1166 | { |
| 1128 | struct nfs_inode *nfsi = NFS_I(inode); | 1167 | struct nfs_inode *nfsi = NFS_I(inode); |
| @@ -1231,13 +1270,6 @@ static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fat | |||
| 1231 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; | 1270 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; |
| 1232 | } | 1271 | } |
| 1233 | 1272 | ||
| 1234 | static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | ||
| 1235 | { | ||
| 1236 | if (!(fattr->valid & NFS_ATTR_FATTR_SIZE)) | ||
| 1237 | return 0; | ||
| 1238 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | static atomic_long_t nfs_attr_generation_counter; | 1273 | static atomic_long_t nfs_attr_generation_counter; |
| 1242 | 1274 | ||
| 1243 | static unsigned long nfs_read_attr_generation_counter(void) | 1275 | static unsigned long nfs_read_attr_generation_counter(void) |
| @@ -1249,6 +1281,7 @@ unsigned long nfs_inc_attr_generation_counter(void) | |||
| 1249 | { | 1281 | { |
| 1250 | return atomic_long_inc_return(&nfs_attr_generation_counter); | 1282 | return atomic_long_inc_return(&nfs_attr_generation_counter); |
| 1251 | } | 1283 | } |
| 1284 | EXPORT_SYMBOL_GPL(nfs_inc_attr_generation_counter); | ||
| 1252 | 1285 | ||
| 1253 | void nfs_fattr_init(struct nfs_fattr *fattr) | 1286 | void nfs_fattr_init(struct nfs_fattr *fattr) |
| 1254 | { | 1287 | { |
| @@ -1260,6 +1293,22 @@ void nfs_fattr_init(struct nfs_fattr *fattr) | |||
| 1260 | } | 1293 | } |
| 1261 | EXPORT_SYMBOL_GPL(nfs_fattr_init); | 1294 | EXPORT_SYMBOL_GPL(nfs_fattr_init); |
| 1262 | 1295 | ||
| 1296 | /** | ||
| 1297 | * nfs_fattr_set_barrier | ||
| 1298 | * @fattr: attributes | ||
| 1299 | * | ||
| 1300 | * Used to set a barrier after an attribute was updated. This | ||
| 1301 | * barrier ensures that older attributes from RPC calls that may | ||
| 1302 | * have raced with our update cannot clobber these new values. | ||
| 1303 | * Note that you are still responsible for ensuring that other | ||
| 1304 | * operations which change the attribute on the server do not | ||
| 1305 | * collide. | ||
| 1306 | */ | ||
| 1307 | void nfs_fattr_set_barrier(struct nfs_fattr *fattr) | ||
| 1308 | { | ||
| 1309 | fattr->gencount = nfs_inc_attr_generation_counter(); | ||
| 1310 | } | ||
| 1311 | |||
| 1263 | struct nfs_fattr *nfs_alloc_fattr(void) | 1312 | struct nfs_fattr *nfs_alloc_fattr(void) |
| 1264 | { | 1313 | { |
| 1265 | struct nfs_fattr *fattr; | 1314 | struct nfs_fattr *fattr; |
| @@ -1370,7 +1419,6 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n | |||
| 1370 | 1419 | ||
| 1371 | return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 || | 1420 | return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 || |
| 1372 | nfs_ctime_need_update(inode, fattr) || | 1421 | nfs_ctime_need_update(inode, fattr) || |
| 1373 | nfs_size_need_update(inode, fattr) || | ||
| 1374 | ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); | 1422 | ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); |
| 1375 | } | 1423 | } |
| 1376 | 1424 | ||
| @@ -1460,6 +1508,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1460 | int status; | 1508 | int status; |
| 1461 | 1509 | ||
| 1462 | spin_lock(&inode->i_lock); | 1510 | spin_lock(&inode->i_lock); |
| 1511 | nfs_fattr_set_barrier(fattr); | ||
| 1463 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1512 | status = nfs_post_op_update_inode_locked(inode, fattr); |
| 1464 | spin_unlock(&inode->i_lock); | 1513 | spin_unlock(&inode->i_lock); |
| 1465 | 1514 | ||
| @@ -1468,7 +1517,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1468 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); | 1517 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); |
| 1469 | 1518 | ||
| 1470 | /** | 1519 | /** |
| 1471 | * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache | 1520 | * nfs_post_op_update_inode_force_wcc_locked - update the inode attribute cache |
| 1472 | * @inode - pointer to inode | 1521 | * @inode - pointer to inode |
| 1473 | * @fattr - updated attributes | 1522 | * @fattr - updated attributes |
| 1474 | * | 1523 | * |
| @@ -1478,11 +1527,10 @@ EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); | |||
| 1478 | * | 1527 | * |
| 1479 | * This function is mainly designed to be used by the ->write_done() functions. | 1528 | * This function is mainly designed to be used by the ->write_done() functions. |
| 1480 | */ | 1529 | */ |
| 1481 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) | 1530 | int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr) |
| 1482 | { | 1531 | { |
| 1483 | int status; | 1532 | int status; |
| 1484 | 1533 | ||
| 1485 | spin_lock(&inode->i_lock); | ||
| 1486 | /* Don't do a WCC update if these attributes are already stale */ | 1534 | /* Don't do a WCC update if these attributes are already stale */ |
| 1487 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || | 1535 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || |
| 1488 | !nfs_inode_attrs_need_update(inode, fattr)) { | 1536 | !nfs_inode_attrs_need_update(inode, fattr)) { |
| @@ -1514,6 +1562,27 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa | |||
| 1514 | } | 1562 | } |
| 1515 | out_noforce: | 1563 | out_noforce: |
| 1516 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1564 | status = nfs_post_op_update_inode_locked(inode, fattr); |
| 1565 | return status; | ||
| 1566 | } | ||
| 1567 | |||
| 1568 | /** | ||
| 1569 | * nfs_post_op_update_inode_force_wcc - try to update the inode attribute cache | ||
| 1570 | * @inode - pointer to inode | ||
| 1571 | * @fattr - updated attributes | ||
| 1572 | * | ||
| 1573 | * After an operation that has changed the inode metadata, mark the | ||
| 1574 | * attribute cache as being invalid, then try to update it. Fake up | ||
| 1575 | * weak cache consistency data, if none exist. | ||
| 1576 | * | ||
| 1577 | * This function is mainly designed to be used by the ->write_done() functions. | ||
| 1578 | */ | ||
| 1579 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) | ||
| 1580 | { | ||
| 1581 | int status; | ||
| 1582 | |||
| 1583 | spin_lock(&inode->i_lock); | ||
| 1584 | nfs_fattr_set_barrier(fattr); | ||
| 1585 | status = nfs_post_op_update_inode_force_wcc_locked(inode, fattr); | ||
| 1517 | spin_unlock(&inode->i_lock); | 1586 | spin_unlock(&inode->i_lock); |
| 1518 | return status; | 1587 | return status; |
| 1519 | } | 1588 | } |
| @@ -1715,6 +1784,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1715 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1784 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
| 1716 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1785 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
| 1717 | nfsi->attrtimeo_timestamp = now; | 1786 | nfsi->attrtimeo_timestamp = now; |
| 1787 | /* Set barrier to be more recent than all outstanding updates */ | ||
| 1718 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); | 1788 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); |
| 1719 | } else { | 1789 | } else { |
| 1720 | if (!time_in_range_open(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) { | 1790 | if (!time_in_range_open(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) { |
| @@ -1722,6 +1792,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1722 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); | 1792 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); |
| 1723 | nfsi->attrtimeo_timestamp = now; | 1793 | nfsi->attrtimeo_timestamp = now; |
| 1724 | } | 1794 | } |
| 1795 | /* Set the barrier to be more recent than this fattr */ | ||
| 1796 | if ((long)fattr->gencount - (long)nfsi->attr_gencount > 0) | ||
| 1797 | nfsi->attr_gencount = fattr->gencount; | ||
| 1725 | } | 1798 | } |
| 1726 | invalid &= ~NFS_INO_INVALID_ATTR; | 1799 | invalid &= ~NFS_INO_INVALID_ATTR; |
| 1727 | /* Don't invalidate the data if we were to blame */ | 1800 | /* Don't invalidate the data if we were to blame */ |
