diff options
author | Zongxun Wang <wangzongxun@huawei.com> | 2014-02-06 15:04:20 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-06 16:48:51 -0500 |
commit | fb951eb5e167de9f07973ce0dfff674a2019bfab (patch) | |
tree | 4af8a9764fa9050b2aa70cf6683cdff8becb342d /fs/ocfs2/alloc.c | |
parent | 277cba1d28b99169f2a056d0d6f98a4039531cb8 (diff) |
ocfs2: free allocated clusters if error occurs after ocfs2_claim_clusters
Even if using the same jbd2 handle, we cannot rollback a transaction.
So once some error occurs after successfully allocating clusters, the
allocated clusters will never be used and it means they are lost. For
example, call ocfs2_claim_clusters successfully when expanding a file,
but failed in ocfs2_insert_extent. So we need free the allocated
clusters if they are not used indeed.
Signed-off-by: Zongxun Wang <wangzongxun@huawei.com>
Signed-off-by: Joseph Qi <joseph.qi@huawei.com>
Acked-by: Joel Becker <jlbec@evilplan.org>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Li Zefan <lizefan@huawei.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ocfs2/alloc.c')
-rw-r--r-- | fs/ocfs2/alloc.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 8750ae1b8636..aada5801567a 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -4742,6 +4742,7 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, | |||
4742 | enum ocfs2_alloc_restarted *reason_ret) | 4742 | enum ocfs2_alloc_restarted *reason_ret) |
4743 | { | 4743 | { |
4744 | int status = 0, err = 0; | 4744 | int status = 0, err = 0; |
4745 | int need_free = 0; | ||
4745 | int free_extents; | 4746 | int free_extents; |
4746 | enum ocfs2_alloc_restarted reason = RESTART_NONE; | 4747 | enum ocfs2_alloc_restarted reason = RESTART_NONE; |
4747 | u32 bit_off, num_bits; | 4748 | u32 bit_off, num_bits; |
@@ -4796,7 +4797,8 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, | |||
4796 | OCFS2_JOURNAL_ACCESS_WRITE); | 4797 | OCFS2_JOURNAL_ACCESS_WRITE); |
4797 | if (status < 0) { | 4798 | if (status < 0) { |
4798 | mlog_errno(status); | 4799 | mlog_errno(status); |
4799 | goto leave; | 4800 | need_free = 1; |
4801 | goto bail; | ||
4800 | } | 4802 | } |
4801 | 4803 | ||
4802 | block = ocfs2_clusters_to_blocks(osb->sb, bit_off); | 4804 | block = ocfs2_clusters_to_blocks(osb->sb, bit_off); |
@@ -4807,7 +4809,8 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, | |||
4807 | num_bits, flags, meta_ac); | 4809 | num_bits, flags, meta_ac); |
4808 | if (status < 0) { | 4810 | if (status < 0) { |
4809 | mlog_errno(status); | 4811 | mlog_errno(status); |
4810 | goto leave; | 4812 | need_free = 1; |
4813 | goto bail; | ||
4811 | } | 4814 | } |
4812 | 4815 | ||
4813 | ocfs2_journal_dirty(handle, et->et_root_bh); | 4816 | ocfs2_journal_dirty(handle, et->et_root_bh); |
@@ -4821,6 +4824,19 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, | |||
4821 | reason = RESTART_TRANS; | 4824 | reason = RESTART_TRANS; |
4822 | } | 4825 | } |
4823 | 4826 | ||
4827 | bail: | ||
4828 | if (need_free) { | ||
4829 | if (data_ac->ac_which == OCFS2_AC_USE_LOCAL) | ||
4830 | ocfs2_free_local_alloc_bits(osb, handle, data_ac, | ||
4831 | bit_off, num_bits); | ||
4832 | else | ||
4833 | ocfs2_free_clusters(handle, | ||
4834 | data_ac->ac_inode, | ||
4835 | data_ac->ac_bh, | ||
4836 | ocfs2_clusters_to_blocks(osb->sb, bit_off), | ||
4837 | num_bits); | ||
4838 | } | ||
4839 | |||
4824 | leave: | 4840 | leave: |
4825 | if (reason_ret) | 4841 | if (reason_ret) |
4826 | *reason_ret = reason; | 4842 | *reason_ret = reason; |
@@ -6805,6 +6821,8 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
6805 | struct buffer_head *di_bh) | 6821 | struct buffer_head *di_bh) |
6806 | { | 6822 | { |
6807 | int ret, i, has_data, num_pages = 0; | 6823 | int ret, i, has_data, num_pages = 0; |
6824 | int need_free = 0; | ||
6825 | u32 bit_off, num; | ||
6808 | handle_t *handle; | 6826 | handle_t *handle; |
6809 | u64 uninitialized_var(block); | 6827 | u64 uninitialized_var(block); |
6810 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 6828 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
@@ -6850,7 +6868,6 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
6850 | } | 6868 | } |
6851 | 6869 | ||
6852 | if (has_data) { | 6870 | if (has_data) { |
6853 | u32 bit_off, num; | ||
6854 | unsigned int page_end; | 6871 | unsigned int page_end; |
6855 | u64 phys; | 6872 | u64 phys; |
6856 | 6873 | ||
@@ -6886,6 +6903,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
6886 | ret = ocfs2_grab_eof_pages(inode, 0, end, pages, &num_pages); | 6903 | ret = ocfs2_grab_eof_pages(inode, 0, end, pages, &num_pages); |
6887 | if (ret) { | 6904 | if (ret) { |
6888 | mlog_errno(ret); | 6905 | mlog_errno(ret); |
6906 | need_free = 1; | ||
6889 | goto out_commit; | 6907 | goto out_commit; |
6890 | } | 6908 | } |
6891 | 6909 | ||
@@ -6896,6 +6914,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
6896 | ret = ocfs2_read_inline_data(inode, pages[0], di_bh); | 6914 | ret = ocfs2_read_inline_data(inode, pages[0], di_bh); |
6897 | if (ret) { | 6915 | if (ret) { |
6898 | mlog_errno(ret); | 6916 | mlog_errno(ret); |
6917 | need_free = 1; | ||
6899 | goto out_commit; | 6918 | goto out_commit; |
6900 | } | 6919 | } |
6901 | 6920 | ||
@@ -6927,6 +6946,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
6927 | ret = ocfs2_insert_extent(handle, &et, 0, block, 1, 0, NULL); | 6946 | ret = ocfs2_insert_extent(handle, &et, 0, block, 1, 0, NULL); |
6928 | if (ret) { | 6947 | if (ret) { |
6929 | mlog_errno(ret); | 6948 | mlog_errno(ret); |
6949 | need_free = 1; | ||
6930 | goto out_commit; | 6950 | goto out_commit; |
6931 | } | 6951 | } |
6932 | 6952 | ||
@@ -6938,6 +6958,18 @@ out_commit: | |||
6938 | dquot_free_space_nodirty(inode, | 6958 | dquot_free_space_nodirty(inode, |
6939 | ocfs2_clusters_to_bytes(osb->sb, 1)); | 6959 | ocfs2_clusters_to_bytes(osb->sb, 1)); |
6940 | 6960 | ||
6961 | if (need_free) { | ||
6962 | if (data_ac->ac_which == OCFS2_AC_USE_LOCAL) | ||
6963 | ocfs2_free_local_alloc_bits(osb, handle, data_ac, | ||
6964 | bit_off, num); | ||
6965 | else | ||
6966 | ocfs2_free_clusters(handle, | ||
6967 | data_ac->ac_inode, | ||
6968 | data_ac->ac_bh, | ||
6969 | ocfs2_clusters_to_blocks(osb->sb, bit_off), | ||
6970 | num); | ||
6971 | } | ||
6972 | |||
6941 | ocfs2_commit_trans(osb, handle); | 6973 | ocfs2_commit_trans(osb, handle); |
6942 | 6974 | ||
6943 | out_unlock: | 6975 | out_unlock: |