summaryrefslogtreecommitdiff
path: root/mdadm.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2013-05-16 15:07:16 +1000
committerNeilBrown <neilb@suse.de>2013-05-16 15:07:16 +1000
commit74db60b00a43a5ae636477c10c24e923e76049ce (patch)
tree168664568b7c8d27b12ef00ad0119ac29b2c1056 /mdadm.c
parentb31df43682216d1c65813eae49ebdd8253db8907 (diff)
Add --dump / --restore functionality.
This allows the metadata on a device to be saved and later restored. This can be useful before experimenting on an array that is misbehaving. Suggested-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'mdadm.c')
-rw-r--r--mdadm.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/mdadm.c b/mdadm.c
index e053db59..ff3fed72 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -37,6 +37,7 @@ static int misc_scan(char devmode, struct context *c);
static int stop_scan(int verbose);
static int misc_list(struct mddev_dev *devlist,
struct mddev_ident *ident,
+ char *dump_directory,
struct supertype *ss, struct context *c);
@@ -94,6 +95,7 @@ int main(int argc, char *argv[])
int rebuild_map = 0;
char *remove_path = NULL;
char *udev_filename = NULL;
+ char *dump_directory = NULL;
int print_help = 0;
FILE *outf;
@@ -234,6 +236,8 @@ int main(int argc, char *argv[])
case 'X':
case 'Q':
case ExamineBB:
+ case Dump:
+ case Restore:
newmode = MISC;
break;
@@ -982,6 +986,8 @@ int main(int argc, char *argv[])
case O(MISC, DetailPlatform):
case O(MISC, KillSubarray):
case O(MISC, UpdateSubarray):
+ case O(MISC, Dump):
+ case O(MISC, Restore):
if (opt == KillSubarray || opt == UpdateSubarray) {
if (c.subarray) {
pr_err("subarray can only"
@@ -1006,6 +1012,14 @@ int main(int argc, char *argv[])
exit(2);
}
devmode = opt;
+ if (opt == Dump || opt == Restore) {
+ if (dump_directory != NULL) {
+ pr_err("dump/restore directory specified twice: %s and %s\n",
+ dump_directory, optarg);
+ exit(2);
+ }
+ dump_directory = optarg;
+ }
continue;
case O(MISC, UdevRules):
if (devmode && devmode != opt) {
@@ -1407,7 +1421,7 @@ int main(int argc, char *argv[])
exit(2);
}
} else
- rv = misc_list(devlist, &ident, ss, &c);
+ rv = misc_list(devlist, &ident, dump_directory, ss, &c);
break;
case MONITOR:
if (!devlist && !c.scan) {
@@ -1721,12 +1735,13 @@ static int stop_scan(int verbose)
static int misc_list(struct mddev_dev *devlist,
struct mddev_ident *ident,
+ char *dump_directory,
struct supertype *ss, struct context *c)
{
struct mddev_dev *dv;
int rv = 0;
- for (dv=devlist ; dv; dv=dv->next) {
+ for (dv=devlist ; dv; dv=(rv & 16) ? NULL : dv->next) {
int mdfd;
switch(dv->disposition) {
@@ -1768,6 +1783,13 @@ static int misc_list(struct mddev_dev *devlist,
rv |= Update_subarray(dv->devname, c->subarray,
c->update, ident, c->verbose);
continue;
+ case Dump:
+ rv |= Dump_metadata(dv->devname, dump_directory, c, ss);
+ continue;
+ case Restore:
+ rv |= Restore_metadata(dv->devname, dump_directory, c, ss,
+ (dv == devlist && dv->next == NULL));
+ continue;
}
mdfd = open_mddev(dv->devname, 1);
if (mdfd>=0) {