| From 5c9ee4cbf2a945271f25b89b137f2c03bbc3be33 Mon Sep 17 00:00:00 2001 |
| From: Joseph Qi <joseph.qi@huawei.com> |
| Date: Tue, 29 Dec 2015 14:54:06 -0800 |
| Subject: ocfs2: fix BUG when calculate new backup super |
| |
| commit 5c9ee4cbf2a945271f25b89b137f2c03bbc3be33 upstream. |
| |
| When resizing, it firstly extends the last gd. Once it should backup |
| super in the gd, it calculates new backup super and update the |
| corresponding value. |
| |
| But it currently doesn't consider the situation that the backup super is |
| already done. And in this case, it still sets the bit in gd bitmap and |
| then decrease from bg_free_bits_count, which leads to a corrupted gd and |
| trigger the BUG in ocfs2_block_group_set_bits: |
| |
| BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits); |
| |
| So check whether the backup super is done and then do the updates. |
| |
| Signed-off-by: Joseph Qi <joseph.qi@huawei.com> |
| Reviewed-by: Jiufei Xue <xuejiufei@huawei.com> |
| Reviewed-by: Yiwen Jiang <jiangyiwen@huawei.com> |
| Cc: Mark Fasheh <mfasheh@suse.de> |
| Cc: Joel Becker <jlbec@evilplan.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| [lizf: Backported to 3.4: adjust context] |
| Signed-off-by: Zefan Li <lizefan@huawei.com> |
| --- |
| fs/ocfs2/resize.c | 15 ++++++++++++--- |
| 1 file changed, 12 insertions(+), 3 deletions(-) |
| |
| --- a/fs/ocfs2/resize.c |
| +++ b/fs/ocfs2/resize.c |
| @@ -56,11 +56,12 @@ static u16 ocfs2_calc_new_backup_super(s |
| int new_clusters, |
| u32 first_new_cluster, |
| u16 cl_cpg, |
| + u16 old_bg_clusters, |
| int set) |
| { |
| int i; |
| u16 backups = 0; |
| - u32 cluster; |
| + u32 cluster, lgd_cluster; |
| u64 blkno, gd_blkno, lgd_blkno = le64_to_cpu(gd->bg_blkno); |
| |
| for (i = 0; i < OCFS2_MAX_BACKUP_SUPERBLOCKS; i++) { |
| @@ -73,6 +74,12 @@ static u16 ocfs2_calc_new_backup_super(s |
| else if (gd_blkno > lgd_blkno) |
| break; |
| |
| + /* check if already done backup super */ |
| + lgd_cluster = ocfs2_blocks_to_clusters(inode->i_sb, lgd_blkno); |
| + lgd_cluster += old_bg_clusters; |
| + if (lgd_cluster >= cluster) |
| + continue; |
| + |
| if (set) |
| ocfs2_set_bit(cluster % cl_cpg, |
| (unsigned long *)gd->bg_bitmap); |
| @@ -101,6 +108,7 @@ static int ocfs2_update_last_group_and_i |
| u16 chain, num_bits, backups = 0; |
| u16 cl_bpc = le16_to_cpu(cl->cl_bpc); |
| u16 cl_cpg = le16_to_cpu(cl->cl_cpg); |
| + u16 old_bg_clusters; |
| |
| trace_ocfs2_update_last_group_and_inode(new_clusters, |
| first_new_cluster); |
| @@ -114,6 +122,7 @@ static int ocfs2_update_last_group_and_i |
| |
| group = (struct ocfs2_group_desc *)group_bh->b_data; |
| |
| + old_bg_clusters = le16_to_cpu(group->bg_bits) / cl_bpc; |
| /* update the group first. */ |
| num_bits = new_clusters * cl_bpc; |
| le16_add_cpu(&group->bg_bits, num_bits); |
| @@ -129,7 +138,7 @@ static int ocfs2_update_last_group_and_i |
| group, |
| new_clusters, |
| first_new_cluster, |
| - cl_cpg, 1); |
| + cl_cpg, old_bg_clusters, 1); |
| le16_add_cpu(&group->bg_free_bits_count, -1 * backups); |
| } |
| |
| @@ -169,7 +178,7 @@ out_rollback: |
| group, |
| new_clusters, |
| first_new_cluster, |
| - cl_cpg, 0); |
| + cl_cpg, old_bg_clusters, 0); |
| le16_add_cpu(&group->bg_free_bits_count, backups); |
| le16_add_cpu(&group->bg_bits, -1 * num_bits); |
| le16_add_cpu(&group->bg_free_bits_count, -1 * num_bits); |