diff -Nua evms-2.5.1/plugins/md/md_discover.c engine2/plugins/md/md_discover.c --- evms-2.5.1/plugins/md/md_discover.c 2005-01-19 10:08:53.000000000 -0600 +++ engine2/plugins/md/md_discover.c 2005-02-10 23:39:43.000000000 -0600 @@ -570,6 +570,23 @@ goto out; } + for (i=0; i<md_info.nr_disks && !rc; i++) { + d.number = i; + rc = md_ioctl_get_disk_info(region, &d); + if (rc) { + LOG_WARNING("Can't get info for disk[%d].\n", i); + rc = 0; + continue; + } + member = md_volume_find_member_from_major_minor(vol, d.major, d.minor); + if (member && (member->dev_number != d.number)) { + LOG_WARNING("The kernel said disk(%d:%d) is at index[%d].\n", + d.major, d.minor, d.number); + member->dev_number = d.number; + EngFncs->sort_list(vol->members, md_volume_sort_members, NULL); + } + } + md_volume_get_super_info(vol, &sb_info); if (md_info.raid_disks != sb_info.raid_disks) { if (vol->flags & MD_ARRAY_RESIZE_PENDING) { @@ -724,9 +741,27 @@ /* This disk is not in the MD volume. */ if (d.state & (1<<MD_DISK_REMOVED)) { LOG_DEBUG("Disk[%d] was removed.\n", d.number); + } else if (d.state & (1<<MD_DISK_FAULTY)) { + length = sprintf(message_buffer, + _("%s region %s contains a failed disk with major %d and minor %d." + " The Kernel MD driver still has a reference to this disk." + " However, EVMS did not find MD superblock on this disk.\n\n" + " Would you like to request the kernel to release the reference to this disk?\n"), + level_to_string(md_info.level), vol->name, + d.major, d.minor); + + if (md_get_yes_no_response(message_buffer) == TRUE) { + md_ioctl_hot_remove_disk(region, makedev(d.major, d.minor)); + } + } else { - LOG_MD_BUG(); - rc = EINVAL; + LOG_WARNING("Missing disk[%d] info:" + " raid_disk(%d), major(%d), minor(%d) state(0x%08X).\n", + d.number, d.raid_disk, d.major, d.minor, d.state); + if (EngFncs->is_2_4_kernel() == FALSE) { + LOG_MD_BUG(); + rc = EINVAL; + } } } } diff -Nua evms-2.5.1/plugins/md/md.h engine2/plugins/md/md.h --- evms-2.5.1/plugins/md/md.h 2005-01-20 09:30:47.000000000 -0600 +++ engine2/plugins/md/md.h 2005-02-10 23:39:43.000000000 -0600 @@ -357,10 +357,12 @@ int find_disk_in_active_region(storage_object_t *region, int major, int minor); md_member_t *md_find_member(int major, int minor); md_member_t * md_volume_find_member(md_volume_t *vol, int dev_number); +md_member_t * md_volume_find_member_from_major_minor(md_volume_t *vol, int major, int minor); //int find_empty_slot(mdp_super_t *sb); int md_fix_dev_major_minor(md_volume_t * vol, boolean do_msg); boolean follow_up_mark_faulty(md_volume_t *volume, storage_object_t *faulty); +boolean md_get_yes_no_response(char *question); md_volume_t * md_allocate_volume(void); void md_free_volume(md_volume_t *vol); diff -Nua evms-2.5.1/plugins/md/md_info.c engine2/plugins/md/md_info.c --- evms-2.5.1/plugins/md/md_info.c 2005-01-16 23:50:21.000000000 -0600 +++ engine2/plugins/md/md_info.c 2005-02-10 22:19:39.000000000 -0600 @@ -60,7 +60,7 @@ } if (region->flags & SOFLAG_ACTIVE) { - rc = md_analyze_active_region(vol); + md_analyze_active_region(vol); } info_entries = NUM_VOLUME_INFO_ENTRIES + EngFncs->list_count(vol->members); @@ -70,7 +70,6 @@ info = EngFncs->engine_alloc(sizeof(extended_info_array_t) + sizeof(extended_info_t) * info_entries); if (info != NULL) { - info->count = info_entries; cur_info = info->info; cur_info->name = EngFncs->engine_strdup("name"); @@ -126,7 +125,7 @@ } strcat(message_buffer, _("Active")); } - if (vol->flags & MD_ARRAY_SYNCING) { + if (md_is_recovery_running(vol->region)) { if (message_buffer[0] != '\0') { strcat(message_buffer, ", "); } @@ -289,7 +288,7 @@ int info_count = 0; char buf[64]; - sprintf(buf, _("number %d"), info->number); + sprintf(buf, "number %d", info->number); cur_info->name = EngFncs->engine_strdup(buf); cur_info->title = EngFncs->engine_strdup(_("Number")); cur_info->desc = EngFncs->engine_strdup(_("Disk number in the array")); @@ -302,7 +301,7 @@ cur_info->group.group_number = 0; cur_info->group.group_level = 0; cur_info->group.group_name = NULL; - cur_info->flags = EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE; + cur_info->flags = 0; cur_info++; info_count++; @@ -414,7 +413,7 @@ } // If none of the flags are set, it must be a spare disk. - if (message_buffer[0] == '\0') { + if (buffer[0] == '\0') { strcpy(buffer, _("Spare")); } @@ -476,10 +475,40 @@ int rc = 0; extended_info_array_t * info; + extended_info_t *cur_info; + char buf[64]; + + LOG_ENTRY(); - info = EngFncs->engine_alloc(sizeof(extended_info_array_t) + sizeof(extended_info_t) * NUM_DISK_INFO_ENTRIES); + info = EngFncs->engine_alloc(sizeof(extended_info_array_t) + sizeof(extended_info_t) * (NUM_DISK_INFO_ENTRIES + 1)); if (info != NULL) { + info->count = get_member_disk_info(member, info->info); + + if (info->count != NUM_DISK_INFO_ENTRIES) { + LOG_MD_BUG(); + EngFncs->engine_free(info); + return EINVAL; + } + + cur_info = &info->info[info->count]; + + sprintf(buf, "superblock_child_object_%d", member->dev_number); + cur_info->name = EngFncs->engine_strdup(buf); + cur_info->title = EngFncs->engine_strdup(_("Superblock Index")); + cur_info->desc = EngFncs->engine_strdup(_("Superblock information on the child object")); + cur_info->type = EVMS_Type_Unsigned_Int32; + cur_info->unit = EVMS_Unit_None; + cur_info->format = EVMS_Format_Normal; + cur_info->value.ui32 = member->dev_number; + cur_info->collection_type = EVMS_Collection_None; + cur_info->collection.list = NULL; + cur_info->group.group_number = 0; + cur_info->group.group_level = 0; + cur_info->group.group_name = NULL; + cur_info->flags = EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE; + + info->count++; *info_array = info; } else { LOG_CRITICAL("Error getting memory for an extended_info_array./n"); @@ -494,10 +523,40 @@ { int rc = 0; extended_info_array_t * info; + extended_info_t *cur_info; + char buf[64]; - info = EngFncs->engine_alloc(sizeof(extended_info_array_t) + sizeof(extended_info_t) * NUM_DISK_INFO_ENTRIES); + LOG_ENTRY(); + + info = EngFncs->engine_alloc(sizeof(extended_info_array_t) + sizeof(extended_info_t) * (NUM_DISK_INFO_ENTRIES + 1)); if (info != NULL) { + info->count = get_superblock_disk_info(member->vol, member->dev_number, info->info); + + if (info->count != NUM_DISK_INFO_ENTRIES) { + LOG_MD_BUG(); + EngFncs->engine_free(info); + return EINVAL; + } + + cur_info = &info->info[info->count]; + + sprintf(buf, "superblock_stale_object_%d", member->dev_number); + cur_info->name = EngFncs->engine_strdup(buf); + cur_info->title = EngFncs->engine_strdup(_("Superblock Index")); + cur_info->desc = EngFncs->engine_strdup(_("Superblock information on the stale object")); + cur_info->type = EVMS_Type_Unsigned_Int32; + cur_info->unit = EVMS_Unit_None; + cur_info->format = EVMS_Format_Normal; + cur_info->value.ui32 = member->dev_number; + cur_info->collection_type = EVMS_Collection_None; + cur_info->collection.list = NULL; + cur_info->group.group_number = 0; + cur_info->group.group_level = 0; + cur_info->group.group_name = NULL; + cur_info->flags = EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE; + + info->count++; *info_array = info; } else { LOG_CRITICAL("Error getting memory for an extended_info_array./n"); @@ -512,32 +571,26 @@ /* * md_get_superblock_info * - * if child_index is -1, the master superblock will be used. + * if member is NULL, the master superblock will be used. */ static int md_get_superblock_info( md_volume_t *vol, - int child_index, + md_member_t *member, extended_info_array_t ** info_array ) { extended_info_array_t * info; extended_info_t *cur_info; int info_entries; md_super_info_t super; - md_member_t *member; int i; - if (child_index == -1) { + LOG_ENTRY(); + + if (member == NULL) { // Request to display volume's master superblock information md_volume_get_super_info(vol, &super); } else { - member = md_volume_find_member(vol, child_index); - if (member) { - LOG_CRITICAL("Could not locate member index %d in %s.\n", - child_index, vol->name); - md_member_get_super_info(member, &super); - } else { - return EINVAL; - } + md_member_get_super_info(member, &super); } info_entries = NUM_SUPER_INFO_ENTRIES + super.nr_disks*NUM_DISK_INFO_ENTRIES; @@ -546,6 +599,7 @@ sizeof(extended_info_t) * info_entries); if (info == NULL) { LOG_CRITICAL("Error getting memory for an extended_info_array.\n"); + LOG_EXIT_INT(ENOMEM); return ENOMEM; } cur_info = info->info; @@ -1002,6 +1056,9 @@ int rc = 0; int idx = -1; md_member_t *member; + list_element_t iter; + + LOG_ENTRY(); if (!name) { // Default case. Return all basic info about the region. @@ -1010,7 +1067,11 @@ else if ( ! strncmp(name, "child_object", 12) ) { // "Extra" information about the child's superblock idx = atoi(name + 12); - member = md_volume_find_member(vol, idx); + LIST_FOR_EACH(vol->members, iter, member) { + if ((member->dev_number == idx) && !(member->flags & MD_MEMBER_STALE)) { + break; + } + } if (member) { rc = md_get_child_disk_info(member, info_array); } else { @@ -1023,6 +1084,11 @@ // "Extra" information about the stale disk's superblock idx = atoi(name + 12); member = md_volume_find_member(vol, idx); + LIST_FOR_EACH(vol->members, iter, member) { + if ((member->dev_number == idx) && (member->flags & MD_MEMBER_STALE)) { + break; + } + } if (member) { rc = md_get_stale_disk_info(member, info_array); } else { @@ -1031,11 +1097,20 @@ return EINVAL; } } - else if ( ! strncmp(name, "number", 6) ) { - // "Extra" information about a disk in the array - idx = atoi(name + 6); - if (idx >= 0) { - rc = md_get_superblock_info(vol, idx, info_array); + else if ( ! strncmp(name, "superblock", 10) ) { + // "Extra" information about the master superblock + rc = md_get_superblock_info(vol, NULL, info_array); + } + else if ( ! strncmp(name, "superblock_child_object_", 24) ) { + // "Extra" information about the child superblock + idx = atoi(name + 24); + LIST_FOR_EACH(vol->members, iter, member) { + if ((member->dev_number == idx) && !(member->flags & MD_MEMBER_STALE)) { + break; + } + } + if (member) { + rc = md_get_superblock_info(vol, member, info_array); } else { LOG_ERROR("No support for extra region information about \"%s\"\n", name); @@ -1043,9 +1118,22 @@ return EINVAL; } } - else if ( ! strncmp(name, "superblock", 10) ) { - // "Extra" information about the master superblock - rc = md_get_superblock_info(vol, -1, info_array); + else if ( ! strncmp(name, "superblock_stale_object_", 24) ) { + // "Extra" information about the stale superblock + idx = atoi(name + 24); + LIST_FOR_EACH(vol->members, iter, member) { + if ((member->dev_number == idx) && (member->flags & MD_MEMBER_STALE)) { + break; + } + } + if (member) { + rc = md_get_superblock_info(vol, member, info_array); + } + else { + LOG_ERROR("No support for extra region information about \"%s\"\n", name); + LOG_EXIT_INT(EINVAL); + return EINVAL; + } } else { LOG_ERROR("No support for extra region information about \"%s\"\n", name); diff -Nua evms-2.5.1/plugins/md/md_io.c engine2/plugins/md/md_io.c --- evms-2.5.1/plugins/md/md_io.c 2005-01-16 23:50:21.000000000 -0600 +++ engine2/plugins/md/md_io.c 2005-02-11 17:00:14.000000000 -0600 @@ -97,6 +97,13 @@ int rc = 0, fd; LOG_ENTRY(); + if (obj->dev_major == MD_MAJOR) { + LOG_DEBUG("%s (%d:%d) is an MD device, skip flushing buffer cache.\n", + obj->name, obj->dev_major, obj->dev_minor); + LOG_EXIT_INT(0); + return 0; + } + fd = EngFncs->open_object(obj, O_RDONLY); if (fd <= 0) { LOG_DEBUG("Unable to open object %s to send ioctl\n", obj->name); diff -Nua evms-2.5.1/plugins/md/md_main.c engine2/plugins/md/md_main.c --- evms-2.5.1/plugins/md/md_main.c 2005-01-20 09:30:47.000000000 -0600 +++ engine2/plugins/md/md_main.c 2005-02-10 23:39:56.000000000 -0600 @@ -669,6 +669,14 @@ return 0; } +boolean md_get_yes_no_response(char *question) +{ + int answer = 0; + char * choice_text[3] = { _("Yes"), _("No"), NULL }; + QUESTION(&answer, choice_text, question); + return (answer == 0) ? TRUE : FALSE; +} + boolean follow_up_mark_faulty(md_volume_t *volume, storage_object_t *faulty) { int answer = 0; @@ -809,6 +817,23 @@ return NULL; } +md_member_t * md_volume_find_member_from_major_minor(md_volume_t *vol, int major, int minor) +{ + list_element_t iter; + md_member_t *member; + + LOG_ENTRY(); + LIST_FOR_EACH(vol->members, iter, member) { + if ((member->obj->dev_major == major) && + (member->obj->dev_minor == minor)) { + LOG_EXIT_PTR(member); + return member; + } + } + LOG_EXIT_PTR(NULL); + return NULL; +} + md_member_t * md_volume_find_member(md_volume_t *vol, int dev_number) { list_element_t iter; @@ -1809,6 +1834,7 @@ evms_md_ioctl_parm_t parm; mdu_disk_info_t info; md_member_t *member; + int kernel_idx; LOG_ENTRY(); @@ -1829,7 +1855,6 @@ /* * Removing a faulty disk which is still in the array */ - int kernel_idx; kernel_idx = find_disk_in_active_region(vol->region, faulty->dev_major, faulty->dev_minor); diff -Nua evms-2.5.1/plugins/md/md_super.c engine2/plugins/md/md_super.c --- evms-2.5.1/plugins/md/md_super.c 2005-01-19 06:25:00.000000000 -0600 +++ engine2/plugins/md/md_super.c 2005-02-10 16:12:21.000000000 -0600 @@ -145,7 +145,7 @@ goto queue_corrupt_message; } - if ( (1 << ffz(~(chunksize_in_bytes))) != chunksize_in_bytes) { + if ( (1 << (ffs(chunksize_in_bytes)-1)) != chunksize_in_bytes) { length = sprintf(message_buffer, _("%s region %s is corrupt." " The chunk size (%d bytes) is not a power of 2."), @@ -2909,6 +2909,7 @@ return -1; } member->vol->sb_func->get_sb_disk_info(member, &info); + LOG_EXIT_INT(info.raid_disk); return info.raid_disk; } diff -Nua evms-2.5.1/plugins/md/raid1_mgr.c engine2/plugins/md/raid1_mgr.c --- evms-2.5.1/plugins/md/raid1_mgr.c 2005-01-18 21:33:09.000000000 -0600 +++ engine2/plugins/md/raid1_mgr.c 2005-02-05 17:31:07.000000000 -0600 @@ -768,6 +768,7 @@ static int raid1_create_region(md_volume_t * vol, list_anchor_t output_list, boolean final_call) { int rc = 0; + int length; storage_object_t * region; LOG_ENTRY(); @@ -781,9 +782,12 @@ if (!vol->active_disks) { if (final_call) { vol->flags |= MD_CORRUPT; - LOG_CRITICAL("Volume %s does not have any active disks." - " This is final discovery call, the volume is corrupt.\n", - vol->name); + length = sprintf(message_buffer, + _("RAID1 region %s is corrupt. " + " The number of raid disks for a full functional array is %d." + " The number of active disks is %d."), + vol->name, vol->raid_disks, vol->active_disks); + md_queue_corrupt_message(vol->personality, message_buffer, length); } else { LOG_DEBUG("Volume %s does not have any active disks, delaying discovery.\n", vol->name);