diff options
Diffstat (limited to 'fs/ocfs2/aops.c')
| -rw-r--r-- | fs/ocfs2/aops.c | 69 |
1 files changed, 49 insertions, 20 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index b2c52b3a1484..8a1e61545f41 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
| @@ -193,6 +193,7 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock, | |||
| 193 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | 193 | (unsigned long long)OCFS2_I(inode)->ip_blkno); |
| 194 | mlog(ML_ERROR, "Size %llu, clusters %u\n", (unsigned long long)i_size_read(inode), OCFS2_I(inode)->ip_clusters); | 194 | mlog(ML_ERROR, "Size %llu, clusters %u\n", (unsigned long long)i_size_read(inode), OCFS2_I(inode)->ip_clusters); |
| 195 | dump_stack(); | 195 | dump_stack(); |
| 196 | goto bail; | ||
| 196 | } | 197 | } |
| 197 | 198 | ||
| 198 | past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode)); | 199 | past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode)); |
| @@ -894,18 +895,17 @@ struct ocfs2_write_cluster_desc { | |||
| 894 | */ | 895 | */ |
| 895 | unsigned c_new; | 896 | unsigned c_new; |
| 896 | unsigned c_unwritten; | 897 | unsigned c_unwritten; |
| 898 | unsigned c_needs_zero; | ||
| 897 | }; | 899 | }; |
| 898 | 900 | ||
| 899 | static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d) | ||
| 900 | { | ||
| 901 | return d->c_new || d->c_unwritten; | ||
| 902 | } | ||
| 903 | |||
| 904 | struct ocfs2_write_ctxt { | 901 | struct ocfs2_write_ctxt { |
| 905 | /* Logical cluster position / len of write */ | 902 | /* Logical cluster position / len of write */ |
| 906 | u32 w_cpos; | 903 | u32 w_cpos; |
| 907 | u32 w_clen; | 904 | u32 w_clen; |
| 908 | 905 | ||
| 906 | /* First cluster allocated in a nonsparse extend */ | ||
| 907 | u32 w_first_new_cpos; | ||
| 908 | |||
| 909 | struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE]; | 909 | struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE]; |
| 910 | 910 | ||
| 911 | /* | 911 | /* |
| @@ -983,6 +983,7 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp, | |||
| 983 | return -ENOMEM; | 983 | return -ENOMEM; |
| 984 | 984 | ||
| 985 | wc->w_cpos = pos >> osb->s_clustersize_bits; | 985 | wc->w_cpos = pos >> osb->s_clustersize_bits; |
| 986 | wc->w_first_new_cpos = UINT_MAX; | ||
| 986 | cend = (pos + len - 1) >> osb->s_clustersize_bits; | 987 | cend = (pos + len - 1) >> osb->s_clustersize_bits; |
| 987 | wc->w_clen = cend - wc->w_cpos + 1; | 988 | wc->w_clen = cend - wc->w_cpos + 1; |
| 988 | get_bh(di_bh); | 989 | get_bh(di_bh); |
| @@ -1217,20 +1218,18 @@ out: | |||
| 1217 | */ | 1218 | */ |
| 1218 | static int ocfs2_write_cluster(struct address_space *mapping, | 1219 | static int ocfs2_write_cluster(struct address_space *mapping, |
| 1219 | u32 phys, unsigned int unwritten, | 1220 | u32 phys, unsigned int unwritten, |
| 1221 | unsigned int should_zero, | ||
| 1220 | struct ocfs2_alloc_context *data_ac, | 1222 | struct ocfs2_alloc_context *data_ac, |
| 1221 | struct ocfs2_alloc_context *meta_ac, | 1223 | struct ocfs2_alloc_context *meta_ac, |
| 1222 | struct ocfs2_write_ctxt *wc, u32 cpos, | 1224 | struct ocfs2_write_ctxt *wc, u32 cpos, |
| 1223 | loff_t user_pos, unsigned user_len) | 1225 | loff_t user_pos, unsigned user_len) |
| 1224 | { | 1226 | { |
| 1225 | int ret, i, new, should_zero = 0; | 1227 | int ret, i, new; |
| 1226 | u64 v_blkno, p_blkno; | 1228 | u64 v_blkno, p_blkno; |
| 1227 | struct inode *inode = mapping->host; | 1229 | struct inode *inode = mapping->host; |
| 1228 | struct ocfs2_extent_tree et; | 1230 | struct ocfs2_extent_tree et; |
| 1229 | 1231 | ||
| 1230 | new = phys == 0 ? 1 : 0; | 1232 | new = phys == 0 ? 1 : 0; |
| 1231 | if (new || unwritten) | ||
| 1232 | should_zero = 1; | ||
| 1233 | |||
| 1234 | if (new) { | 1233 | if (new) { |
| 1235 | u32 tmp_pos; | 1234 | u32 tmp_pos; |
| 1236 | 1235 | ||
| @@ -1301,7 +1300,7 @@ static int ocfs2_write_cluster(struct address_space *mapping, | |||
| 1301 | if (tmpret) { | 1300 | if (tmpret) { |
| 1302 | mlog_errno(tmpret); | 1301 | mlog_errno(tmpret); |
| 1303 | if (ret == 0) | 1302 | if (ret == 0) |
| 1304 | tmpret = ret; | 1303 | ret = tmpret; |
| 1305 | } | 1304 | } |
| 1306 | } | 1305 | } |
| 1307 | 1306 | ||
| @@ -1341,7 +1340,9 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping, | |||
| 1341 | local_len = osb->s_clustersize - cluster_off; | 1340 | local_len = osb->s_clustersize - cluster_off; |
| 1342 | 1341 | ||
| 1343 | ret = ocfs2_write_cluster(mapping, desc->c_phys, | 1342 | ret = ocfs2_write_cluster(mapping, desc->c_phys, |
| 1344 | desc->c_unwritten, data_ac, meta_ac, | 1343 | desc->c_unwritten, |
| 1344 | desc->c_needs_zero, | ||
| 1345 | data_ac, meta_ac, | ||
| 1345 | wc, desc->c_cpos, pos, local_len); | 1346 | wc, desc->c_cpos, pos, local_len); |
| 1346 | if (ret) { | 1347 | if (ret) { |
| 1347 | mlog_errno(ret); | 1348 | mlog_errno(ret); |
| @@ -1391,14 +1392,14 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb, | |||
| 1391 | * newly allocated cluster. | 1392 | * newly allocated cluster. |
| 1392 | */ | 1393 | */ |
| 1393 | desc = &wc->w_desc[0]; | 1394 | desc = &wc->w_desc[0]; |
| 1394 | if (ocfs2_should_zero_cluster(desc)) | 1395 | if (desc->c_needs_zero) |
| 1395 | ocfs2_figure_cluster_boundaries(osb, | 1396 | ocfs2_figure_cluster_boundaries(osb, |
| 1396 | desc->c_cpos, | 1397 | desc->c_cpos, |
| 1397 | &wc->w_target_from, | 1398 | &wc->w_target_from, |
| 1398 | NULL); | 1399 | NULL); |
| 1399 | 1400 | ||
| 1400 | desc = &wc->w_desc[wc->w_clen - 1]; | 1401 | desc = &wc->w_desc[wc->w_clen - 1]; |
| 1401 | if (ocfs2_should_zero_cluster(desc)) | 1402 | if (desc->c_needs_zero) |
| 1402 | ocfs2_figure_cluster_boundaries(osb, | 1403 | ocfs2_figure_cluster_boundaries(osb, |
| 1403 | desc->c_cpos, | 1404 | desc->c_cpos, |
| 1404 | NULL, | 1405 | NULL, |
| @@ -1466,13 +1467,28 @@ static int ocfs2_populate_write_desc(struct inode *inode, | |||
| 1466 | phys++; | 1467 | phys++; |
| 1467 | } | 1468 | } |
| 1468 | 1469 | ||
| 1470 | /* | ||
| 1471 | * If w_first_new_cpos is < UINT_MAX, we have a non-sparse | ||
| 1472 | * file that got extended. w_first_new_cpos tells us | ||
| 1473 | * where the newly allocated clusters are so we can | ||
| 1474 | * zero them. | ||
| 1475 | */ | ||
| 1476 | if (desc->c_cpos >= wc->w_first_new_cpos) { | ||
| 1477 | BUG_ON(phys == 0); | ||
| 1478 | desc->c_needs_zero = 1; | ||
| 1479 | } | ||
| 1480 | |||
| 1469 | desc->c_phys = phys; | 1481 | desc->c_phys = phys; |
| 1470 | if (phys == 0) { | 1482 | if (phys == 0) { |
| 1471 | desc->c_new = 1; | 1483 | desc->c_new = 1; |
| 1484 | desc->c_needs_zero = 1; | ||
| 1472 | *clusters_to_alloc = *clusters_to_alloc + 1; | 1485 | *clusters_to_alloc = *clusters_to_alloc + 1; |
| 1473 | } | 1486 | } |
| 1474 | if (ext_flags & OCFS2_EXT_UNWRITTEN) | 1487 | |
| 1488 | if (ext_flags & OCFS2_EXT_UNWRITTEN) { | ||
| 1475 | desc->c_unwritten = 1; | 1489 | desc->c_unwritten = 1; |
| 1490 | desc->c_needs_zero = 1; | ||
| 1491 | } | ||
| 1476 | 1492 | ||
| 1477 | num_clusters--; | 1493 | num_clusters--; |
| 1478 | } | 1494 | } |
| @@ -1632,10 +1648,13 @@ static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos, | |||
| 1632 | if (newsize <= i_size_read(inode)) | 1648 | if (newsize <= i_size_read(inode)) |
| 1633 | return 0; | 1649 | return 0; |
| 1634 | 1650 | ||
| 1635 | ret = ocfs2_extend_no_holes(inode, newsize, newsize - len); | 1651 | ret = ocfs2_extend_no_holes(inode, newsize, pos); |
| 1636 | if (ret) | 1652 | if (ret) |
| 1637 | mlog_errno(ret); | 1653 | mlog_errno(ret); |
| 1638 | 1654 | ||
| 1655 | wc->w_first_new_cpos = | ||
| 1656 | ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode)); | ||
| 1657 | |||
| 1639 | return ret; | 1658 | return ret; |
| 1640 | } | 1659 | } |
| 1641 | 1660 | ||
| @@ -1644,7 +1663,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
| 1644 | struct page **pagep, void **fsdata, | 1663 | struct page **pagep, void **fsdata, |
| 1645 | struct buffer_head *di_bh, struct page *mmap_page) | 1664 | struct buffer_head *di_bh, struct page *mmap_page) |
| 1646 | { | 1665 | { |
| 1647 | int ret, credits = OCFS2_INODE_UPDATE_CREDITS; | 1666 | int ret, cluster_of_pages, credits = OCFS2_INODE_UPDATE_CREDITS; |
| 1648 | unsigned int clusters_to_alloc, extents_to_split; | 1667 | unsigned int clusters_to_alloc, extents_to_split; |
| 1649 | struct ocfs2_write_ctxt *wc; | 1668 | struct ocfs2_write_ctxt *wc; |
| 1650 | struct inode *inode = mapping->host; | 1669 | struct inode *inode = mapping->host; |
| @@ -1722,8 +1741,19 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
| 1722 | 1741 | ||
| 1723 | } | 1742 | } |
| 1724 | 1743 | ||
| 1725 | ocfs2_set_target_boundaries(osb, wc, pos, len, | 1744 | /* |
| 1726 | clusters_to_alloc + extents_to_split); | 1745 | * We have to zero sparse allocated clusters, unwritten extent clusters, |
| 1746 | * and non-sparse clusters we just extended. For non-sparse writes, | ||
| 1747 | * we know zeros will only be needed in the first and/or last cluster. | ||
| 1748 | */ | ||
| 1749 | if (clusters_to_alloc || extents_to_split || | ||
| 1750 | (wc->w_clen && (wc->w_desc[0].c_needs_zero || | ||
| 1751 | wc->w_desc[wc->w_clen - 1].c_needs_zero))) | ||
| 1752 | cluster_of_pages = 1; | ||
| 1753 | else | ||
| 1754 | cluster_of_pages = 0; | ||
| 1755 | |||
| 1756 | ocfs2_set_target_boundaries(osb, wc, pos, len, cluster_of_pages); | ||
| 1727 | 1757 | ||
| 1728 | handle = ocfs2_start_trans(osb, credits); | 1758 | handle = ocfs2_start_trans(osb, credits); |
| 1729 | if (IS_ERR(handle)) { | 1759 | if (IS_ERR(handle)) { |
| @@ -1756,8 +1786,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
| 1756 | * extent. | 1786 | * extent. |
| 1757 | */ | 1787 | */ |
| 1758 | ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, | 1788 | ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, |
| 1759 | clusters_to_alloc + extents_to_split, | 1789 | cluster_of_pages, mmap_page); |
| 1760 | mmap_page); | ||
| 1761 | if (ret) { | 1790 | if (ret) { |
| 1762 | mlog_errno(ret); | 1791 | mlog_errno(ret); |
| 1763 | goto out_quota; | 1792 | goto out_quota; |
