aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSunil Mushran <sunil.mushran@oracle.com>2009-08-06 19:12:58 -0400
committerJoel Becker <joel.becker@oracle.com>2009-08-07 16:16:23 -0400
commite7432675f8ca868a4af365759a8d4c3779a3d922 (patch)
tree238d57e12fae632c9baeca98ddec701b3391ff29 /fs
parentab57a40827d99e2d8e59066a56b93bf6c844c916 (diff)
ocfs2: Initialize the cluster we're writing to in a non-sparse extend
In a non-sparse extend, we correctly allocate (and zero) the clusters between the old_i_size and pos, but we don't zero the portions of the cluster we're writing to outside of pos<->len. It handles clustersize > pagesize and blocksize < pagesize. [Cleaned up by Joel Becker.] Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com> Signed-off-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ocfs2/aops.c66
1 files changed, 47 insertions, 19 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index e511df101451..b401654011a2 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -895,18 +895,17 @@ struct ocfs2_write_cluster_desc {
895 */ 895 */
896 unsigned c_new; 896 unsigned c_new;
897 unsigned c_unwritten; 897 unsigned c_unwritten;
898 unsigned c_needs_zero;
898}; 899};
899 900
900static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d)
901{
902 return d->c_new || d->c_unwritten;
903}
904
905struct ocfs2_write_ctxt { 901struct ocfs2_write_ctxt {
906 /* Logical cluster position / len of write */ 902 /* Logical cluster position / len of write */
907 u32 w_cpos; 903 u32 w_cpos;
908 u32 w_clen; 904 u32 w_clen;
909 905
906 /* First cluster allocated in a nonsparse extend */
907 u32 w_first_new_cpos;
908
910 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];
911 910
912 /* 911 /*
@@ -984,6 +983,7 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
984 return -ENOMEM; 983 return -ENOMEM;
985 984
986 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;
987 cend = (pos + len - 1) >> osb->s_clustersize_bits; 987 cend = (pos + len - 1) >> osb->s_clustersize_bits;
988 wc->w_clen = cend - wc->w_cpos + 1; 988 wc->w_clen = cend - wc->w_cpos + 1;
989 get_bh(di_bh); 989 get_bh(di_bh);
@@ -1218,20 +1218,18 @@ out:
1218 */ 1218 */
1219static int ocfs2_write_cluster(struct address_space *mapping, 1219static int ocfs2_write_cluster(struct address_space *mapping,
1220 u32 phys, unsigned int unwritten, 1220 u32 phys, unsigned int unwritten,
1221 unsigned int should_zero,
1221 struct ocfs2_alloc_context *data_ac, 1222 struct ocfs2_alloc_context *data_ac,
1222 struct ocfs2_alloc_context *meta_ac, 1223 struct ocfs2_alloc_context *meta_ac,
1223 struct ocfs2_write_ctxt *wc, u32 cpos, 1224 struct ocfs2_write_ctxt *wc, u32 cpos,
1224 loff_t user_pos, unsigned user_len) 1225 loff_t user_pos, unsigned user_len)
1225{ 1226{
1226 int ret, i, new, should_zero = 0; 1227 int ret, i, new;
1227 u64 v_blkno, p_blkno; 1228 u64 v_blkno, p_blkno;
1228 struct inode *inode = mapping->host; 1229 struct inode *inode = mapping->host;
1229 struct ocfs2_extent_tree et; 1230 struct ocfs2_extent_tree et;
1230 1231
1231 new = phys == 0 ? 1 : 0; 1232 new = phys == 0 ? 1 : 0;
1232 if (new || unwritten)
1233 should_zero = 1;
1234
1235 if (new) { 1233 if (new) {
1236 u32 tmp_pos; 1234 u32 tmp_pos;
1237 1235
@@ -1342,7 +1340,9 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping,
1342 local_len = osb->s_clustersize - cluster_off; 1340 local_len = osb->s_clustersize - cluster_off;
1343 1341
1344 ret = ocfs2_write_cluster(mapping, desc->c_phys, 1342 ret = ocfs2_write_cluster(mapping, desc->c_phys,
1345 desc->c_unwritten, data_ac, meta_ac, 1343 desc->c_unwritten,
1344 desc->c_needs_zero,
1345 data_ac, meta_ac,
1346 wc, desc->c_cpos, pos, local_len); 1346 wc, desc->c_cpos, pos, local_len);
1347 if (ret) { 1347 if (ret) {
1348 mlog_errno(ret); 1348 mlog_errno(ret);
@@ -1392,14 +1392,14 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
1392 * newly allocated cluster. 1392 * newly allocated cluster.
1393 */ 1393 */
1394 desc = &wc->w_desc[0]; 1394 desc = &wc->w_desc[0];
1395 if (ocfs2_should_zero_cluster(desc)) 1395 if (desc->c_needs_zero)
1396 ocfs2_figure_cluster_boundaries(osb, 1396 ocfs2_figure_cluster_boundaries(osb,
1397 desc->c_cpos, 1397 desc->c_cpos,
1398 &wc->w_target_from, 1398 &wc->w_target_from,
1399 NULL); 1399 NULL);
1400 1400
1401 desc = &wc->w_desc[wc->w_clen - 1]; 1401 desc = &wc->w_desc[wc->w_clen - 1];
1402 if (ocfs2_should_zero_cluster(desc)) 1402 if (desc->c_needs_zero)
1403 ocfs2_figure_cluster_boundaries(osb, 1403 ocfs2_figure_cluster_boundaries(osb,
1404 desc->c_cpos, 1404 desc->c_cpos,
1405 NULL, 1405 NULL,
@@ -1467,13 +1467,28 @@ static int ocfs2_populate_write_desc(struct inode *inode,
1467 phys++; 1467 phys++;
1468 } 1468 }
1469 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
1470 desc->c_phys = phys; 1481 desc->c_phys = phys;
1471 if (phys == 0) { 1482 if (phys == 0) {
1472 desc->c_new = 1; 1483 desc->c_new = 1;
1484 desc->c_needs_zero = 1;
1473 *clusters_to_alloc = *clusters_to_alloc + 1; 1485 *clusters_to_alloc = *clusters_to_alloc + 1;
1474 } 1486 }
1475 if (ext_flags & OCFS2_EXT_UNWRITTEN) 1487
1488 if (ext_flags & OCFS2_EXT_UNWRITTEN) {
1476 desc->c_unwritten = 1; 1489 desc->c_unwritten = 1;
1490 desc->c_needs_zero = 1;
1491 }
1477 1492
1478 num_clusters--; 1493 num_clusters--;
1479 } 1494 }
@@ -1633,10 +1648,13 @@ static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos,
1633 if (newsize <= i_size_read(inode)) 1648 if (newsize <= i_size_read(inode))
1634 return 0; 1649 return 0;
1635 1650
1636 ret = ocfs2_extend_no_holes(inode, newsize, newsize - len); 1651 ret = ocfs2_extend_no_holes(inode, newsize, pos);
1637 if (ret) 1652 if (ret)
1638 mlog_errno(ret); 1653 mlog_errno(ret);
1639 1654
1655 wc->w_first_new_cpos =
1656 ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode));
1657
1640 return ret; 1658 return ret;
1641} 1659}
1642 1660
@@ -1645,7 +1663,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
1645 struct page **pagep, void **fsdata, 1663 struct page **pagep, void **fsdata,
1646 struct buffer_head *di_bh, struct page *mmap_page) 1664 struct buffer_head *di_bh, struct page *mmap_page)
1647{ 1665{
1648 int ret, credits = OCFS2_INODE_UPDATE_CREDITS; 1666 int ret, cluster_of_pages, credits = OCFS2_INODE_UPDATE_CREDITS;
1649 unsigned int clusters_to_alloc, extents_to_split; 1667 unsigned int clusters_to_alloc, extents_to_split;
1650 struct ocfs2_write_ctxt *wc; 1668 struct ocfs2_write_ctxt *wc;
1651 struct inode *inode = mapping->host; 1669 struct inode *inode = mapping->host;
@@ -1723,8 +1741,19 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
1723 1741
1724 } 1742 }
1725 1743
1726 ocfs2_set_target_boundaries(osb, wc, pos, len, 1744 /*
1727 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_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);
1728 1757
1729 handle = ocfs2_start_trans(osb, credits); 1758 handle = ocfs2_start_trans(osb, credits);
1730 if (IS_ERR(handle)) { 1759 if (IS_ERR(handle)) {
@@ -1757,8 +1786,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
1757 * extent. 1786 * extent.
1758 */ 1787 */
1759 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,
1760 clusters_to_alloc + extents_to_split, 1789 cluster_of_pages, mmap_page);
1761 mmap_page);
1762 if (ret) { 1790 if (ret) {
1763 mlog_errno(ret); 1791 mlog_errno(ret);
1764 goto out_quota; 1792 goto out_quota;