]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-ddf.c
Teach sysfs_add_disk() callers to use ->recovery_start versus 'insync' parameter
[thirdparty/mdadm.git] / super-ddf.c
index 77a481f37461cc8411b01b530764a53d6fcf0833..14f83304bde10c8f4ddff2bc17d5f4eb1d08dce5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2006-2007 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2006-2009 Neil Brown <neilb@suse.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
@@ -762,6 +762,9 @@ static int load_ddf_local(int fd, struct ddf_super *super,
 static int load_super_ddf_all(struct supertype *st, int fd,
                              void **sbp, char *devname, int keep_fd);
 #endif
+
+static void free_super_ddf(struct supertype *st);
+
 static int load_super_ddf(struct supertype *st, int fd,
                          char *devname)
 {
@@ -798,6 +801,8 @@ static int load_super_ddf(struct supertype *st, int fd,
                return 1;
        }
 
+       free_super_ddf(st);
+
        if (posix_memalign((void**)&super, 512, sizeof(*super))!= 0) {
                fprintf(stderr, Name ": malloc of %zu failed.\n",
                        sizeof(*super));
@@ -835,6 +840,18 @@ static int load_super_ddf(struct supertype *st, int fd,
                return rv;
        }
 
+       if (st->subarray[0]) {
+               struct vcl *v;
+
+               for (v = super->conflist; v; v = v->next)
+                       if (v->vcnum == atoi(st->subarray))
+                               super->currentconf = v;
+               if (!super->currentconf) {
+                       free(super);
+                       return 1;
+               }
+       }
+
        /* Should possibly check the sections .... */
 
        st->sb = super;
@@ -1163,6 +1180,18 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info);
 static void uuid_from_super_ddf(struct supertype *st, int uuid[4]);
 
 static void brief_examine_super_ddf(struct supertype *st, int verbose)
+{
+       /* We just write a generic DDF ARRAY entry
+        */
+       struct mdinfo info;
+       char nbuf[64];
+       getinfo_super_ddf(st, &info);
+       fname_from_uuid(st, &info, nbuf, ':');
+
+       printf("ARRAY metadata=ddf UUID=%s\n", nbuf + 5);
+}
+
+static void brief_examine_subarrays_ddf(struct supertype *st, int verbose)
 {
        /* We just write a generic DDF ARRAY entry
         */
@@ -1172,7 +1201,6 @@ static void brief_examine_super_ddf(struct supertype *st, int verbose)
        char nbuf[64];
        getinfo_super_ddf(st, &info);
        fname_from_uuid(st, &info, nbuf, ':');
-       printf("ARRAY metadata=ddf UUID=%s\n", nbuf + 5);
 
        for (i=0; i<__be16_to_cpu(ddf->virt->max_vdes); i++) {
                struct virtual_entry *ve = &ddf->virt->entries[i];
@@ -1338,7 +1366,7 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info)
                info->disk.raid_disk = -1;
 //             info->disk.raid_disk = find refnum in the table and use index;
        }
-       info->disk.state = (1 << MD_DISK_SYNC);
+       info->disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
 
 
        info->reshape_active = 0;
@@ -1405,7 +1433,7 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info)
            (ddf->virt->entries[info->container_member].init_state
             & DDF_initstate_mask)
            == DDF_init_full)
-               info->resync_start = ~0ULL;
+               info->resync_start = MaxSector;
 
        uuid_from_super_ddf(st, info->uuid);
 
@@ -1495,17 +1523,6 @@ static int update_super_ddf(struct supertype *st, struct mdinfo *info,
        return rv;
 }
 
-__u32 random32(void)
-{
-       __u32 rv;
-       int rfd = open("/dev/urandom", O_RDONLY);
-       if (rfd < 0 || read(rfd, &rv, 4) != 4)
-               rv = random();
-       if (rfd >= 0)
-               close(rfd);
-       return rv;
-}
-
 static void make_header_guid(char *guid)
 {
        __u32 stamp;
@@ -1572,13 +1589,8 @@ static int init_super_ddf(struct supertype *st,
        struct phys_disk *pd;
        struct virtual_disk *vd;
 
-       if (!info) {
-               st->sb = NULL;
-               return 0;
-       }
        if (st->sb)
-               return init_super_ddf_bvd(st, info, size, name, homehost,
-                                         uuid);
+               return init_super_ddf_bvd(st, info, size, name, homehost, uuid);
 
        if (posix_memalign((void**)&ddf, 512, sizeof(*ddf)) != 0) {
                fprintf(stderr, Name ": %s could not allocate superblock\n", __func__);
@@ -1587,6 +1599,12 @@ static int init_super_ddf(struct supertype *st,
        memset(ddf, 0, sizeof(*ddf));
        ddf->dlist = NULL; /* no physical disks yet */
        ddf->conflist = NULL; /* No virtual disks yet */
+       st->sb = ddf;
+
+       if (info == NULL) {
+               /* zeroing superblock */
+               return 0;
+       }
 
        /* At least 32MB *must* be reserved for the ddf.  So let's just
         * start 32MB from the end, and put the primary header there.
@@ -2345,15 +2363,19 @@ static int __write_init_super_ddf(struct supertype *st, int do_close)
 
 static int write_init_super_ddf(struct supertype *st)
 {
+       struct ddf_super *ddf = st->sb;
+       struct vcl *currentconf = ddf->currentconf;
+
+       /* we are done with currentconf reset it to point st at the container */
+       ddf->currentconf = NULL;
 
        if (st->update_tail) {
                /* queue the virtual_disk and vd_config as metadata updates */
                struct virtual_disk *vd;
                struct vd_config *vc;
-               struct ddf_super *ddf = st->sb;
                int len;
 
-               if (!ddf->currentconf) {
+               if (!currentconf) {
                        int len = (sizeof(struct phys_disk) +
                                   sizeof(struct phys_disk_entry));
 
@@ -2372,14 +2394,14 @@ static int write_init_super_ddf(struct supertype *st)
                len = sizeof(struct virtual_disk) + sizeof(struct virtual_entry);
                vd = malloc(len);
                *vd = *ddf->virt;
-               vd->entries[0] = ddf->virt->entries[ddf->currentconf->vcnum];
-               vd->populated_vdes = __cpu_to_be16(ddf->currentconf->vcnum);
+               vd->entries[0] = ddf->virt->entries[currentconf->vcnum];
+               vd->populated_vdes = __cpu_to_be16(currentconf->vcnum);
                append_metadata_update(st, vd, len);
 
                /* Then the vd_config */
                len = ddf->conf_rec_len * 512;
                vc = malloc(len);
-               memcpy(vc, &ddf->currentconf->conf, len);
+               memcpy(vc, &currentconf->conf, len);
                append_metadata_update(st, vc, len);
 
                /* FIXME I need to close the fds! */
@@ -2533,8 +2555,12 @@ static int validate_geometry_ddf(struct supertype *st,
                for (i=0; ddf_level_num[i].num1 != MAXINT; i++)
                        if (ddf_level_num[i].num2 == level)
                                break;
-               if (ddf_level_num[i].num1 == MAXINT)
+               if (ddf_level_num[i].num1 == MAXINT) {
+                       if (verbose)
+                               fprintf(stderr, Name ": DDF does not support level %d arrays\n",
+                                       level);
                        return 0;
+               }
                /* Should check layout? etc */
 
                if (st->sb && freesize) {
@@ -2582,7 +2608,7 @@ static int validate_geometry_ddf(struct supertype *st,
                if (verbose)
                        fprintf(stderr,
                                Name ": ddf: Cannot create this array "
-                               "on device %s\n",
+                               "on device %s - a container is required.\n",
                                dev);
                return 0;
        }
@@ -2674,8 +2700,11 @@ static int validate_geometry_ddf_bvd(struct supertype *st,
        struct extent *e;
        int i;
        /* ddf/bvd supports lots of things, but not containers */
-       if (level == LEVEL_CONTAINER)
+       if (level == LEVEL_CONTAINER) {
+               if (verbose)
+                       fprintf(stderr, Name ": DDF cannot create a container within an container\n");
                return 0;
+       }
        /* We must have the container info already read in. */
        if (!ddf)
                return 0;
@@ -2892,7 +2921,7 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
                        this->resync_start = 0;
                } else {
                        this->array.state = 1;
-                       this->resync_start = ~0ULL;
+                       this->resync_start = MaxSector;
                }
                memcpy(this->name, ddf->virt->entries[i].name, 16);
                this->name[16]=0;
@@ -2939,6 +2968,7 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
                        dev->disk.minor = d->minor;
                        dev->disk.raid_disk = i;
                        dev->disk.state = (1<<MD_DISK_SYNC)|(1<<MD_DISK_ACTIVE);
+                       dev->recovery_start = MaxSector;
 
                        dev->events = __be32_to_cpu(ddf->primary.seq);
                        dev->data_offset = __be64_to_cpu(vc->lba_offset[i]);
@@ -2950,12 +2980,22 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
        return rest;
 }
 
-static int store_zero_ddf(struct supertype *st, int fd)
+static int store_super_ddf(struct supertype *st, int fd)
 {
+       struct ddf_super *ddf = st->sb;
        unsigned long long dsize;
        void *buf;
        int rc;
 
+       if (!ddf)
+               return 1;
+
+       /* ->dlist and ->conflist will be set for updates, currently not
+        * supported
+        */
+       if (ddf->dlist || ddf->conflist)
+               return 1;
+
        if (!get_dev_size(fd, NULL, &dsize))
                return 1;
 
@@ -3027,7 +3067,7 @@ static int ddf_set_array_state(struct active_array *a, int consistent)
        if (consistent == 2) {
                /* Should check if a recovery should be started FIXME */
                consistent = 1;
-               if (!is_resync_complete(a))
+               if (!is_resync_complete(&a->info))
                        consistent = 0;
        }
        if (consistent)
@@ -3039,9 +3079,9 @@ static int ddf_set_array_state(struct active_array *a, int consistent)
 
        old = ddf->virt->entries[inst].init_state;
        ddf->virt->entries[inst].init_state &= ~DDF_initstate_mask;
-       if (is_resync_complete(a))
+       if (is_resync_complete(&a->info))
                ddf->virt->entries[inst].init_state |= DDF_init_full;
-       else if (a->resync_start == 0)
+       else if (a->info.resync_start == 0)
                ddf->virt->entries[inst].init_state |= DDF_init_not;
        else
                ddf->virt->entries[inst].init_state |= DDF_init_quick;
@@ -3049,7 +3089,7 @@ static int ddf_set_array_state(struct active_array *a, int consistent)
                ddf->updates_pending = 1;
 
        dprintf("ddf mark %d %s %llu\n", inst, consistent?"clean":"dirty",
-               a->resync_start);
+               a->info.resync_start);
        return consistent;
 }
 
@@ -3508,6 +3548,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
                        di->disk.major = dl->major;
                        di->disk.minor = dl->minor;
                        di->disk.state = 0;
+                       di->recovery_start = 0;
                        di->data_offset = pos;
                        di->component_size = a->info.component_size;
                        di->container_member = dl->pdnum;
@@ -3587,6 +3628,7 @@ struct superswitch super_ddf = {
 #ifndef        MDASSEMBLE
        .examine_super  = examine_super_ddf,
        .brief_examine_super = brief_examine_super_ddf,
+       .brief_examine_subarrays = brief_examine_subarrays_ddf,
        .export_examine_super = export_examine_super_ddf,
        .detail_super   = detail_super_ddf,
        .brief_detail_super = brief_detail_super_ddf,
@@ -3605,7 +3647,7 @@ struct superswitch super_ddf = {
 
        .load_super     = load_super_ddf,
        .init_super     = init_super_ddf,
-       .store_super    = store_zero_ddf,
+       .store_super    = store_super_ddf,
        .free_super     = free_super_ddf,
        .match_metadata_desc = match_metadata_desc_ddf,
        .container_content = container_content_ddf,