From patchwork Tue Mar 11 06:57:22 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Darrick Wong X-Patchwork-Id: 328966 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 9CBD52C00AB for ; Tue, 11 Mar 2014 17:57:28 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754662AbaCKG51 (ORCPT ); Tue, 11 Mar 2014 02:57:27 -0400 Received: from aserp1040.oracle.com ([141.146.126.69]:22079 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753254AbaCKG50 (ORCPT ); Tue, 11 Mar 2014 02:57:26 -0400 Received: from ucsinet22.oracle.com (ucsinet22.oracle.com [156.151.31.94]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id s2B6vOmg003811 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 11 Mar 2014 06:57:25 GMT Received: from aserz7021.oracle.com (aserz7021.oracle.com [141.146.126.230]) by ucsinet22.oracle.com (8.14.5+Sun/8.14.5) with ESMTP id s2B6vN71017840 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 11 Mar 2014 06:57:24 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by aserz7021.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id s2B6vNeb003863; Tue, 11 Mar 2014 06:57:23 GMT Received: from localhost (/67.160.151.179) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 10 Mar 2014 23:57:23 -0700 Subject: [PATCH 32/49] resize2fs: when toggling 64bit, don't free in-use bg data clusters To: tytso@mit.edu, darrick.wong@oracle.com From: "Darrick J. Wong" Cc: linux-ext4@vger.kernel.org Date: Mon, 10 Mar 2014 23:57:22 -0700 Message-ID: <20140311065722.30585.96456.stgit@birch.djwong.org> In-Reply-To: <20140311065356.30585.47192.stgit@birch.djwong.org> References: <20140311065356.30585.47192.stgit@birch.djwong.org> User-Agent: StGit/0.15 MIME-Version: 1.0 X-Source-IP: ucsinet22.oracle.com [156.151.31.94] Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org Currently, move_bg_metadata() assumes that if a block containing a superblock or a group descriptor is no longer needed, then it is safe to free the whole cluster. This of course isn't true, for bitmaps and inode tables can share these clusters. Therefore, check a little more carefully before freeing clusters. Signed-off-by: Darrick J. Wong --- resize/resize2fs.c | 71 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 16 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/resize/resize2fs.c b/resize/resize2fs.c index cf5bef2..d40b058 100644 --- a/resize/resize2fs.c +++ b/resize/resize2fs.c @@ -317,11 +317,11 @@ static errcode_t resize_group_descriptors(ext2_resize_t rfs, blk64_t new_size) static errcode_t move_bg_metadata(ext2_resize_t rfs) { dgrp_t i; - blk64_t b, c, d; + blk64_t b, c, d, old_desc_blocks, new_desc_blocks, j; ext2fs_block_bitmap old_map, new_map; int old, new; errcode_t retval; - int zero = 0, one = 1; + int zero = 0, one = 1, cluster_ratio; if (!(rfs->flags & (RESIZE_DISABLE_64BIT | RESIZE_ENABLE_64BIT))) return 0; @@ -334,6 +334,17 @@ static errcode_t move_bg_metadata(ext2_resize_t rfs) if (retval) goto out; + if (EXT2_HAS_INCOMPAT_FEATURE(rfs->old_fs->super, + EXT2_FEATURE_INCOMPAT_META_BG)) { + old_desc_blocks = rfs->old_fs->super->s_first_meta_bg; + new_desc_blocks = rfs->new_fs->super->s_first_meta_bg; + } else { + old_desc_blocks = rfs->old_fs->desc_blocks + + rfs->old_fs->super->s_reserved_gdt_blocks; + new_desc_blocks = rfs->new_fs->desc_blocks + + rfs->new_fs->super->s_reserved_gdt_blocks; + } + /* Construct bitmaps of super/descriptor blocks in old and new fs */ for (i = 0; i < rfs->old_fs->group_desc_count; i++) { retval = ext2fs_super_and_bgd_loc2(rfs->old_fs, i, &b, &c, &d, @@ -341,7 +352,8 @@ static errcode_t move_bg_metadata(ext2_resize_t rfs) if (retval) goto out; ext2fs_mark_block_bitmap2(old_map, b); - ext2fs_mark_block_bitmap2(old_map, c); + for (j = 0; c != 0 && j < old_desc_blocks; j++) + ext2fs_mark_block_bitmap2(old_map, c + j); ext2fs_mark_block_bitmap2(old_map, d); retval = ext2fs_super_and_bgd_loc2(rfs->new_fs, i, &b, &c, &d, @@ -349,45 +361,72 @@ static errcode_t move_bg_metadata(ext2_resize_t rfs) if (retval) goto out; ext2fs_mark_block_bitmap2(new_map, b); - ext2fs_mark_block_bitmap2(new_map, c); + for (j = 0; c != 0 && j < new_desc_blocks; j++) + ext2fs_mark_block_bitmap2(new_map, c + j); ext2fs_mark_block_bitmap2(new_map, d); } + cluster_ratio = EXT2FS_CLUSTER_RATIO(rfs->new_fs); + /* Find changes in block allocations for bg metadata */ for (b = 0; b < ext2fs_blocks_count(rfs->new_fs->super); - b += EXT2FS_CLUSTER_RATIO(rfs->new_fs)) { + b += cluster_ratio) { old = ext2fs_test_block_bitmap2(old_map, b); new = ext2fs_test_block_bitmap2(new_map, b); - if (old && !new) - ext2fs_unmark_block_bitmap2(rfs->new_fs->block_map, b); - else if (!old && new) - ; /* empty ext2fs_mark_block_bitmap2(new_map, b); */ - else + if (old && !new) { + /* mark old_map, unmark new_map */ + if (cluster_ratio == 1) + ext2fs_unmark_block_bitmap2( + rfs->new_fs->block_map, b); + } else if (!old && new) + ; /* unmark old_map, mark new_map */ + else { + ext2fs_unmark_block_bitmap2(old_map, b); ext2fs_unmark_block_bitmap2(new_map, b); + } } - /* new_map now shows blocks that have been newly allocated. */ - /* Move any conflicting bitmaps and inode tables */ + /* + * new_map now shows blocks that have been newly allocated. + * old_map now shows blocks that have been newly freed. + */ + + /* + * Move any conflicting bitmaps and inode tables. Ensure that we + * don't try to free clusters associated with bitmaps or tables. + */ for (i = 0; i < rfs->old_fs->group_desc_count; i++) { b = ext2fs_block_bitmap_loc(rfs->new_fs, i); if (ext2fs_test_block_bitmap2(new_map, b)) ext2fs_block_bitmap_loc_set(rfs->new_fs, i, 0); + else if (ext2fs_test_block_bitmap2(old_map, b)) + ext2fs_unmark_block_bitmap2(old_map, b); b = ext2fs_inode_bitmap_loc(rfs->new_fs, i); if (ext2fs_test_block_bitmap2(new_map, b)) ext2fs_inode_bitmap_loc_set(rfs->new_fs, i, 0); + else if (ext2fs_test_block_bitmap2(old_map, b)) + ext2fs_unmark_block_bitmap2(old_map, b); c = ext2fs_inode_table_loc(rfs->new_fs, i); - for (b = 0; b < rfs->new_fs->inode_blocks_per_group; b++) { - if (ext2fs_test_block_bitmap2(new_map, b + c)) { + for (b = 0; + b < rfs->new_fs->inode_blocks_per_group; + b++) { + if (ext2fs_test_block_bitmap2(new_map, b + c)) ext2fs_inode_table_loc_set(rfs->new_fs, i, 0); - break; - } + else if (ext2fs_test_block_bitmap2(old_map, b + c)) + ext2fs_unmark_block_bitmap2(old_map, b + c); } } + /* Free unused clusters */ + for (b = 0; + cluster_ratio > 1 && b < ext2fs_blocks_count(rfs->new_fs->super); + b += cluster_ratio) + if (ext2fs_test_block_bitmap2(old_map, b)) + ext2fs_unmark_block_bitmap2(rfs->new_fs->block_map, b); out: if (old_map) ext2fs_free_block_bitmap(old_map);