diff options
| author | Mark Fasheh <mark.fasheh@oracle.com> | 2007-08-28 20:13:23 -0400 |
|---|---|---|
| committer | Mark Fasheh <mark.fasheh@oracle.com> | 2007-10-12 14:54:35 -0400 |
| commit | 65ed39d6ca78f07d2958814e08440e4264b6b488 (patch) | |
| tree | 477623ef58810a6d32c8d23fbf17e5258495ddb0 /fs/ocfs2 | |
| parent | 92e91ce2a30b2af53ebf077512801dc01e75cca5 (diff) | |
ocfs2: move nonsparse hole-filling into ocfs2_write_begin()
By doing this, we can remove any higher level logic which has to have
knowledge of btree functionality - any callers of ocfs2_write_begin() can
now expect it to do anything necessary to prepare the inode for new data.
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Reviewed-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2')
| -rw-r--r-- | fs/ocfs2/aops.c | 40 | ||||
| -rw-r--r-- | fs/ocfs2/file.c | 217 | ||||
| -rw-r--r-- | fs/ocfs2/file.h | 2 |
3 files changed, 115 insertions, 144 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index f37f25c931..fae07672eb 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
| @@ -301,12 +301,8 @@ int ocfs2_prepare_write_nolock(struct inode *inode, struct page *page, | |||
| 301 | { | 301 | { |
| 302 | int ret; | 302 | int ret; |
| 303 | 303 | ||
| 304 | down_read(&OCFS2_I(inode)->ip_alloc_sem); | ||
| 305 | |||
| 306 | ret = block_prepare_write(page, from, to, ocfs2_get_block); | 304 | ret = block_prepare_write(page, from, to, ocfs2_get_block); |
| 307 | 305 | ||
| 308 | up_read(&OCFS2_I(inode)->ip_alloc_sem); | ||
| 309 | |||
| 310 | return ret; | 306 | return ret; |
| 311 | } | 307 | } |
| 312 | 308 | ||
| @@ -1360,6 +1356,36 @@ out: | |||
| 1360 | return ret; | 1356 | return ret; |
| 1361 | } | 1357 | } |
| 1362 | 1358 | ||
| 1359 | /* | ||
| 1360 | * This function only does anything for file systems which can't | ||
| 1361 | * handle sparse files. | ||
| 1362 | * | ||
| 1363 | * What we want to do here is fill in any hole between the current end | ||
| 1364 | * of allocation and the end of our write. That way the rest of the | ||
| 1365 | * write path can treat it as an non-allocating write, which has no | ||
| 1366 | * special case code for sparse/nonsparse files. | ||
| 1367 | */ | ||
| 1368 | static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos, | ||
| 1369 | unsigned len, | ||
| 1370 | struct ocfs2_write_ctxt *wc) | ||
| 1371 | { | ||
| 1372 | int ret; | ||
| 1373 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
| 1374 | loff_t newsize = pos + len; | ||
| 1375 | |||
| 1376 | if (ocfs2_sparse_alloc(osb)) | ||
| 1377 | return 0; | ||
| 1378 | |||
| 1379 | if (newsize <= i_size_read(inode)) | ||
| 1380 | return 0; | ||
| 1381 | |||
| 1382 | ret = ocfs2_extend_no_holes(inode, newsize, newsize - len); | ||
| 1383 | if (ret) | ||
| 1384 | mlog_errno(ret); | ||
| 1385 | |||
| 1386 | return ret; | ||
| 1387 | } | ||
| 1388 | |||
| 1363 | int ocfs2_write_begin_nolock(struct address_space *mapping, | 1389 | int ocfs2_write_begin_nolock(struct address_space *mapping, |
| 1364 | loff_t pos, unsigned len, unsigned flags, | 1390 | loff_t pos, unsigned len, unsigned flags, |
| 1365 | struct page **pagep, void **fsdata, | 1391 | struct page **pagep, void **fsdata, |
| @@ -1381,6 +1407,12 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
| 1381 | return ret; | 1407 | return ret; |
| 1382 | } | 1408 | } |
| 1383 | 1409 | ||
| 1410 | ret = ocfs2_expand_nonsparse_inode(inode, pos, len, wc); | ||
| 1411 | if (ret) { | ||
| 1412 | mlog_errno(ret); | ||
| 1413 | goto out; | ||
| 1414 | } | ||
| 1415 | |||
| 1384 | ret = ocfs2_populate_write_desc(inode, wc, &clusters_to_alloc, | 1416 | ret = ocfs2_populate_write_desc(inode, wc, &clusters_to_alloc, |
| 1385 | &extents_to_split); | 1417 | &extents_to_split); |
| 1386 | if (ret) { | 1418 | if (ret) { |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index f3bc3658e7..781ba6c4ef 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -779,25 +779,6 @@ leave: | |||
| 779 | return status; | 779 | return status; |
| 780 | } | 780 | } |
| 781 | 781 | ||
| 782 | static int ocfs2_extend_allocation(struct inode *inode, u32 logical_start, | ||
| 783 | u32 clusters_to_add, int mark_unwritten) | ||
| 784 | { | ||
| 785 | int ret; | ||
| 786 | |||
| 787 | /* | ||
| 788 | * The alloc sem blocks peope in read/write from reading our | ||
| 789 | * allocation until we're done changing it. We depend on | ||
| 790 | * i_mutex to block other extend/truncate calls while we're | ||
| 791 | * here. | ||
| 792 | */ | ||
| 793 | down_write(&OCFS2_I(inode)->ip_alloc_sem); | ||
| 794 | ret = __ocfs2_extend_allocation(inode, logical_start, clusters_to_add, | ||
| 795 | mark_unwritten); | ||
| 796 | up_write(&OCFS2_I(inode)->ip_alloc_sem); | ||
| 797 | |||
| 798 | return ret; | ||
| 799 | } | ||
| 800 | |||
| 801 | /* Some parts of this taken from generic_cont_expand, which turned out | 782 | /* Some parts of this taken from generic_cont_expand, which turned out |
| 802 | * to be too fragile to do exactly what we need without us having to | 783 | * to be too fragile to do exactly what we need without us having to |
| 803 | * worry about recursive locking in ->prepare_write() and | 784 | * worry about recursive locking in ->prepare_write() and |
| @@ -889,25 +870,47 @@ out: | |||
| 889 | return ret; | 870 | return ret; |
| 890 | } | 871 | } |
| 891 | 872 | ||
| 892 | /* | 873 | int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size, u64 zero_to) |
| 893 | * A tail_to_skip value > 0 indicates that we're being called from | 874 | { |
| 894 | * ocfs2_file_aio_write(). This has the following implications: | 875 | int ret; |
| 895 | * | 876 | u32 clusters_to_add; |
| 896 | * - we don't want to update i_size | 877 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
| 897 | * - di_bh will be NULL, which is fine because it's only used in the | 878 | |
| 898 | * case where we want to update i_size. | 879 | clusters_to_add = ocfs2_clusters_for_bytes(inode->i_sb, new_i_size); |
| 899 | * - ocfs2_zero_extend() will then only be filling the hole created | 880 | if (clusters_to_add < oi->ip_clusters) |
| 900 | * between i_size and the start of the write. | 881 | clusters_to_add = 0; |
| 901 | */ | 882 | else |
| 883 | clusters_to_add -= oi->ip_clusters; | ||
| 884 | |||
| 885 | if (clusters_to_add) { | ||
| 886 | ret = __ocfs2_extend_allocation(inode, oi->ip_clusters, | ||
| 887 | clusters_to_add, 0); | ||
| 888 | if (ret) { | ||
| 889 | mlog_errno(ret); | ||
| 890 | goto out; | ||
| 891 | } | ||
| 892 | } | ||
| 893 | |||
| 894 | /* | ||
| 895 | * Call this even if we don't add any clusters to the tree. We | ||
| 896 | * still need to zero the area between the old i_size and the | ||
| 897 | * new i_size. | ||
| 898 | */ | ||
| 899 | ret = ocfs2_zero_extend(inode, zero_to); | ||
| 900 | if (ret < 0) | ||
| 901 | mlog_errno(ret); | ||
| 902 | |||
| 903 | out: | ||
| 904 | return ret; | ||
| 905 | } | ||
| 906 | |||
| 902 | static int ocfs2_extend_file(struct inode *inode, | 907 | static int ocfs2_extend_file(struct inode *inode, |
| 903 | struct buffer_head *di_bh, | 908 | struct buffer_head *di_bh, |
| 904 | u64 new_i_size, | 909 | u64 new_i_size) |
| 905 | size_t tail_to_skip) | ||
| 906 | { | 910 | { |
| 907 | int ret = 0; | 911 | int ret = 0; |
| 908 | u32 clusters_to_add = 0; | ||
| 909 | 912 | ||
| 910 | BUG_ON(!tail_to_skip && !di_bh); | 913 | BUG_ON(!di_bh); |
| 911 | 914 | ||
| 912 | /* setattr sometimes calls us like this. */ | 915 | /* setattr sometimes calls us like this. */ |
| 913 | if (new_i_size == 0) | 916 | if (new_i_size == 0) |
| @@ -917,13 +920,8 @@ static int ocfs2_extend_file(struct inode *inode, | |||
| 917 | goto out; | 920 | goto out; |
| 918 | BUG_ON(new_i_size < i_size_read(inode)); | 921 | BUG_ON(new_i_size < i_size_read(inode)); |
| 919 | 922 | ||
| 920 | if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) { | 923 | if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) |
| 921 | BUG_ON(tail_to_skip != 0); | ||
| 922 | goto out_update_size; | 924 | goto out_update_size; |
| 923 | } | ||
| 924 | |||
| 925 | clusters_to_add = ocfs2_clusters_for_bytes(inode->i_sb, new_i_size) - | ||
| 926 | OCFS2_I(inode)->ip_clusters; | ||
| 927 | 925 | ||
| 928 | /* | 926 | /* |
| 929 | * protect the pages that ocfs2_zero_extend is going to be | 927 | * protect the pages that ocfs2_zero_extend is going to be |
| @@ -938,35 +936,25 @@ static int ocfs2_extend_file(struct inode *inode, | |||
| 938 | goto out; | 936 | goto out; |
| 939 | } | 937 | } |
| 940 | 938 | ||
| 941 | if (clusters_to_add) { | ||
| 942 | ret = ocfs2_extend_allocation(inode, | ||
| 943 | OCFS2_I(inode)->ip_clusters, | ||
| 944 | clusters_to_add, 0); | ||
| 945 | if (ret < 0) { | ||
| 946 | mlog_errno(ret); | ||
| 947 | goto out_unlock; | ||
| 948 | } | ||
| 949 | } | ||
| 950 | |||
| 951 | /* | 939 | /* |
| 952 | * Call this even if we don't add any clusters to the tree. We | 940 | * The alloc sem blocks people in read/write from reading our |
| 953 | * still need to zero the area between the old i_size and the | 941 | * allocation until we're done changing it. We depend on |
| 954 | * new i_size. | 942 | * i_mutex to block other extend/truncate calls while we're |
| 943 | * here. | ||
| 955 | */ | 944 | */ |
| 956 | ret = ocfs2_zero_extend(inode, (u64)new_i_size - tail_to_skip); | 945 | down_write(&OCFS2_I(inode)->ip_alloc_sem); |
| 946 | ret = ocfs2_extend_no_holes(inode, new_i_size, new_i_size); | ||
| 947 | up_write(&OCFS2_I(inode)->ip_alloc_sem); | ||
| 948 | |||
| 957 | if (ret < 0) { | 949 | if (ret < 0) { |
| 958 | mlog_errno(ret); | 950 | mlog_errno(ret); |
| 959 | goto out_unlock; | 951 | goto out_unlock; |
| 960 | } | 952 | } |
| 961 | 953 | ||
| 962 | out_update_size: | 954 | out_update_size: |
| 963 | if (!tail_to_skip) { | 955 | ret = ocfs2_simple_size_update(inode, di_bh, new_i_size); |
| 964 | /* We're being called from ocfs2_setattr() which wants | 956 | if (ret < 0) |
| 965 | * us to update i_size */ | 957 | mlog_errno(ret); |
| 966 | ret = ocfs2_simple_size_update(inode, di_bh, new_i_size); | ||
| 967 | if (ret < 0) | ||
| 968 | mlog_errno(ret); | ||
| 969 | } | ||
| 970 | 958 | ||
| 971 | out_unlock: | 959 | out_unlock: |
| 972 | if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) | 960 | if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) |
| @@ -1035,7 +1023,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 1035 | if (i_size_read(inode) > attr->ia_size) | 1023 | if (i_size_read(inode) > attr->ia_size) |
| 1036 | status = ocfs2_truncate_file(inode, bh, attr->ia_size); | 1024 | status = ocfs2_truncate_file(inode, bh, attr->ia_size); |
| 1037 | else | 1025 | else |
| 1038 | status = ocfs2_extend_file(inode, bh, attr->ia_size, 0); | 1026 | status = ocfs2_extend_file(inode, bh, attr->ia_size); |
| 1039 | if (status < 0) { | 1027 | if (status < 0) { |
| 1040 | if (status != -ENOSPC) | 1028 | if (status != -ENOSPC) |
| 1041 | mlog_errno(status); | 1029 | mlog_errno(status); |
| @@ -1713,15 +1701,13 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry, | |||
| 1713 | int appending, | 1701 | int appending, |
| 1714 | int *direct_io) | 1702 | int *direct_io) |
| 1715 | { | 1703 | { |
| 1716 | int ret = 0, meta_level = appending; | 1704 | int ret = 0, meta_level = 0; |
| 1717 | struct inode *inode = dentry->d_inode; | 1705 | struct inode *inode = dentry->d_inode; |
| 1718 | u32 clusters; | 1706 | loff_t saved_pos, end; |
| 1719 | loff_t newsize, saved_pos; | ||
| 1720 | 1707 | ||
| 1721 | /* | 1708 | /* |
| 1722 | * We sample i_size under a read level meta lock to see if our write | 1709 | * We start with a read level meta lock and only jump to an ex |
| 1723 | * is extending the file, if it is we back off and get a write level | 1710 | * if we need to make modifications here. |
| 1724 | * meta lock. | ||
| 1725 | */ | 1711 | */ |
| 1726 | for(;;) { | 1712 | for(;;) { |
| 1727 | ret = ocfs2_meta_lock(inode, NULL, meta_level); | 1713 | ret = ocfs2_meta_lock(inode, NULL, meta_level); |
| @@ -1763,87 +1749,38 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry, | |||
| 1763 | saved_pos = *ppos; | 1749 | saved_pos = *ppos; |
| 1764 | } | 1750 | } |
| 1765 | 1751 | ||
| 1766 | if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) { | 1752 | end = saved_pos + count; |
| 1767 | loff_t end = saved_pos + count; | ||
| 1768 | |||
| 1769 | /* | ||
| 1770 | * Skip the O_DIRECT checks if we don't need | ||
| 1771 | * them. | ||
| 1772 | */ | ||
| 1773 | if (!direct_io || !(*direct_io)) | ||
| 1774 | break; | ||
| 1775 | |||
| 1776 | /* | ||
| 1777 | * Allowing concurrent direct writes means | ||
| 1778 | * i_size changes wouldn't be synchronized, so | ||
| 1779 | * one node could wind up truncating another | ||
| 1780 | * nodes writes. | ||
| 1781 | */ | ||
| 1782 | if (end > i_size_read(inode)) { | ||
| 1783 | *direct_io = 0; | ||
| 1784 | break; | ||
| 1785 | } | ||
| 1786 | 1753 | ||
| 1787 | /* | 1754 | /* |
| 1788 | * We don't fill holes during direct io, so | 1755 | * Skip the O_DIRECT checks if we don't need |
| 1789 | * check for them here. If any are found, the | 1756 | * them. |
| 1790 | * caller will have to retake some cluster | 1757 | */ |
| 1791 | * locks and initiate the io as buffered. | 1758 | if (!direct_io || !(*direct_io)) |
| 1792 | */ | ||
| 1793 | ret = ocfs2_check_range_for_holes(inode, saved_pos, | ||
| 1794 | count); | ||
| 1795 | if (ret == 1) { | ||
| 1796 | *direct_io = 0; | ||
| 1797 | ret = 0; | ||
| 1798 | } else if (ret < 0) | ||
| 1799 | mlog_errno(ret); | ||
| 1800 | break; | 1759 | break; |
| 1801 | } | ||
| 1802 | 1760 | ||
| 1803 | /* | 1761 | /* |
| 1804 | * The rest of this loop is concerned with legacy file | 1762 | * Allowing concurrent direct writes means |
| 1805 | * systems which don't support sparse files. | 1763 | * i_size changes wouldn't be synchronized, so |
| 1764 | * one node could wind up truncating another | ||
| 1765 | * nodes writes. | ||
| 1806 | */ | 1766 | */ |
| 1807 | 1767 | if (end > i_size_read(inode)) { | |
| 1808 | newsize = count + saved_pos; | 1768 | *direct_io = 0; |
| 1809 | |||
| 1810 | mlog(0, "pos=%lld newsize=%lld cursize=%lld\n", | ||
| 1811 | (long long) saved_pos, (long long) newsize, | ||
| 1812 | (long long) i_size_read(inode)); | ||
| 1813 | |||
| 1814 | /* No need for a higher level metadata lock if we're | ||
| 1815 | * never going past i_size. */ | ||
| 1816 | if (newsize <= i_size_read(inode)) | ||
| 1817 | break; | 1769 | break; |
| 1818 | |||
| 1819 | if (meta_level == 0) { | ||
| 1820 | ocfs2_meta_unlock(inode, meta_level); | ||
| 1821 | meta_level = 1; | ||
| 1822 | continue; | ||
| 1823 | } | 1770 | } |
| 1824 | 1771 | ||
| 1825 | spin_lock(&OCFS2_I(inode)->ip_lock); | 1772 | /* |
| 1826 | clusters = ocfs2_clusters_for_bytes(inode->i_sb, newsize) - | 1773 | * We don't fill holes during direct io, so |
| 1827 | OCFS2_I(inode)->ip_clusters; | 1774 | * check for them here. If any are found, the |
| 1828 | spin_unlock(&OCFS2_I(inode)->ip_lock); | 1775 | * caller will have to retake some cluster |
| 1829 | 1776 | * locks and initiate the io as buffered. | |
| 1830 | mlog(0, "Writing at EOF, may need more allocation: " | 1777 | */ |
| 1831 | "i_size = %lld, newsize = %lld, need %u clusters\n", | 1778 | ret = ocfs2_check_range_for_holes(inode, saved_pos, count); |
| 1832 | (long long) i_size_read(inode), (long long) newsize, | 1779 | if (ret == 1) { |
| 1833 | clusters); | 1780 | *direct_io = 0; |
| 1834 | 1781 | ret = 0; | |
| 1835 | /* We only want to continue the rest of this loop if | 1782 | } else if (ret < 0) |
| 1836 | * our extend will actually require more | 1783 | mlog_errno(ret); |
| 1837 | * allocation. */ | ||
| 1838 | if (!clusters) | ||
| 1839 | break; | ||
| 1840 | |||
| 1841 | ret = ocfs2_extend_file(inode, NULL, newsize, count); | ||
| 1842 | if (ret < 0) { | ||
| 1843 | if (ret != -ENOSPC) | ||
| 1844 | mlog_errno(ret); | ||
| 1845 | goto out_unlock; | ||
| 1846 | } | ||
| 1847 | break; | 1784 | break; |
| 1848 | } | 1785 | } |
| 1849 | 1786 | ||
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index 36fe27f268..066f14add3 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h | |||
| @@ -47,6 +47,8 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb, | |||
| 47 | struct ocfs2_alloc_context *data_ac, | 47 | struct ocfs2_alloc_context *data_ac, |
| 48 | struct ocfs2_alloc_context *meta_ac, | 48 | struct ocfs2_alloc_context *meta_ac, |
| 49 | enum ocfs2_alloc_restarted *reason_ret); | 49 | enum ocfs2_alloc_restarted *reason_ret); |
| 50 | int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size, | ||
| 51 | u64 zero_to); | ||
| 50 | int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di, | 52 | int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di, |
| 51 | u32 clusters_to_add, u32 extents_to_split, | 53 | u32 clusters_to_add, u32 extents_to_split, |
| 52 | struct ocfs2_alloc_context **data_ac, | 54 | struct ocfs2_alloc_context **data_ac, |
