The attached patch is for EVMS 2.2.1. This patch rebuild a corrupt raid5 array from the one of the most up-to-date MD superblock. This patch only works if all disk members are still accessible. When you see messages regarding a RAID5 region being corrupt. - Go to the region view/panel - Bring up the context menu for that region, select Fix. - The messages panel will appear again with the information about the "rebuilt" array. - Important: Make sure to verify the displayed information before saving the changes. To apply: cd /usr/src/evms-2.2.1 patch -p1 < raid5_reconstruct.patch diff -Naur evms-2.2.1a/plugins/md/md_discover.c evms-2.2.1b/plugins/md/md_discover.c --- evms-2.2.1a/plugins/md/md_discover.c 2003-11-05 07:42:17.000000000 -0600 +++ evms-2.2.1b/plugins/md/md_discover.c 2004-01-14 19:42:46.000000000 -0600 @@ -1010,6 +1010,15 @@ volume->child_object[i] = NULL; } +static void move_stale_object_to_child_list(md_volume_t *volume, int i) +{ + if (volume->child_object[i]) { + md_log_internal_bug(__FILE__, __FUNCTION__, __LINE__); + return; + } + volume->child_object[i] = volume->stale_object[i]; + volume->stale_object[i] = NULL; +} static inline void debug_print_desc(mdp_disk_t *d) { @@ -1018,6 +1027,50 @@ } /* + * Function: md_rebuild_array_from_master_sb + * + * This function rebuilds the MD array from the master MD superblock + */ +int md_rebuild_array_from_master_sb(md_volume_t *vol) +{ + int i, count; + + LOG_ENTRY(); + + if (vol->flags & MD_CORRUPT) { + LOG_DEFAULT("MD region %s is %s.\n", vol->name, + (vol->flags & MD_CORRUPT) ? "corrupt" : + (vol->flags & MD_PROBLEMATIC_SB) ? "inconsistent" : "???"); + } + + if (vol->super_block->failed_disks) { + LOG_ERROR("Master superblock has %d failed disks.\n", + vol->super_block->failed_disks); + LOG_EXIT_INT(vol->flags); + return vol->flags; + } + + count = md_count_children(vol) + md_count_stale_disks(vol); + + if (vol->super_block->nr_disks != count) { + LOG_ERROR("Master superblock has %d disks, but we found only %d children.\n", + vol->super_block->nr_disks, count); + LOG_EXIT_INT(EINVAL); + return EINVAL; + } + + for (i=0; i < MAX_MD_DEVICES; i++) { + move_stale_object_to_child_list(vol, i); + md_clone_superblock(vol, i); + } + + md_analyze_volume(vol); + + LOG_EXIT_INT(vol->flags); + return vol->flags; +} + +/* * Function: md_analyze_volume * * Note: This function can be called before the region is allocated and initilized. diff -Naur evms-2.2.1a/plugins/md/md_discover.h evms-2.2.1b/plugins/md/md_discover.h --- evms-2.2.1a/plugins/md/md_discover.h 2003-10-13 17:50:34.000000000 -0500 +++ evms-2.2.1b/plugins/md/md_discover.h 2004-01-14 19:38:38.000000000 -0600 @@ -37,6 +37,7 @@ int md_register_name_space(void); int md_discover_final_call(dlist_t input_list, dlist_t output_list, int *count); int md_analyze_volume(md_volume_t *volume); +int md_rebuild_array_from_master_sb(md_volume_t *volume); void md_remove_missing_disk_entries(md_volume_t * vol); void md_print_array_sb(char *buf, u_int32_t buf_size, mdp_super_t *sb); int md_free_volume(md_volume_t *volume); diff -Naur evms-2.2.1a/plugins/md/raid5_discover.c evms-2.2.1b/plugins/md/raid5_discover.c --- evms-2.2.1a/plugins/md/raid5_discover.c 2003-11-05 18:10:56.000000000 -0600 +++ evms-2.2.1b/plugins/md/raid5_discover.c 2004-01-14 19:38:38.000000000 -0600 @@ -573,6 +573,22 @@ LOG_EXIT_VOID(); } +static void raid5_rebuild_array_from_master_sb(md_volume_t *vol) +{ + LOG_ENTRY(); + + md_rebuild_array_from_master_sb(vol); + + if ((vol->flags & (MD_CORRUPT | MD_PROBLEMATIC_SB)) == 0) { + md_print_array_sb(message_buffer, MD_MESSAGE_BUF_SIZE, vol->super_block); + MESSAGE("%s", message_buffer); + MESSAGE("Region %s has been rebuilt from one of most up-to-date MD superblocks." + " Please verify the MD array information above before saving the changes.\n", vol->name); + vol->flags |= MD_DIRTY; + vol->region->flags |= (SOFLAG_DIRTY | SOFLAG_NEEDS_DEACTIVATE); + } + LOG_EXIT_VOID(); +} /* @@ -653,7 +669,15 @@ break; case 2: - raid5_fix_master_sb(vol); + raid5_rebuild_array_from_master_sb(vol); + if (vol->flags & (MD_CORRUPT | MD_PROBLEMATIC_SB)) { + raid5_fix_master_sb(vol); + } + + if ((vol->flags & MD_CORRUPT) == 0) { + create_raid5_conf(vol); + } + break; }