@@ -2283,16 +2283,19 @@ 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;
dest->image_io = dest_image_io;
dest->inode_map = inode_map;
dest->block_map = block_map;
+ dest->badblocks = badblocks;
/*
* PASS1_MERGE_FS_BITMAP might return directly from this function,
* so please do NOT leave any garbage behind after returning.
@@ -2309,7 +2312,10 @@ static int _e2fsck_pass1_merge_fs(ext2_filsys dest, ext2_filsys src)
}
if (src->badblocks) {
- retval = ext2fs_badblocks_copy(src->badblocks, &dest->badblocks);
+ if (dest->badblocks == NULL)
+ retval = ext2fs_badblocks_copy(src->badblocks, &dest->badblocks);
+ else
+ retval = ext2fs_badblocks_merge(src->badblocks, dest->badblocks);
if (retval)
goto out_dblist;
}
@@ -11,6 +11,7 @@
#include "config.h"
#include <stdio.h>
+#include <assert.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
@@ -56,6 +57,65 @@ static errcode_t make_u32_list(int size, int num, __u32 *list,
return 0;
}
+/*
+ * 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->size + dest->size;
+ int size_entry = sizeof(blk_t);
+ blk_t *array;
+ blk_t *array_ptr;
+ blk_t *src_array = src->list;
+ blk_t *dest_array = dest->list;
+ int src_index = 0;
+ int dest_index = 0;
+
+ if (src->num == 0)
+ return 0;
+
+ retval = ext2fs_get_array(size, size_entry, &array);
+ if (retval)
+ return retval;
+
+ array_ptr = array;
+ /*
+ * This can be improved by binary search and memcpy, but codes would
+ * be complexer. And if number of bad blocks is small, the optimization
+ * won't improve performance a lot.
+ */
+ while (src_index < src_count || dest_index < dest_count) {
+ if (src_index >= src_count) {
+ memcpy(array_ptr, &dest_array[dest_index],
+ (dest_count - dest_index) * size_entry);
+ break;
+ }
+ if (dest_index >= dest_count) {
+ memcpy(array_ptr, &src_array[src_index],
+ (src_count - src_index) * size_entry);
+ break;
+ }
+ if (src_array[src_index] < dest_array[dest_index]) {
+ *array_ptr = src_array[src_index];
+ src_index++;
+ } else {
+ assert(src_array[src_index] > dest_array[dest_index]);
+ *array_ptr = dest_array[dest_index];
+ dest_index++;
+ }
+ array_ptr++;
+ }
+
+ ext2fs_free_mem(&dest->list);
+ dest->list = array;
+ dest->num = src_count + dest_count;
+ dest->size = size;
+ return 0;
+}
+
/*
* This procedure creates an empty u32 list.
@@ -79,13 +139,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 +149,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.
*
@@ -814,6 +814,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);
@@ -34,7 +34,6 @@ struct ext2_struct_u32_list {
int num;
int size;
__u32 *list;
- int badblocks_flags;
};
struct ext2_struct_u32_iterate {