summaryrefslogtreecommitdiffstats
path: root/super0.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2013-05-16 07:07:16 +0200
committerNeilBrown <neilb@suse.de>2013-05-16 07:07:16 +0200
commit74db60b00a43a5ae636477c10c24e923e76049ce (patch)
tree168664568b7c8d27b12ef00ad0119ac29b2c1056 /super0.c
parentintel,ddf: don't require partitions when ignore_hw_compat is set. (diff)
downloadmdadm-74db60b00a43a5ae636477c10c24e923e76049ce.tar.xz
mdadm-74db60b00a43a5ae636477c10c24e923e76049ce.zip
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 'super0.c')
-rw-r--r--super0.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/super0.c b/super0.c
index 1f4dc750..58785e29 100644
--- a/super0.c
+++ b/super0.c
@@ -47,7 +47,6 @@ static unsigned long calc_sb0_csum(mdp_super_t *super)
return newcsum;
}
-
static void super0_swap_endian(struct mdp_superblock_s *sb)
{
/* as super0 superblocks are host-endian, it is sometimes
@@ -281,6 +280,51 @@ static void export_examine_super0(struct supertype *st)
+ sb->events_lo);
}
+static int copy_metadata0(struct supertype *st, int from, int to)
+{
+ /* Read 64K from the appropriate offset of 'from'
+ * and if it looks a little like a 0.90 superblock,
+ * write it to the same offset of 'to'
+ */
+ void *buf;
+ unsigned long long dsize, offset;
+ const int bufsize = 64*1024;
+ mdp_super_t *super;
+
+ if (posix_memalign(&buf, 4096, bufsize) != 0)
+ return 1;
+
+ if (!get_dev_size(from, NULL, &dsize))
+ goto err;
+
+ if (dsize < MD_RESERVED_SECTORS*512)
+ goto err;
+
+ offset = MD_NEW_SIZE_SECTORS(dsize>>9);
+
+ offset *= 512;
+
+ if (lseek64(from, offset, 0) < 0LL)
+ goto err;
+ if (read(from, buf, bufsize) != bufsize)
+ goto err;
+
+ if (lseek64(to, offset, 0) < 0LL)
+ goto err;
+ super = buf;
+ if (super->md_magic != MD_SB_MAGIC ||
+ super->major_version != 0 ||
+ calc_sb0_csum(super) != super->sb_csum)
+ goto err;
+ if (write(to, buf, bufsize) != bufsize)
+ goto err;
+ free(buf);
+ return 0;
+err:
+ free(buf);
+ return 1;
+}
+
static void detail_super0(struct supertype *st, char *homehost)
{
mdp_super_t *sb = st->sb;
@@ -1201,6 +1245,7 @@ struct superswitch super0 = {
.write_init_super = write_init_super0,
.validate_geometry = validate_geometry0,
.add_to_super = add_to_super0,
+ .copy_metadata = copy_metadata0,
#endif
.match_home = match_home0,
.uuid_from_super = uuid_from_super0,