Whamcloud - gitweb
e2fsck: merge badblocks after thread finishes
authorWang Shilong <wshilong@ddn.com>
Tue, 22 Sep 2020 10:00:39 +0000 (18:00 +0800)
committerAndreas Dilger <adilger@whamcloud.com>
Mon, 19 Sep 2022 23:15:26 +0000 (17:15 -0600)
Badblocks should be merged properly after threads finish.

E2fsprogs-commit: f39197f53ef5d90cd6952d7e75f2d2e3a02bf7ef

Change-Id: Ieb9a96a5e4438270ba6e939155e2666bb53177e4
Signed-off-by: Li Xi <lixi@ddn.com>
Signed-off-by: Wang Shilong <wshilong@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
e2fsck/pass1.c
lib/ext2fs/badblocks.c
lib/ext2fs/ext2fs.h
lib/ext2fs/ext2fsP.h

index 03af46d..eff6edc 100644 (file)
@@ -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;
 }
 
index 0f23983..3c9a608 100644 (file)
@@ -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,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.
  *
index 5eb9526..fa29770 100644 (file)
@@ -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);
index a20a050..d2045af 100644 (file)
@@ -34,7 +34,6 @@ struct ext2_struct_u32_list {
        int     num;
        int     size;
        __u32   *list;
-       int     badblocks_flags;
 };
 
 struct ext2_struct_u32_iterate {