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 */ |