From: Wang Shilong Date: Tue, 22 Sep 2020 10:00:39 +0000 (+0800) Subject: e2fsck: merge badblocks after thread finishes X-Git-Tag: v1.46.6-wc1~74 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=bdef499432178a6a4f43e66a78c889250e74e254;p=tools%2Fe2fsprogs.git e2fsck: merge badblocks after thread finishes Badblocks should be merged properly after threads finish. E2fsprogs-commit: f39197f53ef5d90cd6952d7e75f2d2e3a02bf7ef Change-Id: Ieb9a96a5e4438270ba6e939155e2666bb53177e4 Signed-off-by: Li Xi Signed-off-by: Wang Shilong Reviewed-by: Andreas Dilger Signed-off-by: Theodore Ts'o --- diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 03af46d..eff6edc 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -2217,6 +2217,7 @@ static errcode_t e2fsck_pass1_copy_fs(ext2_filsys dest, e2fsck_t src_context, memcpy(dest, src, sizeof(struct struct_ext2_filsys)); dest->inode_map = NULL; dest->block_map = NULL; + dest->badblocks = NULL; if (dest->dblist) dest->dblist->fs = dest; if (src->block_map) { @@ -2233,7 +2234,8 @@ static errcode_t e2fsck_pass1_copy_fs(ext2_filsys dest, e2fsck_t src_context, } if (src->badblocks) { - retval = ext2fs_badblocks_copy(src->badblocks, &dest->badblocks); + retval = ext2fs_badblocks_copy(src->badblocks, + &dest->badblocks); if (retval) return retval; } @@ -2278,11 +2280,13 @@ static int e2fsck_pass1_merge_fs(ext2_filsys dest, ext2_filsys src) io_channel dest_image_io; ext2fs_inode_bitmap inode_map; ext2fs_block_bitmap block_map; + ext2_badblocks_list badblocks; dest_io = dest->io; dest_image_io = dest->image_io; inode_map = dest->inode_map; block_map = dest->block_map; + badblocks = dest->badblocks; memcpy(dest, src, sizeof(struct struct_ext2_filsys)); dest->io = dest_io; @@ -2290,6 +2294,7 @@ static int e2fsck_pass1_merge_fs(ext2_filsys dest, ext2_filsys src) dest->icache = icache; dest->inode_map = inode_map; dest->block_map = block_map; + dest->badblocks = badblocks; if (dest->dblist) dest->dblist->fs = dest; @@ -2309,10 +2314,12 @@ static int e2fsck_pass1_merge_fs(ext2_filsys dest, ext2_filsys src) goto out; if (src->badblocks) { - retval = ext2fs_badblocks_copy(src->badblocks, &dest->badblocks); - - ext2fs_badblocks_list_free(src->badblocks); - src->badblocks = NULL; + if (dest->badblocks == NULL) + retval = ext2fs_badblocks_copy(src->badblocks, + &dest->badblocks); + else + retval = ext2fs_badblocks_merge(src->badblocks, + dest->badblocks); } out: io_channel_close(src->io); @@ -2320,6 +2327,8 @@ out: ext2fs_free_generic_bmap(src->inode_map); if (src->block_map) ext2fs_free_generic_bmap(src->block_map); + if (src->badblocks) + ext2fs_badblocks_list_free(src->badblocks); return retval; } diff --git a/lib/ext2fs/badblocks.c b/lib/ext2fs/badblocks.c index 0f23983..3c9a608 100644 --- a/lib/ext2fs/badblocks.c +++ b/lib/ext2fs/badblocks.c @@ -11,6 +11,7 @@ #include "config.h" #include +#include #include #if HAVE_UNISTD_H #include @@ -56,6 +57,75 @@ static errcode_t make_u32_list(int size, int num, __u32 *list, return 0; } +static inline int insert_ok(blk_t *array, int cnt, blk_t new) +{ + return (cnt == 0 || array[cnt - 1] != new); +} + +/* + * Merge list from src to dest + */ +static errcode_t merge_u32_list(ext2_u32_list src, ext2_u32_list dest) +{ + errcode_t retval; + int src_count = src->num; + int dest_count = dest->num; + int size = src_count + dest_count; + int size_entry = sizeof(blk_t); + blk_t *array; + blk_t *src_array = src->list; + blk_t *dest_array = dest->list; + int src_index = 0; + int dest_index = 0; + int uniq_cnt = 0; + + if (src->num == 0) + return 0; + + retval = ext2fs_get_array(size, size_entry, &array); + if (retval) + return retval; + + /* + * It is possible that src list and dest list could be + * duplicated when merging badblocks. + */ + while (src_index < src_count || dest_index < dest_count) { + if (src_index >= src_count) { + for (; dest_index < dest_count; dest_index++) + if (insert_ok(array, uniq_cnt, dest_array[dest_index])) + array[uniq_cnt++] = dest_array[dest_index]; + break; + } + if (dest_index >= dest_count) { + for (; src_index < src_count; src_index++) + if (insert_ok(array, uniq_cnt, src_array[src_index])) + array[uniq_cnt++] = src_array[src_index]; + break; + } + if (src_array[src_index] < dest_array[dest_index]) { + if (insert_ok(array, uniq_cnt, src_array[src_index])) + array[uniq_cnt++] = src_array[src_index]; + src_index++; + } else if (src_array[src_index] > dest_array[dest_index]) { + if (insert_ok(array, uniq_cnt, dest_array[dest_index])) + array[uniq_cnt++] = dest_array[dest_index]; + dest_index++; + } else { + if (insert_ok(array, uniq_cnt, dest_array[dest_index])) + array[uniq_cnt++] = dest_array[dest_index]; + src_index++; + dest_index++; + } + } + + ext2fs_free_mem(&dest->list); + dest->list = array; + dest->num = uniq_cnt; + dest->size = size; + return 0; +} + /* * This procedure creates an empty u32 list. @@ -79,13 +149,7 @@ errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size) */ errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest) { - errcode_t retval; - - retval = make_u32_list(src->size, src->num, src->list, dest); - if (retval) - return retval; - (*dest)->badblocks_flags = src->badblocks_flags; - return 0; + return make_u32_list(src->size, src->num, src->list, dest); } errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src, @@ -95,6 +159,13 @@ errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src, (ext2_u32_list *) dest); } +errcode_t ext2fs_badblocks_merge(ext2_badblocks_list src, + ext2_badblocks_list dest) +{ + return merge_u32_list((ext2_u32_list) src, + (ext2_u32_list) dest); +} + /* * This procedure frees a badblocks list. * diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 5eb9526..fa29770 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -842,6 +842,8 @@ extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter); extern errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src, ext2_badblocks_list *dest); +extern errcode_t ext2fs_badblocks_merge(ext2_badblocks_list src, + ext2_badblocks_list dest); extern int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2); extern int ext2fs_u32_list_count(ext2_u32_list bb); diff --git a/lib/ext2fs/ext2fsP.h b/lib/ext2fs/ext2fsP.h index a20a050..d2045af 100644 --- a/lib/ext2fs/ext2fsP.h +++ b/lib/ext2fs/ext2fsP.h @@ -34,7 +34,6 @@ struct ext2_struct_u32_list { int num; int size; __u32 *list; - int badblocks_flags; }; struct ext2_struct_u32_iterate {