From 11b391ece9fa284a151362537af093aa44883696 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Thu, 8 Sep 2011 13:05:31 +1000
Subject: [PATCH 56/56] Discourage large devices from being added to 0.90
 arrays.

0.90 arrays can only use up to 4TB per device.  So when a larger
device is added, complain a bit.  Still allow it if --force is given
as there could be a valid use.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 Grow.c        |    2 +-
 Incremental.c |    8 ++++----
 Manage.c      |   29 +++++++++++++++++++++++++----
 mdadm.c       |    3 ++-
 mdadm.h       |    2 +-
 5 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/Grow.c b/Grow.c
index 1aab113..048351d 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1893,7 +1893,7 @@ static int reshape_array(char *container, int fd, char *devname,
 	 */
 	if (devlist)
 		Manage_subdevs(devname, fd, devlist, !quiet,
-			       0,NULL);
+			       0,NULL, 0);
 
 	if (reshape.backup_blocks == 0) {
 		/* No restriping needed, but we might need to impose
diff --git a/Incremental.c b/Incremental.c
index 09cdd9b..791ad85 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -1035,7 +1035,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
 			close(dfd);
 			*dfdp = -1;
 			rv =  Manage_subdevs(chosen->sys_name, mdfd, &devlist,
-					     -1, 0, NULL);
+					     -1, 0, NULL, 0);
 			close(mdfd);
 		}
 		if (verbose > 0) {
@@ -1666,15 +1666,15 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
 				if (subfd >= 0) {
 					Manage_subdevs(memb->dev, subfd,
 						       &devlist, verbose, 0,
-						       NULL);
+						       NULL, 0);
 					close(subfd);
 				}
 			}
 		free_mdstat(mdstat);
 	} else
-		Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0, NULL);
+		Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0, NULL, 0);
 	devlist.disposition = 'r';
-	rv = Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0, NULL);
+	rv = Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0, NULL, 0);
 	close(mdfd);
 	free_mdstat(ent);
 	return rv;
diff --git a/Manage.c b/Manage.c
index 66d6978..1b2b75a 100644
--- a/Manage.c
+++ b/Manage.c
@@ -371,7 +371,7 @@ int Manage_resize(char *devname, int fd, long long size, int raid_disks)
 
 int Manage_subdevs(char *devname, int fd,
 		   struct mddev_dev *devlist, int verbose, int test,
-		   char *update)
+		   char *update, int force)
 {
 	/* do something to each dev.
 	 * devmode can be
@@ -632,6 +632,27 @@ int Manage_subdevs(char *devname, int fd,
 				continue;
 			}
 
+			if (tst->ss->validate_geometry(
+				    tst, array.level, array.layout,
+				    array.raid_disks, NULL,
+				    ldsize >> 9, NULL, NULL, 0) == 0) {
+				if (!force) {
+					fprintf(stderr, Name
+						": %s is larger than %s can "
+						"effectively use.\n"
+						"       Add --force is you "
+						"really wan to add this device.\n",
+						add_dev, devname);
+					close(tfd);
+					return 1;
+				}
+				fprintf(stderr, Name
+					": %s is larger than %s can "
+					"effectively use.\n"
+					"       Adding anyway as --force "
+					"was given.\n",
+					add_dev, devname);
+			}
 			if (!tst->ss->external &&
 			    array.major_version == 0 &&
 			    md_get_version(fd)%100 < 2) {
@@ -1188,9 +1209,9 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid)
 	sprintf(devname, "%d:%d", major(devid), minor(devid));
 
 	devlist.disposition = 'r';
-	if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL) == 0) {
+	if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL, 0) == 0) {
 		devlist.disposition = 'a';
-		if (Manage_subdevs(to_devname, fd1, &devlist, -1, 0, NULL) == 0) {
+		if (Manage_subdevs(to_devname, fd1, &devlist, -1, 0, NULL, 0) == 0) {
 			/* make sure manager is aware of changes */
 			ping_manager(to_devname);
 			ping_manager(from_devname);
@@ -1198,7 +1219,7 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid)
 			close(fd2);
 			return 1;
 		}
-		else Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL);
+		else Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL, 0);
 	}
 	close(fd1);
 	close(fd2);
diff --git a/mdadm.c b/mdadm.c
index fb51051..4b817ab 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -609,6 +609,7 @@ int main(int argc, char *argv[])
 		case O(ASSEMBLE,Force): /* force assembly */
 		case O(MISC,'f'): /* force zero */
 		case O(MISC,Force): /* force zero */
+		case O(MANAGE,Force): /* add device which is too large */
 			force=1;
 			continue;
 
@@ -1202,7 +1203,7 @@ int main(int argc, char *argv[])
 		if (!rv && devs_found>1)
 			rv = Manage_subdevs(devlist->devname, mdfd,
 					    devlist->next, verbose-quiet, test,
-					    update);
+					    update, force);
 		if (!rv && readonly < 0)
 			rv = Manage_ro(devlist->devname, mdfd, readonly);
 		if (!rv && runstop)
diff --git a/mdadm.h b/mdadm.h
index 8bd0077..d616966 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1010,7 +1010,7 @@ extern int Manage_runstop(char *devname, int fd, int runstop, int quiet);
 extern int Manage_resize(char *devname, int fd, long long size, int raid_disks);
 extern int Manage_subdevs(char *devname, int fd,
 			  struct mddev_dev *devlist, int verbose, int test,
-			  char *update);
+			  char *update, int force);
 extern int autodetect(void);
 extern int Grow_Add_device(char *devname, int fd, char *newdev);
 extern int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int write_behind, int force);
-- 
1.7.6.1

