* [PATCH 00/13] imsm: new imsm metadata features
@ 2010-04-22 22:10 Hawrylewicz Czarnowski, Przemyslaw
2010-04-30 0:57 ` Dan Williams
0 siblings, 1 reply; 4+ messages in thread
From: Hawrylewicz Czarnowski, Przemyslaw @ 2010-04-22 22:10 UTC (permalink / raw)
To: Neil Brown; +Cc: linux-raid@vger.kernel.org, Williams, Dan J, Ciechanowski, Ed
The following series of patches adds two new functionalities to mdadm for
Intel metadata: Volume Delete and Volume Rename.
The patches makes Linux SW RAID implementation based on imsm metadata closer
to Intel(R) Rapid Storage Technology for Windows(TM).
Patches 1-6 contain fixes of bugs found during development and modifications
of existing code making main features easier to implement.
Patches 7-9 contain implementation of Volume Delete; ie. makes possible to
remove only one volume from container while the other one keeps running.
Patches 10-12 makes possible to change internal serial ID of volume leaving
the rest of superblock data untouched.
The last patch contains an update of manual page for above features.
[PATCH 01/13] fix: memory leak in mdmon_pid()
[PATCH 02/13] map file: Extract record update routine from map_update
[PATCH 03/13] Add mdstat_by_component
[PATCH 04/13] fix: possible segfault if current_vol does not match subarray
[PATCH 05/13] sysfs: simple write to sysfs file
[PATCH 06/13] imsm: delete subarray metadata manipulation routine
[PATCH 07/13] imsm: extension of delete subarray to handle active container
[PATCH 08/13] mdmon: enable delete subarray for managed containers
[PATCH 09/13] imsm: delete subarray: main procedure and command line support
[PATCH 10/13] imsm: rename subarray functionality
[PATCH 11/13] mdmon: enable rename subarray for managed containers
[PATCH 12/13] imsm: rename subarray: main procedure and command line support
[PATCH 13/13] manual: update for subarray delete/rename
ps. It is reworked version of patches sent earlier.
Signed-off-by: Przemyslaw Czarnowski <przemyslaw.hawrylewicz.czarnowski@intel.com>
---
Kill.c | 58 ++++++++++++
Makefile | 4 +-
Manage.c | 88 +++++++++++++++++++
ReadMe.c | 1 +
mapfile.c | 31 +++++--
mdadm.8 | 27 ++++++
mdadm.c | 32 ++++++-
mdadm.h | 35 ++++++++
mdstat.c | 69 ++++++++++++++--
super-intel.c | 253 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
sysfs.c | 21 +++++
util.c | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
12 files changed, 864 insertions(+), 23 deletions(-)
--
Best Regards,
Przemyslaw Hawrylewicz-Czarnowski
Software Development Engineer
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 00/13] imsm: new imsm metadata features
2010-04-22 22:10 [PATCH 00/13] imsm: new imsm metadata features Hawrylewicz Czarnowski, Przemyslaw
@ 2010-04-30 0:57 ` Dan Williams
2010-04-30 20:45 ` Doug Ledford
0 siblings, 1 reply; 4+ messages in thread
From: Dan Williams @ 2010-04-30 0:57 UTC (permalink / raw)
To: Hawrylewicz Czarnowski, Przemyslaw
Cc: Neil Brown, linux-raid@vger.kernel.org, Ciechanowski, Ed
First, thanks for going back and breaking out these patches it makes
it much easier to review. Note that patch-9 never came through either
on the list, or direct to my intel.com address.
On Thu, Apr 22, 2010 at 3:10 PM, Hawrylewicz Czarnowski, Przemyslaw
<przemyslaw.hawrylewicz.czarnowski@intel.com> wrote:
> The following series of patches adds two new functionalities to mdadm for
> Intel metadata: Volume Delete and Volume Rename.
> The patches makes Linux SW RAID implementation based on imsm metadata closer
> to Intel(R) Rapid Storage Technology for Windows(TM).
> Patches 1-6 contain fixes of bugs found during development and modifications
> of existing code making main features easier to implement.
> Patches 7-9 contain implementation of Volume Delete; ie. makes possible to
> remove only one volume from container while the other one keeps running.
> Patches 10-12 makes possible to change internal serial ID of volume leaving
> the rest of superblock data untouched.
> The last patch contains an update of manual page for above features.
>
> [PATCH 01/13] fix: memory leak in mdmon_pid()
Applied
> [PATCH 02/13] map file: Extract record update routine from map_update
I don't understand the benefit over the standard map_update() routine?
> [PATCH 03/13] Add mdstat_by_component
...already applied to Neil's hotunplug branch
> [PATCH 04/13] fix: possible segfault if current_vol does not match subarray
Klockwork seems to be missing that ->current_vol is always initialized
to a valid value. If we ever call getinfo_super_imsm_volume() with an
invalid current_vol that is a real bug. We should not silently return
invalid info.
> [PATCH 05/13] sysfs: simple write to sysfs file
I would prefer you just call sysfs_read(mdfd, 0, GET_VERSION); in the
locations where you want to make simple updates
> [PATCH 06/13] imsm: delete subarray metadata manipulation routine
For testing and future-proofing purposes this routine should handle N
raid subarrays rather than assume 2 in the num_raid_devs > 1 case.
This patch also says that delete active from an active container is
not allowed but the code does nothing to prevent it. I know this
would require moving the command line changes up in the series, but I
think it is important to fully understand the ramifications of this
delete functionality before going forward with the rest of the series.
I want to rehash the main points of the off-list discussion with Neil
and bring up some other thoughts about the rename patches...
Volume delete and volume rename are fairly innocuous features of the
Windows driver, the primary issue with the Linux implementation is
that volume-delete may change the array UUID and volume-rename
definitely will. Unlike name changes for native metadata which have
no effect on the UUID. My main concern is user's getting surprised by
having an mdadm.conf file in the initrd that has an out of date UUID
after doing a simple name change. Ideally there would be some
distribution notification infrastructure we could use to post an event
like "invalidate/rebuild initrd", but nothing like that exists to my
knowledge.
The other concern with volume rename is that it cannot take effect
until the next assembly, and may not even change the actual OS device
name / symlink if a conflicting name is in the configuration file. So
at the very least we are violating the rule of least surprise by not
actually changing the name of the array as the OS sees it, only as the
metadata sees it... and invalidating all occurrences of the old UUID
in the process.
Can we mitigate that pain? We can't really go the alternate route of
stop using volume-position and volume-name in the calculation of the
UUID because there isn't any 'static' identification data left. The
status quo has the nice property of being robust, UUIDs never change
unless you blow away the entire superblock at which point I'm not so
concerned about the initrd and other references to the UUID because
the previous array is gone.
Basically I am looking for a distro person to say "I guess we can live
with this" or "no, this violates too many assumptions of our storage
management code".
--
Dan
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 00/13] imsm: new imsm metadata features
2010-04-30 0:57 ` Dan Williams
@ 2010-04-30 20:45 ` Doug Ledford
2010-05-19 1:09 ` Dan Williams
0 siblings, 1 reply; 4+ messages in thread
From: Doug Ledford @ 2010-04-30 20:45 UTC (permalink / raw)
To: Dan Williams
Cc: Hawrylewicz Czarnowski, Przemyslaw, Neil Brown,
linux-raid@vger.kernel.org, Ciechanowski, Ed
[-- Attachment #1: Type: text/plain, Size: 3265 bytes --]
On 04/29/2010 08:57 PM, Dan Williams wrote:
> Basically I am looking for a distro person to say "I guess we can live
> with this" or "no, this violates too many assumptions of our storage
> management code".
So here's the scoop on Fedora and Red Hat Enterprise Linux.
Starting with F12 we use dracut instead of mkinitrd to generate an
initramfs instead of an initrd. Starting with F13, dracut no longer
needs to embed the mdadm.conf in the image and instead uses the grub
command line to tell the image what arrays to start. All current
versions of Red Hat Enterprise Linux use mkinitrd/initrd and not dracut,
but as of 6.0 that will change to dracut.
mkinitrd (and maybe dracut in F12, I'm fuzzy on F12's version of
dracut): copies mdadm.conf to initrd, uses name of / raid array *during*
mkinitrd run to determine what to start in initrd on next boot. So,
your statement that the name is wrong until the next assembly totally
blows this out of the water. You could run mkinitrd to try and update
things for the new mdadm.conf file and uuid, but the name of the array
will be wrong as reported by the running block subsystem and so mkinitrd
will pull out the old name, and mkinitrd will insert mdadm -A
/dev/md/oldname into the initrd image. Changing the name of the root
raid array with mkinitrd almost always involves building the initrd
using mkinitrd, then decompressing the image, un-cpioing the image back
into a tree, modifying the linuxrc script from the image to have the
proper mdadm commands, then re-cpioing and compressing the image back
into place.
dracut in F13 or later: things are much simpler here...the dracut images
are much larger, but intended to be generic and they only need to be
built once per kernel version so that the right modules are on there,
after that if you want to update the boot process to a different raid
array all you have to do is change the boot command line. But, that's
where things are kind of ugly. The dracut command line starts md raid
arrays by passing the uuid of the array on the command line. My current
dracut boot command looks like this in grub.conf:
title Fedora (2.6.33.1-19.fc13.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.33.1-19.fc13.x86_64 ro
root=/dev/mapper/vg_matrix-root
rd_MD_UUID=84c5c9ad:a88bff66:1b228240:bccae394
rd_MD_UUID=d6669b87:ee4c7baf:b196130c:ed87340b rd_LVM_LV=vg_matrix/root
rd_NO_LUKS rd_NO_DM LANG=en_US.UTF-8 SYSFONT=latarcyrheb-sun16 KEYTABLE=us
initrd /initramfs-2.6.33.1-19.fc13.x86_64.img
So, for F13 or later and for Enterprise Linux 6 or later, it would just
mean modifying the uuid in grub.conf (and in mdadm.conf if there is an
appropriate ARRAY line as well) to match the new uuid. That's at least
more doable than the hackish mkinitrd stuff. But it's still not good
and any failure to update the config file would result in a failed boot.
And this is just for x86 arches of course, that doesn't begin to cover
other arch boot mechanisms. In general, changing uuids is just *bad*.
--
Doug Ledford <dledford@redhat.com>
GPG KeyID: CFBFF194
http://people.redhat.com/dledford
Infiniband specific RPMs available at
http://people.redhat.com/dledford/Infiniband
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 00/13] imsm: new imsm metadata features
2010-04-30 20:45 ` Doug Ledford
@ 2010-05-19 1:09 ` Dan Williams
0 siblings, 0 replies; 4+ messages in thread
From: Dan Williams @ 2010-05-19 1:09 UTC (permalink / raw)
To: Hawrylewicz Czarnowski, Przemyslaw
Cc: Neil Brown, linux-raid@vger.kernel.org, Ciechanowski, Ed,
Doug Ledford, Doug Healey
[ catching up on the patch backlog ]
On Fri, 2010-04-30 at 13:45 -0700, Doug Ledford wrote:
> On 04/29/2010 08:57 PM, Dan Williams wrote:
> > Basically I am looking for a distro person to say "I guess we can live
> > with this" or "no, this violates too many assumptions of our storage
> > management code".
>
[..]
> So, for F13 or later and for Enterprise Linux 6 or later, it would just
> mean modifying the uuid in grub.conf (and in mdadm.conf if there is an
> appropriate ARRAY line as well) to match the new uuid. That's at least
> more doable than the hackish mkinitrd stuff. But it's still not good
> and any failure to update the config file would result in a failed boot.
> And this is just for x86 arches of course, that doesn't begin to cover
> other arch boot mechanisms. In general, changing uuids is just *bad*.
>
So here is a (lightly tested) version of subarray delete that I would be
comfortable with given the unfortunate/unavoidable side effect of
changing uuids. Przemek, this does not include the delete by name and
delete by uuid support, only delete by index. Are those methods
required for the other code you are implementing? I would just as soon
leave them out, but we can add that functionality on top of this if need
be. It made the interfaces simpler to maintain the current meaning of
st->subarray == (string) index.
Comments welcome,
Dan
--
Subject: Kill subarray
From: Dan Williams <dan.j.williams@intel.com>
Support for deleting a subarray out of an inactive container. When all
subarrays are deleted the component devices are converted back into
spares, a --zero-superblock is still needed to kill the remaining
metadata at this point. This operation is specifically only supported
on inactive containers for the following reasons:
1/ Deleting a subarray might change the uuid of other subarrays. As long
as the container is inactive we can be assured that we are not changing
the uuid of the boot array.
2/ Deleting a subarray needs to be a container wide event to ensure
disks that record the modified subarray list perceive other disks that
did not receive this change as out of date.
Notes:
The st->subarray parsing in super-intel.c and super-ddf.c is updated to
be more strict now that we are reading user supplied subarray values.
Offline container modification performs some mdmon'ish operations so
make is_container_member() and version_to_superswitch() (formerly
find_metadata_methods()) generic utility functions.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
Kill.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ReadMe.c | 1
mdadm.c | 8 +++
mdadm.h | 6 +++
mdmon.c | 25 +----------
super-ddf.c | 25 +++++++++--
super-intel.c | 97 ++++++++++++++++++++++++++++++++++++------
util.c | 26 +++++++++++
8 files changed, 281 insertions(+), 40 deletions(-)
diff --git a/Kill.c b/Kill.c
index e738978..1957881 100644
--- a/Kill.c
+++ b/Kill.c
@@ -79,3 +79,136 @@ int Kill(char *dev, struct supertype *st, int force, int quiet, int noexcl)
close(fd);
return rv;
}
+
+int Kill_subarray(char *dev, char *subarray, int quiet)
+{
+ /* Delete a subarray out of a container, the container must be
+ * inactive. The subarray string must be a subarray index
+ * number.
+ *
+ * 0 = successfully deleted subarray from all container members
+ * 1 = failed to sync metadata to one or more devices
+ * 2 = failed to find the container, subarray, or other resource
+ * issue
+ */
+ struct mdstat_ent *mdstat, *ent;
+ struct supertype *st, supertype;
+ struct mdinfo *mdi;
+ int fd, rv = 2;
+
+ st = &supertype;
+ memset(st, 0, sizeof(*st));
+
+ fd = open(dev, O_RDWR|O_EXCL);
+ if (fd < 0) {
+ if (!quiet)
+ fprintf(stderr, Name ": Couldn't open %s, aborting\n",
+ dev);
+ return 2;
+ }
+
+ st->devnum = fd2devnum(fd);
+ if (st->devnum == NoMdDev) {
+ if (!quiet)
+ fprintf(stderr,
+ Name ": Failed to determine device number for %s\n",
+ dev);
+ goto close_fd;
+ }
+
+ mdi = sysfs_read(fd, st->devnum, GET_VERSION|GET_LEVEL);
+ if (!mdi) {
+ if (!quiet)
+ fprintf(stderr, Name ": Failed to read sysfs for %s\n",
+ dev);
+ goto close_fd;
+ }
+
+ if (mdi->array.level != UnSet) {
+ if (!quiet)
+ fprintf(stderr, Name ": %s is not a container\n", dev);
+ goto free_sysfs;
+ }
+
+ st->ss = version_to_superswitch(mdi->text_version);
+ if (!st->ss || !st->ss->kill_subarray) {
+ if (!quiet)
+ fprintf(stderr,
+ Name ": Operation not supported for %s metadata\n",
+ mdi->text_version);
+ goto free_sysfs;
+ }
+
+ if (snprintf(st->subarray, sizeof(st->subarray), "%s", subarray) >=
+ sizeof(st->subarray)) {
+ if (!quiet)
+ fprintf(stderr,
+ Name ": Input overflow for subarray '%s' > %zu bytes\n",
+ subarray, sizeof(st->subarray) - 1);
+ goto free_sysfs;
+ }
+
+ st->devname = devnum2devname(st->devnum);
+ if (!st->devname) {
+ if (!quiet)
+ fprintf(stderr, Name ": Failed to allocate device name\n");
+ goto free_sysfs;
+ }
+
+ if (st->ss->load_super(st, fd, NULL)) {
+ if (!quiet)
+ fprintf(stderr, Name ": Failed to find subarray-%s in %s\n",
+ subarray, dev);
+ goto free_name;
+ }
+
+ if (!st->loaded_container) {
+ if (!quiet)
+ fprintf(stderr, Name ": %s is not a container\n", dev);
+ goto free_super;
+ }
+
+ mdstat = mdstat_read(0, 0);
+ if (!mdstat) {
+ if (!quiet)
+ fprintf(stderr, Name ": Failed to read /proc/mdstat\n");
+ goto free_super;
+ }
+
+ for (ent = mdstat; ent; ent = ent->next)
+ if (is_container_member(ent, st->devname))
+ break;
+ if (ent) {
+ if (!quiet)
+ fprintf(stderr,
+ Name ": %s has active subarray(s), aborting\n",
+ dev);
+ goto free_mdstat;
+ }
+
+ /* ok we've found our victim, drop the axe */
+ st->ss->kill_subarray(st);
+
+ /* FIXME ->sync_metadata() does not report success/failure */
+ st->ss->sync_metadata(st);
+
+ if (!quiet)
+ fprintf(stderr,
+ Name ": Deleted subarray-%s from %s, UUIDs may have changed\n",
+ subarray, dev);
+
+ rv = 0;
+
+ free_mdstat:
+ free_mdstat(mdstat);
+ free_super:
+ st->ss->free_super(st);
+ free_name:
+ free(st->devname);
+ free_sysfs:
+ sysfs_free(mdi);
+ close_fd:
+ close(fd);
+
+ return rv;
+}
diff --git a/ReadMe.c b/ReadMe.c
index 9d5a211..387ba6d 100644
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -108,6 +108,7 @@ struct option long_options[] = {
{"examine-bitmap", 0, 0, 'X'},
{"auto-detect", 0, 0, AutoDetect},
{"detail-platform", 0, 0, DetailPlatform},
+ {"kill-subarray", 1, 0, KillSubarray},
/* synonyms */
{"monitor", 0, 0, 'F'},
diff --git a/mdadm.c b/mdadm.c
index d5e34c0..446fab8 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -103,6 +103,7 @@ int main(int argc, char *argv[])
int dosyslog = 0;
int rebuild_map = 0;
int auto_update_home = 0;
+ char *subarray = NULL;
int print_help = 0;
FILE *outf;
@@ -216,6 +217,9 @@ int main(int argc, char *argv[])
case 'W':
case Waitclean:
case DetailPlatform:
+ case KillSubarray:
+ if (opt == KillSubarray)
+ subarray = optarg;
case 'K': if (!mode) newmode = MISC; break;
}
if (mode && newmode == mode) {
@@ -807,6 +811,7 @@ int main(int argc, char *argv[])
case O(MISC,'W'):
case O(MISC, Waitclean):
case O(MISC, DetailPlatform):
+ case O(MISC, KillSubarray):
if (devmode && devmode != opt &&
(devmode == 'E' || (opt == 'E' && devmode != 'Q'))) {
fprintf(stderr, Name ": --examine/-E cannot be given with -%c\n",
@@ -1403,6 +1408,9 @@ int main(int argc, char *argv[])
rv |= Wait(dv->devname); continue;
case Waitclean:
rv |= WaitClean(dv->devname, -1, verbose-quiet); continue;
+ case KillSubarray:
+ rv |= Kill_subarray(dv->devname, subarray, quiet);
+ continue;
}
mdfd = open_mddev(dv->devname, 1);
if (mdfd>=0) {
diff --git a/mdadm.h b/mdadm.h
index d9d17b0..bf055c0 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -273,6 +273,7 @@ enum special_options {
AutoDetect,
Waitclean,
DetailPlatform,
+ KillSubarray,
};
/* structures read from config file */
@@ -609,6 +610,8 @@ extern struct superswitch {
struct mdinfo *(*container_content)(struct supertype *st);
/* Allow a metadata handler to override mdadm's default layouts */
int (*default_layout)(int level); /* optional */
+ /* Permit subarray's to be deleted from inactive containers */
+ void (*kill_subarray)(struct supertype *st);
/* for mdmon */
int (*open_new)(struct supertype *c, struct active_array *a,
@@ -805,6 +808,7 @@ extern int Monitor(mddev_dev_t devlist,
int dosyslog, int test, char *pidfile, int increments);
extern int Kill(char *dev, struct supertype *st, int force, int quiet, int noexcl);
+extern int Kill_subarray(char *dev, char *subarray, int quiet);
extern int Wait(char *dev);
extern int WaitClean(char *dev, int sock, int verbose);
@@ -911,6 +915,8 @@ extern int create_mddev(char *dev, char *name, int autof, int trustworthy,
#define METADATA 3
extern int open_mddev(char *dev, int report_errors);
extern int open_container(int fd);
+extern int is_container_member(struct mdstat_ent *ent, char *devname);
+extern struct superswitch *version_to_superswitch(char *vers);
extern char *pid_dir;
extern int mdmon_running(int devnum);
diff --git a/mdmon.c b/mdmon.c
index 69c320e..beb39cf 100644
--- a/mdmon.c
+++ b/mdmon.c
@@ -104,15 +104,6 @@ int __clone2(int (*fn)(void *),
return mon_tid;
}
-static struct superswitch *find_metadata_methods(char *vers)
-{
- if (strcmp(vers, "ddf") == 0)
- return &super_ddf;
- if (strcmp(vers, "imsm") == 0)
- return &super_imsm;
- return NULL;
-}
-
static int make_pidfile(char *devname)
{
char path[100];
@@ -136,18 +127,6 @@ static int make_pidfile(char *devname)
return 0;
}
-int is_container_member(struct mdstat_ent *mdstat, char *container)
-{
- if (mdstat->metadata_version == NULL ||
- strncmp(mdstat->metadata_version, "external:", 9) != 0 ||
- !is_subarray(mdstat->metadata_version+9) ||
- strncmp(mdstat->metadata_version+10, container, strlen(container)) != 0 ||
- mdstat->metadata_version[10+strlen(container)] != '/')
- return 0;
-
- return 1;
-}
-
static void try_kill_monitor(pid_t pid, char *devname, int sock)
{
char buf[100];
@@ -414,9 +393,9 @@ static int mdmon(char *devname, int devnum, int must_fork, int takeover)
exit(3);
}
- container->ss = find_metadata_methods(mdi->text_version);
+ container->ss = version_to_superswitch(mdi->text_version);
if (container->ss == NULL) {
- fprintf(stderr, "mdmon: %s uses unknown metadata: %s\n",
+ fprintf(stderr, "mdmon: %s uses unsupported metadata: %s\n",
devname, mdi->text_version);
exit(3);
}
diff --git a/super-ddf.c b/super-ddf.c
index 0e6f1e5..736e07f 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -845,10 +845,18 @@ static int load_super_ddf(struct supertype *st, int fd,
}
if (st->subarray[0]) {
+ unsigned long val;
struct vcl *v;
+ char *ep;
+
+ val = strtoul(st->subarray, &ep, 10);
+ if (*ep != '\0') {
+ free(super);
+ return 1;
+ }
for (v = super->conflist; v; v = v->next)
- if (v->vcnum == atoi(st->subarray))
+ if (v->vcnum == val)
super->currentconf = v;
if (!super->currentconf) {
free(super);
@@ -2870,14 +2878,25 @@ static int load_super_ddf_all(struct supertype *st, int fd,
return 1;
}
if (st->subarray[0]) {
+ unsigned long val;
struct vcl *v;
+ char *ep;
+
+ val = strtoul(st->subarray, &ep, 10);
+ if (*ep != '\0') {
+ free(super);
+ return 1;
+ }
for (v = super->conflist; v; v = v->next)
- if (v->vcnum == atoi(st->subarray))
+ if (v->vcnum == val)
super->currentconf = v;
- if (!super->currentconf)
+ if (!super->currentconf) {
+ free(super);
return 1;
+ }
}
+
*sbp = super;
if (st->ss == NULL) {
st->ss = &super_ddf;
diff --git a/super-intel.c b/super-intel.c
index bdd7a96..7344a09 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -2753,11 +2753,20 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
}
if (st->subarray[0]) {
- if (atoi(st->subarray) <= super->anchor->num_raid_devs)
- super->current_vol = atoi(st->subarray);
+ unsigned long val;
+ char *ep;
+
+ err = 1;
+ val = strtoul(st->subarray, &ep, 10);
+ if (*ep != '\0') {
+ free_imsm(super);
+ goto error;
+ }
+
+ if (val < super->anchor->num_raid_devs)
+ super->current_vol = val;
else {
free_imsm(super);
- err = 1;
goto error;
}
}
@@ -2824,8 +2833,17 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
}
if (st->subarray[0]) {
- if (atoi(st->subarray) <= super->anchor->num_raid_devs)
- super->current_vol = atoi(st->subarray);
+ unsigned long val;
+ char *ep;
+
+ val = strtoul(st->subarray, &ep, 10);
+ if (*ep != '\0') {
+ free_imsm(super);
+ return 1;
+ }
+
+ if (val < super->anchor->num_raid_devs)
+ super->current_vol = val;
else {
free_imsm(super);
return 1;
@@ -4007,6 +4025,45 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
close(cfd);
return 0;
}
+
+static void handle_missing(struct intel_super *super, struct imsm_dev *dev);
+
+static void kill_subarray_imsm(struct supertype *st)
+{
+ /* remove the subarray currently referenced by ->current_vol */
+ struct intel_dev **dp;
+ struct intel_super *super = st->sb;
+ struct imsm_super *mpb = super->anchor;
+
+ if (super->current_vol < 0)
+ return;
+
+ for (dp = &super->devlist; *dp;)
+ if ((*dp)->index == super->current_vol) {
+ *dp = (*dp)->next;
+ } else {
+ handle_missing(super, (*dp)->dev);
+ if ((*dp)->index > super->current_vol)
+ (*dp)->index--;
+ dp = &(*dp)->next;
+ }
+
+ /* no more raid devices, all active components are now spares,
+ * but of course failed are still failed
+ */
+ if (--mpb->num_raid_devs == 0) {
+ struct dl *d;
+
+ for (d = super->disks; d; d = d->next)
+ if (d->index > -2) {
+ d->index = -1;
+ d->disk.status = SPARE_DISK;
+ }
+ }
+
+ super->current_vol = -1;
+ super->updates_pending++;
+}
#endif /* MDASSEMBLE */
static int is_rebuilding(struct imsm_dev *dev)
@@ -4347,6 +4404,24 @@ static void mark_missing(struct imsm_dev *dev, struct imsm_disk *disk, int idx)
memmove(&disk->serial[0], &disk->serial[1], MAX_RAID_SERIAL_LEN - 1);
}
+static void handle_missing(struct intel_super *super, struct imsm_dev *dev)
+{
+ __u8 map_state;
+ struct dl *dl;
+ int failed;
+
+ if (!super->missing)
+ return;
+ failed = imsm_count_failed(super, dev);
+ map_state = imsm_check_degraded(super, dev, failed);
+
+ dprintf("imsm: mark missing\n");
+ end_migration(dev, map_state);
+ for (dl = super->missing; dl; dl = dl->next)
+ mark_missing(dev, &dl->disk, dl->index);
+ super->updates_pending++;
+}
+
/* Handle dirty -> clean transititions and resync. Degraded and rebuild
* states are handled in imsm_set_disk() with one exception, when a
* resync is stopped due to a new failure this routine will set the
@@ -4363,15 +4438,8 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
__u32 blocks_per_unit;
/* before we activate this array handle any missing disks */
- if (consistent == 2 && super->missing) {
- struct dl *dl;
-
- dprintf("imsm: mark missing\n");
- end_migration(dev, map_state);
- for (dl = super->missing; dl; dl = dl->next)
- mark_missing(dev, &dl->disk, dl->index);
- super->updates_pending++;
- }
+ if (consistent == 2)
+ handle_missing(super, dev);
if (consistent == 2 &&
(!is_resync_complete(&a->info) ||
@@ -5242,6 +5310,7 @@ struct superswitch super_imsm = {
.validate_geometry = validate_geometry_imsm,
.add_to_super = add_to_super_imsm,
.detail_platform = detail_platform_imsm,
+ .kill_subarray = kill_subarray_imsm,
#endif
.match_home = match_home_imsm,
.uuid_from_super= uuid_from_super_imsm,
diff --git a/util.c b/util.c
index 25f1e56..2e07912 100644
--- a/util.c
+++ b/util.c
@@ -1392,6 +1392,32 @@ int open_container(int fd)
return -1;
}
+struct superswitch *version_to_superswitch(char *vers)
+{
+ int i;
+
+ for (i = 0; superlist[i]; i++) {
+ struct superswitch *ss = superlist[i];
+
+ if (strcmp(vers, ss->name) == 0)
+ return ss;
+ }
+
+ return NULL;
+}
+
+int is_container_member(struct mdstat_ent *mdstat, char *container)
+{
+ if (mdstat->metadata_version == NULL ||
+ strncmp(mdstat->metadata_version, "external:", 9) != 0 ||
+ !is_subarray(mdstat->metadata_version+9) ||
+ strncmp(mdstat->metadata_version+10, container, strlen(container)) != 0 ||
+ mdstat->metadata_version[10+strlen(container)] != '/')
+ return 0;
+
+ return 1;
+}
+
int add_disk(int mdfd, struct supertype *st,
struct mdinfo *sra, struct mdinfo *info)
{
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-05-19 1:09 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-22 22:10 [PATCH 00/13] imsm: new imsm metadata features Hawrylewicz Czarnowski, Przemyslaw
2010-04-30 0:57 ` Dan Williams
2010-04-30 20:45 ` Doug Ledford
2010-05-19 1:09 ` Dan Williams
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).