Upgrade to mdadm-3.2.4

Resolves: bz820534 (rawhide) bz820527 (f17) bz820531 (f16) bz820532 (f15)

Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
This commit is contained in:
Jes Sorensen 2012-05-10 13:08:42 +02:00
parent 252d3d6557
commit 76ff773cd6
71 changed files with 35 additions and 6252 deletions

View File

@ -1,21 +1,5 @@
--- mdadm-3.2.1/Makefile.static 2011-03-27 22:31:20.000000000 -0400 --- mdadm-3.2.1/Makefile.static 2011-03-27 22:31:20.000000000 -0400
+++ mdadm-3.2.1/Makefile 2011-03-28 10:16:55.277900184 -0400 +++ mdadm-3.2.1/Makefile 2011-03-28 10:16:55.277900184 -0400
@@ -68,11 +68,11 @@ CONFFILEFLAGS = -DCONFFILE=\"$(CONFFILE)
# pivotroot from early boot to late boot.
# /dev is an odd place to put this, but it is the only directory that
# meets the requirements.
-MAP_DIR=/dev/.mdadm
-MAP_FILE = map
-MDMON_DIR = /dev/.mdadm
+MAP_DIR=/dev/md
+MAP_FILE = md-device-map
+MDMON_DIR = /dev/md
# place for autoreplace cookies
-FAILED_SLOTS_DIR = /dev/.mdadm/failed-slots
+FAILED_SLOTS_DIR = /dev/md/failed-slots
DIRFLAGS = -DMAP_DIR=\"$(MAP_DIR)\" -DMAP_FILE=\"$(MAP_FILE)\"
DIRFLAGS += -DMDMON_DIR=\"$(MDMON_DIR)\"
DIRFLAGS += -DFAILED_SLOTS_DIR=\"$(FAILED_SLOTS_DIR)\"
@@ -238,16 +238,16 @@ install : mdadm mdmon install-man instal @@ -238,16 +238,16 @@ install : mdadm mdmon install-man instal
$(INSTALL) -D $(STRIP) -m 755 mdmon $(DESTDIR)$(BINDIR)/mdmon $(INSTALL) -D $(STRIP) -m 755 mdmon $(DESTDIR)$(BINDIR)/mdmon

View File

@ -1,101 +0,0 @@
From 08ca2adffffeb3bfda3cafababfc26706a60463b Mon Sep 17 00:00:00 2001
From: Jes Sorensen <Jes.Sorensen@redhat.com>
Date: Wed, 25 Jan 2012 15:18:02 +0100
Subject: [PATCH 2/4] Add --offroot argument to mdadm
When --offroot is specified, mdadm will change the first character of
argv[0] to '@'. This is used to signal to systemd that mdadm was
launched from initramfs and should not be shut down before returning
to the initramfs.
Acked-by: Doug Ledford <dledford@redhat.com>
Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
ReadMe.c | 5 +++++
mdadm.8.in | 12 ++++++++++++
mdadm.c | 9 +++++++++
mdadm.h | 1 +
4 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/ReadMe.c b/ReadMe.c
index 9aa798b..a60e11b 100644
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -111,6 +111,7 @@ struct option long_options[] = {
{"kill-subarray", 1, 0, KillSubarray},
{"update-subarray", 1, 0, UpdateSubarray},
{"udev-rules", 2, 0, UdevRules},
+ {"offroot", 0, 0, OffRootOpt},
/* synonyms */
{"monitor", 0, 0, 'F'},
@@ -268,6 +269,10 @@ char OptionHelp[] =
" --query -Q : Display general information about how a\n"
" device relates to the md driver\n"
" --auto-detect : Start arrays auto-detected by the kernel\n"
+" --offroot : Set first character of argv[0] to @ to indicate the\n"
+" application was launched from initrd/initramfs and\n"
+" should not be shutdown by systemd as part of the\n"
+" regular shutdown process.\n"
;
/*
"\n"
diff --git a/mdadm.8.in b/mdadm.8.in
index 27be110..4f06a88 100644
--- a/mdadm.8.in
+++ b/mdadm.8.in
@@ -255,6 +255,18 @@ Avoid printing purely informative messages. With this,
will be silent unless there is something really important to report.
.TP
+.BR \-\-offroot
+Set first character of argv[0] to @ to indicate mdadm was launched
+from initrd/initramfs and should not be shutdown by systemd as part of
+the regular shutdown process. This option is normally only used by
+the system's initscripts. Please see here for more details on how
+systemd handled argv[0]:
+.IP
+.B http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons
+.PP
+
+
+.TP
.BR \-f ", " \-\-force
Be more forceful about certain operations. See the various modes for
the exact meaning of this option in different contexts.
diff --git a/mdadm.c b/mdadm.c
index f07fac2..78f28d5 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -174,6 +174,15 @@ int main(int argc, char *argv[])
homehost = optarg;
continue;
+ /*
+ * --offroot sets first char of argv[0] to @. This is used
+ * by systemd to signal that the tast was launched from
+ * initrd/initramfs and should be preserved during shutdown
+ */
+ case OffRootOpt:
+ argv[0][0] = '@';
+ continue;
+
case ':':
case '?':
fputs(Usage, stderr);
diff --git a/mdadm.h b/mdadm.h
index 381ef86..fec93aa 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -321,6 +321,7 @@ enum special_options {
UdevRules,
FreezeReshape,
Continue,
+ OffRootOpt,
};
/* structures read from config file */
--
1.7.8.4

View File

@ -1,79 +0,0 @@
From da827518c1f062e7d49433691d33e103525f9d6a Mon Sep 17 00:00:00 2001
From: Jes Sorensen <Jes.Sorensen@redhat.com>
Date: Wed, 25 Jan 2012 15:18:03 +0100
Subject: [PATCH 3/4] Add --offroot argument to mdmon
Acked-by: Doug Ledford <dledford@redhat.com>
Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
mdmon.8 | 12 +++++++++++-
mdmon.c | 8 ++++++++
2 files changed, 19 insertions(+), 1 deletions(-)
diff --git a/mdmon.8 b/mdmon.8
index 8c1ce5f..a9178b6 100644
--- a/mdmon.8
+++ b/mdmon.8
@@ -5,7 +5,7 @@ mdmon \- monitor MD external metadata arrays
.SH SYNOPSIS
-.BI mdmon " [--all] [--takeover] CONTAINER"
+.BI mdmon " [--all] [--takeover] [--offroot] CONTAINER"
.SH OVERVIEW
The 2.6.27 kernel brings the ability to support external metadata arrays.
@@ -165,6 +165,16 @@ argument is over-written with the name of the container. To allow for
containers with names longer than 5 characters, this argument can be
arbitrarily extended, e.g. to
.BR \-\-all-active-arrays .
+.TP
+.BR \-\-offroot
+Set first character of argv[0] to @ to indicate mdmon was launched
+from initrd/initramfs and should not be shutdown by systemd as part of
+the regular shutdown process. This option is normally only used by
+the system's initscripts. Please see here for more details on how
+systemd handled argv[0]:
+.IP
+.B http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons
+.PP
.PP
Note that
diff --git a/mdmon.c b/mdmon.c
index a65c4a4..2093476 100644
--- a/mdmon.c
+++ b/mdmon.c
@@ -272,6 +272,10 @@ void usage(void)
" --help -h : This message\n"
" --all : All devices\n"
" --takeover -t : Takeover container\n"
+" --offroot : Set first character of argv[0] to @ to indicate the\n"
+" application was launched from initrd/initramfs and\n"
+" should not be shutdown by systemd as part of the\n"
+" regular shutdown process.\n"
);
exit(2);
}
@@ -291,6 +295,7 @@ int main(int argc, char *argv[])
{"all", 0, NULL, 'a'},
{"takeover", 0, NULL, 't'},
{"help", 0, NULL, 'h'},
+ {"offroot", 0, NULL, OffRootOpt},
{NULL, 0, NULL, 0}
};
@@ -304,6 +309,9 @@ int main(int argc, char *argv[])
container_name = optarg;
takeover = 1;
break;
+ case OffRootOpt:
+ argv[0][0] = '@';
+ break;
case 'h':
default:
usage();
--
1.7.8.4

View File

@ -1,66 +0,0 @@
From fbdef49811c9e2b54e2064d9af68cfffa77c6e77 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Wed, 4 Apr 2012 14:00:42 +1000
Subject: [PATCH] Bitmap_offset is a signed number
As the bitmap can be before the superblock, bitmap_offset is signed.
But some of the code didn't honour that :-(
Signed-off-by: NeilBrown <neilb@suse.de>
---
mdadm.h | 2 +-
super1.c | 4 ++--
sysfs.c | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/mdadm.h b/mdadm.h
index 941cffa..9f58800 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -211,7 +211,7 @@ struct mdinfo {
unsigned long long recovery_start; /* per-device rebuild position */
#define MaxSector (~0ULL) /* resync/recovery complete position */
};
- unsigned long bitmap_offset; /* 0 == none, 1 == a file */
+ long bitmap_offset; /* 0 == none, 1 == a file */
unsigned long safe_mode_delay; /* ms delay to mark clean */
int new_level, delta_disks, new_layout, new_chunk;
int errors;
diff --git a/super1.c b/super1.c
index 20f4c86..2770a7f 100644
--- a/super1.c
+++ b/super1.c
@@ -620,7 +620,7 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
info->data_offset = __le64_to_cpu(sb->data_offset);
info->component_size = __le64_to_cpu(sb->size);
if (sb->feature_map & __le32_to_cpu(MD_FEATURE_BITMAP_OFFSET))
- info->bitmap_offset = __le32_to_cpu(sb->bitmap_offset);
+ info->bitmap_offset = (long)__le32_to_cpu(sb->bitmap_offset);
info->disk.major = 0;
info->disk.minor = 0;
@@ -1636,7 +1636,7 @@ add_internal_bitmap1(struct supertype *st,
offset = -room;
}
- sb->bitmap_offset = __cpu_to_le32(offset);
+ sb->bitmap_offset = (long)__cpu_to_le32(offset);
sb->feature_map = __cpu_to_le32(__le32_to_cpu(sb->feature_map)
| MD_FEATURE_BITMAP_OFFSET);
diff --git a/sysfs.c b/sysfs.c
index cddabae..a1007cf 100644
--- a/sysfs.c
+++ b/sysfs.c
@@ -226,7 +226,7 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options)
else if (strncmp(buf, "none", 4) == 0)
sra->bitmap_offset = 0;
else if (buf[0] == '+')
- sra->bitmap_offset = strtoul(buf+1, NULL, 10);
+ sra->bitmap_offset = strtol(buf+1, NULL, 10);
else
goto abort;
}
--
1.7.7.6

View File

@ -1,30 +0,0 @@
From 111e9fdaa8a5084bd329819a0906a685b2271c0d Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Tue, 7 Feb 2012 15:03:19 +0100
Subject: [PATCH 03/12] FIX: Array is not run when expansion disks are added
When added disk is disk added by expansion and this is last disk added
to array, assemble_container_content() will not even try to run such array.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Assemble.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Assemble.c b/Assemble.c
index ad4eb9c..13adfc3 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -1557,7 +1557,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
working++;
} else if (errno == EEXIST)
preexist++;
- if (working == 0)
+ if (working + expansion == 0)
return 1;/* Nothing new, don't try to start */
map_update(&map, fd2devnum(mdfd),
--
1.7.4.4

View File

@ -1,85 +0,0 @@
From 4aecb54a211a77aa0589aa2abb8acd992ae8795a Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Fri, 13 Apr 2012 16:52:08 +0200
Subject: [PATCH 14/14] FIX: Assembled second array is in read only state
during reshape
When arrays using external metadata are assembled, and one of array
in container is under reshape, second array will remain in read only
state (not auto read only). It is caused by array fact that array
is frozen and mdmon doesn't has opportunity to switch array in r/w mode.
Freezing not reshaped array just after it is being assembled allows mdmon
to enable it for writing.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Assemble.c | 29 +++++++++++++++++++++--------
1 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/Assemble.c b/Assemble.c
index 23695e7..080993d 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -1558,6 +1558,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
int expansion = 0;
struct map_ent *map = NULL;
int old_raid_disks;
+ int start_reshape;
sysfs_init(content, mdfd, 0);
@@ -1569,7 +1570,17 @@ int assemble_container_content(struct supertype *st, int mdfd,
return 1;
}
- if (st->ss->external && content->recovery_blocked)
+ /* There are two types of reshape: container wide or sub-array specific
+ * Check if metadata requests blocking container wide reshapes
+ */
+ start_reshape = (content->reshape_active &&
+ !((content->reshape_active == CONTAINER_RESHAPE) &&
+ (content->array.state & (1<<MD_SB_BLOCK_CONTAINER_RESHAPE))));
+
+ /* Block subarray here if it is under reshape now
+ * Do not allow for any changes in this array
+ */
+ if (st->ss->external && content->recovery_blocked && start_reshape)
block_subarray(content);
if (sra)
@@ -1595,14 +1606,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
(working + preexist + expansion) >=
content->array.working_disks) {
int err;
- int start_reshape;
- /* There are two types of reshape: container wide or sub-array specific
- * Check if metadata requests blocking container wide reshapes
- */
- start_reshape = (content->reshape_active &&
- !((content->reshape_active == CONTAINER_RESHAPE) &&
- (content->array.state & (1<<MD_SB_BLOCK_CONTAINER_RESHAPE))));
if (start_reshape) {
int spare = content->array.raid_disks + expansion;
if (restore_backup(st, content,
@@ -1646,6 +1650,15 @@ int assemble_container_content(struct supertype *st, int mdfd,
}
if (!err)
sysfs_set_safemode(content, content->safe_mode_delay);
+
+ /* Block subarray here if it is not reshaped now
+ * It has be blocked a little later to allow mdmon to switch in
+ * in to R/W state
+ */
+ if (st->ss->external && content->recovery_blocked &&
+ !start_reshape)
+ block_subarray(content);
+
if (verbose >= 0) {
if (err)
fprintf(stderr, Name
--
1.7.7.6

View File

@ -1,63 +0,0 @@
From d7592845d4a9b885af7121f8ff6ba4f77610cd32 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Thu, 16 Feb 2012 14:16:04 +0100
Subject: [PATCH 15/15] FIX: Changes in '0' case for reshape position
verification
Reading sysfs entry that is '0' long should cause an error.
Reshape position cannot be empty.
Absence of reshape position should be ignored. It is possible
that we are about raid0 reshape continuation and it is before takeover.
This means that according metadata (changed by mdmon) it should be reshaped
but md knows nothing about it at this moment. Reshape continuation
in reshape_array() will change it to raid4 and reshape position appears
in sysfs.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
---
Grow.c | 12 ++++++++++--
1 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/Grow.c b/Grow.c
index 53a7cad..239b50d 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1876,9 +1876,12 @@ static int verify_reshape_position(struct mdinfo *info, int level)
{
int ret_val = 0;
char buf[40];
+ int rv;
/* read sync_max, failure can mean raid0 array */
- if (sysfs_get_str(info, NULL, "sync_max", buf, 40) > 0) {
+ rv = sysfs_get_str(info, NULL, "sync_max", buf, 40);
+
+ if (rv > 0) {
char *ep;
unsigned long long position = strtoull(buf, &ep, 0);
@@ -1906,6 +1909,11 @@ static int verify_reshape_position(struct mdinfo *info, int level)
ret_val = 1;
}
}
+ } else if (rv == 0) {
+ /* for valid sysfs entry, 0-length content
+ * should be indicated as error
+ */
+ ret_val = -1;
}
return ret_val;
@@ -3975,7 +3983,7 @@ int Grow_continue_command(char *devname, int fd,
* correct position
*/
if (verify_reshape_position(content,
- map_name(pers, mdstat->level)) <= 0) {
+ map_name(pers, mdstat->level)) < 0) {
ret_val = 1;
goto Grow_continue_command_exit;
}
--
1.7.4.4

View File

@ -1,62 +0,0 @@
From 65a9798b58b4e4de0157043e2b30a738c27eff43 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Fri, 13 Apr 2012 16:52:03 +0200
Subject: [PATCH 09/14] FIX: Detect error and rollback metadata
Some setting size error cases were not detected.
When error occurs, stop setting new size action and rollback metadata
changes.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Grow.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/Grow.c b/Grow.c
index 86d1020..1b45199 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1665,9 +1665,12 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
* understands '0' to mean 'max'.
*/
min_csize = 0;
+ rv = 0;
for (mdi = sra->devs; mdi; mdi = mdi->next) {
- if (sysfs_set_num(sra, mdi, "size", size) < 0)
+ if (sysfs_set_num(sra, mdi, "size", size) < 0) {
+ rv = 1;
break;
+ }
if (array.not_persistent == 0 &&
array.major_version == 0 &&
get_linux_version() < 3001000) {
@@ -1682,11 +1685,16 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
}
}
}
+ if (rv) {
+ fprintf(stderr, Name ": Cannot set size on "
+ "array members.\n");
+ goto size_change_error;
+ }
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;
+ goto size_change_error;
}
if (min_csize && size == 0) {
/* Don't let the kernel choose a size - it will get
@@ -1748,6 +1756,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
ioctl(fd, GET_ARRAY_INFO, &array);
}
+size_change_error:
if (rv != 0) {
int err = errno;
--
1.7.7.6

View File

@ -1,50 +0,0 @@
From 1ca90aa6484a6f5d4fdd6122ad1d2015209bd8e0 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Thu, 9 Feb 2012 12:38:15 +1100
Subject: [PATCH 12/12] FIX: Do not try to (continue) reshape using inactive
array
When one of arrays is inactive, do not try to continue reshape
on this array. Just skip it.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Grow.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/Grow.c b/Grow.c
index 61adefa..53a7cad 100644
--- a/Grow.c
+++ b/Grow.c
@@ -2626,6 +2626,13 @@ int reshape_container(char *container, char *devname,
devname2devnum(container));
if (!mdstat)
continue;
+ if (mdstat->active == 0) {
+ fprintf(stderr, Name ": Skipping inactive "
+ "array md%i.\n", mdstat->devnum);
+ free_mdstat(mdstat);
+ mdstat = NULL;
+ continue;
+ }
break;
}
if (!content)
@@ -3922,6 +3929,13 @@ int Grow_continue_command(char *devname, int fd,
mdstat = mdstat_by_subdev(array, container_dev);
if (!mdstat)
continue;
+ if (mdstat->active == 0) {
+ fprintf(stderr, Name ": Skipping inactive "
+ "array md%i.\n", mdstat->devnum);
+ free_mdstat(mdstat);
+ mdstat = NULL;
+ continue;
+ }
break;
}
if (!content) {
--
1.7.4.4

View File

@ -1,84 +0,0 @@
From 44f6f18113b1764a9d1234d3ff9a6bac968b03b8 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Fri, 13 Apr 2012 16:52:01 +0200
Subject: [PATCH 07/14] FIX: Extend size of raid0 array
For raid0, takeover operation is required for size change.
Add takeover to degraded raid4 before size change and back to raid0 after.
Array information has to be read again from md after takeover.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Grow.c | 35 +++++++++++++++++++++++++++++++++++
1 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/Grow.c b/Grow.c
index 8c7bafc..e8f6554 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1626,6 +1626,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
long long orig_size = get_component_size(fd)/2;
long long min_csize;
struct mdinfo *mdi;
+ int raid0_takeover = 0;
if (orig_size == 0)
orig_size = array.size;
@@ -1674,6 +1675,28 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
"2TB per device\n");
size = min_csize;
}
+ if (st->ss->external) {
+ if (sra->array.level == 0) {
+ rv = sysfs_set_str(sra, NULL, "level",
+ "raid5");
+ if (!rv) {
+ raid0_takeover = 1;
+ /* get array parametes after takeover
+ * to chane one parameter at time only
+ */
+ rv = ioctl(fd, GET_ARRAY_INFO, &array);
+ }
+ }
+ /* make sure mdmon is
+ * aware of the new level */
+ if (!mdmon_running(st->container_dev))
+ start_mdmon(st->container_dev);
+ ping_monitor(container);
+ if (mdmon_running(st->container_dev) &&
+ st->update_tail == NULL)
+ st->update_tail = &st->updates;
+ }
+
array.size = size;
if (array.size != size) {
/* got truncated to 32bit, write to
@@ -1686,12 +1709,24 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
rv = -1;
} else {
rv = ioctl(fd, SET_ARRAY_INFO, &array);
+
/* manage array size when it is managed externally
*/
if ((rv == 0) && st->ss->external)
rv = set_array_size(st, sra, sra->text_version);
}
+ if (raid0_takeover) {
+ /* do not recync non-existing parity,
+ * we will drop it anyway
+ */
+ sysfs_set_str(sra, NULL, "sync_action", "idle");
+ /* go back to raid0, drop parity disk
+ */
+ sysfs_set_str(sra, NULL, "level", "raid0");
+ ioctl(fd, GET_ARRAY_INFO, &array);
+ }
+
if (rv != 0) {
int err = errno;
--
1.7.7.6

View File

@ -1,35 +0,0 @@
From 5d1c7cdaca575d8a32a7a82517d88e2099f6a213 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Thu, 12 Jan 2012 08:12:39 +0100
Subject: [PATCH] FIX: External metadata sometimes is not updated
External metadata sometimes is not updated.
It can be observed during 2 raid0 arrays Capacity Expansion.
New array size is not set, because metadata is not updated and on the reshape
end mdadm doesn't read new array size from metadata.
This happens when mdmon finishes his work (due to takeover to raid0),
before all metadata updates are processed.
Make sure that all updates are flushed to disk before executing takeover.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Grow.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/Grow.c b/Grow.c
index b2c1360..89f563c 100644
--- a/Grow.c
+++ b/Grow.c
@@ -2396,6 +2396,7 @@ started:
/* Re-load the metadata as much could have changed */
int cfd = open_dev(st->container_dev);
if (cfd >= 0) {
+ ping_manager(container);
ping_monitor(container);
st->ss->free_super(st);
st->ss->load_container(st, cfd, container);
--
1.7.4.4

View File

@ -1,38 +0,0 @@
From 92d49ecfaabcd015cf9957a0863996eaa5755747 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Tue, 7 Feb 2012 15:03:03 +0100
Subject: [PATCH 01/12] FIX: NULL pointer to strdup() can be passed
When result from strchr() is NULL and it is assigned to subarray,
NULL pointer can be passed to strdup() function and coredump file
is generated.
Subarray is checked for NULL pointer, so it is assumed that it can
be NULL at this moment.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
util.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/util.c b/util.c
index e5f7a20..7abbff7 100644
--- a/util.c
+++ b/util.c
@@ -966,9 +966,10 @@ struct supertype *super_by_fd(int fd, char **subarrayp)
char *dev = verstr+1;
subarray = strchr(dev, '/');
- if (subarray)
+ if (subarray) {
*subarray++ = '\0';
- subarray = strdup(subarray);
+ subarray = strdup(subarray);
+ }
container = devname2devnum(dev);
if (sra)
sysfs_free(sra);
--
1.7.4.4

View File

@ -1,50 +0,0 @@
From 7e7e9a4d72323fe0298c9f5741245b0f11165a31 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Fri, 13 Apr 2012 16:52:02 +0200
Subject: [PATCH 08/14] FIX: Respect metadata size limitations
When reshape_super() updates metadata with new size, due to some metadata
limitations saved value can be different than requested value by user.
Update size (read it from metadata) for setting it in md.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Grow.c | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/Grow.c b/Grow.c
index e8f6554..86d1020 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1637,6 +1637,27 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
goto release;
}
sync_metadata(st);
+ if (st->ss->external) {
+ /* metadata can have size limitation
+ * update size value according to metadata information
+ */
+ struct mdinfo *sizeinfo =
+ st->ss->container_content(st, subarray);
+ if (sizeinfo) {
+ unsigned long long new_size =
+ sizeinfo->custom_array_size/2;
+ int data_disks = get_data_disks(
+ sizeinfo->array.level,
+ sizeinfo->array.layout,
+ sizeinfo->array.raid_disks);
+ new_size /= data_disks;
+ dprintf("Metadata size correction from %llu to "
+ "%llu (%llu)\n", orig_size, new_size,
+ new_size * data_disks);
+ size = new_size;
+ sysfs_free(sizeinfo);
+ }
+ }
/* Update the size of each member device in case
* they have been resized. This will never reduce
--
1.7.7.6

View File

@ -1,30 +0,0 @@
From 58d26a2a81c4ad93ccce88865f2c4ac2588bec69 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Fri, 13 Apr 2012 16:52:07 +0200
Subject: [PATCH 13/14] FIX: Size change is possible as standalone change only
Size change is possible as standalone change only. To make sure size change
is not requested pass '-1' as size parameter.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Grow.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Grow.c b/Grow.c
index 1b45199..389992e 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1973,7 +1973,7 @@ size_change_error:
/* Impose these changes on a single array. First
* check that the metadata is OK with the change. */
- if (reshape_super(st, info.component_size, info.new_level,
+ if (reshape_super(st, -1, info.new_level,
info.new_layout, info.new_chunk,
info.array.raid_disks, info.delta_disks,
backup_file, devname, APPLY_METADATA_CHANGES,
--
1.7.7.6

View File

@ -1,118 +0,0 @@
From 016e00f54635138ce34b9e4ba18d37e182288bd1 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Fri, 13 Apr 2012 16:51:59 +0200
Subject: [PATCH 05/14] FIX: Support metadata changes rollback
Function reshape_super() guards metadata changes.
It is used to apply changes rollback in error case also.
As change (apply and rollback) can be not bi-directional reshape_super()
has to know if current action is metadata change that should be guarded
using metadata restrictions, or this is metadata rollback change
executed due to error occurrence.
In second case change has to be unconditional.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Grow.c | 16 ++++++++++------
mdadm.h | 4 ++++
super-intel.c | 2 +-
3 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/Grow.c b/Grow.c
index 5fd44aa..8c7bafc 100644
--- a/Grow.c
+++ b/Grow.c
@@ -650,7 +650,7 @@ static void wait_reshape(struct mdinfo *sra)
static int reshape_super(struct supertype *st, long long size, int level,
int layout, int chunksize, int raid_disks,
int delta_disks, char *backup_file, char *dev,
- int verbose)
+ int direction, int verbose)
{
/* nothing extra to check in the native case */
if (!st->ss->external)
@@ -664,7 +664,7 @@ static int reshape_super(struct supertype *st, long long size, int level,
return st->ss->reshape_super(st, size, level, layout, chunksize,
raid_disks, delta_disks, backup_file, dev,
- verbose);
+ direction, verbose);
}
static void sync_metadata(struct supertype *st)
@@ -1631,7 +1631,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
orig_size = array.size;
if (reshape_super(st, size, UnSet, UnSet, 0, 0, UnSet, NULL,
- devname, !quiet)) {
+ devname, APPLY_METADATA_CHANGES, !quiet)) {
rv = 1;
goto release;
}
@@ -1697,7 +1697,9 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
/* restore metadata */
if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0,
- UnSet, NULL, devname, !quiet) == 0)
+ UnSet, NULL, devname,
+ ROLLBACK_METADATA_CHANGES,
+ !quiet) == 0)
sync_metadata(st);
fprintf(stderr, Name ": Cannot set device size for %s: %s\n",
devname, strerror(err));
@@ -1909,7 +1911,8 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
if (reshape_super(st, info.component_size, info.new_level,
info.new_layout, info.new_chunk,
info.array.raid_disks, info.delta_disks,
- backup_file, devname, quiet)) {
+ backup_file, devname, APPLY_METADATA_CHANGES,
+ quiet)) {
rv = 1;
goto release;
}
@@ -2608,7 +2611,8 @@ int reshape_container(char *container, char *devname,
reshape_super(st, -1, info->new_level,
info->new_layout, info->new_chunk,
info->array.raid_disks, info->delta_disks,
- backup_file, devname, quiet)) {
+ backup_file, devname, APPLY_METADATA_CHANGES,
+ quiet)) {
unfreeze(st);
return 1;
}
diff --git a/mdadm.h b/mdadm.h
index 9f58800..686d4b4 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -740,9 +740,13 @@ extern struct superswitch {
* initialized to indicate if reshape is being performed at the
* container or subarray level
*/
+#define APPLY_METADATA_CHANGES 1
+#define ROLLBACK_METADATA_CHANGES 0
+
int (*reshape_super)(struct supertype *st, long long size, int level,
int layout, int chunksize, int raid_disks,
int delta_disks, char *backup, char *dev,
+ int direction,
int verbose); /* optional */
int (*manage_reshape)( /* optional */
int afd, struct mdinfo *sra, struct reshape *reshape,
diff --git a/super-intel.c b/super-intel.c
index ac8922f..32a53d1 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -10018,7 +10018,7 @@ int imsm_takeover(struct supertype *st, struct geo_params *geo)
static int imsm_reshape_super(struct supertype *st, long long size, int level,
int layout, int chunksize, int raid_disks,
int delta_disks, char *backup, char *dev,
- int verbose)
+ int direction, int verbose)
{
int ret_val = 1;
struct geo_params geo;
--
1.7.7.6

View File

@ -1,39 +0,0 @@
From 3c20f9899bc95b35f5b9544c6741b4fccd616326 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Thu, 12 Jan 2012 08:12:47 +0100
Subject: [PATCH] FIX: mdmon check in reshape_container() can cause a problem
When raid0 reshape is executed mdmon can dissappear due to raid level
takeover operation. If this happen before mdmon check, mdadm would treat
it as error condition. It is not true for this case.
Remove mdmon check from reshape_container() function.
Error condition check will remain using reshape_array() reentry test
for the same array (line 2577).
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Grow.c | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)
diff --git a/Grow.c b/Grow.c
index 89f563c..c1bc1ca 100644
--- a/Grow.c
+++ b/Grow.c
@@ -2608,12 +2608,6 @@ int reshape_container(char *container, char *devname,
restart = 0;
if (rv)
break;
- rv = !mdmon_running(devname2devnum(container));
- if (rv) {
- printf(Name ": Mdmon is not found. "
- "Cannot continue container reshape.\n");
- break;
- }
}
if (!rv)
unfreeze(st);
--
1.7.4.4

View File

@ -1,45 +0,0 @@
From e1dd332a09c66ef0df68229cc633b8f2521e5db4 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Thu, 9 Feb 2012 12:37:40 +1100
Subject: [PATCH 11/12] FIX: restart reshape when reshape process is stopped
just between 2 reshapes
When reshape is restarted from '0', very begin of array
it is possible that for external metadata reshape and array
configuration doesn't happen.
Check if md has the same opinion, and reshape is restarted
from 0. If so, this is regular reshape start after reshape
switch in metadata to next array only.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Grow.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/Grow.c b/Grow.c
index 6b1380a..61adefa 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1980,6 +1980,18 @@ static int reshape_array(char *container, int fd, char *devname,
goto release;
}
+ if (st->ss->external && restart && (info->reshape_progress == 0)) {
+ /* When reshape is restarted from '0', very begin of array
+ * it is possible that for external metadata reshape and array
+ * configuration doesn't happen.
+ * Check if md has the same opinion, and reshape is restarted
+ * from 0. If so, this is regular reshape start after reshape
+ * switch in metadata to next array only.
+ */
+ if ((verify_reshape_position(info, reshape.level) >= 0) &&
+ (info->reshape_progress == 0))
+ restart = 0;
+ }
if (restart) {
/* reshape already started. just skip to monitoring the reshape */
if (reshape.backup_blocks == 0)
--
1.7.4.4

View File

@ -1,139 +0,0 @@
From f93346ef078fde20e46849901efa16dd1b05ec33 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Thu, 9 Feb 2012 12:36:41 +1100
Subject: [PATCH 08/12] FIX: use md position to reshape restart
When reshape is broken, it can occur that metadata is not saved properly.
This can cause that reshape process is farther in md than metadata states.
On reshape restart use md position as start position, if it is farther than
position specified in metadata. Opposite situation treat as error.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Grow.c | 86 ++++++++++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 60 insertions(+), 26 deletions(-)
diff --git a/Grow.c b/Grow.c
index 70bdee1..6b1380a 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1862,6 +1862,55 @@ release:
return rv;
}
+/* verify_reshape_position()
+ * Function checks if reshape position in metadata is not farther
+ * than position in md.
+ * Return value:
+ * 0 : not valid sysfs entry
+ * it can be caused by not started reshape, it should be started
+ * by reshape array or raid0 array is before takeover
+ * -1 : error, reshape position is obviously wrong
+ * 1 : success, reshape progress correct or updated
+*/
+static int verify_reshape_position(struct mdinfo *info, int level)
+{
+ int ret_val = 0;
+ char buf[40];
+
+ /* read sync_max, failure can mean raid0 array */
+ if (sysfs_get_str(info, NULL, "sync_max", buf, 40) > 0) {
+ char *ep;
+ unsigned long long position = strtoull(buf, &ep, 0);
+
+ dprintf(Name": Read sync_max sysfs entry is: %s\n", buf);
+ if (!(ep == buf || (*ep != 0 && *ep != '\n' && *ep != ' '))) {
+ position *= get_data_disks(level,
+ info->new_layout,
+ info->array.raid_disks);
+ if (info->reshape_progress < position) {
+ dprintf("Corrected reshape progress (%llu) to "
+ "md position (%llu)\n",
+ info->reshape_progress, position);
+ info->reshape_progress = position;
+ ret_val = 1;
+ } else if (info->reshape_progress > position) {
+ fprintf(stderr, Name ": Fatal error: array "
+ "reshape was not properly frozen "
+ "(expected reshape position is %llu, "
+ "but reshape progress is %llu.\n",
+ position, info->reshape_progress);
+ ret_val = -1;
+ } else {
+ dprintf("Reshape position in md and metadata "
+ "are the same;");
+ ret_val = 1;
+ }
+ }
+ }
+
+ return ret_val;
+}
+
static int reshape_array(char *container, int fd, char *devname,
struct supertype *st, struct mdinfo *info,
int force, struct mddev_dev *devlist,
@@ -2251,9 +2300,16 @@ started:
sra->new_chunk = info->new_chunk;
- if (restart)
+ if (restart) {
+ /* for external metadata checkpoint saved by mdmon can be lost
+ * or missed /due to e.g. crash/. Check if md is not during
+ * restart farther than metadata points to.
+ * If so, this means metadata information is obsolete.
+ */
+ if (st->ss->external)
+ verify_reshape_position(info, reshape.level);
sra->reshape_progress = info->reshape_progress;
- else {
+ } else {
sra->reshape_progress = 0;
if (reshape.after.data_disks < reshape.before.data_disks)
/* start from the end of the new array */
@@ -3765,8 +3821,6 @@ int Grow_continue_command(char *devname, int fd,
char buf[40];
int cfd = -1;
int fd2 = -1;
- char *ep;
- unsigned long long position;
dprintf("Grow continue from command line called for %s\n",
devname);
@@ -3894,28 +3948,8 @@ int Grow_continue_command(char *devname, int fd,
/* verify that array under reshape is started from
* correct position
*/
- ret_val = sysfs_get_str(content, NULL, "sync_max", buf, 40);
- if (ret_val <= 0) {
- fprintf(stderr, Name
- ": cannot open verify reshape progress for %s (%i)\n",
- content->sys_name, ret_val);
- ret_val = 1;
- goto Grow_continue_command_exit;
- }
- dprintf(Name ": Read sync_max sysfs entry is: %s\n", buf);
- position = strtoull(buf, &ep, 0);
- if (ep == buf || (*ep != 0 && *ep != '\n' && *ep != ' ')) {
- fprintf(stderr, Name ": Fatal error: array reshape was"
- " not properly frozen\n");
- ret_val = 1;
- goto Grow_continue_command_exit;
- }
- position *= get_data_disks(map_name(pers, mdstat->level),
- content->new_layout,
- content->array.raid_disks);
- if (position != content->reshape_progress) {
- fprintf(stderr, Name ": Fatal error: array reshape was"
- " not properly frozen.\n");
+ if (verify_reshape_position(content,
+ map_name(pers, mdstat->level)) <= 0) {
ret_val = 1;
goto Grow_continue_command_exit;
}
--
1.7.4.4

View File

@ -1,46 +0,0 @@
From 50927b1323a4cfcbf3729ff552c496695d6199eb Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Tue, 7 Feb 2012 15:03:35 +0100
Subject: [PATCH 05/12] Fix: Sometimes mdmon throws core dump during reshape
Problem was found during reshaping 2 volumes /raid0 and raid5/ in container.
Sometimes mdmon throws core dump due to NULL pointer exception.
Problem occurs in scenario:
- managemon: is about spare activation (degraded raid4 volume == raid0 under takeover)
- managemon: detect level change and signals monitor (manage_member() calls replace_array())
- monitor: detects transition raid4/5->raid0 and sets a->container to NULL
to indicate array deactivation
- managemon : continues his work and tries to activate spare (a->check_degraded is set).
NULL pointer is passed to metadata handler activate_spare()
Core dump is generated.
To resolve this situation managemon (after monitor kick) checks again
a->container pointer to learn if current array is not to be deactivated.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
managemon.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/managemon.c b/managemon.c
index cde0d8b..6c21ecb 100644
--- a/managemon.c
+++ b/managemon.c
@@ -486,6 +486,12 @@ static void manage_member(struct mdstat_ent *mdstat,
}
}
+ /* we are after monitor kick,
+ * so container field can be cleared - check it again
+ */
+ if (a->container == NULL)
+ return;
+
/* We don't check the array while any update is pending, as it
* might container a change (such as a spare assignment) which
* could affect our decisions.
--
1.7.4.4

View File

@ -1,40 +0,0 @@
From 119374a0ac7d6a73cd296134b0151aa213bbee42 Mon Sep 17 00:00:00 2001
From: Jes Sorensen <Jes.Sorensen@redhat.com>
Date: Thu, 26 Apr 2012 16:55:10 +0200
Subject: [PATCH 1/2] Fix sign extension of bitmap_offset in super1.c
fbdef49811c9e2b54e2064d9af68cfffa77c6e77 incorrectly tried to fix sign
extension of the bitmap offset. However mdinfo->bitmap_offset is a u32
and needs to be converted to a 32 bit signed integer before the sign
extension.
Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
---
super1.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/super1.c b/super1.c
index 36369d8..be77c33 100644
--- a/super1.c
+++ b/super1.c
@@ -620,7 +620,7 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
info->data_offset = __le64_to_cpu(sb->data_offset);
info->component_size = __le64_to_cpu(sb->size);
if (sb->feature_map & __le32_to_cpu(MD_FEATURE_BITMAP_OFFSET))
- info->bitmap_offset = (long)__le32_to_cpu(sb->bitmap_offset);
+ info->bitmap_offset = (int32_t)__le32_to_cpu(sb->bitmap_offset);
info->disk.major = 0;
info->disk.minor = 0;
@@ -1651,7 +1651,7 @@ add_internal_bitmap1(struct supertype *st,
offset = -room;
}
- sb->bitmap_offset = (long)__cpu_to_le32(offset);
+ sb->bitmap_offset = (int32_t)__cpu_to_le32(offset);
sb->feature_map = __cpu_to_le32(__le32_to_cpu(sb->feature_map)
| MD_FEATURE_BITMAP_OFFSET);
--
1.7.7.6

View File

@ -1,96 +0,0 @@
From 78340e26a54db960de238b511f5cdc74aebe4453 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Tue, 7 Feb 2012 15:03:43 +0100
Subject: [PATCH 06/12] Flush mdmon before next reshape step during container
operation
Using takeover operation for grow purposes, mdadm has to be sure
that mdmon processes all updates, and if necessary it will be closed
at takeover to raid0 operation. If mdmon is late, next array in container
is processed and due to race condition mdmon closes itself instead to monitor
next reshape operation.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Grow.c | 12 ++++++++++--
msg.c | 10 ++++++++++
msg.h | 1 +
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/Grow.c b/Grow.c
index 36a1de7..70bdee1 100644
--- a/Grow.c
+++ b/Grow.c
@@ -2003,6 +2003,9 @@ static int reshape_array(char *container, int fd, char *devname,
if (reshape.level > 0 && st->ss->external) {
/* make sure mdmon is aware of the new level */
+ if (mdmon_running(st->container_dev))
+ flush_mdmon(container);
+
if (!mdmon_running(st->container_dev))
start_mdmon(st->container_dev);
ping_monitor(container);
@@ -2396,8 +2399,7 @@ started:
/* Re-load the metadata as much could have changed */
int cfd = open_dev(st->container_dev);
if (cfd >= 0) {
- ping_manager(container);
- ping_monitor(container);
+ flush_mdmon(container);
st->ss->free_super(st);
st->ss->load_container(st, cfd, container);
close(cfd);
@@ -2594,6 +2596,9 @@ int reshape_container(char *container, char *devname,
sysfs_init(content, fd, mdstat->devnum);
+ if (mdmon_running(devname2devnum(container)))
+ flush_mdmon(container);
+
rv = reshape_array(container, fd, adev, st,
content, force, NULL,
backup_file, quiet, 1, restart,
@@ -2608,6 +2613,9 @@ int reshape_container(char *container, char *devname,
restart = 0;
if (rv)
break;
+
+ if (mdmon_running(devname2devnum(container)))
+ flush_mdmon(container);
}
if (!rv)
unfreeze(st);
diff --git a/msg.c b/msg.c
index dc780b3..44aad1f 100644
--- a/msg.c
+++ b/msg.c
@@ -487,3 +487,13 @@ int ping_manager(char *devname)
close(sfd);
return err;
}
+
+/* using takeover operation for grow purposes, mdadm has to be sure
+ * that mdmon processes all updates, and if necessary it will be closed
+ * at takeover to raid0 operation
+ */
+void flush_mdmon(char *container)
+{
+ ping_manager(container);
+ ping_monitor(container);
+}
diff --git a/msg.h b/msg.h
index c6d037d..eefa649 100644
--- a/msg.h
+++ b/msg.h
@@ -34,5 +34,6 @@ extern int block_monitor(char *container, const int freeze);
extern void unblock_monitor(char *container, const int unfreeze);
extern int fping_monitor(int sock);
extern int ping_manager(char *devname);
+extern void flush_mdmon(char *container);
#define MSG_MAX_LEN (4*1024*1024)
--
1.7.4.4

View File

@ -1,49 +0,0 @@
From 69fe207ed68e560d76a592fd86af32a9d1deca25 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Thu, 22 Mar 2012 15:53:53 +1100
Subject: [PATCH] Incremental: fix adding devices with --incremental
We should use 'info' here, not 'info2'.
info2 refers to some other device (There may not even be one).l
info is *this* disk.
This is particularly important for getting info.disk.state
correct, which the kernel depends on to get 're-add' functionality
correct.
Signed-off-by: NeilBrown <neilb@suse.de>
---
Incremental.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Incremental.c b/Incremental.c
index 836a6f1..a61f453 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -414,19 +414,19 @@ int Incremental(char *devname, int verbose, int runstop,
goto out_unlock;
}
}
- info2.disk.major = major(stb.st_rdev);
- info2.disk.minor = minor(stb.st_rdev);
+ info.disk.major = major(stb.st_rdev);
+ info.disk.minor = minor(stb.st_rdev);
/* add disk needs to know about containers */
if (st->ss->external)
sra->array.level = LEVEL_CONTAINER;
- err = add_disk(mdfd, st, sra, &info2);
+ err = add_disk(mdfd, st, sra, &info);
if (err < 0 && errno == EBUSY) {
/* could be another device present with the same
* disk.number. Find and reject any such
*/
find_reject(mdfd, st, sra, info.disk.number,
info.events, verbose, chosen_name);
- err = add_disk(mdfd, st, sra, &info2);
+ err = add_disk(mdfd, st, sra, &info);
}
if (err < 0) {
fprintf(stderr, Name ": failed to add %s to %s: %s.\n",
--
1.7.7.6

View File

@ -1,68 +0,0 @@
From 7b5ec34bb072781c0efbba8b21a941fff4d6ae7f Mon Sep 17 00:00:00 2001
From: Jes Sorensen <Jes.Sorensen@redhat.com>
Date: Thu, 26 Apr 2012 17:05:22 +0200
Subject: [PATCH 2/2] Introduce sysfs_set_num_signed() and use it to set
bitmap/offset
mdinfo->bitmap_offset is a signed long and needs to be treated as
such when passed to the kernel.
This resolves the problem with adding internal bitmaps to a 1.0 array.
Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
---
Grow.c | 4 ++--
mdadm.h | 2 ++
sysfs.c | 8 ++++++++
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/Grow.c b/Grow.c
index b4b9ff2..0b0d718 100644
--- a/Grow.c
+++ b/Grow.c
@@ -424,8 +424,8 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int
if (offset_setable) {
st->ss->getinfo_super(st, mdi, NULL);
sysfs_init(mdi, fd, -1);
- rv = sysfs_set_num(mdi, NULL, "bitmap/location",
- mdi->bitmap_offset);
+ rv = sysfs_set_num_signed(mdi, NULL, "bitmap/location",
+ mdi->bitmap_offset);
} else {
array.state |= (1<<MD_SB_BITMAP_PRESENT);
rv = ioctl(fd, SET_ARRAY_INFO, &array);
diff --git a/mdadm.h b/mdadm.h
index e60a706..0c91a34 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -473,6 +473,8 @@ extern int sysfs_set_str(struct mdinfo *sra, struct mdinfo *dev,
char *name, char *val);
extern int sysfs_set_num(struct mdinfo *sra, struct mdinfo *dev,
char *name, unsigned long long val);
+extern int sysfs_set_num_signed(struct mdinfo *sra, struct mdinfo *dev,
+ char *name, long long val);
extern int sysfs_uevent(struct mdinfo *sra, char *event);
extern int sysfs_get_fd(struct mdinfo *sra, struct mdinfo *dev,
char *name);
diff --git a/sysfs.c b/sysfs.c
index a1007cf..8e9d0c5 100644
--- a/sysfs.c
+++ b/sysfs.c
@@ -428,6 +428,14 @@ int sysfs_set_num(struct mdinfo *sra, struct mdinfo *dev,
return sysfs_set_str(sra, dev, name, valstr);
}
+int sysfs_set_num_signed(struct mdinfo *sra, struct mdinfo *dev,
+ char *name, long long val)
+{
+ char valstr[50];
+ sprintf(valstr, "%lli", val);
+ return sysfs_set_str(sra, dev, name, valstr);
+}
+
int sysfs_uevent(struct mdinfo *sra, char *event)
{
char fname[50];
--
1.7.7.6

View File

@ -1,66 +0,0 @@
From c69ffac0d6a068823a1365c3b155ff72f8c4686f Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Wed, 7 Mar 2012 15:25:57 +1100
Subject: [PATCH] Manage: allow --re-add to failed array.
If both "legs" of a RAID1 (or equivalent in RAID10) fail, then one
of the becomes available again it maybe appropriate to re-add the
failed device(s).
So remove the restriction that an array must has 'enough' devices
before being re-added, and if there is no-where to read a superblock
from for matching, then assume the kernel will do necessary checks.
Signed-off-by: NeilBrown <neilb@suse.de>
---
Manage.c | 16 +++++++++++++---
1 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/Manage.c b/Manage.c
index d9775de..4cf6e58 100644
--- a/Manage.c
+++ b/Manage.c
@@ -723,7 +723,13 @@ int Manage_subdevs(char *devname, int fd,
break;
}
/* FIXME this is a bad test to be using */
- if (!tst->sb) {
+ if (!tst->sb &&
+ dv->re_add) {
+ /* we are re-adding a device to a
+ * completely dead array - have to depend
+ * on kernel to check
+ */
+ } else if (!tst->sb) {
close(tfd);
st->ss->free_super(st);
fprintf(stderr, Name ": cannot load array metadata from %s\n", devname);
@@ -747,12 +753,16 @@ int Manage_subdevs(char *devname, int fd,
* and was temporarily removed, and is now being re-added.
* If so, we can simply re-add it.
*/
- tst->ss->uuid_from_super(tst, duuid);
if (st->sb) {
struct mdinfo mdi;
st->ss->getinfo_super(st, &mdi, NULL);
st->ss->uuid_from_super(st, ouuid);
+ if (tst->sb)
+ tst->ss->uuid_from_super(tst, duuid);
+ else
+ /* Assume uuid matches: kernel will check */
+ memcpy(duuid, ouuid, sizeof(ouuid));
if ((mdi.disk.state & (1<<MD_DISK_ACTIVE)) &&
!(mdi.disk.state & (1<<MD_DISK_FAULTY)) &&
memcmp(duuid, ouuid, sizeof(ouuid))==0) {
@@ -768,7 +778,7 @@ int Manage_subdevs(char *devname, int fd,
disc.number = mdi.disk.number;
if (ioctl(fd, GET_DISK_INFO, &disc) != 0
|| disc.major != 0 || disc.minor != 0
- || !enough_fd(fd))
+ )
goto skip_re_add;
disc.major = major(stb.st_rdev);
disc.minor = minor(stb.st_rdev);
--
1.7.7.6

View File

@ -1,66 +0,0 @@
From 9f58469128c99c0d7f434d28657f86789334f253 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Thu, 22 Mar 2012 16:15:03 +1100
Subject: [PATCH 3/3] Manage: freeze recovery while adding multiple devices.
If the kernel supports it, freeze recovery over multiple adds,
so that they can all be added to the array at the same time and
be recovered in parallel.
Signed-off-by: NeilBrown <neilb@suse.de>
---
Manage.c | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/Manage.c b/Manage.c
index f53fe27..7deba3a 100644
--- a/Manage.c
+++ b/Manage.c
@@ -416,12 +416,15 @@ int Manage_subdevs(char *devname, int fd,
int lfd = -1;
int sysfd = -1;
int count = 0; /* number of actions taken */
+ struct mdinfo info;
+ int frozen = 0;
if (ioctl(fd, GET_ARRAY_INFO, &array)) {
fprintf(stderr, Name ": cannot get array info for %s\n",
devname);
goto abort;
}
+ sysfs_init(&info, fd, 0);
/* array.size is only 32 bit and may be truncated.
* So read from sysfs if possible, and record number of sectors
@@ -629,6 +632,12 @@ int Manage_subdevs(char *devname, int fd,
dv->devname, strerror(errno));
goto abort;
}
+ if (!frozen) {
+ if (sysfs_freeze_array(&info) == 1)
+ frozen = 1;
+ else
+ frozen = -1;
+ }
st = dup_super(tst);
@@ -1166,11 +1175,15 @@ int Manage_subdevs(char *devname, int fd,
break;
}
}
+ if (frozen > 0)
+ sysfs_set_str(&info, NULL, "sync_action","idle");
if (test && count == 0)
return 2;
return 0;
abort:
+ if (frozen > 0)
+ sysfs_set_str(&info, NULL, "sync_action","idle");
return 1;
}
--
1.7.7.6

View File

@ -1,347 +0,0 @@
From bcbb3112d2801594358153956191e4cff6021de3 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Thu, 22 Mar 2012 16:07:02 +1100
Subject: [PATCH 2/3] Manage: replace 'return 1' with 'goto abort'.
This will allow exit processing in next patch
Signed-off-by: NeilBrown <neilb@suse.de>
---
Manage.c | 75 ++++++++++++++++++++++++++++++++-----------------------------
1 files changed, 39 insertions(+), 36 deletions(-)
diff --git a/Manage.c b/Manage.c
index 4cf6e58..f53fe27 100644
--- a/Manage.c
+++ b/Manage.c
@@ -420,7 +420,7 @@ int Manage_subdevs(char *devname, int fd,
if (ioctl(fd, GET_ARRAY_INFO, &array)) {
fprintf(stderr, Name ": cannot get array info for %s\n",
devname);
- return 1;
+ goto abort;
}
/* array.size is only 32 bit and may be truncated.
@@ -435,7 +435,7 @@ int Manage_subdevs(char *devname, int fd,
if (!tst) {
fprintf(stderr, Name ": unsupport array - version %d.%d\n",
array.major_version, array.minor_version);
- return 1;
+ goto abort;
}
stb.st_rdev = 0;
@@ -457,7 +457,7 @@ int Manage_subdevs(char *devname, int fd,
fprintf(stderr, Name ": %s only meaningful "
"with -r, not -%c\n",
dv->devname, dv->disposition);
- return 1;
+ goto abort;
}
for (; j < 1024 && remaining_disks > 0; j++) {
unsigned dev;
@@ -490,7 +490,7 @@ int Manage_subdevs(char *devname, int fd,
fprintf(stderr, Name ": %s only meaningful "
"with -r of -f, not -%c\n",
dv->devname, dv->disposition);
- return 1;
+ goto abort;
}
for (; j < 1024 && remaining_disks > 0; j++) {
int sfd;
@@ -530,7 +530,7 @@ int Manage_subdevs(char *devname, int fd,
if (dv->disposition != 'a' || dv->re_add == 0) {
fprintf(stderr, Name ": 'missing' only meaningful "
"with --re-add\n");
- return 1;
+ goto abort;
}
if (add_devlist == NULL)
add_devlist = conf_get_devs();
@@ -554,7 +554,7 @@ int Manage_subdevs(char *devname, int fd,
fprintf(stderr, Name ": %s only meaningful "
"with -r or -f, not -%c\n",
dv->devname, dv->disposition);
- return 1;
+ goto abort;
}
sprintf(dname, "dev-%s", dv->devname);
@@ -576,7 +576,7 @@ int Manage_subdevs(char *devname, int fd,
fprintf(stderr, Name ": %s does not appear "
"to be a component of %s\n",
dv->devname, devname);
- return 1;
+ goto abort;
}
}
} else {
@@ -595,7 +595,7 @@ int Manage_subdevs(char *devname, int fd,
dv->devname, strerror(errno));
if (tfd >= 0)
close(tfd);
- return 1;
+ goto abort;
}
close(tfd);
tfd = -1;
@@ -604,21 +604,21 @@ int Manage_subdevs(char *devname, int fd,
fprintf(stderr, Name ": %s is not a "
"block device.\n",
dv->devname);
- return 1;
+ goto abort;
}
}
switch(dv->disposition){
default:
fprintf(stderr, Name ": internal error - devmode[%s]=%d\n",
dv->devname, dv->disposition);
- return 1;
+ goto abort;
case 'a':
/* add the device */
if (subarray) {
fprintf(stderr, Name ": Cannot add disks to a"
" \'member\' array, perform this"
" operation on the parent container\n");
- return 1;
+ goto abort;
}
/* Make sure it isn't in use (in 2.6 or later) */
tfd = dev_open(add_dev, O_RDONLY|O_EXCL|O_DIRECT);
@@ -627,7 +627,7 @@ int Manage_subdevs(char *devname, int fd,
if (tfd < 0) {
fprintf(stderr, Name ": Cannot open %s: %s\n",
dv->devname, strerror(errno));
- return 1;
+ goto abort;
}
st = dup_super(tst);
@@ -639,7 +639,7 @@ int Manage_subdevs(char *devname, int fd,
if (!get_dev_size(tfd, dv->devname, &ldsize)) {
st->ss->free_super(st);
close(tfd);
- return 1;
+ goto abort;
}
} else if (!get_dev_size(tfd, NULL, &ldsize)) {
st->ss->free_super(st);
@@ -661,7 +661,7 @@ int Manage_subdevs(char *devname, int fd,
add_dev, devname);
st->ss->free_super(st);
close(tfd);
- return 1;
+ goto abort;
}
fprintf(stderr, Name
": %s is larger than %s can "
@@ -686,7 +686,7 @@ int Manage_subdevs(char *devname, int fd,
fprintf(stderr, Name ": hot add failed for %s: %s\n",
add_dev, strerror(errno));
- return 1;
+ goto abort;
}
if (array.not_persistent == 0 || tst->ss->external) {
@@ -733,7 +733,7 @@ int Manage_subdevs(char *devname, int fd,
close(tfd);
st->ss->free_super(st);
fprintf(stderr, Name ": cannot load array metadata from %s\n", devname);
- return 1;
+ goto abort;
}
/* Make sure device is large enough */
@@ -746,7 +746,7 @@ int Manage_subdevs(char *devname, int fd,
continue;
fprintf(stderr, Name ": %s not large enough to join array\n",
dv->devname);
- return 1;
+ goto abort;
}
/* Possibly this device was recently part of the array
@@ -799,7 +799,7 @@ int Manage_subdevs(char *devname, int fd,
fprintf(stderr, Name ": failed to open %s for"
" superblock update during re-add\n", dv->devname);
st->ss->free_super(st);
- return 1;
+ goto abort;
}
if (dv->writemostly == 1)
@@ -822,7 +822,7 @@ int Manage_subdevs(char *devname, int fd,
fprintf(stderr, Name ": failed to update"
" superblock during re-add\n");
st->ss->free_super(st);
- return 1;
+ goto abort;
}
}
/* don't even try if disk is marked as faulty */
@@ -840,7 +840,7 @@ int Manage_subdevs(char *devname, int fd,
st->ss->free_super(st);
if (add_dev != dv->devname)
continue;
- return 1;
+ goto abort;
}
skip_re_add:
re_add_failed = 1;
@@ -864,7 +864,7 @@ int Manage_subdevs(char *devname, int fd,
fprintf(stderr, Name
": --re-add for %s to %s is not possible\n",
dv->devname, devname);
- return 1;
+ goto abort;
}
if (re_add_failed) {
fprintf(stderr, Name ": %s reports being an active member for %s, but a --re-add fails.\n",
@@ -875,7 +875,7 @@ int Manage_subdevs(char *devname, int fd,
dv->devname);
if (tfd >= 0)
close(tfd);
- return 1;
+ goto abort;
}
} else {
/* non-persistent. Must ensure that new drive
@@ -886,7 +886,7 @@ int Manage_subdevs(char *devname, int fd,
dv->devname);
if (tfd >= 0)
close(tfd);
- return 1;
+ goto abort;
}
}
/* committed to really trying this device now*/
@@ -921,11 +921,11 @@ int Manage_subdevs(char *devname, int fd,
if (tst->ss->add_to_super(tst, &disc, dfd,
dv->devname)) {
close(dfd);
- return 1;
+ goto abort;
}
if (tst->ss->write_init_super(tst)) {
close(dfd);
- return 1;
+ goto abort;
}
} else if (dv->re_add) {
/* this had better be raid1.
@@ -974,7 +974,7 @@ int Manage_subdevs(char *devname, int fd,
" could not get exclusive access to container\n",
dv->devname);
tst->ss->free_super(tst);
- return 1;
+ goto abort;
}
dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
@@ -984,7 +984,7 @@ int Manage_subdevs(char *devname, int fd,
dv->devname)) {
close(dfd);
close(container_fd);
- return 1;
+ goto abort;
}
if (tst->update_tail)
flush_metadata_updates(tst);
@@ -997,7 +997,7 @@ int Manage_subdevs(char *devname, int fd,
dv->devname);
close(container_fd);
tst->ss->free_super(tst);
- return 1;
+ goto abort;
}
sra->array.level = LEVEL_CONTAINER;
/* Need to set data_offset and component_size */
@@ -1013,7 +1013,7 @@ int Manage_subdevs(char *devname, int fd,
" failed for %s\n", dv->devname);
close(container_fd);
sysfs_free(sra);
- return 1;
+ goto abort;
}
ping_monitor_by_id(devnum);
sysfs_free(sra);
@@ -1023,7 +1023,7 @@ int Manage_subdevs(char *devname, int fd,
if (ioctl(fd, ADD_NEW_DISK, &disc)) {
fprintf(stderr, Name ": add new device failed for %s as %d: %s\n",
dv->devname, j, strerror(errno));
- return 1;
+ goto abort;
}
}
if (verbose >= 0)
@@ -1038,7 +1038,7 @@ int Manage_subdevs(char *devname, int fd,
" operation on the parent container\n");
if (sysfd >= 0)
close(sysfd);
- return 1;
+ goto abort;
}
if (tst->ss->external) {
/* To remove a device from a container, we must
@@ -1058,7 +1058,7 @@ int Manage_subdevs(char *devname, int fd,
" to container - odd\n");
if (sysfd >= 0)
close(sysfd);
- return 1;
+ goto abort;
}
/* in the detached case it is not possible to
* check if we are the unique holder, so just
@@ -1075,7 +1075,7 @@ int Manage_subdevs(char *devname, int fd,
errno == EEXIST ? "still in use":
"not a member");
close(lfd);
- return 1;
+ goto abort;
}
}
/* FIXME check that it is a current member */
@@ -1118,7 +1118,7 @@ int Manage_subdevs(char *devname, int fd,
strerror(errno));
if (lfd >= 0)
close(lfd);
- return 1;
+ goto abort;
}
if (tst->ss->external) {
/*
@@ -1131,7 +1131,7 @@ int Manage_subdevs(char *devname, int fd,
if (!name) {
fprintf(stderr, Name ": unable to get container name\n");
- return 1;
+ goto abort;
}
ping_manager(name);
@@ -1154,7 +1154,7 @@ int Manage_subdevs(char *devname, int fd,
dnprintable, strerror(errno));
if (sysfd >= 0)
close(sysfd);
- return 1;
+ goto abort;
}
if (sysfd >= 0)
close(sysfd);
@@ -1169,6 +1169,9 @@ int Manage_subdevs(char *devname, int fd,
if (test && count == 0)
return 2;
return 0;
+
+abort:
+ return 1;
}
int autodetect(void)
--
1.7.7.6

View File

@ -1,94 +0,0 @@
From 4011421332681ba733a2fc90de7ac94da8593418 Mon Sep 17 00:00:00 2001
From: Jes Sorensen <Jes.Sorensen@redhat.com>
Date: Thu, 23 Feb 2012 08:55:19 +1100
Subject: [PATCH 2/2] Print error message if failing to write super for 1.x
metadata
In addition remove attempt to print an error message if
write_init_super() fails, as this is handled in the various
write_init_super() functions. This avoids a segfault on error.
Reported by Jim Meyering in
https://bugzilla.redhat.com/show_bug.cgi?id=795461
Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Create.c | 3 ---
super1.c | 25 ++++++++++++++++---------
2 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/Create.c b/Create.c
index 90ff3ed..e5c6b05 100644
--- a/Create.c
+++ b/Create.c
@@ -924,9 +924,6 @@ int Create(struct supertype *st, char *mddev,
}
if (st->ss->write_init_super(st)) {
- fprintf(stderr,
- Name ": Failed to write metadata to %s\n",
- dv->devname);
st->ss->free_super(st);
goto abort_locked;
}
diff --git a/super1.c b/super1.c
index a18952a..341ad53 100644
--- a/super1.c
+++ b/super1.c
@@ -1106,13 +1106,16 @@ static int write_init_super1(struct supertype *st)
}
free(refst);
- if (!get_dev_size(di->fd, NULL, &dsize))
- return 1;
+ if (!get_dev_size(di->fd, NULL, &dsize)) {
+ rv = 1;
+ goto error_out;
+ }
dsize >>= 9;
if (dsize < 24) {
close(di->fd);
- return 2;
+ rv = 2;
+ goto error_out;
}
@@ -1176,22 +1179,26 @@ static int write_init_super1(struct supertype *st)
sb->data_size = __cpu_to_le64(dsize - reserved);
break;
default:
- return -EINVAL;
+ fprintf(stderr, Name ": Failed to write invalid "
+ "metadata format 1.%i to %s\n",
+ st->minor_version, di->devname);
+ rv = -EINVAL;
+ goto out;
}
sb->sb_csum = calc_sb_1_csum(sb);
rv = store_super1(st, di->fd);
- if (rv)
- fprintf(stderr,
- Name ": failed to write superblock to %s\n",
- di->devname);
-
if (rv == 0 && (__le32_to_cpu(sb->feature_map) & 1))
rv = st->ss->write_bitmap(st, di->fd);
close(di->fd);
di->fd = -1;
}
+error_out:
+ if (rv)
+ fprintf(stderr, Name ": Failed to write metadata to %s\n",
+ di->devname);
+out:
return rv;
}
#endif
--
1.7.7.6

View File

@ -1,81 +0,0 @@
From 480f3566411675ec41f18e5f6e15429f891e144c Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Wed, 18 Apr 2012 09:06:02 +1000
Subject: [PATCH] Raid limit of 1024 when scanning for devices.
When we can for devices using GET_DISK_INFO we currently
limit to 1024. But some arrays can have more than this.
So raise it to 4096 and make the constant a #define.
Signed-off-by: NeilBrown <neilb@suse.de>
---
Manage.c | 4 ++--
mdadm.h | 8 ++++++++
util.c | 4 ++--
3 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/Manage.c b/Manage.c
index 102c013..3767f01 100644
--- a/Manage.c
+++ b/Manage.c
@@ -462,7 +462,7 @@ int Manage_subdevs(char *devname, int fd,
dv->devname, dv->disposition);
goto abort;
}
- for (; j < 1024 && remaining_disks > 0; j++) {
+ for (; j < MAX_DISKS && remaining_disks > 0; j++) {
unsigned dev;
disc.number = j;
if (ioctl(fd, GET_DISK_INFO, &disc))
@@ -495,7 +495,7 @@ int Manage_subdevs(char *devname, int fd,
dv->devname, dv->disposition);
goto abort;
}
- for (; j < 1024 && remaining_disks > 0; j++) {
+ for (; j < MAX_DISKS && remaining_disks > 0; j++) {
int sfd;
unsigned dev;
disc.number = j;
diff --git a/mdadm.h b/mdadm.h
index 686d4b4..71cef38 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1388,4 +1388,13 @@ static inline int xasprintf(char **strp, const char *fmt, ...) {
#define PROCESS_DELAYED -2
#define PROCESS_PENDING -3
extern int __offroot;
+
+/* When using "GET_DISK_INFO" it isn't certain how high
+ * we need to check. So we impose an absolute limit of
+ * MAX_DISKS. This needs to be much more than the largest
+ * number of devices any metadata can support. Currently
+ * v1.x can support 1920
+ */
+#define MAX_DISKS 4096
+
diff --git a/util.c b/util.c
index b942058..ac0f78c 100644
--- a/util.c
+++ b/util.c
@@ -378,7 +378,7 @@ int enough_fd(int fd)
array.raid_disks <= 0)
return 0;
avail = calloc(array.raid_disks, 1);
- for (i=0; i < 1024 && array.nr_disks > 0; i++) {
+ for (i=0; i < MAX_DISKS && array.nr_disks > 0; i++) {
disk.number = i;
if (ioctl(fd, GET_DISK_INFO, &disk) != 0)
continue;
@@ -1275,7 +1275,7 @@ void get_one_disk(int mdfd, mdu_array_info_t *ainf, mdu_disk_info_t *disk)
int d;
ioctl(mdfd, GET_ARRAY_INFO, ainf);
- for (d = 0 ; d < 1024 ; d++) {
+ for (d = 0 ; d < MAX_DISKS ; d++) {
if (ioctl(mdfd, GET_DISK_INFO, disk) == 0 &&
(disk->major || disk->minor))
return;
--
1.7.7.6

View File

@ -1,85 +0,0 @@
From 0a999759b54f94fd63ac0ee298a549acef6f7d6f Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Wed, 18 Apr 2012 14:19:49 +1000
Subject: [PATCH 1/3] Relax restrictions on when --add is permitted.
The restriction that --add was not allowed on a device which
looked like a recent member of an array was overly harsh.
The real requirement was to avoid using --add when the array had
failed, and the device being added might contain necessary
information which can only be incorporated by stopping and
re-assembling with --force.
So change the test to reflect the need.
Reported-by: Doug Ledford <dledford@redhat.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Manage.c | 35 ++++++++++++++++++++++++++---------
1 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/Manage.c b/Manage.c
index 3767f01..95aa270 100644
--- a/Manage.c
+++ b/Manage.c
@@ -448,7 +448,7 @@ int Manage_subdevs(char *devname, int fd,
char *dnprintable = dv->devname;
char *add_dev = dv->devname;
int err;
- int re_add_failed = 0;
+ int array_failed;
next = dv->next;
jnext = 0;
@@ -851,9 +851,8 @@ int Manage_subdevs(char *devname, int fd,
continue;
goto abort;
}
- skip_re_add:
- re_add_failed = 1;
}
+ skip_re_add:
st->ss->free_super(st);
}
if (add_dev != dv->devname) {
@@ -875,12 +874,30 @@ int Manage_subdevs(char *devname, int fd,
dv->devname, devname);
goto abort;
}
- if (re_add_failed) {
- fprintf(stderr, Name ": %s reports being an active member for %s, but a --re-add fails.\n",
- dv->devname, devname);
- fprintf(stderr, Name ": not performing --add as that would convert %s in to a spare.\n",
- dv->devname);
- fprintf(stderr, Name ": To make this a spare, use \"mdadm --zero-superblock %s\" first.\n",
+ if (array.active_disks < array.raid_disks) {
+ char *avail = calloc(array.raid_disks, 1);
+ int d;
+ int found = 0;
+
+ for (d = 0; d < MAX_DISKS && found < array.active_disks; d++) {
+ disc.number = d;
+ if (ioctl(fd, GET_DISK_INFO, &disc))
+ continue;
+ if (disc.major == 0 && disc.minor == 0)
+ continue;
+ if (!(disc.state & (1<<MD_DISK_SYNC)))
+ continue;
+ avail[disc.raid_disk] = 1;
+ found++;
+ }
+ array_failed = !enough(array.level, array.raid_disks,
+ array.layout, 1, avail);
+ } else
+ array_failed = 0;
+ if (array_failed) {
+ fprintf(stderr, Name ": %s has failed so using --add cannot work and might destroy\n",
+ devname);
+ fprintf(stderr, Name ": data on %s. You should stop the array and re-assemble it.\n",
dv->devname);
if (tfd >= 0)
close(tfd);
--
1.7.7.6

View File

@ -1,171 +0,0 @@
From de5a472ea32867d002558bac0d2d2b4faf45c7c4 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Tue, 7 Feb 2012 14:04:47 +1100
Subject: [PATCH] Remove avail_disks arg from 'enough'.
It can easily be calculated from 'avail' and 'raid_disks', and we
will soon have a case where we don't have it easily available to pass
in.
Signed-off-by: NeilBrown <neilb@suse.de>
---
Assemble.c | 16 ++++++++--------
Detail.c | 4 ++--
Incremental.c | 2 +-
mdadm.h | 2 +-
util.c | 11 ++++++++---
5 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/Assemble.c b/Assemble.c
index fd94461..972398e 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -934,7 +934,7 @@ int Assemble(struct supertype *st, char *mddev,
}
continue;
}
- /* If this devices thinks that 'most_recent' has failed, then
+ /* If this device thinks that 'most_recent' has failed, then
* we must reject this device.
*/
if (j != most_recent &&
@@ -965,7 +965,7 @@ int Assemble(struct supertype *st, char *mddev,
free(devmap);
while (force && !enough(content->array.level, content->array.raid_disks,
content->array.layout, 1,
- avail, okcnt)) {
+ avail)) {
/* Choose the newest best drive which is
* not up-to-date, update the superblock
* and add it.
@@ -1132,7 +1132,7 @@ int Assemble(struct supertype *st, char *mddev,
if (force && !clean &&
!enough(content->array.level, content->array.raid_disks,
content->array.layout, clean,
- avail, okcnt)) {
+ avail)) {
change += st->ss->update_super(st, content, "force-array",
devices[chosen_drive].devname, verbose,
0, NULL);
@@ -1331,7 +1331,7 @@ int Assemble(struct supertype *st, char *mddev,
if (runstop == 1 ||
(runstop <= 0 &&
( enough(content->array.level, content->array.raid_disks,
- content->array.layout, clean, avail, okcnt) &&
+ content->array.layout, clean, avail) &&
(okcnt + rebuilding_cnt >= req_cnt || start_partial_ok)
))) {
/* This array is good-to-go.
@@ -1437,13 +1437,13 @@ int Assemble(struct supertype *st, char *mddev,
mddev, strerror(errno));
if (!enough(content->array.level, content->array.raid_disks,
- content->array.layout, 1, avail, okcnt))
+ content->array.layout, 1, avail))
fprintf(stderr, Name ": Not enough devices to "
"start the array.\n");
else if (!enough(content->array.level,
content->array.raid_disks,
content->array.layout, clean,
- avail, okcnt))
+ avail))
fprintf(stderr, Name ": Not enough devices to "
"start the array while not clean "
"- consider --force.\n");
@@ -1471,12 +1471,12 @@ int Assemble(struct supertype *st, char *mddev,
if (sparecnt)
fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
if (!enough(content->array.level, content->array.raid_disks,
- content->array.layout, 1, avail, okcnt))
+ content->array.layout, 1, avail))
fprintf(stderr, " - not enough to start the array.\n");
else if (!enough(content->array.level,
content->array.raid_disks,
content->array.layout, clean,
- avail, okcnt))
+ avail))
fprintf(stderr, " - not enough to start the "
"array while not clean - consider "
"--force.\n");
diff --git a/Detail.c b/Detail.c
index e7d1681..1d7e3a1 100644
--- a/Detail.c
+++ b/Detail.c
@@ -367,7 +367,7 @@ int Detail(char *dev, int brief, int export, int test, char *homehost)
if (avail_disks == array.raid_disks)
st = "";
else if (!enough(array.level, array.raid_disks,
- array.layout, 1, avail, avail_disks))
+ array.layout, 1, avail))
st = ", FAILED";
else
st = ", degraded";
@@ -580,7 +580,7 @@ This is pretty boring
if (brief) printf("\n");
if (test &&
!enough(array.level, array.raid_disks, array.layout,
- 1, avail, avail_disks))
+ 1, avail))
rv = 2;
free(disks);
diff --git a/Incremental.c b/Incremental.c
index 60175af..b457bf3 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -486,7 +486,7 @@ int Incremental(char *devname, int verbose, int runstop,
active_disks = count_active(st, sra, mdfd, &avail, &info);
if (enough(info.array.level, info.array.raid_disks,
info.array.layout, info.array.state & 1,
- avail, active_disks) == 0) {
+ avail) == 0) {
if (verbose >= 0)
fprintf(stderr, Name
": %s attached to %s, not enough to start (%d).\n",
diff --git a/mdadm.h b/mdadm.h
index d862b3e..45198bb 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1164,7 +1164,7 @@ extern char *fname_from_uuid(struct supertype *st,
struct mdinfo *info, char *buf, char sep);
extern unsigned long calc_csum(void *super, int bytes);
extern int enough(int level, int raid_disks, int layout, int clean,
- char *avail, int avail_disks);
+ char *avail);
extern int enough_fd(int fd);
extern int ask(char *mesg);
extern unsigned long long get_component_size(int fd);
diff --git a/util.c b/util.c
index 4ba44e6..e5f7a20 100644
--- a/util.c
+++ b/util.c
@@ -311,10 +311,15 @@ int test_partition_from_id(dev_t id)
return rv;
}
-int enough(int level, int raid_disks, int layout, int clean,
- char *avail, int avail_disks)
+int enough(int level, int raid_disks, int layout, int clean, char *avail)
{
int copies, first;
+ int i;
+ int avail_disks = 0;
+
+ for (i = 0; i < raid_disks; i++)
+ avail_disks += !!avail[i];
+
switch (level) {
case 10:
/* This is the tricky one - we need to check
@@ -389,7 +394,7 @@ int enough_fd(int fd)
}
/* This is used on an active array, so assume it is clean */
rv = enough(array.level, array.raid_disks, array.layout,
- 1, avail, avail_disks);
+ 1, avail);
free(avail);
return rv;
}
--
1.7.7.6

View File

@ -1,32 +0,0 @@
From 52f07f57195229809c7b6d71ca81d2182d303058 Mon Sep 17 00:00:00 2001
From: "Czarnowska, Anna" <anna.czarnowska@intel.com>
Date: Wed, 7 Mar 2012 12:51:30 +0000
Subject: [PATCH] Reset bad flag on map update
Map file may miss an entry if bad flag is not cleared on update.
This happens for example when an old entry exists in map that
has no mdstat counterpart and we create a new array with the same devnum.
Newly created array will not appear in map if update doesnt clear bad flag.
Signed-off-by: Anna Czarnowska <anna.czarnowska@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
mapfile.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/mapfile.c b/mapfile.c
index 0bfecd0..9e2c893 100644
--- a/mapfile.c
+++ b/mapfile.c
@@ -246,6 +246,7 @@ int map_update(struct map_ent **mpp, int devnum, char *metadata,
memcpy(mp->uuid, uuid, 16);
free(mp->path);
mp->path = path ? strdup(path) : NULL;
+ mp->bad = 0;
break;
}
if (!mp)
--
1.7.7.6

View File

@ -1,75 +0,0 @@
From a0963a86e12a55d501f421048bd7c09cf4d78b93 Mon Sep 17 00:00:00 2001
From: Jes Sorensen <Jes.Sorensen@redhat.com>
Date: Wed, 25 Jan 2012 15:18:04 +0100
Subject: [PATCH 4/4] Spawn mdmon with --offroot if mdadm was launched with
--offroot
Acked-by: Doug Ledford <dledford@redhat.com>
Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
mdadm.c | 1 +
mdadm.h | 2 ++
util.c | 17 +++++++++++++----
3 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/mdadm.c b/mdadm.c
index 78f28d5..1efa3e8 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -181,6 +181,7 @@ int main(int argc, char *argv[])
*/
case OffRootOpt:
argv[0][0] = '@';
+ __offroot = 1;
continue;
case ':':
diff --git a/mdadm.h b/mdadm.h
index fec93aa..d862b3e 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1383,3 +1383,5 @@ static inline int xasprintf(char **strp, const char *fmt, ...) {
#define PROCESS_DELAYED -2
#define PROCESS_PENDING -3
+
+extern int __offroot;
diff --git a/util.c b/util.c
index 6985a70..4ba44e6 100644
--- a/util.c
+++ b/util.c
@@ -32,6 +32,8 @@
#include <dirent.h>
#include <signal.h>
+int __offroot;
+
/*
* following taken from linux/blkpg.h because they aren't
* anywhere else and it isn't safe to #include linux/ * stuff.
@@ -1622,10 +1624,17 @@ int start_mdmon(int devnum)
skipped = 0;
for (i=0; paths[i]; i++)
- if (paths[i][0])
- execl(paths[i], "mdmon",
- devnum2devname(devnum),
- NULL);
+ if (paths[i][0]) {
+ if (__offroot) {
+ execl(paths[i], "mdmon", "--offroot",
+ devnum2devname(devnum),
+ NULL);
+ } else {
+ execl(paths[i], "mdmon",
+ devnum2devname(devnum),
+ NULL);
+ }
+ }
exit(1);
case -1: fprintf(stderr, Name ": cannot run mdmon. "
"Array remains readonly\n");
--
1.7.8.4

View File

@ -1,122 +0,0 @@
From b89b2007a01f60386fb53107b883eed85319281c Mon Sep 17 00:00:00 2001
From: Jes Sorensen <Jes.Sorensen@redhat.com>
Date: Thu, 5 Jan 2012 12:09:45 +0100
Subject: [PATCH 1/1] Work around gcc-4.7's strict aliasing checks
Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
---
sha1.c | 8 +++++---
super-ddf.c | 22 ++++++++++++++--------
2 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/sha1.c b/sha1.c
index 556d9ca..0258515 100644
--- a/sha1.c
+++ b/sha1.c
@@ -101,6 +101,7 @@ sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf)
/* Take yet unprocessed bytes into account. */
md5_uint32 bytes = ctx->buflen;
size_t pad;
+ md5_uint32 *ptr;
/* Now count remaining bytes. */
ctx->total[0] += bytes;
@@ -111,9 +112,10 @@ sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf)
memcpy (&ctx->buffer[bytes], fillbuf, pad);
/* Put the 64-bit file length in *bits* at the end of the buffer. */
- *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP (ctx->total[0] << 3);
- *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) |
- (ctx->total[0] >> 29));
+ ptr = (md5_uint32 *) &ctx->buffer[bytes + pad + 4];
+ *ptr = SWAP (ctx->total[0] << 3);
+ ptr = (md5_uint32 *) &ctx->buffer[bytes + pad];
+ *ptr = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29));
/* Process last bytes. */
sha1_process_block (ctx->buffer, bytes + pad + 8, ctx);
diff --git a/super-ddf.c b/super-ddf.c
index b5b0b42..abd6793 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -1336,6 +1336,7 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m
{
struct ddf_super *ddf = st->sb;
int map_disks = info->array.raid_disks;
+ __u32 *cptr;
if (ddf->currentconf) {
getinfo_super_ddf_bvd(st, info, map);
@@ -1347,8 +1348,9 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m
info->array.level = LEVEL_CONTAINER;
info->array.layout = 0;
info->array.md_minor = -1;
- info->array.ctime = DECADE + __be32_to_cpu(*(__u32*)
- (ddf->anchor.guid+16));
+ cptr = (__u32 *)(ddf->anchor.guid + 16);
+ info->array.ctime = DECADE + __be32_to_cpu(*cptr);
+
info->array.utime = 0;
info->array.chunk_size = 0;
info->container_enough = 1;
@@ -1407,6 +1409,7 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, cha
int j;
struct dl *dl;
int map_disks = info->array.raid_disks;
+ __u32 *cptr;
memset(info, 0, sizeof(*info));
/* FIXME this returns BVD info - what if we want SVD ?? */
@@ -1416,8 +1419,8 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, cha
info->array.layout = rlq_to_layout(vc->conf.rlq, vc->conf.prl,
info->array.raid_disks);
info->array.md_minor = -1;
- info->array.ctime = DECADE +
- __be32_to_cpu(*(__u32*)(vc->conf.guid+16));
+ cptr = (__u32 *)(vc->conf.guid + 16);
+ info->array.ctime = DECADE + __be32_to_cpu(*cptr);
info->array.utime = DECADE + __be32_to_cpu(vc->conf.timestamp);
info->array.chunk_size = 512 << vc->conf.chunk_shift;
info->custom_array_size = 0;
@@ -2192,6 +2195,7 @@ static int add_to_super_ddf(struct supertype *st,
struct phys_disk_entry *pde;
unsigned int n, i;
struct stat stb;
+ __u32 *tptr;
if (ddf->currentconf) {
add_to_super_ddf_bvd(st, dk, fd, devname);
@@ -2220,8 +2224,9 @@ static int add_to_super_ddf(struct supertype *st,
tm = localtime(&now);
sprintf(dd->disk.guid, "%8s%04d%02d%02d",
T10, tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
- *(__u32*)(dd->disk.guid + 16) = random32();
- *(__u32*)(dd->disk.guid + 20) = random32();
+ tptr = (__u32 *)(dd->disk.guid + 16);
+ *tptr++ = random32();
+ *tptr = random32();
do {
/* Cannot be bothered finding a CRC of some irrelevant details*/
@@ -2967,6 +2972,7 @@ static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray
unsigned int j;
struct mdinfo *this;
char *ep;
+ __u32 *cptr;
if (subarray &&
(strtoul(subarray, &ep, 10) != vc->vcnum ||
@@ -2986,8 +2992,8 @@ static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray
this->array.md_minor = -1;
this->array.major_version = -1;
this->array.minor_version = -2;
- this->array.ctime = DECADE +
- __be32_to_cpu(*(__u32*)(vc->conf.guid+16));
+ cptr = (__u32 *)(vc->conf.guid + 16);
+ this->array.ctime = DECADE + __be32_to_cpu(*cptr);
this->array.utime = DECADE +
__be32_to_cpu(vc->conf.timestamp);
this->array.chunk_size = 512 << vc->conf.chunk_shift;
--
1.7.8.2

View File

@ -1,31 +0,0 @@
From 9200d418d049aff77b3d0ad8f30f1a16adc56030 Mon Sep 17 00:00:00 2001
From: Jim Meyering <jim@meyering.net>
Date: Tue, 21 Feb 2012 13:02:22 +0100
Subject: [PATCH 1/2] avoid double-free upon "old buggy kernel" sysfs_read
failure
* Incremental.c (Incremental): On sysfs_read failure, don't call
sysfs_free(sra) just before "goto out_unlock", since that very
same "sra" is freed the same way by the clean-up code below.
Signed-off-by: Jim Meyering <meyering@redhat.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Incremental.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/Incremental.c b/Incremental.c
index b457bf3..836a6f1 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -325,7 +325,6 @@ int Incremental(char *devname, int verbose, int runstop,
fprintf(stderr, Name
": You have an old buggy kernel which cannot support\n"
" --incremental reliably. Aborting.\n");
- sysfs_free(sra);
rv = 2;
goto out_unlock;
}
--
1.7.7.6

View File

@ -1,52 +0,0 @@
From 9126b9a816b1576f58718dbb71bcaff2bfc274e3 Mon Sep 17 00:00:00 2001
From: "Czarnowska, Anna" <anna.czarnowska@intel.com>
Date: Mon, 2 Apr 2012 10:18:37 +1000
Subject: [PATCH 6/7] check that no disk over 2TB is used to create container
when no support
Creation of a container using disks over 2TB should be allowed only when orom supports large disks
Signed-off-by: Anna Czarnowska <anna.czarnowska@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 24 ++++++++++++++++--------
1 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 7803a2e..1bc9e9c 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -5331,14 +5331,22 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
return 0;
}
close(fd);
- if (super->orom && raiddisks > super->orom->tds) {
- if (verbose)
- fprintf(stderr, Name ": %d exceeds maximum number of"
- " platform supported disks: %d\n",
- raiddisks, super->orom->tds);
-
- free_imsm(super);
- return 0;
+ if (super->orom) {
+ if (raiddisks > super->orom->tds) {
+ if (verbose)
+ fprintf(stderr, Name ": %d exceeds maximum number of"
+ " platform supported disks: %d\n",
+ raiddisks, super->orom->tds);
+ free_imsm(super);
+ return 0;
+ }
+ if ((super->orom->attr & IMSM_OROM_ATTR_2TB_DISK) == 0 &&
+ (ldsize >> 9) >> 32 > 0) {
+ if (verbose)
+ fprintf(stderr, Name ": %s exceeds maximum platform supported size\n", dev);
+ free_imsm(super);
+ return 0;
+ }
}
*freesize = avail_size_imsm(st, ldsize >> 9);
--
1.7.7.6

View File

@ -1,69 +0,0 @@
From 2cc699afbf0a05baf02d26309eb4ad0e4e81c5d5 Mon Sep 17 00:00:00 2001
From: "Czarnowska, Anna" <anna.czarnowska@intel.com>
Date: Mon, 2 Apr 2012 10:17:55 +1000
Subject: [PATCH 5/7] check volume size in validate_geometry_imsm_orom
When orom does not support volumes over 2TB the creation should be disallowed
Signed-off-by: Anna Czarnowska <anna.czarnowska@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 14 ++++++++++----
1 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 0c38b45..7803a2e 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -5860,7 +5860,7 @@ static int imsm_default_chunk(const struct imsm_orom *orom)
static int
validate_geometry_imsm_orom(struct intel_super *super, int level, int layout,
- int raiddisks, int *chunk, int verbose)
+ int raiddisks, int *chunk, unsigned long long size, int verbose)
{
/* check/set platform and metadata limits/defaults */
if (super->orom && raiddisks > super->orom->dpa) {
@@ -5895,6 +5895,12 @@ validate_geometry_imsm_orom(struct intel_super *super, int level, int layout,
layout, level);
return 0;
}
+
+ if (super->orom && (super->orom->attr & IMSM_OROM_ATTR_2TB) == 0 && chunk &&
+ (calc_array_size(level, raiddisks, layout, *chunk, size) >> 32) > 0) {
+ pr_vrb(": platform does not support a volume size over 2TB\n");
+ return 0;
+ }
return 1;
}
@@ -5922,7 +5928,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
mpb = super->anchor;
- if (!validate_geometry_imsm_orom(super, level, layout, raiddisks, chunk, verbose)) {
+ if (!validate_geometry_imsm_orom(super, level, layout, raiddisks, chunk, size, verbose)) {
fprintf(stderr, Name ": RAID gemetry validation failed. "
"Cannot proceed with the action(s).\n");
return 0;
@@ -6187,7 +6193,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
if (st->sb) {
struct intel_super *super = st->sb;
if (!validate_geometry_imsm_orom(st->sb, level, layout,
- raiddisks, chunk,
+ raiddisks, chunk, size,
verbose))
return 0;
/* we are being asked to automatically layout a
@@ -6598,7 +6604,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
get_imsm_raid_level(map), /* RAID level */
imsm_level_to_layout(get_imsm_raid_level(map)),
map->num_members, /* raid disks */
- &chunk,
+ &chunk, join_u32(dev->size_low, dev->size_high),
1 /* verbose */)) {
fprintf(stderr, Name ": IMSM RAID geometry validation"
" failed. Array %s activation is blocked.\n",
--
1.7.7.6

View File

@ -1,72 +0,0 @@
From 97f81ee2635d8c1283ef857bc46d7314acffa1c3 Mon Sep 17 00:00:00 2001
From: "Czarnowska, Anna" <anna.czarnowska@intel.com>
Date: Mon, 2 Apr 2012 10:15:08 +1000
Subject: [PATCH 2/7] clear hi bits if not used after loading metadata from
disk
Functions retrieving sizes from metadata do not need to check
2TB attribute only when we can guarantee the hi bits are always
clear when the MPB_ATTR_2TB_DISK attribute is not set.
Therefore the following fields are cleared on metadata load
when not in use according to attribute:
struct imsm_disk.total_blocks_hi
struct imsm_map.pba_of_lba0_hi
struct imsm_map.blocks_per_member_hi
struct imsm_map.num_data_stripes_hi
Signed-off-by: Anna Czarnowska <anna.czarnowska@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 28 +++++++++++++++++++++++++++-
1 files changed, 27 insertions(+), 1 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index c65d39b..480b379 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -3590,6 +3590,32 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
static int read_imsm_migr_rec(int fd, struct intel_super *super);
+/* clears hi bits in metadata if MPB_ATTRIB_2TB_DISK not set */
+static void clear_hi(struct intel_super *super)
+{
+ struct imsm_super *mpb = super->anchor;
+ int i, n;
+ if (mpb->attributes & MPB_ATTRIB_2TB_DISK)
+ return;
+ for (i = 0; i < mpb->num_disks; ++i) {
+ struct imsm_disk *disk = &mpb->disk[i];
+ disk->total_blocks_hi = 0;
+ }
+ for (i = 0; i < mpb->num_raid_devs; ++i) {
+ struct imsm_dev *dev = get_imsm_dev(super, i);
+ if (!dev)
+ return;
+ for (n = 0; n < 2; ++n) {
+ struct imsm_map *map = get_imsm_map(dev, n);
+ if (!map)
+ continue;
+ map->pba_of_lba0_hi = 0;
+ map->blocks_per_member_hi = 0;
+ map->num_data_stripes_hi = 0;
+ }
+ }
+}
+
static int
load_and_parse_mpb(int fd, struct intel_super *super, char *devname, int keep_fd)
{
@@ -3602,7 +3628,7 @@ load_and_parse_mpb(int fd, struct intel_super *super, char *devname, int keep_fd
if (err)
return err;
err = parse_raid_devices(super);
-
+ clear_hi(super);
return err;
}
--
1.7.7.6

View File

@ -1,34 +0,0 @@
From 8453f8d0df0111cfd25e984afb7a64153b04bc27 Mon Sep 17 00:00:00 2001
From: Lukasz Dorau <lukasz.dorau@intel.com>
Date: Thu, 12 Jan 2012 10:40:00 +1100
Subject: [PATCH] fix: Monitor sometimes crashes
The "char cnt [40]" buffer is sometimes too small to hold all message
- in such case monitor crashes.
The buffer must be larger to be able to hold all message.
Signed-off-by: Lukasz Dorau <lukasz.dorau@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Monitor.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/Monitor.c b/Monitor.c
index 8bc8824..77f22aa 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -563,8 +563,9 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
struct mdinfo *sra =
sysfs_read(-1, st->devnum, GET_MISMATCH);
if (sra && sra->mismatch_cnt > 0) {
- char cnt[40];
- sprintf(cnt, " mismatches found: %d (on raid level %d)",
+ char cnt[80];
+ snprintf(cnt, sizeof(cnt),
+ " mismatches found: %d (on raid level %d)",
sra->mismatch_cnt, array.level);
alert("RebuildFinished", dev, cnt, ainfo);
} else
--
1.7.7.6

View File

@ -1,34 +0,0 @@
From 0c4304ca8b3328132537922fed8ee9e3bbb8a0fa Mon Sep 17 00:00:00 2001
From: Lukasz Dorau <lukasz.dorau@intel.com>
Date: Thu, 12 Jan 2012 10:57:20 +1100
Subject: [PATCH] fix: container creation with --incremental used.
If there is no name provided for a container by the metadata it is
always appropriate to use the metadata version name. create_mddev
will still add a uniquifying digit to the end so there is little risk
of confusion.
This makes the --incremental code behave the same as the --assemble code.
Signed-off-by: Lukasz Dorau <lukasz.dorau@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Incremental.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/Incremental.c b/Incremental.c
index 78c9712..60175af 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -259,8 +259,7 @@ int Incremental(char *devname, int verbose, int runstop,
name_to_use = info.name;
if (name_to_use[0] == 0 &&
- info.array.level == LEVEL_CONTAINER &&
- trustworthy == LOCAL) {
+ info.array.level == LEVEL_CONTAINER) {
name_to_use = info.text_version;
trustworthy = METADATA;
}
--
1.7.7.6

View File

@ -1,31 +0,0 @@
From b51702b82767b726e34d205c9e00a4f61d3044a7 Mon Sep 17 00:00:00 2001
From: Lukasz Dorau <lukasz.dorau@intel.com>
Date: Fri, 20 Apr 2012 11:00:25 +0200
Subject: [PATCH 3/3] fix: correct extending size of raid0 array
Setting "sync_action" to "idle" while extending size of raid0 array
is racy and sometimes fails.
"sync_action" should be set to "frozen" instead.
Signed-off-by: Lukasz Dorau <lukasz.dorau@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Grow.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Grow.c b/Grow.c
index 389992e..b4b9ff2 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1749,7 +1749,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
/* do not recync non-existing parity,
* we will drop it anyway
*/
- sysfs_set_str(sra, NULL, "sync_action", "idle");
+ sysfs_set_str(sra, NULL, "sync_action", "frozen");
/* go back to raid0, drop parity disk
*/
sysfs_set_str(sra, NULL, "level", "raid0");
--
1.7.7.6

View File

@ -1,63 +0,0 @@
From 13bcac9059b6aef7bf9e828fbdea285cf6adcbd2 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Fri, 13 Apr 2012 16:52:04 +0200
Subject: [PATCH 10/14] imsm: Add function imsm_get_free_size()
Add function imsm_imsm_get_free_size() using part of code from function
reserve_space().
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 25 ++++++++++++++++++++++++-
1 files changed, 24 insertions(+), 1 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 49e383f..7cc0ed5 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -6108,7 +6108,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
return 1;
}
-static int reserve_space(struct supertype *st, int raiddisks,
+static int imsm_get_free_size(struct supertype *st, int raiddisks,
unsigned long long size, int chunk,
unsigned long long *freesize)
{
@@ -6186,9 +6186,32 @@ static int reserve_space(struct supertype *st, int raiddisks,
*freesize = size;
+ dprintf("imsm: imsm_get_free_size() returns : %llu\n", size);
+
return 1;
}
+static int reserve_space(struct supertype *st, int raiddisks,
+ unsigned long long size, int chunk,
+ unsigned long long *freesize)
+{
+ struct intel_super *super = st->sb;
+ struct dl *dl;
+ int cnt;
+ int rv = 0;
+
+ rv = imsm_get_free_size(st, raiddisks, size, chunk, freesize);
+ if (rv) {
+ cnt = 0;
+ for (dl = super->disks; dl; dl = dl->next)
+ if (dl->e)
+ dl->raiddisk = cnt++;
+ rv = 1;
+ }
+
+ return rv;
+}
+
static int validate_geometry_imsm(struct supertype *st, int level, int layout,
int raiddisks, int *chunk, unsigned long long size,
char *dev, unsigned long long *freesize,
--
1.7.7.6

View File

@ -1,238 +0,0 @@
From f3871fdc6841a0505d3a987f4ea1cfb16f6cc201 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Fri, 13 Apr 2012 16:51:57 +0200
Subject: [PATCH 03/14] imsm: Add new metadata update for volume size
expansion
Add new meatdata update type imsm_update_size_change, and update metadata
for volume size expansion operation.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 124 insertions(+), 8 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 2e6a899..ac8922f 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -419,6 +419,7 @@ enum imsm_update_type {
update_reshape_migration,
update_takeover,
update_general_migration_checkpoint,
+ update_size_change,
};
struct imsm_update_activate_spare {
@@ -471,6 +472,12 @@ struct imsm_update_reshape_migration {
int new_disks[1]; /* new_raid_disks - old_raid_disks makedev number */
};
+struct imsm_update_size_change {
+ enum imsm_update_type type;
+ int subdev;
+ long long new_size;
+};
+
struct imsm_update_general_migration_checkpoint {
enum imsm_update_type type;
__u32 curr_migr_unit;
@@ -6974,7 +6981,8 @@ static void handle_missing(struct intel_super *super, struct imsm_dev *dev)
super->updates_pending++;
}
-static unsigned long long imsm_set_array_size(struct imsm_dev *dev)
+static unsigned long long imsm_set_array_size(struct imsm_dev *dev,
+ long long new_size)
{
int used_disks = imsm_num_data_members(dev, MAP_0);
unsigned long long array_blocks;
@@ -6993,8 +7001,17 @@ static unsigned long long imsm_set_array_size(struct imsm_dev *dev)
/* set array size in metadata
*/
- map = get_imsm_map(dev, MAP_0);
- array_blocks = blocks_per_member(map) * used_disks;
+ if (new_size <= 0) {
+ /* OLCE size change is caused by added disks
+ */
+ map = get_imsm_map(dev, MAP_0);
+ array_blocks = blocks_per_member(map) * used_disks;
+ } else {
+ /* Online Volume Size Change
+ * Using available free space
+ */
+ array_blocks = new_size;
+ }
/* round array size down to closest MB
*/
@@ -7051,7 +7068,7 @@ static void imsm_progress_container_reshape(struct intel_super *super)
memcpy(map2, map, copy_map_size);
map2->num_members = prev_num_members;
- imsm_set_array_size(dev);
+ imsm_set_array_size(dev, -1);
super->clean_migration_record_by_mdmon = 1;
super->updates_pending++;
}
@@ -7941,7 +7958,7 @@ skip_disk_add:
*tofree = *space_list;
/* calculate new size
*/
- imsm_set_array_size(new_dev);
+ imsm_set_array_size(new_dev, -1);
ret_val = 1;
}
@@ -7956,6 +7973,44 @@ error_disk_add:
return ret_val;
}
+static int apply_size_change_update(struct imsm_update_size_change *u,
+ struct intel_super *super)
+{
+ struct intel_dev *id;
+ int ret_val = 0;
+
+ dprintf("apply_size_change_update()\n");
+ if ((u->subdev < 0) ||
+ (u->subdev > 1)) {
+ dprintf("imsm: Error: Wrong subdev: %i\n", u->subdev);
+ return ret_val;
+ }
+
+ for (id = super->devlist ; id; id = id->next) {
+ if (id->index == (unsigned)u->subdev) {
+ struct imsm_dev *dev = get_imsm_dev(super, u->subdev);
+ struct imsm_map *map = get_imsm_map(dev, MAP_0);
+ int used_disks = imsm_num_data_members(dev, MAP_0);
+ unsigned long long blocks_per_member;
+
+ /* calculate new size
+ */
+ blocks_per_member = u->new_size / used_disks;
+ dprintf("imsm: apply_size_change_update(size: %llu, "
+ "blocks per member: %llu)\n",
+ u->new_size, blocks_per_member);
+ set_blocks_per_member(map, blocks_per_member);
+ imsm_set_array_size(dev, u->new_size);
+
+ ret_val = 1;
+ break;
+ }
+ }
+
+ return ret_val;
+}
+
+
static int apply_update_activate_spare(struct imsm_update_activate_spare *u,
struct intel_super *super,
struct active_array *active_array)
@@ -8155,7 +8210,7 @@ static int apply_reshape_container_disks_update(struct imsm_update_reshape *u,
newmap = get_imsm_map(newdev, MAP_1);
memcpy(newmap, oldmap, sizeof_imsm_map(oldmap));
- imsm_set_array_size(newdev);
+ imsm_set_array_size(newdev, -1);
}
sp = (void **)id->dev;
@@ -8363,6 +8418,12 @@ static void imsm_process_update(struct supertype *st,
super->updates_pending++;
break;
}
+ case update_size_change: {
+ struct imsm_update_size_change *u = (void *)update->buf;
+ if (apply_size_change_update(u, super))
+ super->updates_pending++;
+ break;
+ }
case update_activate_spare: {
struct imsm_update_activate_spare *u = (void *) update->buf;
if (apply_update_activate_spare(u, super, st->arrays))
@@ -8757,6 +8818,9 @@ static void imsm_prepare_update(struct supertype *st,
dprintf("New anchor length is %llu\n", (unsigned long long)len);
break;
}
+ case update_size_change: {
+ break;
+ }
case update_create_array: {
struct imsm_update_create_array *u = (void *) update->buf;
struct intel_dev *dv;
@@ -9614,6 +9678,43 @@ abort:
return 0;
}
+
+/******************************************************************************
+ * function: imsm_create_metadata_update_for_size_change()
+ * Creates update for IMSM array for array size change.
+ *
+ ******************************************************************************/
+static int imsm_create_metadata_update_for_size_change(
+ struct supertype *st,
+ struct geo_params *geo,
+ struct imsm_update_size_change **updatep)
+{
+ struct intel_super *super = st->sb;
+ int update_memory_size = 0;
+ struct imsm_update_size_change *u = NULL;
+
+ dprintf("imsm_create_metadata_update_for_size_change(enter)"
+ " New size = %llu\n", geo->size);
+
+ /* size of all update data without anchor */
+ update_memory_size = sizeof(struct imsm_update_size_change);
+
+ u = calloc(1, update_memory_size);
+ if (u == NULL) {
+ dprintf("error: cannot get memory for "
+ "imsm_create_metadata_update_for_size_change\n");
+ return 0;
+ }
+ u->type = update_size_change;
+ u->subdev = super->current_vol;
+ u->new_size = geo->size;
+
+ dprintf("imsm: reshape update preparation : OK\n");
+ *updatep = u;
+
+ return update_memory_size;
+}
+
/******************************************************************************
* function: imsm_create_metadata_update_for_migration()
* Creates update for IMSM array.
@@ -10023,8 +10124,23 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
}
break;
case CH_ARRAY_SIZE: {
- /* ToDo: Prepare metadata update here
- */
+ struct imsm_update_size_change *u = NULL;
+ int len =
+ imsm_create_metadata_update_for_size_change(
+ st, &geo, &u);
+ if (len < 1) {
+ dprintf("imsm: "
+ "Cannot prepare update\n");
+ break;
+ }
+ ret_val = 0;
+ /* update metadata locally */
+ imsm_update_metadata_locally(st, u, len);
+ /* and possibly remotely */
+ if (st->update_tail)
+ append_metadata_update(st, u, len);
+ else
+ free(u);
}
break;
default:
--
1.7.7.6

View File

@ -1,129 +0,0 @@
From 54397ed97af065b1e3a12d6beab09bc05a07a9d0 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Fri, 13 Apr 2012 16:51:58 +0200
Subject: [PATCH 04/14] imsm: Execute size change for external metatdata
For external metatdata ioctl doesn't set new size. Set new size using sysfs.
Put code for size change in to function to re-use the same code as during
On-line Capacity Expansion
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
Grow.c | 78 ++++++++++++++++++++++++++++++++++++++-------------------------
1 files changed, 47 insertions(+), 31 deletions(-)
diff --git a/Grow.c b/Grow.c
index e3ef8d4..5fd44aa 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1386,6 +1386,44 @@ char *analyse_change(struct mdinfo *info, struct reshape *re)
return NULL;
}
+static int set_array_size(struct supertype *st, struct mdinfo *sra,
+ char *text_version)
+{
+ struct mdinfo *info;
+ char *subarray;
+ int ret_val = -1;
+
+ if ((st == NULL) || (sra == NULL))
+ return ret_val;
+
+ if (text_version == NULL)
+ text_version = sra->text_version;
+ subarray = strchr(text_version+1, '/')+1;
+ info = st->ss->container_content(st, subarray);
+ if (info) {
+ unsigned long long current_size = 0;
+ unsigned long long new_size =
+ info->custom_array_size/2;
+
+ if (sysfs_get_ll(sra, NULL, "array_size", &current_size) == 0 &&
+ new_size > current_size) {
+ if (sysfs_set_num(sra, NULL, "array_size", new_size)
+ < 0)
+ dprintf("Error: Cannot set array size");
+ else {
+ ret_val = 0;
+ dprintf("Array size changed");
+ }
+ dprintf(" from %llu to %llu.\n",
+ current_size, new_size);
+ }
+ sysfs_free(info);
+ } else
+ dprintf("Error: set_array_size(): info pointer in NULL\n");
+
+ return ret_val;
+}
+
static int reshape_array(char *container, int fd, char *devname,
struct supertype *st, struct mdinfo *info,
int force, struct mddev_dev *devlist,
@@ -1636,7 +1674,6 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
"2TB per device\n");
size = min_csize;
}
-
array.size = size;
if (array.size != size) {
/* got truncated to 32bit, write to
@@ -1647,8 +1684,14 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
"component_size", size);
else
rv = -1;
- } else
+ } else {
rv = ioctl(fd, SET_ARRAY_INFO, &array);
+ /* manage array size when it is managed externally
+ */
+ if ((rv == 0) && st->ss->external)
+ rv = set_array_size(st, sra, sra->text_version);
+ }
+
if (rv != 0) {
int err = errno;
@@ -2507,35 +2550,8 @@ started:
*/
if (reshape.before.data_disks !=
reshape.after.data_disks &&
- info->custom_array_size) {
- struct mdinfo *info2;
- char *subarray = strchr(info->text_version+1, '/')+1;
-
- info2 = st->ss->container_content(st, subarray);
- if (info2) {
- unsigned long long current_size = 0;
- unsigned long long new_size =
- info2->custom_array_size/2;
-
- if (sysfs_get_ll(sra,
- NULL,
- "array_size",
- &current_size) == 0 &&
- new_size > current_size) {
- if (sysfs_set_num(sra, NULL,
- "array_size", new_size)
- < 0)
- dprintf("Error: Cannot"
- " set array size");
- else
- dprintf("Array size "
- "changed");
- dprintf(" from %llu to %llu.\n",
- current_size, new_size);
- }
- sysfs_free(info2);
- }
- }
+ info->custom_array_size)
+ set_array_size(st, info, info->text_version);
if (info->new_level != reshape.level) {
--
1.7.7.6

View File

@ -1,103 +0,0 @@
From 7abc98717c32d08a2aab366e79c12a91573fb538 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Fri, 13 Apr 2012 16:51:56 +0200
Subject: [PATCH 02/14] imsm: FIX: Add volume size expand support to
imsm_analyze_change()
Patch adds ability to function imsm_analyze_change() for:
1. Detect size change request for volume operation.
2. Check and correct size for change.
3. Set new change kind to CH_ARRAY_SIZE
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 5f86539..2e6a899 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -405,6 +405,7 @@ struct extent {
enum imsm_reshape_type {
CH_TAKEOVER,
CH_MIGRATION,
+ CH_ARRAY_SIZE,
};
/* definition of messages passed to imsm_process_update */
@@ -9726,6 +9727,10 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
int devNumChange = 0;
/* imsm compatible layout value for array geometry verification */
int imsm_layout = -1;
+ int data_disks;
+ struct imsm_dev *dev;
+ struct intel_super *super;
+ long long current_size;
getinfo_super_imsm_volume(st, &info, NULL);
if ((geo->level != info.array.level) &&
@@ -9807,6 +9812,47 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
geo->chunksize = info.array.chunk_size;
chunk = geo->chunksize / 1024;
+
+ super = st->sb;
+ dev = get_imsm_dev(super, super->current_vol);
+ data_disks = imsm_num_data_members(dev , MAP_0);
+ /* compute current size in K per disk member
+ */
+ current_size = info.custom_array_size / 2 / data_disks;
+
+ if ((current_size != geo->size) && (geo->size > 0)) {
+ if (change != -1) {
+ fprintf(stderr,
+ Name " Error. Size change should be the only "
+ "one at a time.\n");
+ change = -1;
+ goto analyse_change_exit;
+ }
+ if ((super->current_vol + 1) != super->anchor->num_raid_devs) {
+ fprintf(stderr,
+ Name " Error. The last volume in container "
+ "can be expanded only (%i/%i).\n",
+ super->current_vol, st->devnum);
+ goto analyse_change_exit;
+ }
+ geo->size *= 2;
+ /* round size due to metadata compatibility
+ */
+ geo->size = (geo->size >> SECT_PER_MB_SHIFT)
+ << SECT_PER_MB_SHIFT;
+ dprintf("Prepare update for size change to %llu\n", geo->size );
+ if (current_size >= geo->size) {
+ fprintf(stderr,
+ Name " Error. Size expanssion is supported only"
+ " (current size is %llu, requested size "
+ "/rounded/ is %llu).\n",
+ current_size, geo->size);
+ goto analyse_change_exit;
+ }
+ geo->size *= data_disks;
+ geo->raid_disks = dev->vol.map->num_members;
+ change = CH_ARRAY_SIZE;
+ }
if (!validate_geometry_imsm(st,
geo->level,
imsm_layout,
@@ -9976,6 +10022,11 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
free(u);
}
break;
+ case CH_ARRAY_SIZE: {
+ /* ToDo: Prepare metadata update here
+ */
+ }
+ break;
default:
ret_val = 1;
}
--
1.7.7.6

View File

@ -1,32 +0,0 @@
From e1742195ff3dba97929f81af6b7633481a23397a Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Tue, 7 Feb 2012 15:03:51 +0100
Subject: [PATCH 07/12] imsm: FIX: Chunk size migration problem
When chunk size migration occurs (e.g. 128k->4k) first checkpoint cannot
be set in md due to too small step. Correct migration record initialization
to allow whole copy area usage and increase migration checkpoint step.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 19a2c84..f5762d8 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -8913,7 +8913,8 @@ void init_migr_record_imsm(struct supertype *st, struct imsm_dev *dev,
migr_rec->dest_depth_per_unit = GEN_MIGR_AREA_SIZE /
max(map_dest->blocks_per_strip, map_src->blocks_per_strip);
- migr_rec->dest_depth_per_unit *= map_dest->blocks_per_strip;
+ migr_rec->dest_depth_per_unit *=
+ max(map_dest->blocks_per_strip, map_src->blocks_per_strip);
new_data_disks = imsm_num_data_members(dev, MAP_0);
migr_rec->blocks_per_unit =
__cpu_to_le32(migr_rec->dest_depth_per_unit * new_data_disks);
--
1.7.4.4

View File

@ -1,88 +0,0 @@
From 51d83f5d119f9b727cc715b22b1625332bd0130b Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Thu, 9 Feb 2012 12:37:04 +1100
Subject: [PATCH 10/12] imsm: FIX: Clear migration record when migration
switches to next volume.
When OLCE is in progress, checkpoint steps are getting bigger due to added space during process.
When mdadm fails after saving "max" to sync_max, mdmon will monitor process
and switch reshape to next array. At this moment we have got information
inconsistency between metadata and migration record.
To avoid this, clear migration record by mdmon /exception from the rule
that migration record is maintained by mdadm/ when reshape switches
to next array.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 19 ++++++++++++++++---
1 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 5f451f3..958edb5 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -353,6 +353,9 @@ struct intel_super {
void *migr_rec_buf; /* buffer for I/O operations */
struct migr_record *migr_rec; /* migration record */
};
+ int clean_migration_record_by_mdmon; /* when reshape is switched to next
+ array, it indicates that mdmon is allowed to clean migration
+ record */
size_t len; /* size of the 'buf' allocation */
void *next_buf; /* for realloc'ing buf from the manager */
size_t next_len;
@@ -3465,6 +3468,7 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
free(super->buf);
return 2;
}
+ super->clean_migration_record_by_mdmon = 0;
if (!sectors) {
check_sum = __gen_imsm_checksum(super->anchor);
@@ -5029,6 +5033,10 @@ static int write_super_imsm(struct supertype *st, int doclose)
sum = __gen_imsm_checksum(mpb);
mpb->check_sum = __cpu_to_le32(sum);
+ if (super->clean_migration_record_by_mdmon) {
+ clear_migration_record = 1;
+ super->clean_migration_record_by_mdmon = 0;
+ }
if (clear_migration_record)
memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SIZE);
@@ -5036,9 +5044,6 @@ static int write_super_imsm(struct supertype *st, int doclose)
for (d = super->disks; d ; d = d->next) {
if (d->index < 0 || is_failed(&d->disk))
continue;
- if (store_imsm_mpb(d->fd, mpb))
- fprintf(stderr, "%s: failed for device %d:%d (fd: %d)%s\n",
- __func__, d->major, d->minor, d->fd, strerror(errno));
if (clear_migration_record) {
unsigned long long dsize;
@@ -5050,6 +5055,13 @@ static int write_super_imsm(struct supertype *st, int doclose)
perror("Write migr_rec failed");
}
}
+
+ if (store_imsm_mpb(d->fd, mpb))
+ fprintf(stderr,
+ "%s: failed for device %d:%d (fd: %d)%s\n",
+ __func__, d->major, d->minor,
+ d->fd, strerror(errno));
+
if (doclose) {
close(d->fd);
d->fd = -1;
@@ -6928,6 +6940,7 @@ static void imsm_progress_container_reshape(struct intel_super *super)
map2->num_members = prev_num_members;
imsm_set_array_size(dev);
+ super->clean_migration_record_by_mdmon = 1;
super->updates_pending++;
}
}
--
1.7.4.4

View File

@ -1,126 +0,0 @@
From c41e00b2e68aed0ab9d41f70a3e119d86a92cf29 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Fri, 13 Apr 2012 16:52:06 +0200
Subject: [PATCH 12/14] imsm: FIX: Component size alignment check
Put currently existing code for alignment correction in to function
imsm_component_size_aligment_check() and use it for align component size
to chunk size during volume size expansion operation.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 68 ++++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 48 insertions(+), 20 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 1f47234..9685726 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -2454,6 +2454,32 @@ int imsm_reshape_blocks_arrays_changes(struct intel_super *super)
}
return rv;
}
+static unsigned long long imsm_component_size_aligment_check(int level,
+ int chunk_size,
+ unsigned long long component_size)
+{
+ unsigned int component_size_alligment;
+
+ /* check component size aligment
+ */
+ component_size_alligment = component_size % (chunk_size/512);
+
+ dprintf("imsm_component_size_aligment_check(Level: %i, "
+ "chunk_size = %i, component_size = %llu), "
+ "component_size_alligment = %u\n",
+ level, chunk_size, component_size,
+ component_size_alligment);
+
+ if (component_size_alligment && (level != 1) && (level != UnSet)) {
+ dprintf("imsm: reported component size alligned from %llu ",
+ component_size);
+ component_size -= component_size_alligment;
+ dprintf("to %llu (%i).\n",
+ component_size, component_size_alligment);
+ }
+
+ return component_size;
+}
static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, char *dmap)
{
@@ -2465,7 +2491,6 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
struct imsm_map *map_to_analyse = map;
struct dl *dl;
char *devname;
- unsigned int component_size_alligment;
int map_disks = info->array.raid_disks;
memset(info, 0, sizeof(*info));
@@ -2548,19 +2573,10 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
info->data_offset = pba_of_lba0(map_to_analyse);
info->component_size = blocks_per_member(map_to_analyse);
- /* check component size aligment
- */
- component_size_alligment =
- info->component_size % (info->array.chunk_size/512);
-
- if (component_size_alligment &&
- (info->array.level != 1) && (info->array.level != UnSet)) {
- dprintf("imsm: reported component size alligned from %llu ",
- info->component_size);
- info->component_size -= component_size_alligment;
- dprintf("to %llu (%i).\n",
- info->component_size, component_size_alligment);
- }
+ info->component_size = imsm_component_size_aligment_check(
+ info->array.level,
+ info->array.chunk_size,
+ info->component_size);
memset(info->uuid, 0, sizeof(info->uuid));
info->recovery_start = MaxSector;
@@ -9949,9 +9965,18 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
super = st->sb;
dev = get_imsm_dev(super, super->current_vol);
data_disks = imsm_num_data_members(dev , MAP_0);
- /* compute current size in K per disk member
+ /* compute current size per disk member
*/
- current_size = info.custom_array_size / 2 / data_disks;
+ current_size = info.custom_array_size / data_disks;
+
+ if (geo->size > 0) {
+ /* align component size
+ */
+ geo->size = imsm_component_size_aligment_check(
+ get_imsm_raid_level(dev->vol.map),
+ chunk * 1024,
+ geo->size * 2);
+ }
if ((current_size != geo->size) && (geo->size >= 0)) {
if (change != -1) {
@@ -9984,10 +10009,13 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
}
geo->size = freesize + current_size;
- /* round to chunk size */
- geo->size &= ~(chunk-1);
- } else
- geo->size *= 2;
+ /* align component size
+ */
+ geo->size = imsm_component_size_aligment_check(
+ get_imsm_raid_level(dev->vol.map),
+ chunk * 1024,
+ geo->size);
+ }
if ((direction == ROLLBACK_METADATA_CHANGES)) {
/* accept size for rollback only
--
1.7.7.6

View File

@ -1,44 +0,0 @@
From d2bde6d3aa9468ddf0965f09907a666b92186e42 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Tue, 7 Feb 2012 15:03:11 +0100
Subject: [PATCH 02/12] imsm: FIX: No new missing disks are allowed during
general migration
When during incremental assembly general migration is in progress,
starting degraded array causes that no more disks (even present)
can be added later as array is already started.
Request all previously present disks during general migration for assembly.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index eba11d6..17034bb 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -2683,7 +2683,17 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
enough = 0;
else /* we're normal, or already degraded */
enough = 1;
-
+ if (is_gen_migration(dev) && missing) {
+ /* during general migration we need all disks
+ * that process is running on.
+ * No new missing disk is allowed.
+ */
+ max_enough = -1;
+ enough = -1;
+ /* no more checks necessary
+ */
+ break;
+ }
/* in the missing/failed disk case check to see
* if at least one array is runnable
*/
--
1.7.4.4

View File

@ -1,130 +0,0 @@
From fbf3d20214537e5e4bf6fb04f191418a58e88463 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Fri, 13 Apr 2012 16:52:00 +0200
Subject: [PATCH 06/14] imsm: FIX: Support metadata changes rollback
Add metadata rollback specific code for imsm.
Let reshape_super() ability to differentiate metadata apply and rollback
actions.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 56 ++++++++++++++++++++++++++++++++++++++------------------
1 files changed, 38 insertions(+), 18 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 32a53d1..49e383f 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -9470,7 +9470,8 @@ static int imsm_find_array_minor_by_subdev(int subdev, int container, int *minor
static int imsm_reshape_is_allowed_on_container(struct supertype *st,
struct geo_params *geo,
- int *old_raid_disks)
+ int *old_raid_disks,
+ int direction)
{
/* currently we only support increasing the number of devices
* for a container. This increases the number of device for each
@@ -9494,6 +9495,12 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
return ret_val;
}
+ if (direction == ROLLBACK_METADATA_CHANGES) {
+ dprintf("imsm: Metadata changes rollback is not supported for "
+ "container operation.\n");
+ return ret_val;
+ }
+
info = container_content_imsm(st, NULL);
for (member = info; member; member = member->next) {
int result;
@@ -9814,11 +9821,13 @@ static void imsm_update_metadata_locally(struct supertype *st,
* Function: imsm_analyze_change
* Description: Function analyze change for single volume
* and validate if transition is supported
-* Parameters: Geometry parameters, supertype structure
+* Parameters: Geometry parameters, supertype structure,
+* metadata change direction (apply/rollback)
* Returns: Operation type code on success, -1 if fail
****************************************************************************/
enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
- struct geo_params *geo)
+ struct geo_params *geo,
+ int direction)
{
struct mdinfo info;
int change = -1;
@@ -9937,18 +9946,24 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
goto analyse_change_exit;
}
geo->size *= 2;
- /* round size due to metadata compatibility
- */
- geo->size = (geo->size >> SECT_PER_MB_SHIFT)
- << SECT_PER_MB_SHIFT;
- dprintf("Prepare update for size change to %llu\n", geo->size );
- if (current_size >= geo->size) {
- fprintf(stderr,
- Name " Error. Size expanssion is supported only"
- " (current size is %llu, requested size "
- "/rounded/ is %llu).\n",
- current_size, geo->size);
- goto analyse_change_exit;
+ if ((direction == ROLLBACK_METADATA_CHANGES)) {
+ /* accept size for rollback only
+ */
+ } else {
+ /* round size due to metadata compatibility
+ */
+ geo->size = (geo->size >> SECT_PER_MB_SHIFT)
+ << SECT_PER_MB_SHIFT;
+ dprintf("Prepare update for size change to %llu\n",
+ geo->size );
+ if (current_size >= geo->size) {
+ fprintf(stderr,
+ Name " Error. Size expanssion is "
+ "supported only (current size is %llu, "
+ "requested size /rounded/ is %llu).\n",
+ current_size, geo->size);
+ goto analyse_change_exit;
+ }
}
geo->size *= data_disks;
geo->raid_disks = dev->vol.map->num_members;
@@ -9978,7 +9993,12 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
}
analyse_change_exit:
-
+ if ((direction == ROLLBACK_METADATA_CHANGES) &&
+ ((change == CH_MIGRATION) || (change == CH_TAKEOVER))) {
+ dprintf("imsm: Metadata changes rollback is not supported for "
+ "migration and takeover operations.\n");
+ change = -1;
+ }
return change;
}
@@ -10049,7 +10069,7 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
int old_raid_disks = 0;
if (imsm_reshape_is_allowed_on_container(
- st, &geo, &old_raid_disks)) {
+ st, &geo, &old_raid_disks, direction)) {
struct imsm_update_reshape *u = NULL;
int len;
@@ -10098,7 +10118,7 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
goto exit_imsm_reshape_super;
}
super->current_vol = dev->index;
- change = imsm_analyze_change(st, &geo);
+ change = imsm_analyze_change(st, &geo, direction);
switch (change) {
case CH_TAKEOVER:
ret_val = imsm_takeover(st, &geo);
--
1.7.7.6

View File

@ -1,36 +0,0 @@
From 36fd8ccc0e755042e3983a2bd02523461b5f8307 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Fri, 13 Apr 2012 16:51:55 +0200
Subject: [PATCH 01/14] imsm: FIX: Update function imsm_num_data_members() for
Raid1/10
Function imsm_num_data_members() returns wrong value for raid 1 and 10.
It returns all data member but it should return number of unique data
members (excluding mirror devices)
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 088e6bc..5f86539 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -2032,9 +2032,11 @@ static __u8 imsm_num_data_members(struct imsm_dev *dev, int second_map)
switch (get_imsm_raid_level(map)) {
case 0:
+ return map->num_members;
+ break;
case 1:
case 10:
- return map->num_members;
+ return map->num_members/2;
case 5:
return map->num_members - 1;
default:
--
1.7.7.6

View File

@ -1,29 +0,0 @@
From bf5cf7c705f292a070746c83f9dd00d7662f458d Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Tue, 7 Feb 2012 15:03:27 +0100
Subject: [PATCH 04/12] imsm: FIX: imsm_get_allowed_degradation() doesn't
count degradation for raid1
Missing case raid1 added to function.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 17034bb..19a2c84 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -8771,6 +8771,7 @@ static int imsm_get_allowed_degradation(int level, int raid_disks,
struct imsm_dev *dev)
{
switch (level) {
+ case 1:
case 10:{
int ret_val = 0;
struct imsm_map *map;
--
1.7.4.4

View File

@ -1,43 +0,0 @@
From 6a75c8ca79b4cf89a5d1ac24b484b75e8a7e9fb4 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Thu, 9 Feb 2012 12:36:42 +1100
Subject: [PATCH 09/12] imsm: FIX: use md position to reshape restart
When reshape is broken it can occur that metadata is not saved properly.
This can cause that reshape process is farther in md than metadata states.
On restart save checkpoint to store current position /probably farther/
that can be read from md.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index f5762d8..5f451f3 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -10067,6 +10067,18 @@ static int imsm_manage_reshape(
"are present in copy area.\n");
goto abort;
}
+ /* Save checkpoint to update migration record for current
+ * reshape position (in md). It can be farther than current
+ * reshape position in metadata.
+ */
+ if (save_checkpoint_imsm(st, sra, UNIT_SRC_NORMAL) == 1) {
+ /* ignore error == 2, this can mean end of reshape here
+ */
+ dprintf("imsm: Cannot write checkpoint to "
+ "migration record (UNIT_SRC_NORMAL, "
+ "initial save)\n");
+ goto abort;
+ }
}
/* size for data */
--
1.7.4.4

View File

@ -1,60 +0,0 @@
From b130333f39734eed08d38d6c36025fa4d618bc52 Mon Sep 17 00:00:00 2001
From: Adam Kwolek <adam.kwolek@intel.com>
Date: Fri, 13 Apr 2012 16:52:05 +0200
Subject: [PATCH 11/14] imsm: Support setting max size for size change
operation
Add support for setting max size for size change operation using
imsm_get_free_size() function for computing maximum available space.
Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 24 ++++++++++++++++++++++--
1 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 7cc0ed5..1f47234 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -9953,7 +9953,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
*/
current_size = info.custom_array_size / 2 / data_disks;
- if ((current_size != geo->size) && (geo->size > 0)) {
+ if ((current_size != geo->size) && (geo->size >= 0)) {
if (change != -1) {
fprintf(stderr,
Name " Error. Size change should be the only "
@@ -9968,7 +9968,27 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
super->current_vol, st->devnum);
goto analyse_change_exit;
}
- geo->size *= 2;
+ if (geo->size == 0) {
+ /* requested size change to the maximum available size
+ */
+ unsigned long long freesize;
+ int rv;
+
+ rv = imsm_get_free_size(st, dev->vol.map->num_members,
+ 0, chunk, &freesize);
+ if (rv == 0) {
+ fprintf(stderr, Name " Error. Cannot find "
+ "maximum available space.\n");
+ change = -1;
+ goto analyse_change_exit;
+ }
+ geo->size = freesize + current_size;
+
+ /* round to chunk size */
+ geo->size &= ~(chunk-1);
+ } else
+ geo->size *= 2;
+
if ((direction == ROLLBACK_METADATA_CHANGES)) {
/* accept size for rollback only
*/
--
1.7.7.6

View File

@ -1,484 +0,0 @@
From 5551b113dc18a6275fb04c7e7e3b76c656926e0a Mon Sep 17 00:00:00 2001
From: "Czarnowska, Anna" <anna.czarnowska@intel.com>
Date: Mon, 2 Apr 2012 10:15:03 +1000
Subject: [PATCH 1/7] imsm: avoid overflows for disks over 1TB
Calculating array_blocks using info->size causes error on activation of
volume using disks over 1 TB. unsigned long long size parameter
is used instead.
total_blocks, pba_of_lba0, blocks_per_member and num_data_stripes overflow
when using disks over 2TB.
Part of fillers in metadata is used to contain hi bits of the numbers
that are likely to go over 32 bit limit.
Functions are added to get and set such fields as the hi bits are not
adjacent with low bits in the structures.
Acked-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Anna Czarnowska <anna.czarnowska@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 198 +++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 131 insertions(+), 67 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index a351b60..c65d39b 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -95,15 +95,16 @@
#define IMSM_MAX_DEVICES 255
struct imsm_disk {
__u8 serial[MAX_RAID_SERIAL_LEN];/* 0xD8 - 0xE7 ascii serial number */
- __u32 total_blocks; /* 0xE8 - 0xEB total blocks */
+ __u32 total_blocks_lo; /* 0xE8 - 0xEB total blocks lo */
__u32 scsi_id; /* 0xEC - 0xEF scsi ID */
#define SPARE_DISK __cpu_to_le32(0x01) /* Spare */
#define CONFIGURED_DISK __cpu_to_le32(0x02) /* Member of some RaidDev */
#define FAILED_DISK __cpu_to_le32(0x04) /* Permanent failure */
__u32 status; /* 0xF0 - 0xF3 */
__u32 owner_cfg_num; /* which config 0,1,2... owns this disk */
-#define IMSM_DISK_FILLERS 4
- __u32 filler[IMSM_DISK_FILLERS]; /* 0xF4 - 0x107 MPB_DISK_FILLERS for future expansion */
+ __u32 total_blocks_hi; /* 0xF4 - 0xF5 total blocks hi */
+#define IMSM_DISK_FILLERS 3
+ __u32 filler[IMSM_DISK_FILLERS]; /* 0xF5 - 0x107 MPB_DISK_FILLERS for future expansion */
};
/* map selector for map managment
@@ -114,9 +115,9 @@ struct imsm_disk {
/* RAID map configuration infos. */
struct imsm_map {
- __u32 pba_of_lba0; /* start address of partition */
- __u32 blocks_per_member;/* blocks per member */
- __u32 num_data_stripes; /* number of data stripes */
+ __u32 pba_of_lba0_lo; /* start address of partition */
+ __u32 blocks_per_member_lo;/* blocks per member */
+ __u32 num_data_stripes_lo; /* number of data stripes */
__u16 blocks_per_strip;
__u8 map_state; /* Normal, Uninitialized, Degraded, Failed */
#define IMSM_T_STATE_NORMAL 0
@@ -131,7 +132,10 @@ struct imsm_map {
__u8 num_domains; /* number of parity domains */
__u8 failed_disk_num; /* valid only when state is degraded */
__u8 ddf;
- __u32 filler[7]; /* expansion area */
+ __u32 pba_of_lba0_hi;
+ __u32 blocks_per_member_hi;
+ __u32 num_data_stripes_hi;
+ __u32 filler[4]; /* expansion area */
#define IMSM_ORD_REBUILD (1 << 24)
__u32 disk_ord_tbl[1]; /* disk_ord_tbl[num_members],
* top byte contains some flags
@@ -361,7 +365,7 @@ struct intel_super {
size_t next_len;
int updates_pending; /* count of pending updates for mdmon */
int current_vol; /* index of raid device undergoing creation */
- __u32 create_offset; /* common start for 'current_vol' */
+ unsigned long long create_offset; /* common start for 'current_vol' */
__u32 random; /* random data for seeding new family numbers */
struct intel_dev *devlist;
struct dl {
@@ -870,6 +874,69 @@ static int count_memberships(struct dl *dl, struct intel_super *super)
static __u32 imsm_min_reserved_sectors(struct intel_super *super);
+static int split_ull(unsigned long long n, __u32 *lo, __u32 *hi)
+{
+ if (lo == 0 || hi == 0)
+ return 1;
+ *lo = __le32_to_cpu((unsigned)n);
+ *hi = __le32_to_cpu((unsigned)(n >> 32));
+ return 0;
+}
+
+static unsigned long long join_u32(__u32 lo, __u32 hi)
+{
+ return (unsigned long long)__le32_to_cpu(lo) |
+ (((unsigned long long)__le32_to_cpu(hi)) << 32);
+}
+
+static unsigned long long total_blocks(struct imsm_disk *disk)
+{
+ if (disk == NULL)
+ return 0;
+ return join_u32(disk->total_blocks_lo, disk->total_blocks_hi);
+}
+
+static unsigned long long pba_of_lba0(struct imsm_map *map)
+{
+ if (map == NULL)
+ return 0;
+ return join_u32(map->pba_of_lba0_lo, map->pba_of_lba0_hi);
+}
+
+static unsigned long long blocks_per_member(struct imsm_map *map)
+{
+ if (map == NULL)
+ return 0;
+ return join_u32(map->blocks_per_member_lo, map->blocks_per_member_hi);
+}
+
+static unsigned long long num_data_stripes(struct imsm_map *map)
+{
+ if (map == NULL)
+ return 0;
+ return join_u32(map->num_data_stripes_lo, map->num_data_stripes_hi);
+}
+
+static void set_total_blocks(struct imsm_disk *disk, unsigned long long n)
+{
+ split_ull(n, &disk->total_blocks_lo, &disk->total_blocks_hi);
+}
+
+static void set_pba_of_lba0(struct imsm_map *map, unsigned long long n)
+{
+ split_ull(n, &map->pba_of_lba0_lo, &map->pba_of_lba0_hi);
+}
+
+static void set_blocks_per_member(struct imsm_map *map, unsigned long long n)
+{
+ split_ull(n, &map->blocks_per_member_lo, &map->blocks_per_member_hi);
+}
+
+static void set_num_data_stripes(struct imsm_map *map, unsigned long long n)
+{
+ split_ull(n, &map->num_data_stripes_lo, &map->num_data_stripes_hi);
+}
+
static struct extent *get_extents(struct intel_super *super, struct dl *dl)
{
/* find a list of used extents on the given physical device */
@@ -897,8 +964,8 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl)
struct imsm_map *map = get_imsm_map(dev, MAP_0);
if (get_imsm_disk_slot(map, dl->index) >= 0) {
- e->start = __le32_to_cpu(map->pba_of_lba0);
- e->size = __le32_to_cpu(map->blocks_per_member);
+ e->start = pba_of_lba0(map);
+ e->size = blocks_per_member(map);
e++;
}
}
@@ -911,10 +978,9 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl)
*/
if (memberships) {
struct extent *last = &rv[memberships - 1];
- __u32 remainder;
+ unsigned long long remainder;
- remainder = __le32_to_cpu(dl->disk.total_blocks) -
- (last->start + last->size);
+ remainder = total_blocks(&dl->disk) - (last->start + last->size);
/* round down to 1k block to satisfy precision of the kernel
* 'size' interface
*/
@@ -925,7 +991,7 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl)
if (reservation > remainder)
reservation = remainder;
}
- e->start = __le32_to_cpu(dl->disk.total_blocks) - reservation;
+ e->start = total_blocks(&dl->disk) - reservation;
e->size = 0;
return rv;
}
@@ -954,7 +1020,7 @@ static __u32 imsm_reserved_sectors(struct intel_super *super, struct dl *dl)
for (i = 0; e[i].size; i++)
continue;
- rv = __le32_to_cpu(dl->disk.total_blocks) - e[i].start;
+ rv = total_blocks(&dl->disk) - e[i].start;
free(e);
@@ -984,7 +1050,8 @@ static __u32 imsm_min_reserved_sectors(struct intel_super *super)
{
struct extent *e;
int i;
- __u32 min_active, remainder;
+ unsigned long long min_active;
+ __u32 remainder;
__u32 rv = MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS;
struct dl *dl, *dl_min = NULL;
@@ -995,9 +1062,10 @@ static __u32 imsm_min_reserved_sectors(struct intel_super *super)
for (dl = super->disks; dl; dl = dl->next) {
if (dl->index < 0)
continue;
- if (dl->disk.total_blocks < min_active || min_active == 0) {
+ unsigned long long blocks = total_blocks(&dl->disk);
+ if (blocks < min_active || min_active == 0) {
dl_min = dl;
- min_active = dl->disk.total_blocks;
+ min_active = blocks;
}
}
if (!dl_min)
@@ -1115,13 +1183,13 @@ static void print_imsm_dev(struct intel_super *super,
sz += __le32_to_cpu(dev->size_low);
printf(" Array Size : %llu%s\n", (unsigned long long)sz,
human_size(sz * 512));
- sz = __le32_to_cpu(map->blocks_per_member);
+ sz = blocks_per_member(map);
printf(" Per Dev Size : %llu%s\n", (unsigned long long)sz,
human_size(sz * 512));
- printf(" Sector Offset : %u\n",
- __le32_to_cpu(map->pba_of_lba0));
- printf(" Num Stripes : %u\n",
- __le32_to_cpu(map->num_data_stripes));
+ printf(" Sector Offset : %llu\n",
+ pba_of_lba0(map));
+ printf(" Num Stripes : %llu\n",
+ num_data_stripes(map));
printf(" Chunk Size : %u KiB",
__le16_to_cpu(map->blocks_per_strip) / 2);
if (map2)
@@ -1182,7 +1250,7 @@ static void print_imsm_disk(struct imsm_disk *disk, int index, __u32 reserved)
is_configured(disk) ? " active" : "",
is_failed(disk) ? " failed" : "");
printf(" Id : %08x\n", __le32_to_cpu(disk->scsi_id));
- sz = __le32_to_cpu(disk->total_blocks) - reserved;
+ sz = total_blocks(disk) - reserved;
printf(" Usable Size : %llu%s\n", (unsigned long long)sz,
human_size(sz * 512));
}
@@ -2462,9 +2530,8 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
dl->index);
}
- info->data_offset = __le32_to_cpu(map_to_analyse->pba_of_lba0);
- info->component_size =
- __le32_to_cpu(map_to_analyse->blocks_per_member);
+ info->data_offset = pba_of_lba0(map_to_analyse);
+ info->component_size = blocks_per_member(map_to_analyse);
/* check component size aligment
*/
@@ -2525,7 +2592,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
used_disks = imsm_num_data_members(dev, MAP_1);
if (used_disks > 0) {
- array_blocks = map->blocks_per_member *
+ array_blocks = blocks_per_member(map) *
used_disks;
/* round array size down to closest MB
*/
@@ -2709,7 +2776,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
__u32 reserved = imsm_reserved_sectors(super, super->disks);
disk = &super->disks->disk;
- info->data_offset = __le32_to_cpu(disk->total_blocks) - reserved;
+ info->data_offset = total_blocks(&super->disks->disk) - reserved;
info->component_size = reserved;
info->disk.state = is_configured(disk) ? (1 << MD_DISK_ACTIVE) : 0;
/* we don't change info->disk.raid_disk here because
@@ -3377,7 +3444,7 @@ int check_mpb_migr_compatibility(struct intel_super *super)
/* This device is migrating */
map0 = get_imsm_map(dev_iter, MAP_0);
map1 = get_imsm_map(dev_iter, MAP_1);
- if (map0->pba_of_lba0 != map1->pba_of_lba0)
+ if (pba_of_lba0(map0) != pba_of_lba0(map1))
/* migration optimization area was used */
return -1;
if (migr_rec->ascending_migr == 0
@@ -3626,7 +3693,7 @@ static struct intel_super *alloc_super(void)
if (super) {
memset(super, 0, sizeof(*super));
super->current_vol = -1;
- super->create_offset = ~((__u32 ) 0);
+ super->create_offset = ~((unsigned long long) 0);
}
return super;
}
@@ -4346,22 +4413,13 @@ static __u16 info_to_blocks_per_strip(mdu_array_info_t *info)
return info->chunk_size >> 9;
}
-static __u32 info_to_num_data_stripes(mdu_array_info_t *info, int num_domains)
-{
- __u32 num_stripes;
-
- num_stripes = (info->size * 2) / info_to_blocks_per_strip(info);
- num_stripes /= num_domains;
-
- return num_stripes;
-}
-
-static __u32 info_to_blocks_per_member(mdu_array_info_t *info)
+static unsigned long long info_to_blocks_per_member(mdu_array_info_t *info,
+ unsigned long long size)
{
if (info->level == 1)
- return info->size * 2;
+ return size * 2;
else
- return (info->size * 2) & ~(info_to_blocks_per_strip(info) - 1);
+ return (size * 2) & ~(info_to_blocks_per_strip(info) - 1);
}
static void imsm_update_version_info(struct intel_super *super)
@@ -4452,7 +4510,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
int i;
unsigned long long array_blocks;
size_t size_old, size_new;
- __u32 num_data_stripes;
+ unsigned long long num_data_stripes;
if (super->orom && mpb->num_raid_devs >= super->orom->vpa) {
fprintf(stderr, Name": This imsm-container already has the "
@@ -4540,11 +4598,11 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
strncpy((char *) dev->volume, name, MAX_RAID_SERIAL_LEN);
if (info->level == 1)
- array_blocks = info_to_blocks_per_member(info);
+ array_blocks = info_to_blocks_per_member(info, size);
else
array_blocks = calc_array_size(info->level, info->raid_disks,
info->layout, info->chunk_size,
- info->size*2);
+ size * 2);
/* round array size down to closest MB */
array_blocks = (array_blocks >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
@@ -4557,8 +4615,8 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
vol->dirty = !info->state;
vol->curr_migr_unit = 0;
map = get_imsm_map(dev, MAP_0);
- map->pba_of_lba0 = __cpu_to_le32(super->create_offset);
- map->blocks_per_member = __cpu_to_le32(info_to_blocks_per_member(info));
+ set_pba_of_lba0(map, super->create_offset);
+ set_blocks_per_member(map, info_to_blocks_per_member(info, size));
map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info));
map->failed_disk_num = ~0;
if (info->level > 0)
@@ -4585,8 +4643,10 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
else
map->num_domains = 1;
- num_data_stripes = info_to_num_data_stripes(info, map->num_domains);
- map->num_data_stripes = __cpu_to_le32(num_data_stripes);
+ /* info->size is only int so use the 'size' parameter instead */
+ num_data_stripes = (size * 2) / info_to_blocks_per_strip(info);
+ num_data_stripes /= map->num_domains;
+ set_num_data_stripes(map, num_data_stripes);
map->num_members = info->raid_disks;
for (i = 0; i < map->num_members; i++) {
@@ -4729,8 +4789,8 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
*/
if (super->current_vol == 0) {
for (df = super->missing; df; df = df->next) {
- if (dl->disk.total_blocks > df->disk.total_blocks)
- df->disk.total_blocks = dl->disk.total_blocks;
+ if (total_blocks(&dl->disk) > total_blocks(&df->disk))
+ set_total_blocks(&df->disk, total_blocks(&dl->disk));
_disk = __get_imsm_disk(mpb, df->index);
*_disk = df->disk;
}
@@ -4869,7 +4929,11 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
get_dev_size(fd, NULL, &size);
size /= 512;
serialcpy(dd->disk.serial, dd->serial);
- dd->disk.total_blocks = __cpu_to_le32(size);
+ set_total_blocks(&dd->disk, size);
+ if (__le32_to_cpu(dd->disk.total_blocks_hi) > 0) {
+ struct imsm_super *mpb = super->anchor;
+ mpb->attributes |= MPB_ATTRIB_2TB_DISK;
+ }
mark_spare(dd);
if (sysfs_disk_to_scsi_id(fd, &id) == 0)
dd->disk.scsi_id = __cpu_to_le32(id);
@@ -5356,7 +5420,7 @@ static unsigned long long merge_extents(struct intel_super *super, int sum_exten
if (maxsize < reserve)
return 0;
- super->create_offset = ~((__u32) 0);
+ super->create_offset = ~((unsigned long long) 0);
if (start + reserve > super->create_offset)
return 0; /* start overflows create_offset */
super->create_offset = start + reserve;
@@ -6597,8 +6661,8 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
this->array.working_disks++;
info_d->events = __le32_to_cpu(mpb->generation_num);
- info_d->data_offset = __le32_to_cpu(map->pba_of_lba0);
- info_d->component_size = __le32_to_cpu(map->blocks_per_member);
+ info_d->data_offset = pba_of_lba0(map);
+ info_d->component_size = blocks_per_member(map);
}
/* now that the disk list is up-to-date fixup recovery_start */
update_recovery_start(super, dev, this);
@@ -6882,7 +6946,7 @@ static unsigned long long imsm_set_array_size(struct imsm_dev *dev)
/* set array size in metadata
*/
map = get_imsm_map(dev, MAP_0);
- array_blocks = map->blocks_per_member * used_disks;
+ array_blocks = blocks_per_member(map) * used_disks;
/* round array size down to closest MB
*/
@@ -6997,7 +7061,7 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
used_disks = imsm_num_data_members(dev, MAP_0);
if (used_disks > 0) {
array_blocks =
- map->blocks_per_member *
+ blocks_per_member(map) *
used_disks;
/* round array size down to closest MB
*/
@@ -7364,9 +7428,9 @@ static struct dl *imsm_add_spare(struct intel_super *super, int slot,
found = 0;
j = 0;
pos = 0;
- array_start = __le32_to_cpu(map->pba_of_lba0);
+ array_start = pba_of_lba0(map);
array_end = array_start +
- __le32_to_cpu(map->blocks_per_member) - 1;
+ blocks_per_member(map) - 1;
do {
/* check that we can start at pba_of_lba0 with
@@ -7566,7 +7630,7 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a,
di->disk.minor = dl->minor;
di->disk.state = 0;
di->recovery_start = 0;
- di->data_offset = __le32_to_cpu(map->pba_of_lba0);
+ di->data_offset = pba_of_lba0(map);
di->component_size = a->info.component_size;
di->container_member = inst;
super->random = random32();
@@ -8292,8 +8356,8 @@ static void imsm_process_update(struct supertype *st,
}
new_map = get_imsm_map(&u->dev, MAP_0);
- new_start = __le32_to_cpu(new_map->pba_of_lba0);
- new_end = new_start + __le32_to_cpu(new_map->blocks_per_member);
+ new_start = pba_of_lba0(new_map);
+ new_end = new_start + blocks_per_member(new_map);
inf = get_disk_info(u);
/* handle activate_spare versus create race:
@@ -8303,8 +8367,8 @@ static void imsm_process_update(struct supertype *st,
for (i = 0; i < mpb->num_raid_devs; i++) {
dev = get_imsm_dev(super, i);
map = get_imsm_map(dev, MAP_0);
- start = __le32_to_cpu(map->pba_of_lba0);
- end = start + __le32_to_cpu(map->blocks_per_member);
+ start = pba_of_lba0(map);
+ end = start + blocks_per_member(map);
if ((new_start >= start && new_start <= end) ||
(start >= new_start && start <= new_end))
/* overlap */;
@@ -9165,7 +9229,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
write_offset = ((unsigned long long)
__le32_to_cpu(migr_rec->dest_1st_member_lba) +
- __le32_to_cpu(map_dest->pba_of_lba0)) * 512;
+ pba_of_lba0(map_dest)) * 512;
unit_len = __le32_to_cpu(migr_rec->dest_depth_per_unit) * 512;
if (posix_memalign((void **)&buf, 512, unit_len) != 0)
--
1.7.7.6

View File

@ -1,31 +0,0 @@
From 30602f533f151c24fe1345f495f02c30f98895f1 Mon Sep 17 00:00:00 2001
From: Labun, Marcin <Marcin.Labun@intel.com>
Date: Mon, 30 Jan 2012 12:00:43 +1100
Subject: [PATCH] imsm: display fd in error trace when when store_imsm_mpb
failes
Signed-off-by: Marcin Labun <marcin.labun@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 7db5177..8d67a14 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -5027,8 +5027,9 @@ static int write_super_imsm(struct supertype *st, int doclose)
if (d->index < 0 || is_failed(&d->disk))
continue;
if (store_imsm_mpb(d->fd, mpb))
- fprintf(stderr, "%s: failed for device %d:%d %s\n",
- __func__, d->major, d->minor, strerror(errno));
+ fprintf(stderr, "%s: failed for device %d:%d (fd: %d)%s\n",
+ __func__, d->major, d->minor, d->fd, strerror(errno));
+
if (clear_migration_record) {
unsigned long long dsize;
--
1.7.4.4

View File

@ -1,29 +0,0 @@
From 4ff46bbc34aca294afe2127536b620672486598e Mon Sep 17 00:00:00 2001
From: Marcin Labun <Marcin.Labun@intel.com>
Date: Wed, 14 Dec 2011 15:02:49 +0100
Subject: [PATCH 1/6] imsm: display maximum volumes per controller in --detail-platform command
Signed-off-by: Marcin Labun <marcin.labun@intel.com>
---
super-intel.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index b64aa7a..1c22aff 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -1663,8 +1663,9 @@ static void print_imsm_capability(const struct imsm_orom *orom)
imsm_orom_has_chunk(orom, 1024*16) ? " 16M" : "",
imsm_orom_has_chunk(orom, 1024*32) ? " 32M" : "",
imsm_orom_has_chunk(orom, 1024*64) ? " 64M" : "");
- printf(" Max Disks : %d\n", orom->tds);
- printf(" Max Volumes : %d\n", orom->vpa);
+ printf(" Max Disks : %d\n", orom->tds);
+ printf(" Max Volumes per array : %d\n", orom->vpa);
+ printf(" Max Volumes per controller: %d\n", orom->vphba);
return;
}
--
1.7.1

View File

@ -1,62 +0,0 @@
From 7ce05701813496571e1f7f79c726aa6e4868bd5f Mon Sep 17 00:00:00 2001
From: Lukasz Dorau <lukasz.dorau@intel.com>
Date: Fri, 20 Apr 2012 13:45:02 +0200
Subject: [PATCH 2/3] imsm: fix: rebuild does not continue after reboot
If system is rebooted during rebuild, md driver changes sync_action
from 'recover' to 'idle' (during stopping all md devices).
If mdmon is still running then, it detects the change of sync_action state,
finishes rebuild and writes metadata to disks. After computer's restart
the RAID volume is in Normal state in OROM and rebuild seems to be finished.
After system's start-up RAID volume is in auto-read-only state
and metadata is in Dirty state. Rebuild seems to be finished but it is not.
Data is inconsistent (out-of-sync).
When mdmon detects the change of sync_action from 'recover' to 'idle',
it has to check if rebuild is really finished. Appropriate test was added.
Now mdmon examines each volume's member if it is being rebuilt.
Signed-off-by: Lukasz Dorau <lukasz.dorau@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 17 +++++++++++++++++
1 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index e405d97..1ad5e47 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -7273,6 +7273,8 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
struct imsm_dev *dev = get_imsm_dev(super, inst);
struct imsm_map *map = get_imsm_map(dev, MAP_0);
struct imsm_disk *disk;
+ struct mdinfo *mdi;
+ int recovery_not_finished = 0;
int failed;
__u32 ord;
__u8 map_state;
@@ -7313,6 +7315,21 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
dprintf("normal: ");
if (is_rebuilding(dev)) {
dprintf("while rebuilding");
+ /* check if recovery is really finished */
+ for (mdi = a->info.devs; mdi ; mdi = mdi->next)
+ if (mdi->recovery_start != MaxSector) {
+ recovery_not_finished = 1;
+ break;
+ }
+ if (recovery_not_finished) {
+ dprintf("\nimsm: Rebuild has not finished yet, "
+ "state not changed");
+ if (a->last_checkpoint < mdi->recovery_start) {
+ a->last_checkpoint = mdi->recovery_start;
+ super->updates_pending++;
+ }
+ break;
+ }
end_migration(dev, super, map_state);
map = get_imsm_map(dev, MAP_0);
map->failed_disk_num = ~0;
--
1.7.7.6

View File

@ -1,40 +0,0 @@
From f878b24226953f06912ebceb2c811edf36818d2f Mon Sep 17 00:00:00 2001
From: "Labun, Marcin" <Marcin.Labun@intel.com>
Date: Fri, 27 Jan 2012 15:28:36 +0000
Subject: [PATCH] imsm: fix, the second array need to have the whole available
space on devices
Fix the case with creating an array with given container in command line
instead of real devices:
mdadm -CR /dev/md/raid0 -l 0 -n 2 -z5G /dev/md/imsm
Signed-off-by: Marcin Labun <marcin.labun@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 8d67a14..eba11d6 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -6029,8 +6029,15 @@ static int reserve_space(struct supertype *st, int raiddisks,
size /= 2 * chunk;
size *= 2 * chunk;
}
+ maxsize = size;
+ }
+ if (!check_env("IMSM_NO_PLATFORM") &&
+ mpb->num_raid_devs > 0 && size && size != maxsize) {
+ fprintf(stderr, Name ": attempting to create a second "
+ "volume with size less then remaining space. "
+ "Aborting...\n");
+ return 0;
}
-
cnt = 0;
for (dl = super->disks; dl; dl = dl->next)
if (dl->e)
--
1.7.7.6

View File

@ -1,33 +0,0 @@
From 86130b7a213485f1aeb078c6f32c901648e2f679 Mon Sep 17 00:00:00 2001
From: Anna Czarnowska <anna.czarnowska@intel.com>
Date: Mon, 2 Apr 2012 22:42:51 +0200
Subject: [PATCH] imsm: fix: thunderdome may drop 2tb attribute
Spare superblock doesn't depend on other spares in container.
When loading container metadata thunderdome
may pick a small disk for the champion. This will result in incorrect
interpretation of sizes of other disks in container when joint superblock
is returned. If any disk in container has the 2TB attribute set, the result
must have it set too.
Signed-off-by: Anna Czarnowska <anna.czarnowska@intel.com>
---
super-intel.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index ed13542..869a39c 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -4079,6 +4079,8 @@ imsm_thunderdome(struct intel_super **super_list, int len)
if (s == champion)
continue;
+ mpb->attributes |= s->anchor->attributes & MPB_ATTRIB_2TB_DISK;
+
for (i = 0; i < mpb->num_disks; i++) {
struct imsm_disk *disk;
--
1.6.4.2

View File

@ -1,157 +0,0 @@
From ec50f7b6bb3a5218b51e1a953d530ef6b446bcd4 Mon Sep 17 00:00:00 2001
From: "Labun, Marcin" <Marcin.Labun@intel.com>
Date: Mon, 30 Jan 2012 11:57:23 +1100
Subject: [PATCH 2/3] imsm: load_imsm_super_all supports loading metadata from
the device list
This option is going to be used to load and analyse the metadata from
devices. This is needed to count the number of volumes on devcies attached
to particular Intel controller (SATA or SAS). It shall be done without
activation of container and volumes on the devices.
Signed-off-by: Marcin Labun <marcin.labun@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 73 insertions(+), 6 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 733d089..1cf8716 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -277,6 +277,22 @@ struct migr_record {
* (for recovered migrations) */
} __attribute__ ((__packed__));
+struct md_list {
+ /* usage marker:
+ * 1: load metadata
+ * 2: metadata does not match
+ * 4: already checked
+ */
+ int used;
+ char *devname;
+ int found;
+ int container;
+ dev_t st_rdev;
+ struct md_list *next;
+};
+
+#define pr_vrb(fmt, arg...) (void) (verbose && fprintf(stderr, Name fmt, ##arg))
+
static __u8 migr_type(struct imsm_dev *dev)
{
if (dev->vol.migr_type == MIGR_VERIFY &&
@@ -4012,12 +4028,16 @@ imsm_thunderdome(struct intel_super **super_list, int len)
static int
get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int *max, int keep_fd);
-
static int get_super_block(struct intel_super **super_list, int devnum, char *devname,
int major, int minor, int keep_fd);
+static int
+get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list,
+ int *max, int keep_fd);
+
static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
- char *devname, int keep_fd)
+ char *devname, struct md_list *devlist,
+ int keep_fd)
{
struct intel_super *super_list = NULL;
struct intel_super *super = NULL;
@@ -4028,7 +4048,8 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
/* 'fd' is an opened container */
err = get_sra_super_block(fd, &super_list, devname, &i, keep_fd);
else
- return 1;
+ /* get super block from devlist devices */
+ err = get_devlist_super_block(devlist, &super_list, &i, keep_fd);
if (err)
goto error;
/* all mpbs enter, maybe one leaves */
@@ -4094,7 +4115,54 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
}
+static int
+get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list,
+ int *max, int keep_fd)
+{
+ struct md_list *tmpdev;
+ int err = 0;
+ int i = 0;
+ int lmax = 0;
+ for (i = 0, tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) {
+ if (tmpdev->used != 1)
+ continue;
+ if (tmpdev->container == 1) {
+ int fd = dev_open(tmpdev->devname, O_RDONLY|O_EXCL);
+ if (fd < 0) {
+ fprintf(stderr, Name ": cannot open device %s: %s\n",
+ tmpdev->devname, strerror(errno));
+ err = 8;
+ goto error;
+ }
+ err = get_sra_super_block(fd, super_list,
+ tmpdev->devname, &lmax,
+ keep_fd);
+ i += lmax;
+ close(fd);
+ if (err) {
+ err = 7;
+ goto error;
+ }
+ } else {
+ int major = major(tmpdev->st_rdev);
+ int minor = minor(tmpdev->st_rdev);
+ err = get_super_block(super_list,
+ -1,
+ tmpdev->devname,
+ major, minor,
+ keep_fd);
+ i++;
+ if (err) {
+ err = 6;
+ goto error;
+ }
+ }
+ }
+ error:
+ *max = i;
+ return err;
+}
static int get_super_block(struct intel_super **super_list, int devnum, char *devname,
int major, int minor, int keep_fd)
@@ -4187,7 +4255,7 @@ get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int
static int load_container_imsm(struct supertype *st, int fd, char *devname)
{
- return load_super_imsm_all(st, fd, &st->sb, devname, 1);
+ return load_super_imsm_all(st, fd, &st->sb, devname, NULL, 1);
}
#endif
@@ -5305,7 +5373,6 @@ static int imsm_default_chunk(const struct imsm_orom *orom)
return min(512, (1 << fs));
}
-#define pr_vrb(fmt, arg...) (void) (verbose && fprintf(stderr, Name fmt, ##arg))
static int
validate_geometry_imsm_orom(struct intel_super *super, int level, int layout,
int raiddisks, int *chunk, int verbose)
@@ -5678,7 +5745,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
*/
struct intel_super *super;
- if (load_super_imsm_all(st, cfd, (void **) &super, NULL, 1) == 0) {
+ if (load_super_imsm_all(st, cfd, (void **) &super, NULL, NULL, 1) == 0) {
st->sb = super;
st->container_dev = fd2devnum(cfd);
close(cfd);
--
1.7.7.6

View File

@ -1,261 +0,0 @@
From 9587c3739b6d6edc7abfa4a655b9ab46926abdbf Mon Sep 17 00:00:00 2001
From: "Labun, Marcin" <Marcin.Labun@intel.com>
Date: Mon, 30 Jan 2012 11:56:58 +1100
Subject: [PATCH 1/3] imsm: load_super_imsm_all function refactoring
Prepare function for subsequent changes related to
loading metadata from devices list.
Signed-off-by: Marcin Labun <marcin.labun@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 176 +++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 116 insertions(+), 60 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 0e9269f..733d089 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -2985,7 +2985,7 @@ static void fd2devname(int fd, char *name)
rv = readlink(path, dname, sizeof(dname)-1);
if (rv <= 0)
return;
-
+
dname[rv] = '\0';
nm = strrchr(dname, '/');
if (nm) {
@@ -4009,67 +4009,28 @@ imsm_thunderdome(struct intel_super **super_list, int len)
return champion;
}
+
+static int
+get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int *max, int keep_fd);
+
+static int get_super_block(struct intel_super **super_list, int devnum, char *devname,
+ int major, int minor, int keep_fd);
+
static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
- char *devname)
+ char *devname, int keep_fd)
{
- struct mdinfo *sra;
struct intel_super *super_list = NULL;
struct intel_super *super = NULL;
- int devnum = fd2devnum(fd);
- struct mdinfo *sd;
- int retry;
int err = 0;
- int i;
+ int i = 0;
- /* check if 'fd' an opened container */
- sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE);
- if (!sra)
+ if (fd >= 0)
+ /* 'fd' is an opened container */
+ err = get_sra_super_block(fd, &super_list, devname, &i, keep_fd);
+ else
return 1;
-
- if (sra->array.major_version != -1 ||
- sra->array.minor_version != -2 ||
- strcmp(sra->text_version, "imsm") != 0) {
- err = 1;
+ if (err)
goto error;
- }
- /* load all mpbs */
- for (sd = sra->devs, i = 0; sd; sd = sd->next, i++) {
- struct intel_super *s = alloc_super();
- char nm[32];
- int dfd;
- int rv;
-
- err = 1;
- if (!s)
- goto error;
- s->next = super_list;
- super_list = s;
-
- err = 2;
- sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor);
- dfd = dev_open(nm, O_RDWR);
- if (dfd < 0)
- goto error;
-
- rv = find_intel_hba_capability(dfd, s, devname);
- /* no orom/efi or non-intel hba of the disk */
- if (rv != 0)
- goto error;
-
- err = load_and_parse_mpb(dfd, s, NULL, 1);
-
- /* retry the load if we might have raced against mdmon */
- if (err == 3 && mdmon_running(devnum))
- for (retry = 0; retry < 3; retry++) {
- usleep(3000);
- err = load_and_parse_mpb(dfd, s, NULL, 1);
- if (err != 3)
- break;
- }
- if (err)
- goto error;
- }
-
/* all mpbs enter, maybe one leaves */
super = imsm_thunderdome(&super_list, i);
if (!super) {
@@ -4114,13 +4075,16 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
super_list = super_list->next;
free_imsm(s);
}
- sysfs_free(sra);
+
if (err)
return err;
*sbp = super;
- st->container_dev = devnum;
+ if (fd >= 0)
+ st->container_dev = fd2devnum(fd);
+ else
+ st->container_dev = NoMdDev;
if (err == 0 && st->ss == NULL) {
st->ss = &super_imsm;
st->minor_version = 0;
@@ -4129,9 +4093,101 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
return 0;
}
+
+
+
+static int get_super_block(struct intel_super **super_list, int devnum, char *devname,
+ int major, int minor, int keep_fd)
+{
+ struct intel_super*s = NULL;
+ char nm[32];
+ int dfd = -1;
+ int rv;
+ int err = 0;
+ int retry;
+
+ s = alloc_super();
+ if (!s) {
+ err = 1;
+ goto error;
+ }
+
+ sprintf(nm, "%d:%d", major, minor);
+ dfd = dev_open(nm, O_RDWR);
+ if (dfd < 0) {
+ err = 2;
+ goto error;
+ }
+
+ rv = find_intel_hba_capability(dfd, s, devname);
+ /* no orom/efi or non-intel hba of the disk */
+ if (rv != 0) {
+ err = 4;
+ goto error;
+ }
+
+ err = load_and_parse_mpb(dfd, s, NULL, keep_fd);
+
+ /* retry the load if we might have raced against mdmon */
+ if (err == 3 && (devnum != -1) && mdmon_running(devnum))
+ for (retry = 0; retry < 3; retry++) {
+ usleep(3000);
+ err = load_and_parse_mpb(dfd, s, NULL, keep_fd);
+ if (err != 3)
+ break;
+ }
+ error:
+ if (!err) {
+ s->next = *super_list;
+ *super_list = s;
+ } else {
+ if (s)
+ free(s);
+ if (dfd)
+ close(dfd);
+ }
+ if ((dfd >= 0) && (!keep_fd))
+ close(dfd);
+ return err;
+
+}
+
+static int
+get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int *max, int keep_fd)
+{
+ struct mdinfo *sra;
+ int devnum;
+ struct mdinfo *sd;
+ int err = 0;
+ int i = 0;
+ sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE);
+ if (!sra)
+ return 1;
+
+ if (sra->array.major_version != -1 ||
+ sra->array.minor_version != -2 ||
+ strcmp(sra->text_version, "imsm") != 0) {
+ err = 1;
+ goto error;
+ }
+ /* load all mpbs */
+ devnum = fd2devnum(fd);
+ for (sd = sra->devs, i = 0; sd; sd = sd->next, i++) {
+ if (get_super_block(super_list, devnum, devname,
+ sd->disk.major, sd->disk.minor, keep_fd) != 0) {
+ err = 7;
+ goto error;
+ }
+ }
+ error:
+ sysfs_free(sra);
+ *max = i;
+ return err;
+}
+
static int load_container_imsm(struct supertype *st, int fd, char *devname)
{
- return load_super_imsm_all(st, fd, &st->sb, devname);
+ return load_super_imsm_all(st, fd, &st->sb, devname, 1);
}
#endif
@@ -5558,7 +5614,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
dev, freesize,
verbose);
}
-
+
if (!dev) {
if (st->sb) {
if (!validate_geometry_imsm_orom(st->sb, level, layout,
@@ -5622,7 +5678,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
*/
struct intel_super *super;
- if (load_super_imsm_all(st, cfd, (void **) &super, NULL) == 0) {
+ if (load_super_imsm_all(st, cfd, (void **) &super, NULL, 1) == 0) {
st->sb = super;
st->container_dev = fd2devnum(cfd);
close(cfd);
@@ -6198,7 +6254,7 @@ static int imsm_open_new(struct supertype *c, struct active_array *a,
{
struct intel_super *super = c->sb;
struct imsm_super *mpb = super->anchor;
-
+
if (atoi(inst) >= mpb->num_raid_devs) {
fprintf(stderr, "%s: subarry index %d, out of range\n",
__func__, atoi(inst));
--
1.7.7.6

View File

@ -1,30 +0,0 @@
From 027c374fd946824704291da933300da78c32a189 Mon Sep 17 00:00:00 2001
From: "Czarnowska, Anna" <anna.czarnowska@intel.com>
Date: Mon, 2 Apr 2012 10:19:04 +1000
Subject: [PATCH 7/7] imsm: set 2tb disk attribute for spare
This patch ensures metadata attribute is set correctly also for spares.
Signed-off-by: Anna Czarnowska <anna.czarnowska@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 1bc9e9c..dad4c4d 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -5048,6 +5048,9 @@ static int write_super_imsm_spares(struct intel_super *super, int doclose)
continue;
spare->disk[0] = d->disk;
+ if (__le32_to_cpu(d->disk.total_blocks_hi) > 0)
+ spare->attributes |= MPB_ATTRIB_2TB_DISK;
+
sum = __gen_imsm_checksum(spare);
spare->family_num = __cpu_to_le32(sum);
spare->orig_family_num = 0;
--
1.7.7.6

View File

@ -1,497 +0,0 @@
From ca9de185a3b96720adcc5120f6a34c5f9bb98b3f Mon Sep 17 00:00:00 2001
From: "Labun, Marcin" <Marcin.Labun@intel.com>
Date: Mon, 30 Jan 2012 12:00:10 +1100
Subject: [PATCH 3/3] imsm: validate the number of imsm volumes per controller
IMSM OROM limits number of volumes per controller. Volumes
above the limit are blocked in OROM. mdadm should follow OROM limitations
in this area. Therefore we need to count number of volumes on the devices
attached to SATA (ahci driver) or SAS (isci) controller. Adding a new volume
must be blocked if the number of volumes on devices attached to the given
controller is exceeded.
Signed-off-by: Marcin Labun <marcin.labun@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 399 insertions(+), 5 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 1cf8716..7db5177 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -3285,7 +3285,7 @@ static int parse_raid_devices(struct intel_super *super)
len_migr = sizeof_imsm_dev(dev_iter, 1);
if (len_migr > len)
space_needed += len_migr - len;
-
+
dv = malloc(sizeof(*dv));
if (!dv)
return 1;
@@ -3321,7 +3321,7 @@ static int parse_raid_devices(struct intel_super *super)
super->buf = buf;
super->len = len;
}
-
+
return 0;
}
@@ -4122,12 +4122,12 @@ get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list
struct md_list *tmpdev;
int err = 0;
int i = 0;
- int lmax = 0;
for (i = 0, tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) {
if (tmpdev->used != 1)
continue;
if (tmpdev->container == 1) {
+ int lmax = 0;
int fd = dev_open(tmpdev->devname, O_RDONLY|O_EXCL);
if (fd < 0) {
fprintf(stderr, Name ": cannot open device %s: %s\n",
@@ -5363,6 +5363,377 @@ static int is_raid_level_supported(const struct imsm_orom *orom, int level, int
return 0;
}
+
+static int
+active_arrays_by_format(char *name, char* hba, struct md_list **devlist,
+ int dpa, int verbose)
+{
+ struct mdstat_ent *mdstat = mdstat_read(0, 0);
+ struct mdstat_ent *memb = NULL;
+ int count = 0;
+ int num = 0;
+ struct md_list *dv = NULL;
+ int found;
+
+ for (memb = mdstat ; memb ; memb = memb->next) {
+ if (memb->metadata_version &&
+ (strncmp(memb->metadata_version, "external:", 9) == 0) &&
+ (strcmp(&memb->metadata_version[9], name) == 0) &&
+ !is_subarray(memb->metadata_version+9) &&
+ memb->members) {
+ struct dev_member *dev = memb->members;
+ int fd = -1;
+ while(dev && (fd < 0)) {
+ char *path = malloc(strlen(dev->name) + strlen("/dev/") + 1);
+ if (path) {
+ num = sprintf(path, "%s%s", "/dev/", dev->name);
+ if (num > 0)
+ fd = open(path, O_RDONLY, 0);
+ if ((num <= 0) || (fd < 0)) {
+ pr_vrb(": Cannot open %s: %s\n",
+ dev->name, strerror(errno));
+ }
+ free(path);
+ }
+ dev = dev->next;
+ }
+ found = 0;
+ if ((fd >= 0) && disk_attached_to_hba(fd, hba)) {
+ struct mdstat_ent *vol;
+ for (vol = mdstat ; vol ; vol = vol->next) {
+ if ((vol->active > 0) &&
+ vol->metadata_version &&
+ is_container_member(vol, memb->dev)) {
+ found++;
+ count++;
+ }
+ }
+ if (*devlist && (found < dpa)) {
+ dv = calloc(1, sizeof(*dv));
+ if (dv == NULL)
+ fprintf(stderr, Name ": calloc failed\n");
+ else {
+ dv->devname = malloc(strlen(memb->dev) + strlen("/dev/") + 1);
+ if (dv->devname != NULL) {
+ sprintf(dv->devname, "%s%s", "/dev/", memb->dev);
+ dv->found = found;
+ dv->used = 0;
+ dv->next = *devlist;
+ *devlist = dv;
+ } else
+ free(dv);
+ }
+ }
+ }
+ if (fd >= 0)
+ close(fd);
+ }
+ }
+ free_mdstat(mdstat);
+ return count;
+}
+
+#ifdef DEBUG_LOOP
+static struct md_list*
+get_loop_devices(void)
+{
+ int i;
+ struct md_list *devlist = NULL;
+ struct md_list *dv = NULL;
+
+ for(i = 0; i < 12; i++) {
+ dv = calloc(1, sizeof(*dv));
+ if (dv == NULL) {
+ fprintf(stderr, Name ": calloc failed\n");
+ break;
+ }
+ dv->devname = malloc(40);
+ if (dv->devname == NULL) {
+ fprintf(stderr, Name ": malloc failed\n");
+ free(dv);
+ break;
+ }
+ sprintf(dv->devname, "/dev/loop%d", i);
+ dv->next = devlist;
+ devlist = dv;
+ }
+ return devlist;
+}
+#endif
+
+static struct md_list*
+get_devices(const char *hba_path)
+{
+ struct md_list *devlist = NULL;
+ struct md_list *dv = NULL;
+ struct dirent *ent;
+ DIR *dir;
+ int err = 0;
+
+#if DEBUG_LOOP
+ devlist = get_loop_devices();
+ return devlist;
+#endif
+ /* scroll through /sys/dev/block looking for devices attached to
+ * this hba
+ */
+ dir = opendir("/sys/dev/block");
+ for (ent = dir ? readdir(dir) : NULL; ent; ent = readdir(dir)) {
+ int fd;
+ char buf[1024];
+ int major, minor;
+ char *path = NULL;
+ if (sscanf(ent->d_name, "%d:%d", &major, &minor) != 2)
+ continue;
+ path = devt_to_devpath(makedev(major, minor));
+ if (!path)
+ continue;
+ if (!path_attached_to_hba(path, hba_path)) {
+ free(path);
+ path = NULL;
+ continue;
+ }
+ free(path);
+ path = NULL;
+ fd = dev_open(ent->d_name, O_RDONLY);
+ if (fd >= 0) {
+ fd2devname(fd, buf);
+ close(fd);
+ } else {
+ fprintf(stderr, Name ": cannot open device: %s\n",
+ ent->d_name);
+ continue;
+ }
+
+
+ dv = calloc(1, sizeof(*dv));
+ if (dv == NULL) {
+ fprintf(stderr, Name ": malloc failed\n");
+ err = 1;
+ break;
+ }
+ dv->devname = strdup(buf);
+ if (dv->devname == NULL) {
+ fprintf(stderr, Name ": malloc failed\n");
+ err = 1;
+ free(dv);
+ break;
+ }
+ dv->next = devlist;
+ devlist = dv;
+ }
+ if (err) {
+ while(devlist) {
+ dv = devlist;
+ devlist = devlist->next;
+ free(dv->devname);
+ free(dv);
+ }
+ }
+ return devlist;
+}
+
+static int
+count_volumes_list(struct md_list *devlist, char *homehost,
+ int verbose, int *found)
+{
+ struct md_list *tmpdev;
+ int count = 0;
+ struct supertype *st = NULL;
+
+ /* first walk the list of devices to find a consistent set
+ * that match the criterea, if that is possible.
+ * We flag the ones we like with 'used'.
+ */
+ *found = 0;
+ st = match_metadata_desc_imsm("imsm");
+ if (st == NULL) {
+ pr_vrb(": cannot allocate memory for imsm supertype\n");
+ return 0;
+ }
+
+ for (tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) {
+ char *devname = tmpdev->devname;
+ struct stat stb;
+ struct supertype *tst;
+ int dfd;
+ if (tmpdev->used > 1)
+ continue;
+ tst = dup_super(st);
+ if (tst == NULL) {
+ pr_vrb(": cannot allocate memory for imsm supertype\n");
+ goto err_1;
+ }
+ tmpdev->container = 0;
+ dfd = dev_open(devname, O_RDONLY|O_EXCL);
+ if (dfd < 0) {
+ dprintf(": cannot open device %s: %s\n",
+ devname, strerror(errno));
+ tmpdev->used = 2;
+ } else if (fstat(dfd, &stb)< 0) {
+ /* Impossible! */
+ dprintf(": fstat failed for %s: %s\n",
+ devname, strerror(errno));
+ tmpdev->used = 2;
+ } else if ((stb.st_mode & S_IFMT) != S_IFBLK) {
+ dprintf(": %s is not a block device.\n",
+ devname);
+ tmpdev->used = 2;
+ } else if (must_be_container(dfd)) {
+ struct supertype *cst;
+ cst = super_by_fd(dfd, NULL);
+ if (cst == NULL) {
+ dprintf(": cannot recognize container type %s\n",
+ devname);
+ tmpdev->used = 2;
+ } else if (tst->ss != st->ss) {
+ dprintf(": non-imsm container - ignore it: %s\n",
+ devname);
+ tmpdev->used = 2;
+ } else if (!tst->ss->load_container ||
+ tst->ss->load_container(tst, dfd, NULL))
+ tmpdev->used = 2;
+ else {
+ tmpdev->container = 1;
+ }
+ if (cst)
+ cst->ss->free_super(cst);
+ } else {
+ tmpdev->st_rdev = stb.st_rdev;
+ if (tst->ss->load_super(tst,dfd, NULL)) {
+ dprintf(": no RAID superblock on %s\n",
+ devname);
+ tmpdev->used = 2;
+ } else if (tst->ss->compare_super == NULL) {
+ dprintf(": Cannot assemble %s metadata on %s\n",
+ tst->ss->name, devname);
+ tmpdev->used = 2;
+ }
+ }
+ if (dfd >= 0)
+ close(dfd);
+ if (tmpdev->used == 2 || tmpdev->used == 4) {
+ /* Ignore unrecognised devices during auto-assembly */
+ goto loop;
+ }
+ else {
+ struct mdinfo info;
+ tst->ss->getinfo_super(tst, &info, NULL);
+
+ if (st->minor_version == -1)
+ st->minor_version = tst->minor_version;
+
+ if (memcmp(info.uuid, uuid_zero,
+ sizeof(int[4])) == 0) {
+ /* this is a floating spare. It cannot define
+ * an array unless there are no more arrays of
+ * this type to be found. It can be included
+ * in an array of this type though.
+ */
+ tmpdev->used = 3;
+ goto loop;
+ }
+
+ if (st->ss != tst->ss ||
+ st->minor_version != tst->minor_version ||
+ st->ss->compare_super(st, tst) != 0) {
+ /* Some mismatch. If exactly one array matches this host,
+ * we can resolve on that one.
+ * Or, if we are auto assembling, we just ignore the second
+ * for now.
+ */
+ dprintf(": superblock on %s doesn't match others - assembly aborted\n",
+ devname);
+ goto loop;
+ }
+ tmpdev->used = 1;
+ *found = 1;
+ dprintf("found: devname: %s\n", devname);
+ }
+ loop:
+ if (tst)
+ tst->ss->free_super(tst);
+ }
+ if (*found != 0) {
+ int err;
+ if ((err = load_super_imsm_all(st, -1, &st->sb, NULL, devlist, 0)) == 0) {
+ struct mdinfo *iter, *head = st->ss->container_content(st, NULL);
+ for (iter = head; iter; iter = iter->next) {
+ dprintf("content->text_version: %s vol\n",
+ iter->text_version);
+ if (iter->array.state & (1<<MD_SB_BLOCK_VOLUME)) {
+ /* do not assemble arrays with unsupported
+ configurations */
+ dprintf(": Cannot activate member %s.\n",
+ iter->text_version);
+ } else
+ count++;
+ }
+ sysfs_free(head);
+
+ } else {
+ dprintf(" no valid super block on device list: err: %d %p\n",
+ err, st->sb);
+ }
+ } else {
+ dprintf(" no more devices to examin\n");
+ }
+
+ for (tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) {
+ if ((tmpdev->used == 1) && (tmpdev->found)) {
+ if (count) {
+ if (count < tmpdev->found)
+ count = 0;
+ else
+ count -= tmpdev->found;
+ }
+ }
+ if (tmpdev->used == 1)
+ tmpdev->used = 4;
+ }
+ err_1:
+ if (st)
+ st->ss->free_super(st);
+ return count;
+}
+
+
+static int
+count_volumes(char *hba, int dpa, int verbose)
+{
+ struct md_list *devlist = NULL;
+ int count = 0;
+ int found = 0;;
+
+ devlist = get_devices(hba);
+ /* if no intel devices return zero volumes */
+ if (devlist == NULL)
+ return 0;
+
+ count = active_arrays_by_format("imsm", hba, &devlist, dpa, verbose);
+ dprintf(" path: %s active arrays: %d\n", hba, count);
+ if (devlist == NULL)
+ return 0;
+ do {
+ found = 0;
+ count += count_volumes_list(devlist,
+ NULL,
+ verbose,
+ &found);
+ dprintf("found %d count: %d\n", found, count);
+ } while (found);
+
+ dprintf("path: %s total number of volumes: %d\n", hba, count);
+
+ while(devlist) {
+ struct md_list *dv = devlist;
+ devlist = devlist->next;
+ free(dv->devname);
+ free(dv);
+ }
+ return count;
+}
+
static int imsm_default_chunk(const struct imsm_orom *orom)
{
/* up to 512 if the plaform supports it, otherwise the platform max.
@@ -5583,6 +5954,15 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
*freesize = maxsize;
+ if (super->orom) {
+ int count = count_volumes(super->hba->path,
+ super->orom->dpa, verbose);
+ if (super->orom->vphba <= count) {
+ pr_vrb(": platform does not support more then %d raid volumes.\n",
+ super->orom->vphba);
+ return 0;
+ }
+ }
return 1;
}
@@ -5684,6 +6064,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
if (!dev) {
if (st->sb) {
+ struct intel_super *super = st->sb;
if (!validate_geometry_imsm_orom(st->sb, level, layout,
raiddisks, chunk,
verbose))
@@ -5696,6 +6077,19 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
* created. add_to_super and getinfo_super
* detect when autolayout is in progress.
*/
+ /* assuming that freesize is always given when array is
+ created */
+ if (super->orom && freesize) {
+ int count;
+ count = count_volumes(super->hba->path,
+ super->orom->dpa, verbose);
+ if (super->orom->vphba <= count) {
+ pr_vrb(": platform does not support more"
+ "then %d raid volumes.\n",
+ super->orom->vphba);
+ return 0;
+ }
+ }
if (freesize)
return reserve_space(st, raiddisks, size,
chunk?*chunk:0, freesize);
@@ -7176,7 +7570,7 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a,
}
return NULL;
}
-
+
mu->space = NULL;
mu->space_list = NULL;
mu->len = sizeof(struct imsm_update_activate_spare) * num_spares;
@@ -7420,7 +7814,7 @@ error_disk_add:
}
static int apply_update_activate_spare(struct imsm_update_activate_spare *u,
- struct intel_super *super,
+ struct intel_super *super,
struct active_array *active_array)
{
struct imsm_super *mpb = super->anchor;
--
1.7.7.6

View File

@ -1,97 +0,0 @@
From eb155f6de0986dc14c37dc9c4172bf0bcb8779fe Mon Sep 17 00:00:00 2001
From: Jes Sorensen <Jes.Sorensen@redhat.com>
Date: Wed, 25 Jan 2012 15:18:01 +0100
Subject: [PATCH 1/4] mdmon: Use getopt_long() to parse command line options
This changes mdmon over to use getopt_long() for option parsing,
making it easier to add new options. In addition this patch introduces
a short version -t for --takeover and adds -h/--help.
Acked-by: Doug Ledford <dledford@redhat.com>
Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
mdmon.c | 51 ++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 40 insertions(+), 11 deletions(-)
diff --git a/mdmon.c b/mdmon.c
index b6ae0e6..a65c4a4 100644
--- a/mdmon.c
+++ b/mdmon.c
@@ -265,7 +265,14 @@ static int do_fork(void)
void usage(void)
{
- fprintf(stderr, "Usage: mdmon [--all] [--takeover] CONTAINER\n");
+ fprintf(stderr,
+"Usage: mdmon [options] CONTAINER\n"
+"\n"
+"Options are:\n"
+" --help -h : This message\n"
+" --all : All devices\n"
+" --takeover -t : Takeover container\n"
+);
exit(2);
}
@@ -277,25 +284,47 @@ int main(int argc, char *argv[])
int devnum;
char *devname;
int status = 0;
- int arg;
+ int opt;
int all = 0;
int takeover = 0;
-
- for (arg = 1; arg < argc; arg++) {
- if (strncmp(argv[arg], "--all",5) == 0 ||
- strcmp(argv[arg], "/proc/mdstat") == 0) {
- container_name = argv[arg];
+ static struct option options[] = {
+ {"all", 0, NULL, 'a'},
+ {"takeover", 0, NULL, 't'},
+ {"help", 0, NULL, 'h'},
+ {NULL, 0, NULL, 0}
+ };
+
+ while ((opt = getopt_long(argc, argv, "th", options, NULL)) != -1) {
+ switch (opt) {
+ case 'a':
+ container_name = argv[optind-1];
all = 1;
- } else if (strcmp(argv[arg], "--takeover") == 0)
+ break;
+ case 't':
+ container_name = optarg;
takeover = 1;
- else if (container_name == NULL)
- container_name = argv[arg];
- else
+ break;
+ case 'h':
+ default:
usage();
+ break;
+ }
}
+
+ if (all == 0 && container_name == NULL) {
+ if (argv[optind])
+ container_name = argv[optind];
+ }
+
if (container_name == NULL)
usage();
+ if (argc - optind > 1)
+ usage();
+
+ if (strcmp(container_name, "/proc/mdstat") == 0)
+ all = 1;
+
if (all) {
struct mdstat_ent *mdstat, *e;
int container_len = strlen(container_name);
--
1.7.8.4

View File

@ -1,92 +0,0 @@
From 68226a80812cd9fce63dbd14d2225ffdf16a781b Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Tue, 3 Jan 2012 00:36:23 +1100
Subject: [PATCH 2/2] monitor: ensure we retry soon when 'remove' fails.
If a 'remove' fails there is no certainty that another event will
happen soon, so make sure we retry soon anyway.
Reported-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
mdadm.h | 1 +
monitor.c | 16 ++++++++++------
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/mdadm.h b/mdadm.h
index 3bcd052..381ef86 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -867,6 +867,7 @@ struct supertype {
* external:/md0/12
*/
int devcnt;
+ int retry_soon;
struct mdinfo *devs;
diff --git a/monitor.c b/monitor.c
index cfe4178..c987d10 100644
--- a/monitor.c
+++ b/monitor.c
@@ -212,6 +212,7 @@ static void signal_manager(void)
*/
#define ARRAY_DIRTY 1
+#define ARRAY_BUSY 2
static int read_and_act(struct active_array *a)
{
unsigned long long sync_completed;
@@ -419,9 +420,9 @@ static int read_and_act(struct active_array *a)
if ((mdi->next_state & DS_REMOVE) && mdi->state_fd >= 0) {
int remove_result;
- /* the kernel may not be able to immediately remove the
- * disk, we can simply wait until the next event to try
- * again.
+ /* The kernel may not be able to immediately remove the
+ * disk. In that case we wait a little while and
+ * try again.
*/
remove_result = write_attr("remove", mdi->state_fd);
if (remove_result > 0) {
@@ -429,7 +430,8 @@ static int read_and_act(struct active_array *a)
close(mdi->state_fd);
close(mdi->recovery_fd);
mdi->state_fd = -1;
- }
+ } else
+ ret |= ARRAY_BUSY;
}
if (mdi->next_state & DS_INSYNC) {
write_attr("+in_sync", mdi->state_fd);
@@ -597,7 +599,7 @@ static int wait_and_act(struct supertype *container, int nowait)
struct timespec ts;
ts.tv_sec = 24*3600;
ts.tv_nsec = 0;
- if (*aap == NULL) {
+ if (*aap == NULL || container->retry_soon) {
/* just waiting to get O_EXCL access */
ts.tv_sec = 0;
ts.tv_nsec = 20000000ULL;
@@ -612,7 +614,7 @@ static int wait_and_act(struct supertype *container, int nowait)
#ifdef DEBUG
dprint_wake_reasons(&rfds);
#endif
-
+ container->retry_soon = 0;
}
if (update_queue) {
@@ -653,6 +655,8 @@ static int wait_and_act(struct supertype *container, int nowait)
*/
if (sigterm && !(ret & ARRAY_DIRTY))
a->container = NULL; /* stop touching this array */
+ if (ret & ARRAY_BUSY)
+ container->retry_soon = 1;
}
}
--
1.7.8.2

View File

@ -1,109 +0,0 @@
From 77b3ac8c6521d836dd3c6ef247c252293920fd52 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Tue, 3 Jan 2012 11:18:59 +1100
Subject: [PATCH 1/2] monitor: make return from read_and_act more symbolic.
Rather than just a number, use a named flag.
This makes the code easier to understand and allows room for returning
more flags later.
Signed-off-by: NeilBrown <neilb@suse.de>
---
monitor.c | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/monitor.c b/monitor.c
index 29bde18..cfe4178 100644
--- a/monitor.c
+++ b/monitor.c
@@ -211,6 +211,7 @@ static void signal_manager(void)
*
*/
+#define ARRAY_DIRTY 1
static int read_and_act(struct active_array *a)
{
unsigned long long sync_completed;
@@ -218,7 +219,7 @@ static int read_and_act(struct active_array *a)
int check_reshape = 0;
int deactivate = 0;
struct mdinfo *mdi;
- int dirty = 0;
+ int ret = 0;
int count = 0;
a->next_state = bad_word;
@@ -254,14 +255,14 @@ static int read_and_act(struct active_array *a)
if (a->curr_state == write_pending) {
a->container->ss->set_array_state(a, 0);
a->next_state = active;
- dirty = 1;
+ ret |= ARRAY_DIRTY;
}
if (a->curr_state == active_idle) {
/* Set array to 'clean' FIRST, then mark clean
* in the metadata
*/
a->next_state = clean;
- dirty = 1;
+ ret |= ARRAY_DIRTY;
}
if (a->curr_state == clean) {
a->container->ss->set_array_state(a, 1);
@@ -269,7 +270,7 @@ static int read_and_act(struct active_array *a)
if (a->curr_state == active ||
a->curr_state == suspended ||
a->curr_state == bad_word)
- dirty = 1;
+ ret |= ARRAY_DIRTY;
if (a->curr_state == readonly) {
/* Well, I'm ready to handle things. If readonly
* wasn't requested, transition to read-auto.
@@ -284,7 +285,7 @@ static int read_and_act(struct active_array *a)
a->next_state = read_auto; /* array is clean */
else {
a->next_state = active; /* Now active for recovery etc */
- dirty = 1;
+ ret |= ARRAY_DIRTY;
}
}
}
@@ -459,7 +460,7 @@ static int read_and_act(struct active_array *a)
if (deactivate)
a->container = NULL;
- return dirty;
+ return ret;
}
static struct mdinfo *
@@ -629,7 +630,6 @@ static int wait_and_act(struct supertype *container, int nowait)
rv = 0;
dirty_arrays = 0;
for (a = *aap; a ; a = a->next) {
- int is_dirty;
if (a->replaces && !discard_this) {
struct active_array **ap;
@@ -644,14 +644,14 @@ static int wait_and_act(struct supertype *container, int nowait)
signal_manager();
}
if (a->container && !a->to_remove) {
- is_dirty = read_and_act(a);
+ int ret = read_and_act(a);
rv |= 1;
- dirty_arrays += is_dirty;
+ dirty_arrays += !!(ret & ARRAY_DIRTY);
/* when terminating stop manipulating the array after it
* is clean, but make sure read_and_act() is given a
* chance to handle 'active_idle'
*/
- if (sigterm && !is_dirty)
+ if (sigterm && !(ret & ARRAY_DIRTY))
a->container = NULL; /* stop touching this array */
}
}
--
1.7.8.2

View File

@ -1,39 +0,0 @@
From 29cd0821bfe5acdeac0b8bb54b1de9e07a453323 Mon Sep 17 00:00:00 2001
From: "Czarnowska, Anna" <anna.czarnowska@intel.com>
Date: Mon, 2 Apr 2012 10:17:25 +1000
Subject: [PATCH 4/7] show 2TB volumes/disks support in --detail-platform
Signed-off-by: Anna Czarnowska <anna.czarnowska@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
platform-intel.h | 1 +
super-intel.c | 4 ++++
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/platform-intel.h b/platform-intel.h
index c997f1b..94f2e81 100644
--- a/platform-intel.h
+++ b/platform-intel.h
@@ -76,6 +76,7 @@ struct imsm_orom {
#define IMSM_OROM_ATTR_RAID1E IMSM_OROM_RLC_RAID1E
#define IMSM_OROM_ATTR_RAID5 IMSM_OROM_RLC_RAID5
#define IMSM_OROM_ATTR_RAID_CNG IMSM_OROM_RLC_RAID_CNG
+ #define IMSM_OROM_ATTR_2TB_DISK (1 << 26)
#define IMSM_OROM_ATTR_2TB (1 << 29)
#define IMSM_OROM_ATTR_PM (1 << 30)
#define IMSM_OROM_ATTR_ChecksumVerify (1 << 31)
diff --git a/super-intel.c b/super-intel.c
index 642ca26..0c38b45 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -1786,6 +1786,10 @@
printf(" Max Disks : %d\n", orom->tds);
printf(" Max Volumes per array : %d\n", orom->vpa);
printf(" Max Volumes per controller: %d\n", orom->vphba);
+ printf(" 2TB Volumes:%s supported\n",
+ (orom->attr & IMSM_OROM_ATTR_2TB) ? "" : " not");
+ printf(" 2TB Disks:%s supported\n",
+ (orom->attr & IMSM_OROM_ATTR_2TB_DISK) ? "" : " not");
return;
}

View File

@ -1,47 +0,0 @@
From e03640bda562df11b60ceaaa40a56425f358090e Mon Sep 17 00:00:00 2001
From: "Czarnowska, Anna" <anna.czarnowska@intel.com>
Date: Mon, 2 Apr 2012 10:16:04 +1000
Subject: [PATCH 3/7] simplify calculating array_blocks
no point calling info_to_blocks_per_member when it just returns size*2 for level==1
calc_array_size can be used for all levels
Signed-off-by: Anna Czarnowska <anna.czarnowska@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super-intel.c | 5 +----
util.c | 2 ++
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 480b379..642ca26 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -4623,10 +4623,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
}
strncpy((char *) dev->volume, name, MAX_RAID_SERIAL_LEN);
- if (info->level == 1)
- array_blocks = info_to_blocks_per_member(info, size);
- else
- array_blocks = calc_array_size(info->level, info->raid_disks,
+ array_blocks = calc_array_size(info->level, info->raid_disks,
info->layout, info->chunk_size,
size * 2);
/* round array size down to closest MB */
diff --git a/util.c b/util.c
index 7abbff7..d32e650 100644
--- a/util.c
+++ b/util.c
@@ -711,6 +711,8 @@ void print_r10_layout(int layout)
unsigned long long calc_array_size(int level, int raid_disks, int layout,
int chunksize, unsigned long long devsize)
{
+ if (level == 1)
+ return devsize;
devsize &= ~(unsigned long long)((chunksize>>9)-1);
return get_data_disks(level, layout, raid_disks) * devsize;
}
--
1.7.7.6

View File

@ -1,88 +0,0 @@
From 6ef89052d85b8137b8a7100f761d896ae6f61001 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Tue, 7 Feb 2012 11:55:18 +1100
Subject: [PATCH] super1: make aread/awrite always use an aligned buffer.
A recently change to write_bitmap1 meant awrite would sometimes
write from a non-aligned buffer which of course break.
So change awrite (and aread) to always use their own aligned
buffer to ensure safety.
Reported-by: Alexander Lyakas <alex.bolshoy@gmail.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
super1.c | 39 +++++++++++++++++++++++----------------
1 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/super1.c b/super1.c
index d23d6e8..cfa237a 100644
--- a/super1.c
+++ b/super1.c
@@ -143,17 +143,19 @@ static int aread(int fd, void *buf, int len)
* the full sector and copy relevant bits into
* the buffer
*/
- int bsize;
+ int bsize, iosize;
char *b;
int n;
- if (ioctl(fd, BLKSSZGET, &bsize) != 0 ||
- bsize <= len)
- return read(fd, buf, len);
- if (bsize > 4096)
+ if (ioctl(fd, BLKSSZGET, &bsize) != 0)
+ bsize = 512;
+
+ if (bsize > 4096 || len > 4096)
return -1;
b = (char*)(((long)(abuf+4096))&~4095UL);
- n = read(fd, b, bsize);
+ for (iosize = 0; iosize < len; iosize += bsize)
+ ;
+ n = read(fd, b, iosize);
if (n <= 0)
return n;
lseek(fd, len - n, 1);
@@ -171,22 +173,27 @@ static int awrite(int fd, void *buf, int len)
* than the write.
* The address must be sector-aligned.
*/
- int bsize;
+ int bsize, iosize;
char *b;
int n;
- if (ioctl(fd, BLKSSZGET, &bsize) != 0 ||
- bsize <= len)
- return write(fd, buf, len);
- if (bsize > 4096)
+ if (ioctl(fd, BLKSSZGET, &bsize) != 0)
+ bsize = 512;
+ if (bsize > 4096 || len > 4096)
return -1;
b = (char*)(((long)(abuf+4096))&~4095UL);
- n = read(fd, b, bsize);
- if (n <= 0)
- return n;
- lseek(fd, -n, 1);
+ for (iosize = 0; iosize < len ; iosize += bsize)
+ ;
+
+ if (len != iosize) {
+ n = read(fd, b, iosize);
+ if (n <= 0)
+ return n;
+ lseek(fd, -n, 1);
+ }
+
memcpy(b, buf, len);
- n = write(fd, b, bsize);
+ n = write(fd, b, iosize);
if (n <= 0)
return n;
lseek(fd, len - n, 1);
--
1.7.7.6

18
mdadm-3.2.4-map-dir.patch Normal file
View File

@ -0,0 +1,18 @@
--- mdadm-3.2.4/Makefile.map-dir 2012-05-10 12:29:09.687578525 +0200
+++ mdadm-3.2.4/Makefile 2012-05-10 12:28:05.514380800 +0200
@@ -67,12 +67,12 @@
# Both MAP_DIR and MDMON_DIR should be somewhere that persists across the
# pivotroot from early boot to late boot.
# /run is best, but for distros that don't support that, /dev can work.
-MAP_DIR=/run/mdadm
-MAP_FILE = map
+MAP_DIR=/dev/md
+MAP_FILE = md-device-map
MAP_PATH = $(MAP_DIR)/$(MAP_FILE)
MDMON_DIR = $(MAP_DIR)
# place for autoreplace cookies
-FAILED_SLOTS_DIR = /run/mdadm/failed-slots
+FAILED_SLOTS_DIR = $(MDMON_DIR)/failed-slots
DIRFLAGS = -DMAP_DIR=\"$(MAP_DIR)\" -DMAP_FILE=\"$(MAP_FILE)\"
DIRFLAGS += -DMDMON_DIR=\"$(MDMON_DIR)\"
DIRFLAGS += -DFAILED_SLOTS_DIR=\"$(FAILED_SLOTS_DIR)\"

View File

@ -1,8 +1,8 @@
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.3 Version: 3.2.4
Release: 9%{?dist} Release: 1%{?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.xz
Source1: mdmonitor.init Source1: mdmonitor.init
Source2: raid-check Source2: raid-check
Source3: mdadm.rules Source3: mdadm.rules
@ -11,78 +11,11 @@ Source5: mdadm-cron
Source6: mdmonitor.service Source6: mdmonitor.service
Source7: mdmonitor-takeover.service Source7: mdmonitor-takeover.service
Source8: mdadm.conf Source8: mdadm.conf
Patch1: mdadm-3.2.3-Work-around-gcc-4.7-s-strict-aliasing-checks.patch
Patch2: mdadm-3.2.3-monitor-make-return-from-read_and_act-more-symbolic.patch
Patch3: mdadm-3.2.3-monitor-ensure-we-retry-soon-when-remove-fails.patch
Patch4: mdadm-3.2.3-mdmon-Use-getopt_long-to-parse-command-line-options.patch
Patch5: mdadm-3.2.3-Add-offroot-argument-to-mdadm.patch
Patch6: mdadm-3.2.3-Add-offroot-argument-to-mdmon.patch
Patch7: mdadm-3.2.3-Spawn-mdmon-with-offroot-if-mdadm-was-launched-with-.patch
Patch8: mdadm-3.2.3-super1-make-aread-awrite-always-use-an-aligned-buffe.patch
Patch9: mdadm-3.2.3-avoid-double-free-upon-old-buggy-kernel-sysfs_read-f.patch
Patch10: mdadm-3.2.3-Print-error-message-if-failing-to-write-super-for-1..patch
Patch11: mdadm-3.2.3-Incremental-fix-adding-devices-with-incremental.patch
Patch12: mdadm-3.2.3-FIX-External-metadata-sometimes-is-not-updated.patch
Patch13: mdadm-3.2.3-FIX-mdmon-check-in-reshape_container-can-cause-a-pro.patch
Patch14: mdadm-3.2.3-imsm-display-fd-in-error-trace-when-when-store_imsm_.patch
Patch15: mdadm-3.2.3-FIX-NULL-pointer-to-strdup-can-be-passed.patch
Patch16: mdadm-3.2.3-imsm-FIX-No-new-missing-disks-are-allowed-during-gen.patch
Patch17: mdadm-3.2.3-FIX-Array-is-not-run-when-expansion-disks-are-added.patch
Patch18: mdadm-3.2.3-imsm-FIX-imsm_get_allowed_degradation-doesn-t-count-.patch
Patch19: mdadm-3.2.3-Fix-Sometimes-mdmon-throws-core-dump-during-reshape.patch
Patch20: mdadm-3.2.3-Flush-mdmon-before-next-reshape-step-during-containe.patch
Patch21: mdadm-3.2.3-imsm-FIX-Chunk-size-migration-problem.patch
Patch22: mdadm-3.2.3-FIX-use-md-position-to-reshape-restart.patch
Patch23: mdadm-3.2.3-imsm-FIX-use-md-position-to-reshape-restart.patch
Patch24: mdadm-3.2.3-imsm-FIX-Clear-migration-record-when-migration-switc.patch
Patch25: mdadm-3.2.3-FIX-restart-reshape-when-reshape-process-is-stopped-.patch
Patch26: mdadm-3.2.3-FIX-Do-not-try-to-continue-reshape-using-inactive-ar.patch
Patch27: mdadm-3.2.3-FIX-Changes-in-0-case-for-reshape-position-verificat.patch
Patch28: mdadm-3.2.3-fix-Monitor-sometimes-crashes.patch
Patch29: mdadm-3.2.3-fix-container-creation-with-incremental-used.patch
Patch30: mdadm-3.2.3-imsm-fix-the-second-array-need-to-have-the-whole-ava.patch
Patch31: mdadm-3.2.3-imsm-load_super_imsm_all-function-refactoring.patch
Patch32: mdadm-3.2.3-imsm-load_imsm_super_all-supports-loading-metadata-f.patch
Patch33: mdadm-3.2.3-imsm-validate-the-number-of-imsm-volumes-per-control.patch
Patch34: mdadm-3.2.3-imsm-display-maximum-volumes-per-controller-in-detai.patch
Patch35: mdadm-3.2.3-imsm-avoid-overflows-for-disks-over-1TB.patch
Patch36: mdadm-3.2.3-clear-hi-bits-if-not-used-after-loading-metadata-fro.patch
Patch37: mdadm-3.2.3-simplify-calculating-array_blocks.patch
Patch38: mdadm-3.2.3-show-2TB-volumes-disks-support-in-detail-platform.patch
Patch39: mdadm-3.2.3-check-volume-size-in-validate_geometry_imsm_orom.patch
Patch40: mdadm-3.2.3-check-that-no-disk-over-2TB-is-used-to-create-contai.patch
Patch41: mdadm-3.2.3-imsm-set-2tb-disk-attribute-for-spare.patch
Patch42: mdadm-3.2.3-imsm-fix-thunderdome-may-drop-2tb-attribute.patch
Patch43: mdadm-3.2.3-imsm-FIX-Update-function-imsm_num_data_members-for-R.patch
Patch44: mdadm-3.2.3-imsm-FIX-Add-volume-size-expand-support-to-imsm_anal.patch
Patch45: mdadm-3.2.3-imsm-Add-new-metadata-update-for-volume-size-expansi.patch
Patch46: mdadm-3.2.3-imsm-Execute-size-change-for-external-metatdata.patch
Patch47: mdadm-3.2.3-FIX-Support-metadata-changes-rollback.patch
Patch48: mdadm-3.2.3-imsm-FIX-Support-metadata-changes-rollback.patch
Patch49: mdadm-3.2.3-FIX-Extend-size-of-raid0-array.patch
Patch50: mdadm-3.2.3-FIX-Respect-metadata-size-limitations.patch
Patch51: mdadm-3.2.3-FIX-Detect-error-and-rollback-metadata.patch
Patch52: mdadm-3.2.3-imsm-Add-function-imsm_get_free_size.patch
Patch53: mdadm-3.2.3-imsm-Support-setting-max-size-for-size-change-operat.patch
Patch54: mdadm-3.2.3-imsm-FIX-Component-size-alignment-check.patch
Patch55: mdadm-3.2.3-FIX-Size-change-is-possible-as-standalone-change-onl.patch
Patch56: mdadm-3.2.3-FIX-Assembled-second-array-is-in-read-only-state-dur.patch
Patch57: mdadm-3.2.3-fix-correct-extending-size-of-raid0-array.patch
Patch58: mdadm-3.2.3-imsm-fix-rebuild-does-not-continue-after-reboot.patch
Patch59: mdadm-3.2.3-Manage-allow-re-add-to-failed-array.patch
Patch60: mdadm-3.2.3-Manage-replace-return-1-with-goto-abort.patch
Patch61: mdadm-3.2.3-Manage-freeze-recovery-while-adding-multiple-devices.patch
Patch62: mdadm-3.2.3-Relax-restrictions-on-when-add-is-permitted.patch
Patch63: mdadm-3.2.3-Raid-limit-of-1024-when-scanning-for-devices.patch
Patch64: mdadm-3.2.3-Remove-avail_disks-arg-from-enough.patch
Patch65: mdadm-3.2.3-Reset-bad-flag-on-map-update.patch
Patch66: mdadm-3.2.3-Bitmap_offset-is-a-signed-number.patch
Patch67: mdadm-3.2.3-Fix-sign-extension-of-bitmap_offset-in-super1.c.patch
Patch68: mdadm-3.2.3-Introduce-sysfs_set_num_signed-and-use-it-to-set-bit.patch
# Fedora customization patches # Fedora customization patches
Patch98: mdadm-3.2.3-udev.patch Patch97: mdadm-3.2.3-udev.patch
Patch99: mdadm-2.5.2-static.patch Patch98: mdadm-2.5.2-static.patch
# Fedora 15, 16, 17 - only
Patch99: mdadm-3.2.4-map-dir.patch
URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/ URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/
License: GPLv2+ License: GPLv2+
Group: System Environment/Base Group: System Environment/Base
@ -115,78 +48,14 @@ is not used as the system init process.
%prep %prep
%setup -q %setup -q
%patch1 -p1 -b .gcc47
%patch2 -p1 -b .read
%patch3 -p1 -b .retry
%patch4 -p1 -b .getopt
%patch5 -p1 -b .offroot-mdadm
%patch6 -p1 -b .offroot-mdmon
%patch7 -p1 -b .offroot-spawn
%patch8 -p1 -b .bitmap
%patch9 -p1 -b .double
%patch10 -p1 -b .print
%patch11 -p1 -b .incremental
%patch12 -p1 -b .update
%patch13 -p1 -b .mdmon
%patch14 -p1 -b .display
%patch15 -p1 -b .strdup
%patch16 -p1 -b .missing
%patch17 -p1 -b .exp
%patch18 -p1 -b .allowed
%patch19 -p1 -b .core
%patch20 -p1 -b .flush
%patch21 -p1 -b .chunk
%patch22 -p1 -b .position
%patch23 -p1 -b .reshape
%patch24 -p1 -b .record
%patch25 -p1 -b .restart
%patch26 -p1 -b .nocontinue
%patch27 -p1 -b .0case
%patch28 -p1 -b .monitor3
%patch29 -p1 -b .container
%patch30 -p1 -b .available
%patch31 -p1 -b .validate-1
%patch32 -p1 -b .validate-2
%patch33 -p1 -b .validate-3
%patch34 -p1 -b .validate-4
%patch35 -p1 -b .2tb-1
%patch36 -p1 -b .2tb-2
%patch37 -p1 -b .2tb-3
%patch38 -p1 -b .2tb-4
%patch39 -p1 -b .2tb-5
%patch40 -p1 -b .2tb-6
%patch41 -p1 -b .2tb-7
%patch42 -p1 -b .2tb-8
%patch43 -p1 -b .expand-01
%patch44 -p1 -b .expand-02
%patch45 -p1 -b .expand-03
%patch46 -p1 -b .expand-04
%patch47 -p1 -b .expand-05
%patch48 -p1 -b .expand-06
%patch49 -p1 -b .expand-07
%patch50 -p1 -b .expand-08
%patch51 -p1 -b .expand-09
%patch52 -p1 -b .expand-10
%patch53 -p1 -b .expand-11
%patch54 -p1 -b .expand-12
%patch55 -p1 -b .expand-13
%patch56 -p1 -b .expand-14
%patch57 -p1 -b .expand-15
%patch58 -p1 -b .rebuild-continue
%patch59 -p1 -b .allow-re-add
%patch60 -p1 -b .replace-return-1
%patch61 -p1 -b .freeze-recovery
%patch62 -p1 -b .make-add-work
%patch63 -p1 -b .max-devices
%patch64 -p1 -b .enough
%patch65 -p1 -b .bad-flag
%patch66 -p1 -b .bitmap-offset
%patch67 -p1 -b .bitmap-offset2
%patch68 -p1 -b .bitmap-offset3
# Fedora customization patches # Fedora customization patches
%patch98 -p1 -b .udev %patch97 -p1 -b .udev
%patch99 -p1 -b .static %patch98 -p1 -b .static
# Fedora 15, 16, 17 - only
%if "%{fedora}" <= "17"
%patch99 -p1 -b .map-dir
%endif
%build %build
make %{?_smp_mflags} CXFLAGS="$RPM_OPT_FLAGS" SYSCONFDIR="%{_sysconfdir}" mdadm mdmon make %{?_smp_mflags} CXFLAGS="$RPM_OPT_FLAGS" SYSCONFDIR="%{_sysconfdir}" mdadm mdmon
@ -259,6 +128,10 @@ fi
%{_initrddir}/* %{_initrddir}/*
%changelog %changelog
* Thu May 10 2012 Jes Sorensen <Jes.Sorensen@redhat.com> - 3.2.4-1
- Upgrade to mdadm-3.2.4
- Resolves bz820534 (rawhide) bz820527 (f17) bz820531 (f16) bz820532 (f15)
* Mon Apr 30 2012 Jes Sorensen <Jes.Sorensen@redhat.com> - 3.2.3-9 * Mon Apr 30 2012 Jes Sorensen <Jes.Sorensen@redhat.com> - 3.2.3-9
- Fix Monitor mode sometimes crashes when a resync completes - Fix Monitor mode sometimes crashes when a resync completes
- Fix missing symlink for mdadm container device when incremental creates - Fix missing symlink for mdadm container device when incremental creates