Fix problem with 0.9 metadata and > 2TB drives + systemd script fix

Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
This commit is contained in:
Jes Sorensen 2011-11-09 17:58:29 +01:00
parent 06636a8bfc
commit d01dbca186
5 changed files with 362 additions and 2 deletions

View File

@ -0,0 +1,163 @@
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 2/3] 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.4

View File

@ -0,0 +1,76 @@
From 01619b481883926f13da2b1b88f3125359a6a08b Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Thu, 8 Sep 2011 12:20:36 +1000
Subject: [PATCH 1/3] Fix component size checks in validate_super0.
A 0.90 array can use at most 4TB of each device - 2TB between
2.6.39 and 3.1 due to a kernel bug.
The test for this in validate_super0 is very wrong. 'size' is sectors
and the number it is compared against is just confusing.
So fix it all up and correct the spelling of terabytes and remove
a second redundant test on 'size'.
Signed-off-by: NeilBrown <neilb@suse.de>
---
super0.c | 14 ++++++++++----
util.c | 2 +-
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/super0.c b/super0.c
index 4a165f9..62c4ff0 100644
--- a/super0.c
+++ b/super0.c
@@ -1115,6 +1115,13 @@ static int validate_geometry0(struct supertype *st, int level,
{
unsigned long long ldsize;
int fd;
+ unsigned int tbmax = 4;
+
+ /* prior to linux 3.1, a but limits usable device size to 2TB.
+ * It was introduced in 2.6.29, but we won't worry about that detail
+ */
+ if (get_linux_version() < 3001000)
+ tbmax = 2;
if (level == LEVEL_CONTAINER) {
if (verbose)
@@ -1127,9 +1134,10 @@ static int validate_geometry0(struct supertype *st, int level,
MD_SB_DISKS);
return 0;
}
- if (size > (0x7fffffffULL<<9)) {
+ if (size >= tbmax * 1024*1024*1024*2ULL) {
if (verbose)
- fprintf(stderr, Name ": 0.90 metadata supports at most 2 terrabytes per device\n");
+ fprintf(stderr, Name ": 0.90 metadata supports at most "
+ "%d terabytes per device\n", tbmax);
return 0;
}
if (chunk && *chunk == UnSet)
@@ -1154,8 +1162,6 @@ static int validate_geometry0(struct supertype *st, int level,
if (ldsize < MD_RESERVED_SECTORS * 512)
return 0;
- if (size > (0x7fffffffULL<<9))
- return 0;
*freesize = MD_NEW_SIZE_SECTORS(ldsize >> 9);
return 1;
}
diff --git a/util.c b/util.c
index e68d55f..0ea7e0d 100644
--- a/util.c
+++ b/util.c
@@ -640,7 +640,7 @@ char *human_size(long long bytes)
* We allow upto 2048Megabytes before converting to
* gigabytes, as that shows more precision and isn't
* too large a number.
- * Terrabytes are not yet handled.
+ * Terabytes are not yet handled.
*/
if (bytes < 5000*1024)
--
1.7.6.4

View File

@ -0,0 +1,77 @@
From 20a4675688e0384a1b4eac61b05f60fbf7747df9 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Thu, 8 Sep 2011 13:08:51 +1000
Subject: [PATCH 3/3] Grow: refuse to grow a 0.90 array beyond 2TB
A kernel bug makes handling for arrays using more than 2TB per device
incorrect, and the kernel doesn't stop an array from growing beyond
any limit.
This is fixed in 3.1
So prior to 3.1, make sure not to ask for an array to grow bigger than
2TB per device.
Signed-off-by: NeilBrown <neilb@suse.de>
---
Grow.c | 37 ++++++++++++++++++++++++++++++++++---
1 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/Grow.c b/Grow.c
index 048351d..17d14b6 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1446,6 +1446,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
/* ========= set size =============== */
if (size >= 0 && (size == 0 || size != array.size)) {
long long orig_size = get_component_size(fd)/2;
+ long long min_csize;
struct mdinfo *mdi;
if (orig_size == 0)
@@ -1461,10 +1462,40 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
/* Update the size of each member device in case
* they have been resized. This will never reduce
* below the current used-size. The "size" attribute
- * understand '0' to mean 'max'.
+ * understands '0' to mean 'max'.
*/
- for (mdi = sra->devs; mdi; mdi = mdi->next)
- sysfs_set_num(sra, mdi, "size", size);
+ min_csize = 0;
+ for (mdi = sra->devs; mdi; mdi = mdi->next) {
+ if (sysfs_set_num(sra, mdi, "size", size) < 0)
+ break;
+ if (array.not_persistent == 0 &&
+ array.major_version == 0 &&
+ get_linux_version() < 3001000) {
+ /* Dangerous to allow size to exceed 2TB */
+ unsigned long long csize;
+ if (sysfs_get_ll(sra, mdi, "size", &csize) == 0) {
+ if (csize >= 2ULL*1024*1024*1024)
+ csize = 2ULL*1024*1024*1024;
+ if ((min_csize == 0 || (min_csize
+ > (long long)csize)))
+ min_csize = csize;
+ }
+ }
+ }
+ if (min_csize && size > min_csize) {
+ fprintf(stderr, Name ": Cannot safely make this array "
+ "use more than 2TB per device on this kernel.\n");
+ rv = 1;
+ goto release;
+ }
+ if (min_csize && size == 0) {
+ /* Don't let the kernel choose a size - it will get
+ * it wrong
+ */
+ fprintf(stderr, Name ": Limited v0.90 array to "
+ "2TB per device\n");
+ size = min_csize;
+ }
array.size = size;
if (array.size != size) {
--
1.7.6.4

View File

@ -0,0 +1,29 @@
From 9c8c121881769c9ce77fd7d981608c976aac8b5b Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Thu, 20 Oct 2011 13:14:26 +1100
Subject: [PATCH] super0: fix overflow when checking max size.
We need to force multiplication to use ULL before they
get to big, else it overflows. So move the "2ULL" to the start.
Signed-off-by: NeilBrown <neilb@suse.de>
---
super0.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/super0.c b/super0.c
index 3061ecf..f3d0c07 100644
--- a/super0.c
+++ b/super0.c
@@ -1142,7 +1142,7 @@ static int validate_geometry0(struct supertype *st, int level,
MD_SB_DISKS);
return 0;
}
- if (size >= tbmax * 1024*1024*1024*2ULL) {
+ if (size >= tbmax * 2ULL*1024*1024*1024) {
if (verbose)
fprintf(stderr, Name ": 0.90 metadata supports at most "
"%d terabytes per device\n", tbmax);
--
1.7.6.4

View File

@ -1,7 +1,7 @@
Summary: The mdadm program controls Linux md devices (software RAID arrays) Summary: The mdadm program controls Linux md devices (software RAID arrays)
Name: mdadm Name: mdadm
Version: 3.2.2 Version: 3.2.2
Release: 13%{?dist} Release: 14%{?dist}
Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}.tar.bz2 Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}.tar.bz2
Source1: mdmonitor.init Source1: mdmonitor.init
Source2: raid-check Source2: raid-check
@ -21,6 +21,10 @@ Patch6: mdadm-3.2.2-resync-does-not-continue-after-auto.patch
Patch7: mdadm-3.2.2-Remove-race-for-starting-container-devices.patch Patch7: mdadm-3.2.2-Remove-race-for-starting-container-devices.patch
Patch8: mdadm-3.2.2-no-sysfs-launch-container.patch Patch8: mdadm-3.2.2-no-sysfs-launch-container.patch
Patch9: mdadm-3.2.2-hold-lock-during-assemble.patch Patch9: mdadm-3.2.2-hold-lock-during-assemble.patch
Patch10: mdadm-3.2.2-Fix-component-size-checks-in-validate_super0.patch
Patch11: mdadm-3.2.2-Discourage-large-devices-from-being-added-to-0.90-ar.patch
Patch12: mdadm-3.2.2-Grow-refuse-to-grow-a-0.90-array-beyond-2TB.patch
Patch13: mdadm-3.2.2-super0-fix-overflow-when-checking-max-size.patch
Patch19: mdadm-3.1.3-udev.patch Patch19: mdadm-3.1.3-udev.patch
Patch20: mdadm-2.5.2-static.patch Patch20: mdadm-2.5.2-static.patch
URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/ URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/
@ -65,6 +69,10 @@ is not used as the system init process.
%patch7 -p1 -b .container %patch7 -p1 -b .container
%patch8 -p1 -b .sysfs %patch8 -p1 -b .sysfs
%patch9 -p1 -b .assemble %patch9 -p1 -b .assemble
%patch10 -p1 -b .component
%patch11 -p1 -b .discourage
%patch12 -p1 -b .grow
%patch13 -p1 -b .overflow
%patch19 -p1 -b .udev %patch19 -p1 -b .udev
%patch20 -p1 -b .static %patch20 -p1 -b .static
@ -102,7 +110,7 @@ fi
%preun %preun
if [ $1 = 0 ]; then if [ $1 = 0 ]; then
/bin/systemctl --no-reload mdmonitor.service > /dev/null 2>&1 || : /bin/systemctl --no-reload disable mdmonitor.service > /dev/null 2>&1 || :
/bin/systemctl stop mdmonitor.service > /dev/null 2>&1 || : /bin/systemctl stop mdmonitor.service > /dev/null 2>&1 || :
fi fi
@ -139,6 +147,13 @@ fi
%{_initrddir}/* %{_initrddir}/*
%changelog %changelog
* Wed Nov 9 2011 Jes Sorensen <Jes.Sorensen@redhat.com> - 3.2.2-14
- Backport upstream fixes to prevent growing v0.90 metadata raid out
of supported size.
- Add missing 'disable' argument to systemctl in preun script
- Resolves: bz735306 (Fedora 15) bz748731 (Fedora 16) bz748732 (rawhide),
Resolves: bz751716
* Wed Oct 26 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.2.2-13 * Wed Oct 26 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.2.2-13
- Rebuilt for glibc bug#747377 - Rebuilt for glibc bug#747377