]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super0.c
Grow: E2BIG should be reporte differently if --data-offset was requested.
[thirdparty/mdadm.git] / super0.c
index eb902ebd1af5d0cd92b31b22f7322505efcf9aa9..061e475e52a70c6a2685879c0aaac33600e34cb6 100644 (file)
--- 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;
@@ -435,6 +479,18 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
        int rv = 0;
        int uuid[4];
        mdp_super_t *sb = st->sb;
+
+       if (strcmp(update, "homehost") == 0 &&
+           homehost) {
+               /* note that 'homehost' is special as it is really
+                * a "uuid" update.
+                */
+               uuid_set = 0;
+               update = "uuid";
+               info->uuid[0] = sb->set_uuid0;
+               info->uuid[1] = sb->set_uuid1;
+       }
+
        if (strcmp(update, "sparc2.2")==0 ) {
                /* 2.2 sparc put the events in the wrong place
                 * So we copy the tail of the superblock
@@ -551,12 +607,6 @@ static int update_super0(struct supertype *st, struct mdinfo *info,
                /* make sure resync happens */
                sb->state &= ~(1<<MD_SB_CLEAN);
                sb->recovery_cp = 0;
-       } else if (strcmp(update, "homehost") == 0 &&
-                  homehost) {
-               uuid_set = 0;
-               update = "uuid";
-               info->uuid[0] = sb->set_uuid0;
-               info->uuid[1] = sb->set_uuid1;
        } else if (strcmp(update, "uuid") == 0) {
                if (!uuid_set && homehost) {
                        char buf[20];
@@ -607,7 +657,7 @@ static int init_super0(struct supertype *st, mdu_array_info_t *info,
        int spares;
 
        if (data_offset != INVALID_SECTORS) {
-               fprintf(stderr, Name ": data-offset not support for 0.90\n");
+               pr_err("data-offset not support for 0.90\n");
                return 0;
        }
 
@@ -638,9 +688,9 @@ static int init_super0(struct supertype *st, mdu_array_info_t *info,
        sb->gvalid_words = 0; /* ignored */
        sb->ctime = time(0);
        sb->level = info->level;
-       if (size != (unsigned long long)info->size)
+       sb->size = size;
+       if (size != (unsigned long long)sb->size)
                return 0;
-       sb->size = info->size;
        sb->nr_disks = info->nr_disks;
        sb->raid_disks = info->raid_disks;
        sb->md_minor = info->md_minor;
@@ -870,8 +920,6 @@ static int load_super0(struct supertype *st, int fd, char *devname)
 
        offset *= 512;
 
-       ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
-
        if (lseek64(fd, offset, 0)< 0LL) {
                if (devname)
                        pr_err("Cannot seek to superblock on %s: %s\n",
@@ -949,7 +997,7 @@ static struct supertype *match_metadata_desc0(char *arg)
 {
        struct supertype *st = xcalloc(1, sizeof(*st));
 
-       st->container_dev = NoMdDev;
+       st->container_devnm[0] = 0;
        st->ss = &super0;
        st->info = NULL;
        st->minor_version = 90;
@@ -1197,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,