
There are serveral changes in this patch.  The most important is to
correctly recognize and manage RAID-1 and RAID-5 devices that were
created with mdadm using the "missing" option.

--- evms-2.3.3a/plugins/md/md_discover.c	2004-03-05 17:52:13.000000000 -0600
+++ evms-2.3.3b/plugins/md/md_discover.c	2004-05-17 18:04:30.000000000 -0500
@@ -1191,8 +1191,18 @@
 	if (vol->nr_disks != sb->nr_disks) {
 		LOG_WARNING("We found nr_disks(%d), the superblock has nr_disks(%d)\n",
 			    vol->nr_disks, sb->nr_disks);
+		/* 
+		 * Note: Kernel MD driver allows creating an MD array with missing disk(s).
+		 * If this is the case, ignore the difference between sb->nr_disks and 
+		 * volume->nr_disks.
+		 */
+		if ((sb->nr_disks > vol->nr_disks) && 
+		    (sb->failed_disks == (sb->nr_disks - vol->nr_disks))) {
+			LOG_WARNING("But we are ignoring the difference.\n");
+		} else {
 		vol->flags |= MD_PROBLEMATIC_SB;
 	}
+	}
 	
 	if (vol->working_disks != sb->working_disks) {
 		LOG_WARNING("We found working_disks(%d), the superblock has working_disks(%d)\n",
--- evms-2.3.3a/plugins/md/md_dlist.c	2004-03-12 13:48:39.000000000 -0600
+++ evms-2.3.3b/plugins/md/md_dlist.c	2004-05-19 18:41:49.000000000 -0500
@@ -527,7 +527,7 @@
 				if ( (tmp_info.major == disk_info->object->dev_major) &&
 				     (tmp_info.minor == disk_info->object->dev_major) &&
 				     (tmp_info.state & (1 << MD_DISK_ACTIVE)) ) {
-					LOG_WARNING("Device (%d:%d) already exists in region [%s]\n",
+					LOG_WARNING("ADD: Device (%d:%d) already exists in region [%s]\n",
 						    disk_info->object->dev_major,
 						    disk_info->object->dev_minor,
 						    region->name);
@@ -567,9 +567,10 @@
 					region,
 					makedev(disk_info->major, disk_info->minor));
 			} else {
-				LOG_WARNING("cound not find device (%d:%d) in region [%s]\n",
-					    disk_info->object->dev_major,
-					    disk_info->object->dev_minor,
+				LOG_WARNING("REMOVE: cound not find %s (%d:%d) in region [%s]\n",
+					    disk_info->object->name,
+					    disk_info->major,
+					    disk_info->minor,
 					    region->name);
 				rc = ENODEV;
 				break;
@@ -586,15 +587,32 @@
 			if (rc) {
 				break;
 			}
-			if ((tmp_info.major == disk_info->object->dev_major) &&
-			    (tmp_info.minor == disk_info->object->dev_minor) ) {
+
+			/*
+			 * See if the disk to be marked faulty is still at same slot (number)
+			 */
+			if ((tmp_info.major != disk_info->major) ||
+			    (tmp_info.minor != disk_info->minor) ) {
+				/*
+				 * The disk may has been moved to a different slot.
+				 * Find it.
+				 */
+				disk_info->number = find_disk_in_active_region(region,
+									disk_info->major,
+									disk_info->minor);
+				if (disk_info->number == MAX_MD_DEVICES)
+					rc = ENODEV;
+			}
+
+			if (!rc) {
 				rc = md_ioctl_set_disk_faulty(
 					region,
-					makedev(disk_info->object->dev_major, disk_info->object->dev_minor));
+					makedev(disk_info->major, disk_info->minor));
 			} else {
-				LOG_WARNING("Could not find device [%d:%d] in region %s.\n",
-					    disk_info->object->dev_major,
-					    disk_info->object->dev_minor,
+				LOG_WARNING("DEACTIVATE: Could not find %s [%d:%d] in region %s.\n",
+					    disk_info->object->name,
+					    disk_info->major,
+					    disk_info->minor,
 					    region->name);
 				break;
 			}
--- evms-2.3.3a/plugins/md/md_main.c	2004-03-31 13:05:22.000000000 -0600
+++ evms-2.3.3b/plugins/md/md_main.c	2004-05-19 17:59:54.000000000 -0500
@@ -766,6 +766,7 @@
 {
 	int i, j, rc=0;
 	mdp_super_t *sb;
+	mdp_disk_t disk;
 	LOG_ENTRY();
 
 	if (!volume) {
@@ -789,12 +790,18 @@
 		disk_info.number = i;
 		rc = md_ioctl_get_disk_info(volume->region, &disk_info);
 		if (!rc) {
+			/* save a copy before copying */
+			disk = sb->disks[i];
+
 //			sb->disks[i].number = disk_info.number;
 			sb->disks[i].major = disk_info.major;
 			sb->disks[i].minor = disk_info.minor;
 			sb->disks[i].raid_disk = disk_info.raid_disk;
 			sb->disks[i].state = disk_info.state;
 
+			if (memcmp(&disk, &sb->disks[i], sizeof(mdp_disk_t)) == 0)
+				continue;	// the same
+
 			LOG_EXTRA("[%s] number(%d) major(%d) minor(%d) raid_disk(%d) state(0x%08X)\n",	
 				volume->name, disk_info.number,
 				disk_info.major, disk_info.minor,
@@ -826,8 +833,17 @@
 						md_log_internal_bug(__FILE__, __FUNCTION__, __LINE__);
 					} else {
 						void *tmp_ptr;
+						char *name1 = NULL, *name2 = NULL;
+
+						if (volume->child_object[i])
+							name1 = volume->child_object[i]->name;
+						if (volume->child_object[j])
+							name2 = volume->child_object[j]->name;
 						
 						/* swap entries */
+						LOG_DEFAULT("[%s] swapping entries obj[i=%d]=%s obj[j=%d]=%s.\n",
+							volume->name, i, name1, j, name2);
+
 						tmp_ptr = volume->child_object[i];
 						volume->child_object[i] = volume->child_object[j];
 						volume->child_object[j] = (storage_object_t *)tmp_ptr;
@@ -870,14 +886,17 @@
 {
 	boolean rc = TRUE;
 
+	LOG_ENTRY();
 	if (md_is_region_active(region)) {
 		if (region->volume) {
 			if (!(region->volume->flags & VOLFLAG_COMPATIBILITY)) {
-				LOG_DETAILS("Region %s is part of EVMS volume %s.\n", region->name, region->volume->name);
+				LOG_DETAILS("Region %s is part of EVMS volume %s.\n", 
+					    region->name, region->volume->name);
 				rc = FALSE;
 			}
 			if (EngFncs->is_mounted(region->volume->name, NULL)) {
-				LOG_DETAILS("Region %s is part of volume %s which is mounted on %s.\n", region->name, region->volume->name, region->volume->mount_point);
+				LOG_DETAILS("Region %s is part of volume %s which is mounted on %s.\n",
+					    region->name, region->volume->name, region->volume->mount_point);
 				rc = FALSE;
 			}
 		}
--- evms-2.3.3a/plugins/md/raid1_discover.c	2003-12-11 11:48:11.000000000 -0600
+++ evms-2.3.3b/plugins/md/raid1_discover.c	2004-05-19 18:38:18.000000000 -0500
@@ -407,30 +407,46 @@
 		LOG_EXIT_VOID();
 		return;
 	case 1:
+		if (vol->region && (md_is_region_active(vol->region) == TRUE))
+			break;
 		if (sb->active_disks != vol->active_disks) {
-			MESSAGE("Region %s : MD superblock has active_disks=%d, found %d.\n",
+			MESSAGE("WARNING: Region %s : MD superblock has active_disks=%d, found %d.\n",
 				vol->name, sb->active_disks, vol->active_disks);
 		}
 
 		if (sb->working_disks != vol->working_disks) {
-			MESSAGE("Region %s : MD superblock has working_disks=%d, found %d.\n",
+			MESSAGE("WARNING: Region %s : MD superblock has working_disks=%d, found %d.\n",
 				vol->name, sb->working_disks, vol->working_disks);
 		}
 
 		if (sb->failed_disks != vol->failed_disks) {
-			MESSAGE("Region %s : MD superblock has failed_disks=%d, found %d.\n",
+			MESSAGE("WARNING: Region %s : MD superblock has failed_disks=%d, found %d."
+				"  If another disk had been added to replace the failed disk,"
+				" it is safe to ignore this warning message.\n",
 				vol->name, sb->failed_disks, vol->failed_disks);
 		}
 
 		if (sb->spare_disks != vol->spare_disks) {
-			MESSAGE("Region %s : MD superblock has spare_disks=%d, found %d.\n",
+			MESSAGE("WARNING: Region %s : MD superblock has spare_disks=%d, found %d.\n",
 				vol->name, sb->spare_disks, vol->spare_disks);
 		}
 
 		if (sb->nr_disks != vol->nr_disks) {
-			MESSAGE("Region %s : MD superblock has nr_disks=%d, found %d.\n",
+			/* 
+			 * Note: Kernel MD driver allows creating an MD array with missing disk(s).
+			 * If this is the case, ignore the difference between sb->nr_disks and 
+			 * volume->nr_disks.
+			 */
+			if ((sb->nr_disks > vol->nr_disks) && 
+			    (sb->failed_disks == (sb->nr_disks - vol->nr_disks))) {
+				LOG_WARNING("[%s] : MD superblock has nr_disks=%d, found %d.\n"
+					"But we are ignoring the difference.\n",
+					vol->name, sb->nr_disks, vol->nr_disks);
+			} else {
+				MESSAGE("WARNING: Region %s : MD superblock has nr_disks=%d, found %d.\n",
 				vol->name, sb->nr_disks, vol->nr_disks);
 		}
+		}
 
 		if (vol->stale_disks) {
 			raid1_show_stale_disks(vol);
--- evms-2.3.3a/plugins/md/raid1_funcs.c	2004-03-11 15:02:47.000000000 -0600
+++ evms-2.3.3b/plugins/md/raid1_funcs.c	2004-05-19 19:03:02.000000000 -0500
@@ -714,10 +714,17 @@
 					break;
 				} else {
 					if ((info.major != spare->dev_major) || (info.minor != spare->dev_minor)) {
-						LOG_ERROR("(%s) mismatch major/minor, kernel(%d:%d), spare(%d:%d)\n",
-							  spare->name, info.major, info.minor, spare->dev_major, spare->dev_minor);
-						rc = ENODEV;
-						break;
+
+						MESSAGE("WARNING: Region:%s, Device:%s: Index:%d\n"
+							" There is a mismatch major/minor, Kernel MD driver has (%d:%d), EVMS has (%d:%d)."
+							"  However, if %s was created by another MD tool such as mdadm or raidtools,"
+							" the operation will succeed.\n",
+						  volume->name, spare->name, i,
+						  info.major, info.minor,
+						  spare->dev_major, spare->dev_minor,
+						  volume->name);
+						//rc = ENODEV;
+						//break;
 					}
 				}
 				
@@ -729,8 +736,10 @@
 				}
 
 				disk_info->number = i;
-				disk_info->major = spare->dev_major;
-				disk_info->minor = spare->dev_minor;
+				//disk_info->major = spare->dev_major;
+				//disk_info->minor = spare->dev_minor;
+				disk_info->major = info.major;
+				disk_info->minor = info.minor;
 				disk_info->object = spare;
 				parm.disk_info = disk_info;
 				schedule_md_ioctl_pkg(volume, EVMS_MD_REMOVE, &parm, free_disk_info_post_ioctl);
@@ -925,13 +934,16 @@
 			return ENODEV;
 		} else {
 			if ((info.major != faulty_disk->dev_major) || (info.minor != faulty_disk->dev_minor)) {
-				LOG_ERROR("(%s) mismatch major/minor, kernel(%d:%d), faulty_disk(%d:%d)\n",
-					  faulty_disk->name,
+				MESSAGE("WARNING: Region:%s, Device:%s: Index:%d\n"
+					" There is a mismatch major/minor, Kernel MD driver has (%d:%d), EVMS has (%d:%d)."
+					"  However, if %s was created by another MD tool such as mdadm or raidtools,"
+					" the operation will succeed.\n",
+					volume->name, faulty_disk->name, i,
 					  info.major, info.minor,
-					  faulty_disk->dev_major,
-					  faulty_disk->dev_minor);
-				LOG_EXIT_INT(ENODEV);
-				return ENODEV;
+					faulty_disk->dev_major, faulty_disk->dev_minor,
+					volume->name);
+				//LOG_EXIT_INT(ENODEV);
+				//return ENODEV;
 			}
 		}
 		
@@ -944,8 +956,10 @@
 		}
 
 		disk_info->number = i;
-		disk_info->major = faulty_disk->dev_major;
-		disk_info->minor = faulty_disk->dev_minor;
+		//disk_info->major = faulty_disk->dev_major;
+		//disk_info->minor = faulty_disk->dev_minor;
+		disk_info->major = info.major;
+		disk_info->minor = info.minor;
 		disk_info->object = faulty_disk;
 		parm.disk_info = disk_info;
 		schedule_md_ioctl_pkg(volume, EVMS_MD_REMOVE, &parm, free_disk_info_post_ioctl);
@@ -1039,8 +1053,8 @@
 		if ((info.major != active->dev_major) || (info.minor != active->dev_minor)) {
 			LOG_ERROR("(%s) mismatch major/minor, kernel(%d:%d), active(%d:%d)\n",
 				  active->name, info.major, info.minor, active->dev_major, active->dev_minor);
-			LOG_EXIT_INT(EINVAL);
-			return EINVAL;
+			//LOG_EXIT_INT(EINVAL);
+			//return EINVAL;
 		}
 	}
 
@@ -1052,6 +1066,8 @@
 	}
 
 	disk_info->number = i;
+	disk_info->major = info.major;
+	disk_info->minor = info.minor;
 	disk_info->object = active;
 	parm.disk_info = disk_info;
 	schedule_md_ioctl_pkg(volume, EVMS_MD_DEACTIVATE, &parm, mark_disk_faulty_post_ioctl);
--- evms-2.3.3a/plugins/md/raid1_mgr.c	2004-03-26 14:04:18.000000000 -0600
+++ evms-2.3.3b/plugins/md/raid1_mgr.c	2004-05-19 18:56:13.000000000 -0500
@@ -1721,6 +1721,13 @@
 
 #define PERCENT_WARN_THRESHOLD  5
 
+static void issue_warning_big_obj(storage_object_t *obj, u_int64_t diffsize)
+{
+	MESSAGE("The %s object is %"PRIu64" MB larger than the smallest object in the RAID array.  "
+		"The extra space will not be used.\n",
+		obj->name, diffsize * EVMS_VSECTOR_SIZE / (1024*1024) );
+}
+
 static void warn_if_big_objects( task_context_t * context )
 {
 	storage_object_t * obj;
@@ -1730,6 +1737,18 @@
 
 	LOG_ENTRY();
 
+	if ( EngFncs->list_empty(context->selected_objects) ) {
+		LOG_WARNING("Selected objects list is empty!!!.\n");
+		LOG_EXIT_VOID();
+	}
+	obj = EngFncs->first_thing(context->selected_objects, NULL);
+	if (obj) {
+		smallest_size = MD_NEW_SIZE_SECTORS(obj->size);
+	} else {
+		LOG_ERROR("Can not get the first item in selected objects list.\n");
+		LOG_EXIT_VOID();
+	}
+
 	/* Find the smallest object. */
 	LIST_FOR_EACH(context->selected_objects, li, obj) {
 		smallest_size = min(smallest_size, MD_NEW_SIZE_SECTORS(obj->size));
@@ -1750,7 +1769,7 @@
 	}
 
 	/*
-	 * Now go through the objects again and issue a warnign message for
+	 * Now go through the objects again and issue a warning message for
 	 * any object whose size exceeds the threshold over the smallest
 	 * object size.
 	 */
@@ -1761,9 +1780,7 @@
 			diffsize = MD_NEW_SIZE_SECTORS(obj->size) - smallest_size;
 
 			if (diffsize > (smallest_size * PERCENT_WARN_THRESHOLD) / 100) {
-				MESSAGE("The %s object is %"PRIu64" MB larger than the smallest object in the RAID array.  "
-					"The extra space will not be used.\n",
-					obj->name, diffsize * EVMS_VSECTOR_SIZE / (1024*1024) );
+				issue_warning_big_obj(obj, diffsize);
 			}
 		}
 
@@ -1774,9 +1791,7 @@
 			diffsize = MD_NEW_SIZE_SECTORS(spare->size) - smallest_size;
 
 			if (diffsize > (smallest_size * PERCENT_WARN_THRESHOLD) / 100) {
-				MESSAGE("The %s object is %"PRIu64" MB larger than the smallest object in the RAID array.  "
-					"The extra space will not be used.\n",
-					spare->name, diffsize * EVMS_VSECTOR_SIZE / (1024*1024));
+				issue_warning_big_obj(obj, diffsize);
 			}
 		}
 	}
@@ -2210,6 +2225,11 @@
 		return enable;
 	}
 
+	if (md_can_stop_array(volume->region) == FALSE) {
+		LOG_EXIT_INT(enable);
+		return enable;
+	}
+
 	if (volume->flags & (MD_CORRUPT | MD_PROBLEMATIC_SB)) {
 
 		fia->info[*function_count].function = MD_RAID1_FUNCTION_FIX;
@@ -2591,7 +2611,7 @@
 		return enable;
 	}
 
-	if (volume->flags & (MD_CORRUPT | MD_PROBLEMATIC_SB)) {
+	if (volume->flags & MD_CORRUPT) {
 		LOG_EXIT_INT(enable);
 		return enable;
 	}
--- evms-2.3.3a/plugins/md/raid5_discover.c	2004-02-26 15:07:46.000000000 -0600
+++ evms-2.3.3b/plugins/md/raid5_discover.c	2004-05-19 18:39:53.000000000 -0500
@@ -633,30 +633,46 @@
 		LOG_EXIT_VOID();
 		return;
 	case 1:
+		if (vol->region && (md_is_region_active(vol->region) == TRUE))
+			break;
 		if (sb->active_disks != vol->active_disks) {
-			MESSAGE("Region %s : MD superblock has active_disks=%d, found %d.\n",
+			MESSAGE("WARNING: Region %s : MD superblock has active_disks=%d, found %d.\n",
 				vol->name, sb->active_disks, vol->active_disks);
 		}
 
 		if (sb->working_disks != vol->working_disks) {
-			MESSAGE("Region %s : MD superblock has working_disks=%d, found %d.\n",
+			MESSAGE("WARNING: Region %s : MD superblock has working_disks=%d, found %d.\n",
 				vol->name, sb->working_disks, vol->working_disks);
 		}
 
 		if (sb->failed_disks != vol->failed_disks) {
-			MESSAGE("Region %s : MD superblock has failed_disks=%d, found %d.\n",
+			MESSAGE("WARNING: Region %s : MD superblock has failed_disks=%d, found %d."
+				"  If another disk had been added to replace the failed disk,"
+				" it is safe to ignore this warning message.\n",
 				vol->name, sb->failed_disks, vol->failed_disks);
 		}
 
 		if (sb->spare_disks != vol->spare_disks) {
-			MESSAGE("Region %s : MD superblock has spare_disks=%d, found %d.\n",
+			MESSAGE("WARNING: Region %s : MD superblock has spare_disks=%d, found %d.\n",
 				vol->name, sb->spare_disks, vol->spare_disks);
 		}
 
 		if (sb->nr_disks != vol->nr_disks) {
-			MESSAGE("Region %s : MD superblock has nr_disks=%d, found %d.\n",
+			/* 
+			 * Note: Kernel MD driver allows creating an MD array with missing disk(s).
+			 * If this is the case, ignore the difference between sb->nr_disks and 
+			 * volume->nr_disks.
+			 */
+			if ((sb->nr_disks > vol->nr_disks) && 
+			    (sb->failed_disks == (sb->nr_disks - vol->nr_disks))) {
+				LOG_WARNING("[%s] : MD superblock has nr_disks=%d, found %d.\n"
+					"But we are ignoring the difference.\n",
+					vol->name, sb->nr_disks, vol->nr_disks);
+			} else {
+				MESSAGE("WARNING: Region %s : MD superblock has nr_disks=%d, found %d.\n",
 				vol->name, sb->nr_disks, vol->nr_disks);
 		}
+		}
 
 		if (vol->stale_disks) {
 			raid5_show_stale_disks(vol);
--- evms-2.3.3a/plugins/md/raid5_funcs.c	2003-11-11 15:58:33.000000000 -0600
+++ evms-2.3.3b/plugins/md/raid5_funcs.c	2004-05-19 18:42:49.000000000 -0500
@@ -298,10 +298,18 @@
 			goto out_free_mem;
 		} else {
 			if ((info.major != spare->dev_major) || (info.minor != spare->dev_minor)) {
-				MESSAGE("(%s) mismatch major/minor, kernel(%d:%d), spare(%d:%d)\n",
-					  spare->name, info.major, info.minor, spare->dev_major, spare->dev_minor);
-				rc = EINVAL;
-				goto out_free_mem;
+					MESSAGE("WARNING: Region:%s, Device:%s: Index:%d\n"
+						" There is a mismatch major/minor, Kernel MD driver has (%d:%d), EVMS has (%d:%d)."
+						"  However, if %s was created by another MD tool such as mdadm or raidtools,"
+						" the operation will succeed.\n",
+					  volume->name, spare->name, i,
+					  info.major, info.minor,
+					  spare->dev_major, spare->dev_minor,
+					  volume->name);
+				//rc = EINVAL;
+				//goto out_free_mem;
+				disk_info->major = info.major;
+				disk_info->minor = info.minor;
 			}
 		}
 
@@ -359,6 +367,7 @@
 	raid5_conf_t * conf = mdvol_to_conf(volume);
 	evms_md_disk_info_t *disk_info;
 	evms_md_ioctl_parm_t parm;
+	mdu_disk_info_t info;
 
 	LOG_ENTRY();
 
@@ -387,6 +396,25 @@
 			parm.disk_info = disk_info;
 			schedule_md_ioctl_pkg(volume, EVMS_MD_REMOVE, &parm, free_disk_info_post_ioctl);
 
+			info.number = i;
+			if (md_ioctl_get_disk_info(volume->region, &info) == 0) {
+				if ((info.major != faulty->dev_major) || (info.minor != faulty->dev_minor)) {
+					MESSAGE("WARNING: Region:%s, Device:%s: Index:%d\n"
+						" There is a mismatch major/minor, Kernel MD driver has (%d:%d), EVMS has (%d:%d)."
+						"  However, if %s was created by another MD tool such as mdadm or raidtools,"
+						" the operation will succeed.\n",
+						  volume->name, faulty->name, i,
+						  info.major, info.minor,
+						  faulty->dev_major, faulty->dev_minor,
+						  volume->name);
+					//rc = EINVAL;
+					//goto out_free_mem;
+					disk_info->major = info.major;
+					disk_info->minor = info.minor;
+			}
+				
+			}
+
 			md_remove_region_from_object(volume->region, volume->child_object[i]);
 			KILL_SECTORS(volume->child_object[i],
 				     MD_NEW_SIZE_SECTORS(volume->child_object[i]->size),
@@ -573,10 +601,10 @@
 		return ENODEV;
 	} else {
 		if ((info.major != active->dev_major) || (info.minor != active->dev_minor)) {
-			LOG_ERROR("(%s) mismatch major/minor, kernel(%d:%d), active(%d:%d)\n",
+			LOG_WARNING("(%s) mismatch major/minor, kernel(%d:%d), active(%d:%d)\n",
 				  active->name, info.major, info.minor, active->dev_major, active->dev_minor);
-			LOG_EXIT_INT(EINVAL);
-			return EINVAL;
+			//LOG_EXIT_INT(EINVAL);
+			//return EINVAL;
 		}
 	}
 
@@ -588,6 +616,8 @@
 	}
 
 	disk_info->number = i;
+	disk_info->major = info.major;
+	disk_info->minor = info.minor;
 	disk_info->object = active;
 	parm.disk_info = disk_info;
 	schedule_md_ioctl_pkg(volume, EVMS_MD_DEACTIVATE, &parm, mark_disk_faulty_post_ioctl);
--- evms-2.3.3a/plugins/md/raid5_mgr.c	2004-03-26 14:04:19.000000000 -0600
+++ evms-2.3.3b/plugins/md/raid5_mgr.c	2004-05-19 18:43:06.000000000 -0500
@@ -2310,6 +2310,11 @@
 		return enable;
 	}
 
+	if (md_can_stop_array(volume->region) == FALSE) {
+		LOG_EXIT_INT(enable);
+		return enable;
+	}
+
 	if (volume->flags & (MD_CORRUPT | MD_PROBLEMATIC_SB)) {
 
 		fia->info[*function_count].function = MD_RAID5_FUNCTION_FIX;
