Commit db66c715 authored by Younger Liu's avatar Younger Liu Committed by Linus Torvalds

ocfs2: rollback alloc_dinode counts when ocfs2_block_group_set_bits() failed

After updating alloc_dinode counts in ocfs2_alloc_dinode_update_counts(),
if ocfs2_alloc_dinode_update_bitmap() failed, there is a rare case that
some space may be lost.

So, roll back alloc_dinode counts when ocfs2_block_group_set_bits()
failed.

[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: default avatarYounger Liu <younger.liucn@gmail.com>
Reviewed-by: default avatarMark Fasheh <mfasheh@suse.de>
Cc: Joel Becker <jlbec@evilplan.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent e228f643
...@@ -691,8 +691,11 @@ static int ocfs2_move_extent(struct ocfs2_move_extents_context *context, ...@@ -691,8 +691,11 @@ static int ocfs2_move_extent(struct ocfs2_move_extents_context *context,
ret = ocfs2_block_group_set_bits(handle, gb_inode, gd, gd_bh, ret = ocfs2_block_group_set_bits(handle, gb_inode, gd, gd_bh,
goal_bit, len); goal_bit, len);
if (ret) if (ret) {
ocfs2_rollback_alloc_dinode_counts(gb_inode, gb_bh, len,
le16_to_cpu(gd->bg_chain));
mlog_errno(ret); mlog_errno(ret);
}
/* /*
* Here we should write the new page out first if we are * Here we should write the new page out first if we are
......
...@@ -1608,6 +1608,21 @@ int ocfs2_alloc_dinode_update_counts(struct inode *inode, ...@@ -1608,6 +1608,21 @@ int ocfs2_alloc_dinode_update_counts(struct inode *inode,
return ret; return ret;
} }
void ocfs2_rollback_alloc_dinode_counts(struct inode *inode,
struct buffer_head *di_bh,
u32 num_bits,
u16 chain)
{
u32 tmp_used;
struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
struct ocfs2_chain_list *cl;
cl = (struct ocfs2_chain_list *)&di->id2.i_chain;
tmp_used = le32_to_cpu(di->id1.bitmap1.i_used);
di->id1.bitmap1.i_used = cpu_to_le32(tmp_used - num_bits);
le32_add_cpu(&cl->cl_recs[chain].c_free, num_bits);
}
static int ocfs2_bg_discontig_fix_by_rec(struct ocfs2_suballoc_result *res, static int ocfs2_bg_discontig_fix_by_rec(struct ocfs2_suballoc_result *res,
struct ocfs2_extent_rec *rec, struct ocfs2_extent_rec *rec,
struct ocfs2_chain_list *cl) struct ocfs2_chain_list *cl)
...@@ -1708,8 +1723,12 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, ...@@ -1708,8 +1723,12 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
ret = ocfs2_block_group_set_bits(handle, alloc_inode, gd, group_bh, ret = ocfs2_block_group_set_bits(handle, alloc_inode, gd, group_bh,
res->sr_bit_offset, res->sr_bits); res->sr_bit_offset, res->sr_bits);
if (ret < 0) if (ret < 0) {
ocfs2_rollback_alloc_dinode_counts(alloc_inode, ac->ac_bh,
res->sr_bits,
le16_to_cpu(gd->bg_chain));
mlog_errno(ret); mlog_errno(ret);
}
out_loc_only: out_loc_only:
*bits_left = le16_to_cpu(gd->bg_free_bits_count); *bits_left = le16_to_cpu(gd->bg_free_bits_count);
...@@ -1839,6 +1858,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, ...@@ -1839,6 +1858,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
res->sr_bit_offset, res->sr_bit_offset,
res->sr_bits); res->sr_bits);
if (status < 0) { if (status < 0) {
ocfs2_rollback_alloc_dinode_counts(alloc_inode,
ac->ac_bh, res->sr_bits, chain);
mlog_errno(status); mlog_errno(status);
goto bail; goto bail;
} }
...@@ -2150,6 +2171,8 @@ int ocfs2_claim_new_inode_at_loc(handle_t *handle, ...@@ -2150,6 +2171,8 @@ int ocfs2_claim_new_inode_at_loc(handle_t *handle,
res->sr_bit_offset, res->sr_bit_offset,
res->sr_bits); res->sr_bits);
if (ret < 0) { if (ret < 0) {
ocfs2_rollback_alloc_dinode_counts(ac->ac_inode,
ac->ac_bh, res->sr_bits, chain);
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
} }
......
...@@ -91,6 +91,10 @@ int ocfs2_alloc_dinode_update_counts(struct inode *inode, ...@@ -91,6 +91,10 @@ int ocfs2_alloc_dinode_update_counts(struct inode *inode,
struct buffer_head *di_bh, struct buffer_head *di_bh,
u32 num_bits, u32 num_bits,
u16 chain); u16 chain);
void ocfs2_rollback_alloc_dinode_counts(struct inode *inode,
struct buffer_head *di_bh,
u32 num_bits,
u16 chain);
int ocfs2_block_group_set_bits(handle_t *handle, int ocfs2_block_group_set_bits(handle_t *handle,
struct inode *alloc_inode, struct inode *alloc_inode,
struct ocfs2_group_desc *bg, struct ocfs2_group_desc *bg,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment