ocfs2: free allocated clusters if error occurs after ocfs2_claim_clusters
PATCH 2/11 ocfs2: free allocated clusters if error occurs after ocfs2_claim_clusters
From: Zongxun Wang <[email protected]>
Subject: 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.
---
fs/ocfs2/alloc.c | 38 +++++++++++++++++++++++++++++++++++--- fs/ocfs2/localalloc.c | 40 ++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/localalloc.h | 6 ++++++ 3 files changed, 81 insertions(+), 3 deletions(-)
fs/ocfs2/alloc.c renamed from fs/ocfs2/alloc.c~ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters +35 -3
@@ -4742,6 +4742,7 @@ int ocfs2_add_clusters_in_btree(handle_t enum ocfs2_alloc_restarted *reason_ret) {int status =0 , err =0 ; +int need_free =0 ;int free_extents;enum ocfs2_alloc_restarted reason =RESTART_NONE ;u32 bit_off, num_bits;
@@ -4796,7 +4797,8 @@ int ocfs2_add_clusters_in_btree(handle_t OCFS2_JOURNAL_ACCESS_WRITE);if (status <0 ) {mlog_errno (status); - goto leave; + need_free =1 ; + goto bail; } block =ocfs2_clusters_to_blocks (osb->sb, bit_off);
@@ -4807,7 +4809,8 @@ int ocfs2_add_clusters_in_btree(handle_t num_bits, flags, meta_ac);if (status <0 ) {mlog_errno (status); - goto leave; + need_free =1 ; + goto bail; }ocfs2_journal_dirty (handle, et->et_root_bh);
@@ -4821,6 +4824,19 @@ int ocfs2_add_clusters_in_btree(handle_t reason =RESTART_TRANS ; } +bail: +if (need_free) { +if (data_ac->ac_which ==OCFS2_AC_USE_LOCAL ) +ocfs2_free_local_alloc_bits (osb, handle, data_ac, + bit_off, num_bits); +else +ocfs2_free_clusters (handle, + data_ac->ac_inode, + data_ac->ac_bh, +ocfs2_clusters_to_blocks (osb->sb, bit_off), + num_bits); + } + leave:if (reason_ret) *reason_ret = reason;
@@ -6805,6 +6821,8 @@ int ocfs2_convert_inline_data_to_extents struct buffer_head *di_bh) {int ret, i, has_data, num_pages =0 ; +int need_free =0 ; +u32 bit_off, num;handle_t *handle;u64 uninitialized_var (block );struct ocfs2_inode_info *oi =OCFS2_I (inode);
@@ -6850,7 +6868,6 @@ int ocfs2_convert_inline_data_to_extents }if (has_data) { -u32 bit_off, num;unsigned int page_end;u64 phys;
@@ -6886,6 +6903,7 @@ int ocfs2_convert_inline_data_to_extents ret =ocfs2_grab_eof_pages (inode,0 , end, pages, &num_pages);if (ret) {mlog_errno (ret); + need_free =1 ; goto out_commit; }
@@ -6896,6 +6914,7 @@ int ocfs2_convert_inline_data_to_extents ret =ocfs2_read_inline_data (inode, pages[0 ], di_bh);if (ret) {mlog_errno (ret); + need_free =1 ; goto out_commit; }
@@ -6927,6 +6946,7 @@ int ocfs2_convert_inline_data_to_extents ret =ocfs2_insert_extent (handle, &et,0 , block,1 ,0 ,NULL );if (ret) {mlog_errno (ret); + need_free =1 ; goto out_commit; }
@@ -6938,6 +6958,18 @@ out_commit:dquot_free_space_nodirty (inode,ocfs2_clusters_to_bytes (osb->sb,1 )); +if (need_free) { +if (data_ac->ac_which ==OCFS2_AC_USE_LOCAL ) +ocfs2_free_local_alloc_bits (osb, handle, data_ac, + bit_off, num); +else +ocfs2_free_clusters (handle, + data_ac->ac_inode, + data_ac->ac_bh, +ocfs2_clusters_to_blocks (osb->sb, bit_off), + num); + } +ocfs2_commit_trans (osb, handle); out_unlock:
fs/ocfs2/localalloc.c renamed from fs/ocfs2/localalloc.c~ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters +40 -0
@@ -781,6 +781,46 @@ bail:return status; } +int ocfs2_free_local_alloc_bits (struct ocfs2_super *osb, +handle_t *handle, +struct ocfs2_alloc_context *ac, +u32 bit_off, +u32 num_bits) +{ +int status, start; +struct inode *local_alloc_inode; +void *bitmap; +struct ocfs2_dinode *alloc; +struct ocfs2_local_alloc *la; + +BUG_ON (ac->ac_which !=OCFS2_AC_USE_LOCAL ); + + local_alloc_inode = ac->ac_inode; + alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; + la =OCFS2_LOCAL_ALLOC (alloc); + + bitmap = la->la_bitmap; + start = bit_off -le32_to_cpu (la->la_bm_off); + + status =ocfs2_journal_access_di (handle, +INODE_CACHE (local_alloc_inode), + osb->local_alloc_bh, +OCFS2_JOURNAL_ACCESS_WRITE ); +if (status <0 ) { +mlog_errno (status); + goto bail; + } + +while (num_bits--) +ocfs2_clear_bit (start++, bitmap); + +le32_add_cpu (&alloc->id1.bitmap1.i_used, -num_bits); +ocfs2_journal_dirty (handle, osb->local_alloc_bh); + +bail: +return status; +} +static u32 ocfs2_local_alloc_count_bits (struct ocfs2_dinode *alloc) {u32 count;
fs/ocfs2/localalloc.h renamed from fs/ocfs2/localalloc.h~ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters +6 -0
@@ -55,6 +55,12 @@ int ocfs2_claim_local_alloc_bits(struct u32 *bit_off, u32 *num_bits); +int ocfs2_free_local_alloc_bits (struct ocfs2_super *osb, +handle_t *handle, +struct ocfs2_alloc_context *ac, +u32 bit_off, +u32 num_bits); +void ocfs2_local_alloc_seen_free_bits (struct ocfs2_super *osb,unsigned int num_clusters);void ocfs2_la_enable_worker (struct work_struct *work);
_
PATCH 2/11 ocfs2: free allocated clusters if error occurs after ocfs2_claim_clusters
Hi
Quoted 10 lines · akpm at linux-foundation.org
From: Zongxun Wang <[email protected]>
Subject: ocfs2: free allocated clusters if error occurs afterocfs2_claim_clustersEven 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_clusterssuccessfully when expanding a file, but failed inocfs2_insert_extent. So we need free the allocated clusters if they are not used indeed.
We should note down num of bits to be freed, so as to update i_used correspondingly after clearing those bits in bitmap.
I sent a patch based on this:
[PATCH] ocfs2: correctly update i_used in ocfs2_free_local_alloc_bits
https://oss.oracle.com/pipermail/ocfs2-devel/2013-November/009462.html
Quoted 194 lines
Signed-off-by Zongxun Wang <[email protected]>Signed-off-by Joseph Qi <[email protected]>Cc Joel Becker <[email protected]>Cc Mark Fasheh <[email protected]>Cc Li Zefan <[email protected]>Signed-off-by Andrew Morton <[email protected]>---
fs/ocfs2/alloc.c | 38 +++++++++++++++++++++++++++++++++++--- fs/ocfs2/localalloc.c | 40 ++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/localalloc.h | 6 ++++++ 3 files changed, 81 insertions(+), 3 deletions(-)diff -puN
fs/ocfs2/alloc.c~ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clustersfs/ocfs2/alloc.cfs/ocfs2/alloc.c renamed from fs/ocfs2/alloc.c~ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters +35
-3@@ -4742,6 +4742,7 @@ int ocfs2_add_clusters_in_btree(handle_t enum ocfs2_alloc_restarted *reason_ret) {int status =0 , err =0 ; +int need_free =0 ;int free_extents;enum ocfs2_alloc_restarted reason =RESTART_NONE ;u32 bit_off, num_bits;@@ -4796,7 +4797,8 @@ int ocfs2_add_clusters_in_btree(handle_t OCFS2_JOURNAL_ACCESS_WRITE);if (status <0 ) {mlog_errno (status); - goto leave; + need_free =1 ; + goto bail; } block =ocfs2_clusters_to_blocks (osb->sb, bit_off);@@ -4807,7 +4809,8 @@ int ocfs2_add_clusters_in_btree(handle_t num_bits, flags, meta_ac);if (status <0 ) {mlog_errno (status); - goto leave; + need_free =1 ; + goto bail; }ocfs2_journal_dirty (handle, et->et_root_bh);@@ -4821,6 +4824,19 @@ int ocfs2_add_clusters_in_btree(handle_t reason =RESTART_TRANS ; } +bail: +if (need_free) { +if (data_ac->ac_which ==OCFS2_AC_USE_LOCAL ) +ocfs2_free_local_alloc_bits (osb, handle, data_ac, + bit_off, num_bits); +else +ocfs2_free_clusters (handle, + data_ac->ac_inode, + data_ac->ac_bh, +ocfs2_clusters_to_blocks (osb->sb, bit_off), + num_bits); + } + leave:if (reason_ret) *reason_ret = reason;@@ -6805,6 +6821,8 @@ int ocfs2_convert_inline_data_to_extents struct buffer_head *di_bh) {int ret, i, has_data, num_pages =0 ; +int need_free =0 ; +u32 bit_off, num;handle_t *handle;u64 uninitialized_var (block );struct ocfs2_inode_info *oi =OCFS2_I (inode);@@ -6850,7 +6868,6 @@ int ocfs2_convert_inline_data_to_extents }if (has_data) { -u32 bit_off, num;unsigned int page_end;u64 phys;@@ -6886,6 +6903,7 @@ int ocfs2_convert_inline_data_to_extents ret =ocfs2_grab_eof_pages (inode,0 , end, pages, &num_pages);if (ret) {mlog_errno (ret); + need_free =1 ; goto out_commit; }@@ -6896,6 +6914,7 @@ int ocfs2_convert_inline_data_to_extents ret =ocfs2_read_inline_data (inode, pages[0 ], di_bh);if (ret) {mlog_errno (ret); + need_free =1 ; goto out_commit; }@@ -6927,6 +6946,7 @@ int ocfs2_convert_inline_data_to_extents ret =ocfs2_insert_extent (handle, &et,0 , block,1 ,0 ,NULL );if (ret) {mlog_errno (ret); + need_free =1 ; goto out_commit; }@@ -6938,6 +6958,18 @@ out_commit:dquot_free_space_nodirty (inode,ocfs2_clusters_to_bytes (osb->sb,1 )); +if (need_free) { +if (data_ac->ac_which ==OCFS2_AC_USE_LOCAL ) +ocfs2_free_local_alloc_bits (osb, handle, data_ac, + bit_off, num); +else +ocfs2_free_clusters (handle, + data_ac->ac_inode, + data_ac->ac_bh, +ocfs2_clusters_to_blocks (osb->sb, bit_off), + num); + } +ocfs2_commit_trans (osb, handle); out_unlock:diff -puN
fs/ocfs2/localalloc.c~ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clustersfs/ocfs2/localalloc.cfs/ocfs2/localalloc.c renamed from fs/ocfs2/localalloc.c~ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters +40
-0@@ -781,6 +781,46 @@ bail:return status; } +int ocfs2_free_local_alloc_bits (struct ocfs2_super *osb, +handle_t *handle, +struct ocfs2_alloc_context *ac, +u32 bit_off, +u32 num_bits) +{ +int status, start; +struct inode *local_alloc_inode; +void *bitmap; +struct ocfs2_dinode *alloc; +struct ocfs2_local_alloc *la; + +BUG_ON (ac->ac_which !=OCFS2_AC_USE_LOCAL ); + + local_alloc_inode = ac->ac_inode; + alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; + la =OCFS2_LOCAL_ALLOC (alloc); + + bitmap = la->la_bitmap; + start = bit_off -le32_to_cpu (la->la_bm_off); + + status =ocfs2_journal_access_di (handle, +INODE_CACHE (local_alloc_inode), + osb->local_alloc_bh, +OCFS2_JOURNAL_ACCESS_WRITE ); +if (status <0 ) { +mlog_errno (status); + goto bail; + } + +while (num_bits--) +ocfs2_clear_bit (start++, bitmap); + +le32_add_cpu (&alloc->id1.bitmap1.i_used, -num_bits); +ocfs2_journal_dirty (handle, osb->local_alloc_bh); + +bail: +return status; +} +static u32 ocfs2_local_alloc_count_bits (struct ocfs2_dinode *alloc) {u32 count;diff -puN
fs/ocfs2/localalloc.h~ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clustersfs/ocfs2/localalloc.hfs/ocfs2/localalloc.h renamed from fs/ocfs2/localalloc.h~ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters +6
-0@@ -55,6 +55,12 @@ int ocfs2_claim_local_alloc_bits(struct u32 *bit_off, u32 *num_bits); +int ocfs2_free_local_alloc_bits (struct ocfs2_super *osb, +handle_t *handle, +struct ocfs2_alloc_context *ac, +u32 bit_off, +u32 num_bits); +void ocfs2_local_alloc_seen_free_bits (struct ocfs2_super *osb,unsigned int num_clusters);void ocfs2_la_enable_worker (struct work_struct *work);_
.
PATCH 2/11 ocfs2: free allocated clusters if error occurs after ocfs2_claim_clusters
Quoted 14 lines · On Sun, 26 Jan 2014 10:53:24 +0800 Joseph Qi <[email protected]> wrote:
Hi
Quoted 10 lines · akpm at linux-foundation.org
From: Zongxun Wang <[email protected]>
Subject: ocfs2: free allocated clusters if error occurs afterocfs2_claim_clustersEven 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_clusterssuccessfully when expanding a file, but failed inocfs2_insert_extent. So we need free the allocated clusters if they are not used indeed.
Quoted 5 lines
We should note down num of bits to be freed, so as to update
i_usedcorrespondingly after clearing those bits in bitmap.
I sent a patch based on this:
[PATCH] ocfs2: correctly updatei_usedinocfs2_free_local_alloc_bits
https://oss.oracle.com/pipermail/ocfs2-devel/2013-November/009462.html
OK thanks, I now have that, as ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters-fix.patch
Do we think that ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters.patch and ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters-fix.patch should now be merged upstream?
PATCH 2/11 ocfs2: free allocated clusters if error occurs after ocfs2_claim_clusters
Quoted 25 lines · Andrew Morton
Quoted 14 lines · On Sun, 26 Jan 2014 10:53:24 +0800 Joseph Qi <[email protected]> wrote:
Hi
Quoted 10 lines · akpm at linux-foundation.org
From: Zongxun Wang <[email protected]>
Subject: ocfs2: free allocated clusters if error occurs afterocfs2_claim_clustersEven 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_clusterssuccessfully when expanding a file, but failed inocfs2_insert_extent. So we need free the allocated clusters if they are not used indeed.Quoted 5 lines
We should note down num of bits to be freed, so as to update
i_usedcorrespondingly after clearing those bits in bitmap.
I sent a patch based on this:
[PATCH] ocfs2: correctly updatei_usedinocfs2_free_local_alloc_bits
https://oss.oracle.com/pipermail/ocfs2-devel/2013-November/009462.htmlOK thanks, I now have that, as ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters-fix.patch
Quoted 9 lines
Do we think that ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters.patch and ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters-fix.patch should now be merged upstream?
.
Could Mark & Joel review the two patches? Thanks.
Joel Becker
maintainerPATCH 2/11 ocfs2: free allocated clusters if error occurs after ocfs2_claim_clusters
Quoted 23 lines · Joseph Qi
Quoted 22 lines · Andrew Morton
Quoted 19 lines · On Sun, 26 Jan 2014 10:53:24 +0800 Joseph Qi <[email protected]> wrote:
Hi
Quoted 10 lines · akpm at linux-foundation.org
From: Zongxun Wang <[email protected]>
Subject: ocfs2: free allocated clusters if error occurs afterocfs2_claim_clustersEven 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_clusterssuccessfully when expanding a file, but failed inocfs2_insert_extent. So we need free the allocated clusters if they are not used indeed.We should note down num of bits to be freed, so as to update
i_usedcorrespondingly after clearing those bits in bitmap.
I sent a patch based on this:
[PATCH] ocfs2: correctly updatei_usedinocfs2_free_local_alloc_bits
https://oss.oracle.com/pipermail/ocfs2-devel/2013-November/009462.html
Quoted 8 lines
Quoted 8 lines
OK thanks, I now have that, as ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters-fix.patch
Do we think that ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters.patch and ocfs2-free-allocated-clusters-if-error-occurs-after-ocfs2_claim_clusters-fix.patch should now be merged upstream?
These patches combined look sane. I'm curious what failed to cause this to be noticed, but still:
Quoted 6 lines
Quoted 4 lines
.
Could Mark & Joel review the two patches? Thanks.
Signature · 6 lines
Life's Little Instruction Book #139 "Never deprive someone of hope; it might be all they have." http://www.jlbec.org/ jlbec at evilplan.org