The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/geom/raid/md_jmicron.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2010 Alexander Motin <mav@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/9.0/sys/geom/raid/md_jmicron.c 220210 2011-03-31 16:19:53Z mav $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/bio.h>
   32 #include <sys/endian.h>
   33 #include <sys/kernel.h>
   34 #include <sys/kobj.h>
   35 #include <sys/limits.h>
   36 #include <sys/lock.h>
   37 #include <sys/malloc.h>
   38 #include <sys/mutex.h>
   39 #include <sys/systm.h>
   40 #include <sys/taskqueue.h>
   41 #include <geom/geom.h>
   42 #include "geom/raid/g_raid.h"
   43 #include "g_raid_md_if.h"
   44 
   45 static MALLOC_DEFINE(M_MD_JMICRON, "md_jmicron_data", "GEOM_RAID JMicron metadata");
   46 
   47 #define JMICRON_MAX_DISKS       8
   48 #define JMICRON_MAX_SPARE       2
   49 
   50 struct jmicron_raid_conf {
   51     u_int8_t            signature[2];
   52 #define JMICRON_MAGIC           "JM"
   53 
   54     u_int16_t           version;
   55 #define JMICRON_VERSION         0x0001
   56 
   57     u_int16_t           checksum;
   58     u_int8_t            filler_1[10];
   59     u_int32_t           disk_id;
   60     u_int32_t           offset;
   61     u_int32_t           disk_sectors_high;
   62     u_int16_t           disk_sectors_low;
   63     u_int8_t            filler_2[2];
   64     u_int8_t            name[16];
   65     u_int8_t            type;
   66 #define JMICRON_T_RAID0         0
   67 #define JMICRON_T_RAID1         1
   68 #define JMICRON_T_RAID01        2
   69 #define JMICRON_T_CONCAT        3
   70 #define JMICRON_T_RAID5         5
   71 
   72     u_int8_t            stripe_shift;
   73     u_int16_t           flags;
   74 #define JMICRON_F_READY         0x0001
   75 #define JMICRON_F_BOOTABLE      0x0002
   76 #define JMICRON_F_BADSEC        0x0004
   77 #define JMICRON_F_ACTIVE        0x0010
   78 #define JMICRON_F_UNSYNC        0x0020
   79 #define JMICRON_F_NEWEST        0x0040
   80 
   81     u_int8_t            filler_3[4];
   82     u_int32_t           spare[JMICRON_MAX_SPARE];
   83     u_int32_t           disks[JMICRON_MAX_DISKS];
   84 #define JMICRON_DISK_MASK       0xFFFFFFF0
   85 #define JMICRON_SEG_MASK        0x0000000F
   86     u_int8_t            filler_4[32];
   87     u_int8_t            filler_5[384];
   88 };
   89 
   90 struct g_raid_md_jmicron_perdisk {
   91         struct jmicron_raid_conf        *pd_meta;
   92         int                              pd_disk_pos;
   93         int                              pd_disk_id;
   94         off_t                            pd_disk_size;
   95 };
   96 
   97 struct g_raid_md_jmicron_object {
   98         struct g_raid_md_object  mdio_base;
   99         uint32_t                 mdio_config_id;
  100         struct jmicron_raid_conf        *mdio_meta;
  101         struct callout           mdio_start_co; /* STARTING state timer. */
  102         int                      mdio_total_disks;
  103         int                      mdio_disks_present;
  104         int                      mdio_started;
  105         int                      mdio_incomplete;
  106         struct root_hold_token  *mdio_rootmount; /* Root mount delay token. */
  107 };
  108 
  109 static g_raid_md_create_t g_raid_md_create_jmicron;
  110 static g_raid_md_taste_t g_raid_md_taste_jmicron;
  111 static g_raid_md_event_t g_raid_md_event_jmicron;
  112 static g_raid_md_ctl_t g_raid_md_ctl_jmicron;
  113 static g_raid_md_write_t g_raid_md_write_jmicron;
  114 static g_raid_md_fail_disk_t g_raid_md_fail_disk_jmicron;
  115 static g_raid_md_free_disk_t g_raid_md_free_disk_jmicron;
  116 static g_raid_md_free_t g_raid_md_free_jmicron;
  117 
  118 static kobj_method_t g_raid_md_jmicron_methods[] = {
  119         KOBJMETHOD(g_raid_md_create,    g_raid_md_create_jmicron),
  120         KOBJMETHOD(g_raid_md_taste,     g_raid_md_taste_jmicron),
  121         KOBJMETHOD(g_raid_md_event,     g_raid_md_event_jmicron),
  122         KOBJMETHOD(g_raid_md_ctl,       g_raid_md_ctl_jmicron),
  123         KOBJMETHOD(g_raid_md_write,     g_raid_md_write_jmicron),
  124         KOBJMETHOD(g_raid_md_fail_disk, g_raid_md_fail_disk_jmicron),
  125         KOBJMETHOD(g_raid_md_free_disk, g_raid_md_free_disk_jmicron),
  126         KOBJMETHOD(g_raid_md_free,      g_raid_md_free_jmicron),
  127         { 0, 0 }
  128 };
  129 
  130 static struct g_raid_md_class g_raid_md_jmicron_class = {
  131         "JMicron",
  132         g_raid_md_jmicron_methods,
  133         sizeof(struct g_raid_md_jmicron_object),
  134         .mdc_priority = 100
  135 };
  136 
  137 static void
  138 g_raid_md_jmicron_print(struct jmicron_raid_conf *meta)
  139 {
  140         int k;
  141 
  142         if (g_raid_debug < 1)
  143                 return;
  144 
  145         printf("********* ATA JMicron RAID Metadata *********\n");
  146         printf("signature           <%c%c>\n", meta->signature[0], meta->signature[1]);
  147         printf("version             %04x\n", meta->version);
  148         printf("checksum            0x%04x\n", meta->checksum);
  149         printf("disk_id             0x%08x\n", meta->disk_id);
  150         printf("offset              0x%08x\n", meta->offset);
  151         printf("disk_sectors_high   0x%08x\n", meta->disk_sectors_high);
  152         printf("disk_sectors_low    0x%04x\n", meta->disk_sectors_low);
  153         printf("name                <%.16s>\n", meta->name);
  154         printf("type                %d\n", meta->type);
  155         printf("stripe_shift        %d\n", meta->stripe_shift);
  156         printf("flags               %04x\n", meta->flags);
  157         printf("spare              ");
  158         for (k = 0; k < JMICRON_MAX_SPARE; k++)
  159                 printf(" 0x%08x", meta->spare[k]);
  160         printf("\n");
  161         printf("disks              ");
  162         for (k = 0; k < JMICRON_MAX_DISKS; k++)
  163                 printf(" 0x%08x", meta->disks[k]);
  164         printf("\n");
  165         printf("=================================================\n");
  166 }
  167 
  168 static struct jmicron_raid_conf *
  169 jmicron_meta_copy(struct jmicron_raid_conf *meta)
  170 {
  171         struct jmicron_raid_conf *nmeta;
  172 
  173         nmeta = malloc(sizeof(*meta), M_MD_JMICRON, M_WAITOK);
  174         memcpy(nmeta, meta, sizeof(*meta));
  175         return (nmeta);
  176 }
  177 
  178 static int
  179 jmicron_meta_total_disks(struct jmicron_raid_conf *meta)
  180 {
  181         int pos;
  182 
  183         for (pos = 0; pos < JMICRON_MAX_DISKS; pos++) {
  184                 if (meta->disks[pos] == 0)
  185                         break;
  186         }
  187         return (pos);
  188 }
  189 
  190 static int
  191 jmicron_meta_total_spare(struct jmicron_raid_conf *meta)
  192 {
  193         int pos, n;
  194 
  195         n = 0;
  196         for (pos = 0; pos < JMICRON_MAX_SPARE; pos++) {
  197                 if (meta->spare[pos] != 0)
  198                         n++;
  199         }
  200         return (n);
  201 }
  202 
  203 /*
  204  * Generate fake Configuration ID based on disk IDs.
  205  * Note: it will change after each disk set change.
  206  */
  207 static uint32_t
  208 jmicron_meta_config_id(struct jmicron_raid_conf *meta)
  209 {
  210         int pos;
  211         uint32_t config_id;
  212 
  213         config_id = 0;
  214         for (pos = 0; pos < JMICRON_MAX_DISKS; pos++)
  215                 config_id += meta->disks[pos] << pos;
  216         return (config_id);
  217 }
  218 
  219 static void
  220 jmicron_meta_get_name(struct jmicron_raid_conf *meta, char *buf)
  221 {
  222         int i;
  223 
  224         strncpy(buf, meta->name, 16);
  225         buf[16] = 0;
  226         for (i = 15; i >= 0; i--) {
  227                 if (buf[i] > 0x20)
  228                         break;
  229                 buf[i] = 0;
  230         }
  231 }
  232 
  233 static void
  234 jmicron_meta_put_name(struct jmicron_raid_conf *meta, char *buf)
  235 {
  236 
  237         memset(meta->name, 0x20, 16);
  238         memcpy(meta->name, buf, MIN(strlen(buf), 16));
  239 }
  240 
  241 static int
  242 jmicron_meta_find_disk(struct jmicron_raid_conf *meta, uint32_t id)
  243 {
  244         int pos;
  245 
  246         id &= JMICRON_DISK_MASK;
  247         for (pos = 0; pos < JMICRON_MAX_DISKS; pos++) {
  248                 if ((meta->disks[pos] & JMICRON_DISK_MASK) == id)
  249                         return (pos);
  250         }
  251         for (pos = 0; pos < JMICRON_MAX_SPARE; pos++) {
  252                 if ((meta->spare[pos] & JMICRON_DISK_MASK) == id)
  253                         return (-3);
  254         }
  255         return (-1);
  256 }
  257 
  258 static struct jmicron_raid_conf *
  259 jmicron_meta_read(struct g_consumer *cp)
  260 {
  261         struct g_provider *pp;
  262         struct jmicron_raid_conf *meta;
  263         char *buf;
  264         int error, i;
  265         uint16_t checksum, *ptr;
  266 
  267         pp = cp->provider;
  268 
  269         /* Read the anchor sector. */
  270         buf = g_read_data(cp,
  271             pp->mediasize - pp->sectorsize, pp->sectorsize, &error);
  272         if (buf == NULL) {
  273                 G_RAID_DEBUG(1, "Cannot read metadata from %s (error=%d).",
  274                     pp->name, error);
  275                 return (NULL);
  276         }
  277         meta = (struct jmicron_raid_conf *)buf;
  278 
  279         /* Check if this is an JMicron RAID struct */
  280         if (strncmp(meta->signature, JMICRON_MAGIC, strlen(JMICRON_MAGIC))) {
  281                 G_RAID_DEBUG(1, "JMicron signature check failed on %s", pp->name);
  282                 g_free(buf);
  283                 return (NULL);
  284         }
  285         meta = malloc(sizeof(*meta), M_MD_JMICRON, M_WAITOK);
  286         memcpy(meta, buf, min(sizeof(*meta), pp->sectorsize));
  287         g_free(buf);
  288 
  289         /* Check metadata checksum. */
  290         for (checksum = 0, ptr = (uint16_t *)meta, i = 0; i < 64; i++)
  291                 checksum += *ptr++;
  292         if (checksum != 0) {
  293                 G_RAID_DEBUG(1, "JMicron checksum check failed on %s", pp->name);
  294                 free(meta, M_MD_JMICRON);
  295                 return (NULL);
  296         }
  297 
  298         return (meta);
  299 }
  300 
  301 static int
  302 jmicron_meta_write(struct g_consumer *cp, struct jmicron_raid_conf *meta)
  303 {
  304         struct g_provider *pp;
  305         char *buf;
  306         int error, i;
  307         uint16_t checksum, *ptr;
  308 
  309         pp = cp->provider;
  310 
  311         /* Recalculate checksum for case if metadata were changed. */
  312         meta->checksum = 0;
  313         for (checksum = 0, ptr = (uint16_t *)meta, i = 0; i < 64; i++)
  314                 checksum += *ptr++;
  315         meta->checksum -= checksum;
  316 
  317         /* Create and fill buffer. */
  318         buf = malloc(pp->sectorsize, M_MD_JMICRON, M_WAITOK | M_ZERO);
  319         memcpy(buf, meta, sizeof(*meta));
  320 
  321         error = g_write_data(cp,
  322             pp->mediasize - pp->sectorsize, buf, pp->sectorsize);
  323         if (error != 0) {
  324                 G_RAID_DEBUG(1, "Cannot write metadata to %s (error=%d).",
  325                     pp->name, error);
  326         }
  327 
  328         free(buf, M_MD_JMICRON);
  329         return (error);
  330 }
  331 
  332 static int
  333 jmicron_meta_erase(struct g_consumer *cp)
  334 {
  335         struct g_provider *pp;
  336         char *buf;
  337         int error;
  338 
  339         pp = cp->provider;
  340         buf = malloc(pp->sectorsize, M_MD_JMICRON, M_WAITOK | M_ZERO);
  341         error = g_write_data(cp,
  342             pp->mediasize - pp->sectorsize, buf, pp->sectorsize);
  343         if (error != 0) {
  344                 G_RAID_DEBUG(1, "Cannot erase metadata on %s (error=%d).",
  345                     pp->name, error);
  346         }
  347         free(buf, M_MD_JMICRON);
  348         return (error);
  349 }
  350 
  351 static struct g_raid_disk *
  352 g_raid_md_jmicron_get_disk(struct g_raid_softc *sc, int id)
  353 {
  354         struct g_raid_disk      *disk;
  355         struct g_raid_md_jmicron_perdisk *pd;
  356 
  357         TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
  358                 pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
  359                 if (pd->pd_disk_pos == id)
  360                         break;
  361         }
  362         return (disk);
  363 }
  364 
  365 static int
  366 g_raid_md_jmicron_supported(int level, int qual, int disks, int force)
  367 {
  368 
  369         if (disks > 8)
  370                 return (0);
  371         switch (level) {
  372         case G_RAID_VOLUME_RL_RAID0:
  373                 if (disks < 1)
  374                         return (0);
  375                 if (!force && (disks < 2 || disks > 6))
  376                         return (0);
  377                 break;
  378         case G_RAID_VOLUME_RL_RAID1:
  379                 if (disks < 1)
  380                         return (0);
  381                 if (!force && (disks != 2))
  382                         return (0);
  383                 break;
  384         case G_RAID_VOLUME_RL_RAID1E:
  385                 if (disks < 2)
  386                         return (0);
  387                 if (!force && (disks != 4))
  388                         return (0);
  389                 break;
  390         case G_RAID_VOLUME_RL_SINGLE:
  391                 if (disks != 1)
  392                         return (0);
  393                 if (!force)
  394                         return (0);
  395                 break;
  396         case G_RAID_VOLUME_RL_CONCAT:
  397                 if (disks < 2)
  398                         return (0);
  399                 break;
  400         case G_RAID_VOLUME_RL_RAID5:
  401                 if (disks < 3)
  402                         return (0);
  403                 if (!force)
  404                         return (0);
  405                 break;
  406         default:
  407                 return (0);
  408         }
  409         if (qual != G_RAID_VOLUME_RLQ_NONE)
  410                 return (0);
  411         return (1);
  412 }
  413 
  414 static int
  415 g_raid_md_jmicron_start_disk(struct g_raid_disk *disk)
  416 {
  417         struct g_raid_softc *sc;
  418         struct g_raid_subdisk *sd, *tmpsd;
  419         struct g_raid_disk *olddisk, *tmpdisk;
  420         struct g_raid_md_object *md;
  421         struct g_raid_md_jmicron_object *mdi;
  422         struct g_raid_md_jmicron_perdisk *pd, *oldpd;
  423         struct jmicron_raid_conf *meta;
  424         int disk_pos, resurrection = 0;
  425 
  426         sc = disk->d_softc;
  427         md = sc->sc_md;
  428         mdi = (struct g_raid_md_jmicron_object *)md;
  429         meta = mdi->mdio_meta;
  430         pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
  431         olddisk = NULL;
  432 
  433         /* Find disk position in metadata by it's serial. */
  434         if (pd->pd_meta != NULL)
  435                 disk_pos = jmicron_meta_find_disk(meta, pd->pd_disk_id);
  436         else
  437                 disk_pos = -1;
  438         if (disk_pos < 0) {
  439                 G_RAID_DEBUG1(1, sc, "Unknown, probably new or stale disk");
  440                 /* If we are in the start process, that's all for now. */
  441                 if (!mdi->mdio_started)
  442                         goto nofit;
  443                 /*
  444                  * If we have already started - try to get use of the disk.
  445                  * Try to replace OFFLINE disks first, then FAILED.
  446                  */
  447                 TAILQ_FOREACH(tmpdisk, &sc->sc_disks, d_next) {
  448                         if (tmpdisk->d_state != G_RAID_DISK_S_OFFLINE &&
  449                             tmpdisk->d_state != G_RAID_DISK_S_FAILED)
  450                                 continue;
  451                         /* Make sure this disk is big enough. */
  452                         TAILQ_FOREACH(sd, &tmpdisk->d_subdisks, sd_next) {
  453                                 if (sd->sd_offset + sd->sd_size + 512 >
  454                                     pd->pd_disk_size) {
  455                                         G_RAID_DEBUG1(1, sc,
  456                                             "Disk too small (%ju < %ju)",
  457                                             pd->pd_disk_size,
  458                                             sd->sd_offset + sd->sd_size + 512);
  459                                         break;
  460                                 }
  461                         }
  462                         if (sd != NULL)
  463                                 continue;
  464                         if (tmpdisk->d_state == G_RAID_DISK_S_OFFLINE) {
  465                                 olddisk = tmpdisk;
  466                                 break;
  467                         } else if (olddisk == NULL)
  468                                 olddisk = tmpdisk;
  469                 }
  470                 if (olddisk == NULL) {
  471 nofit:
  472                         if (disk_pos == -3 || pd->pd_disk_pos == -3) {
  473                                 g_raid_change_disk_state(disk,
  474                                     G_RAID_DISK_S_SPARE);
  475                                 return (1);
  476                         } else {
  477                                 g_raid_change_disk_state(disk,
  478                                     G_RAID_DISK_S_STALE);
  479                                 return (0);
  480                         }
  481                 }
  482                 oldpd = (struct g_raid_md_jmicron_perdisk *)olddisk->d_md_data;
  483                 disk_pos = oldpd->pd_disk_pos;
  484                 resurrection = 1;
  485         }
  486 
  487         if (olddisk == NULL) {
  488                 /* Find placeholder by position. */
  489                 olddisk = g_raid_md_jmicron_get_disk(sc, disk_pos);
  490                 if (olddisk == NULL)
  491                         panic("No disk at position %d!", disk_pos);
  492                 if (olddisk->d_state != G_RAID_DISK_S_OFFLINE) {
  493                         G_RAID_DEBUG1(1, sc, "More then one disk for pos %d",
  494                             disk_pos);
  495                         g_raid_change_disk_state(disk, G_RAID_DISK_S_STALE);
  496                         return (0);
  497                 }
  498                 oldpd = (struct g_raid_md_jmicron_perdisk *)olddisk->d_md_data;
  499         }
  500 
  501         /* Replace failed disk or placeholder with new disk. */
  502         TAILQ_FOREACH_SAFE(sd, &olddisk->d_subdisks, sd_next, tmpsd) {
  503                 TAILQ_REMOVE(&olddisk->d_subdisks, sd, sd_next);
  504                 TAILQ_INSERT_TAIL(&disk->d_subdisks, sd, sd_next);
  505                 sd->sd_disk = disk;
  506         }
  507         oldpd->pd_disk_pos = -2;
  508         pd->pd_disk_pos = disk_pos;
  509         /* Update global metadata just in case. */
  510         meta->disks[disk_pos] = pd->pd_disk_id;
  511 
  512         /* If it was placeholder -- destroy it. */
  513         if (olddisk->d_state == G_RAID_DISK_S_OFFLINE) {
  514                 g_raid_destroy_disk(olddisk);
  515         } else {
  516                 /* Otherwise, make it STALE_FAILED. */
  517                 g_raid_change_disk_state(olddisk, G_RAID_DISK_S_STALE_FAILED);
  518         }
  519 
  520         /* Welcome the new disk. */
  521         g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE);
  522         TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) {
  523 
  524                 /*
  525                  * Different disks may have different sizes/offsets,
  526                  * especially in concat mode. Update.
  527                  */
  528                 if (!resurrection) {
  529                         sd->sd_offset =
  530                             (off_t)pd->pd_meta->offset * 16 * 512; //ZZZ
  531                         sd->sd_size =
  532                             (((off_t)pd->pd_meta->disk_sectors_high << 16) +
  533                               pd->pd_meta->disk_sectors_low) * 512;
  534                 }
  535 
  536                 if (resurrection) {
  537                         /* Stale disk, almost same as new. */
  538                         g_raid_change_subdisk_state(sd,
  539                             G_RAID_SUBDISK_S_NEW);
  540                 } else if ((meta->flags & JMICRON_F_BADSEC) != 0 &&
  541                     (pd->pd_meta->flags & JMICRON_F_BADSEC) == 0) {
  542                         /* Cold-inserted or rebuilding disk. */
  543                         g_raid_change_subdisk_state(sd,
  544                             G_RAID_SUBDISK_S_NEW);
  545                 } else if (pd->pd_meta->flags & JMICRON_F_UNSYNC) {
  546                         /* Dirty or resyncing disk.. */
  547                         g_raid_change_subdisk_state(sd,
  548                             G_RAID_SUBDISK_S_STALE);
  549                 } else {
  550                         /* Up to date disk. */
  551                         g_raid_change_subdisk_state(sd,
  552                             G_RAID_SUBDISK_S_ACTIVE);
  553                 }
  554                 g_raid_event_send(sd, G_RAID_SUBDISK_E_NEW,
  555                     G_RAID_EVENT_SUBDISK);
  556         }
  557 
  558         /* Update status of our need for spare. */
  559         if (mdi->mdio_started) {
  560                 mdi->mdio_incomplete =
  561                     (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) <
  562                      mdi->mdio_total_disks);
  563         }
  564 
  565         return (resurrection);
  566 }
  567 
  568 static void
  569 g_disk_md_jmicron_retaste(void *arg, int pending)
  570 {
  571 
  572         G_RAID_DEBUG(1, "Array is not complete, trying to retaste.");
  573         g_retaste(&g_raid_class);
  574         free(arg, M_MD_JMICRON);
  575 }
  576 
  577 static void
  578 g_raid_md_jmicron_refill(struct g_raid_softc *sc)
  579 {
  580         struct g_raid_md_object *md;
  581         struct g_raid_md_jmicron_object *mdi;
  582         struct g_raid_disk *disk;
  583         struct task *task;
  584         int update, na;
  585 
  586         md = sc->sc_md;
  587         mdi = (struct g_raid_md_jmicron_object *)md;
  588         update = 0;
  589         do {
  590                 /* Make sure we miss anything. */
  591                 na = g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE);
  592                 if (na == mdi->mdio_total_disks)
  593                         break;
  594 
  595                 G_RAID_DEBUG1(1, md->mdo_softc,
  596                     "Array is not complete (%d of %d), "
  597                     "trying to refill.", na, mdi->mdio_total_disks);
  598 
  599                 /* Try to get use some of STALE disks. */
  600                 TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
  601                         if (disk->d_state == G_RAID_DISK_S_STALE) {
  602                                 update += g_raid_md_jmicron_start_disk(disk);
  603                                 if (disk->d_state == G_RAID_DISK_S_ACTIVE)
  604                                         break;
  605                         }
  606                 }
  607                 if (disk != NULL)
  608                         continue;
  609 
  610                 /* Try to get use some of SPARE disks. */
  611                 TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
  612                         if (disk->d_state == G_RAID_DISK_S_SPARE) {
  613                                 update += g_raid_md_jmicron_start_disk(disk);
  614                                 if (disk->d_state == G_RAID_DISK_S_ACTIVE)
  615                                         break;
  616                         }
  617                 }
  618         } while (disk != NULL);
  619 
  620         /* Write new metadata if we changed something. */
  621         if (update)
  622                 g_raid_md_write_jmicron(md, NULL, NULL, NULL);
  623 
  624         /* Update status of our need for spare. */
  625         mdi->mdio_incomplete = (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) <
  626             mdi->mdio_total_disks);
  627 
  628         /* Request retaste hoping to find spare. */
  629         if (mdi->mdio_incomplete) {
  630                 task = malloc(sizeof(struct task),
  631                     M_MD_JMICRON, M_WAITOK | M_ZERO);
  632                 TASK_INIT(task, 0, g_disk_md_jmicron_retaste, task);
  633                 taskqueue_enqueue(taskqueue_swi, task);
  634         }
  635 }
  636 
  637 static void
  638 g_raid_md_jmicron_start(struct g_raid_softc *sc)
  639 {
  640         struct g_raid_md_object *md;
  641         struct g_raid_md_jmicron_object *mdi;
  642         struct g_raid_md_jmicron_perdisk *pd;
  643         struct jmicron_raid_conf *meta;
  644         struct g_raid_volume *vol;
  645         struct g_raid_subdisk *sd;
  646         struct g_raid_disk *disk;
  647         off_t size;
  648         int j, disk_pos;
  649         char buf[17];
  650 
  651         md = sc->sc_md;
  652         mdi = (struct g_raid_md_jmicron_object *)md;
  653         meta = mdi->mdio_meta;
  654 
  655         /* Create volumes and subdisks. */
  656         jmicron_meta_get_name(meta, buf);
  657         vol = g_raid_create_volume(sc, buf, -1);
  658         size = ((off_t)meta->disk_sectors_high << 16) + meta->disk_sectors_low;
  659         size *= 512; //ZZZ
  660         if (meta->type == JMICRON_T_RAID0) {
  661                 vol->v_raid_level = G_RAID_VOLUME_RL_RAID0;
  662                 vol->v_mediasize = size * mdi->mdio_total_disks;
  663         } else if (meta->type == JMICRON_T_RAID1) {
  664                 vol->v_raid_level = G_RAID_VOLUME_RL_RAID1;
  665                 vol->v_mediasize = size;
  666         } else if (meta->type == JMICRON_T_RAID01) {
  667                 vol->v_raid_level = G_RAID_VOLUME_RL_RAID1E;
  668                 vol->v_mediasize = size * mdi->mdio_total_disks / 2;
  669         } else if (meta->type == JMICRON_T_CONCAT) {
  670                 if (mdi->mdio_total_disks == 1)
  671                         vol->v_raid_level = G_RAID_VOLUME_RL_SINGLE;
  672                 else
  673                         vol->v_raid_level = G_RAID_VOLUME_RL_CONCAT;
  674                 vol->v_mediasize = 0;
  675         } else if (meta->type == JMICRON_T_RAID5) {
  676                 vol->v_raid_level = G_RAID_VOLUME_RL_RAID5;
  677                 vol->v_mediasize = size * (mdi->mdio_total_disks - 1);
  678         } else {
  679                 vol->v_raid_level = G_RAID_VOLUME_RL_UNKNOWN;
  680                 vol->v_mediasize = 0;
  681         }
  682         vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_NONE;
  683         vol->v_strip_size = 1024 << meta->stripe_shift; //ZZZ
  684         vol->v_disks_count = mdi->mdio_total_disks;
  685         vol->v_sectorsize = 512; //ZZZ
  686         for (j = 0; j < vol->v_disks_count; j++) {
  687                 sd = &vol->v_subdisks[j];
  688                 sd->sd_offset = (off_t)meta->offset * 16 * 512; //ZZZ
  689                 sd->sd_size = size;
  690         }
  691         g_raid_start_volume(vol);
  692 
  693         /* Create disk placeholders to store data for later writing. */
  694         for (disk_pos = 0; disk_pos < mdi->mdio_total_disks; disk_pos++) {
  695                 pd = malloc(sizeof(*pd), M_MD_JMICRON, M_WAITOK | M_ZERO);
  696                 pd->pd_disk_pos = disk_pos;
  697                 pd->pd_disk_id = meta->disks[disk_pos];
  698                 disk = g_raid_create_disk(sc);
  699                 disk->d_md_data = (void *)pd;
  700                 disk->d_state = G_RAID_DISK_S_OFFLINE;
  701                 sd = &vol->v_subdisks[disk_pos];
  702                 sd->sd_disk = disk;
  703                 TAILQ_INSERT_TAIL(&disk->d_subdisks, sd, sd_next);
  704         }
  705 
  706         /* Make all disks found till the moment take their places. */
  707         do {
  708                 TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
  709                         if (disk->d_state == G_RAID_DISK_S_NONE) {
  710                                 g_raid_md_jmicron_start_disk(disk);
  711                                 break;
  712                         }
  713                 }
  714         } while (disk != NULL);
  715 
  716         mdi->mdio_started = 1;
  717         G_RAID_DEBUG1(0, sc, "Array started.");
  718         g_raid_md_write_jmicron(md, NULL, NULL, NULL);
  719 
  720         /* Pickup any STALE/SPARE disks to refill array if needed. */
  721         g_raid_md_jmicron_refill(sc);
  722 
  723         g_raid_event_send(vol, G_RAID_VOLUME_E_START, G_RAID_EVENT_VOLUME);
  724 
  725         callout_stop(&mdi->mdio_start_co);
  726         G_RAID_DEBUG1(1, sc, "root_mount_rel %p", mdi->mdio_rootmount);
  727         root_mount_rel(mdi->mdio_rootmount);
  728         mdi->mdio_rootmount = NULL;
  729 }
  730 
  731 static void
  732 g_raid_md_jmicron_new_disk(struct g_raid_disk *disk)
  733 {
  734         struct g_raid_softc *sc;
  735         struct g_raid_md_object *md;
  736         struct g_raid_md_jmicron_object *mdi;
  737         struct jmicron_raid_conf *pdmeta;
  738         struct g_raid_md_jmicron_perdisk *pd;
  739 
  740         sc = disk->d_softc;
  741         md = sc->sc_md;
  742         mdi = (struct g_raid_md_jmicron_object *)md;
  743         pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
  744         pdmeta = pd->pd_meta;
  745 
  746         if (mdi->mdio_started) {
  747                 if (g_raid_md_jmicron_start_disk(disk))
  748                         g_raid_md_write_jmicron(md, NULL, NULL, NULL);
  749         } else {
  750                 /*
  751                  * If we haven't started yet - update common metadata
  752                  * to get subdisks details, avoiding data from spare disks.
  753                  */
  754                 if (mdi->mdio_meta == NULL ||
  755                     jmicron_meta_find_disk(mdi->mdio_meta,
  756                      mdi->mdio_meta->disk_id) == -3) {
  757                         if (mdi->mdio_meta != NULL)
  758                                 free(mdi->mdio_meta, M_MD_JMICRON);
  759                         mdi->mdio_meta = jmicron_meta_copy(pdmeta);
  760                         mdi->mdio_total_disks = jmicron_meta_total_disks(pdmeta);
  761                 }
  762                 mdi->mdio_meta->flags |= pdmeta->flags & JMICRON_F_BADSEC;
  763 
  764                 mdi->mdio_disks_present++;
  765                 G_RAID_DEBUG1(1, sc, "Matching disk (%d of %d+%d up)",
  766                     mdi->mdio_disks_present,
  767                     mdi->mdio_total_disks,
  768                     jmicron_meta_total_spare(mdi->mdio_meta));
  769 
  770                 /* If we collected all needed disks - start array. */
  771                 if (mdi->mdio_disks_present == mdi->mdio_total_disks +
  772                     jmicron_meta_total_spare(mdi->mdio_meta))
  773                         g_raid_md_jmicron_start(sc);
  774         }
  775 }
  776 
  777 static void
  778 g_raid_jmicron_go(void *arg)
  779 {
  780         struct g_raid_softc *sc;
  781         struct g_raid_md_object *md;
  782         struct g_raid_md_jmicron_object *mdi;
  783 
  784         sc = arg;
  785         md = sc->sc_md;
  786         mdi = (struct g_raid_md_jmicron_object *)md;
  787         if (!mdi->mdio_started) {
  788                 G_RAID_DEBUG1(0, sc, "Force array start due to timeout.");
  789                 g_raid_event_send(sc, G_RAID_NODE_E_START, 0);
  790         }
  791 }
  792 
  793 static int
  794 g_raid_md_create_jmicron(struct g_raid_md_object *md, struct g_class *mp,
  795     struct g_geom **gp)
  796 {
  797         struct g_raid_softc *sc;
  798         struct g_raid_md_jmicron_object *mdi;
  799         char name[16];
  800 
  801         mdi = (struct g_raid_md_jmicron_object *)md;
  802         mdi->mdio_config_id = arc4random();
  803         snprintf(name, sizeof(name), "JMicron-%08x", mdi->mdio_config_id);
  804         sc = g_raid_create_node(mp, name, md);
  805         if (sc == NULL)
  806                 return (G_RAID_MD_TASTE_FAIL);
  807         md->mdo_softc = sc;
  808         *gp = sc->sc_geom;
  809         return (G_RAID_MD_TASTE_NEW);
  810 }
  811 
  812 static int
  813 g_raid_md_taste_jmicron(struct g_raid_md_object *md, struct g_class *mp,
  814                               struct g_consumer *cp, struct g_geom **gp)
  815 {
  816         struct g_consumer *rcp;
  817         struct g_provider *pp;
  818         struct g_raid_md_jmicron_object *mdi, *mdi1;
  819         struct g_raid_softc *sc;
  820         struct g_raid_disk *disk;
  821         struct jmicron_raid_conf *meta;
  822         struct g_raid_md_jmicron_perdisk *pd;
  823         struct g_geom *geom;
  824         int error, disk_pos, result, spare, len;
  825         char name[16];
  826         uint16_t vendor;
  827 
  828         G_RAID_DEBUG(1, "Tasting JMicron on %s", cp->provider->name);
  829         mdi = (struct g_raid_md_jmicron_object *)md;
  830         pp = cp->provider;
  831 
  832         /* Read metadata from device. */
  833         meta = NULL;
  834         vendor = 0xffff;
  835         if (g_access(cp, 1, 0, 0) != 0)
  836                 return (G_RAID_MD_TASTE_FAIL);
  837         g_topology_unlock();
  838         len = 2;
  839         if (pp->geom->rank == 1)
  840                 g_io_getattr("GEOM::hba_vendor", cp, &len, &vendor);
  841         meta = jmicron_meta_read(cp);
  842         g_topology_lock();
  843         g_access(cp, -1, 0, 0);
  844         if (meta == NULL) {
  845                 if (g_raid_aggressive_spare) {
  846                         if (vendor == 0x197b) {
  847                                 G_RAID_DEBUG(1,
  848                                     "No JMicron metadata, forcing spare.");
  849                                 spare = 2;
  850                                 goto search;
  851                         } else {
  852                                 G_RAID_DEBUG(1,
  853                                     "JMicron vendor mismatch 0x%04x != 0x197b",
  854                                     vendor);
  855                         }
  856                 }
  857                 return (G_RAID_MD_TASTE_FAIL);
  858         }
  859 
  860         /* Check this disk position in obtained metadata. */
  861         disk_pos = jmicron_meta_find_disk(meta, meta->disk_id);
  862         if (disk_pos == -1) {
  863                 G_RAID_DEBUG(1, "JMicron disk_id %08x not found",
  864                     meta->disk_id);
  865                 goto fail1;
  866         }
  867 
  868         /* Metadata valid. Print it. */
  869         g_raid_md_jmicron_print(meta);
  870         G_RAID_DEBUG(1, "JMicron disk position %d", disk_pos);
  871         spare = (disk_pos == -2) ? 1 : 0;
  872 
  873 search:
  874         /* Search for matching node. */
  875         sc = NULL;
  876         mdi1 = NULL;
  877         LIST_FOREACH(geom, &mp->geom, geom) {
  878                 sc = geom->softc;
  879                 if (sc == NULL)
  880                         continue;
  881                 if (sc->sc_stopping != 0)
  882                         continue;
  883                 if (sc->sc_md->mdo_class != md->mdo_class)
  884                         continue;
  885                 mdi1 = (struct g_raid_md_jmicron_object *)sc->sc_md;
  886                 if (spare == 2) {
  887                         if (mdi1->mdio_incomplete)
  888                                 break;
  889                 } else {
  890                         if (mdi1->mdio_config_id ==
  891                             jmicron_meta_config_id(meta))
  892                                 break;
  893                 }
  894         }
  895 
  896         /* Found matching node. */
  897         if (geom != NULL) {
  898                 G_RAID_DEBUG(1, "Found matching array %s", sc->sc_name);
  899                 result = G_RAID_MD_TASTE_EXISTING;
  900 
  901         } else if (spare) { /* Not found needy node -- left for later. */
  902                 G_RAID_DEBUG(1, "Spare is not needed at this time");
  903                 goto fail1;
  904 
  905         } else { /* Not found matching node -- create one. */
  906                 result = G_RAID_MD_TASTE_NEW;
  907                 mdi->mdio_config_id = jmicron_meta_config_id(meta);
  908                 snprintf(name, sizeof(name), "JMicron-%08x",
  909                     mdi->mdio_config_id);
  910                 sc = g_raid_create_node(mp, name, md);
  911                 md->mdo_softc = sc;
  912                 geom = sc->sc_geom;
  913                 callout_init(&mdi->mdio_start_co, 1);
  914                 callout_reset(&mdi->mdio_start_co, g_raid_start_timeout * hz,
  915                     g_raid_jmicron_go, sc);
  916                 mdi->mdio_rootmount = root_mount_hold("GRAID-JMicron");
  917                 G_RAID_DEBUG1(1, sc, "root_mount_hold %p", mdi->mdio_rootmount);
  918         }
  919 
  920         rcp = g_new_consumer(geom);
  921         g_attach(rcp, pp);
  922         if (g_access(rcp, 1, 1, 1) != 0)
  923                 ; //goto fail1;
  924 
  925         g_topology_unlock();
  926         sx_xlock(&sc->sc_lock);
  927 
  928         pd = malloc(sizeof(*pd), M_MD_JMICRON, M_WAITOK | M_ZERO);
  929         pd->pd_meta = meta;
  930         if (spare == 2) {
  931                 pd->pd_disk_pos = -3;
  932                 pd->pd_disk_id = arc4random() & JMICRON_DISK_MASK;
  933         } else {
  934                 pd->pd_disk_pos = -1;
  935                 pd->pd_disk_id = meta->disk_id;
  936         }
  937         pd->pd_disk_size = pp->mediasize;
  938         disk = g_raid_create_disk(sc);
  939         disk->d_md_data = (void *)pd;
  940         disk->d_consumer = rcp;
  941         rcp->private = disk;
  942 
  943         /* Read kernel dumping information. */
  944         disk->d_kd.offset = 0;
  945         disk->d_kd.length = OFF_MAX;
  946         len = sizeof(disk->d_kd);
  947         error = g_io_getattr("GEOM::kerneldump", rcp, &len, &disk->d_kd);
  948         if (disk->d_kd.di.dumper == NULL)
  949                 G_RAID_DEBUG1(2, sc, "Dumping not supported by %s: %d.", 
  950                     rcp->provider->name, error);
  951 
  952         g_raid_md_jmicron_new_disk(disk);
  953 
  954         sx_xunlock(&sc->sc_lock);
  955         g_topology_lock();
  956         *gp = geom;
  957         return (result);
  958 fail1:
  959         free(meta, M_MD_JMICRON);
  960         return (G_RAID_MD_TASTE_FAIL);
  961 }
  962 
  963 static int
  964 g_raid_md_event_jmicron(struct g_raid_md_object *md,
  965     struct g_raid_disk *disk, u_int event)
  966 {
  967         struct g_raid_softc *sc;
  968         struct g_raid_subdisk *sd;
  969         struct g_raid_md_jmicron_object *mdi;
  970         struct g_raid_md_jmicron_perdisk *pd;
  971 
  972         sc = md->mdo_softc;
  973         mdi = (struct g_raid_md_jmicron_object *)md;
  974         if (disk == NULL) {
  975                 switch (event) {
  976                 case G_RAID_NODE_E_START:
  977                         if (!mdi->mdio_started)
  978                                 g_raid_md_jmicron_start(sc);
  979                         return (0);
  980                 }
  981                 return (-1);
  982         }
  983         pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
  984         switch (event) {
  985         case G_RAID_DISK_E_DISCONNECTED:
  986                 /* If disk was assigned, just update statuses. */
  987                 if (pd->pd_disk_pos >= 0) {
  988                         g_raid_change_disk_state(disk, G_RAID_DISK_S_OFFLINE);
  989                         if (disk->d_consumer) {
  990                                 g_raid_kill_consumer(sc, disk->d_consumer);
  991                                 disk->d_consumer = NULL;
  992                         }
  993                         TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) {
  994                                 g_raid_change_subdisk_state(sd,
  995                                     G_RAID_SUBDISK_S_NONE);
  996                                 g_raid_event_send(sd, G_RAID_SUBDISK_E_DISCONNECTED,
  997                                     G_RAID_EVENT_SUBDISK);
  998                         }
  999                 } else {
 1000                         /* Otherwise -- delete. */
 1001                         g_raid_change_disk_state(disk, G_RAID_DISK_S_NONE);
 1002                         g_raid_destroy_disk(disk);
 1003                 }
 1004 
 1005                 /* Write updated metadata to all disks. */
 1006                 g_raid_md_write_jmicron(md, NULL, NULL, NULL);
 1007 
 1008                 /* Check if anything left except placeholders. */
 1009                 if (g_raid_ndisks(sc, -1) ==
 1010                     g_raid_ndisks(sc, G_RAID_DISK_S_OFFLINE))
 1011                         g_raid_destroy_node(sc, 0);
 1012                 else
 1013                         g_raid_md_jmicron_refill(sc);
 1014                 return (0);
 1015         }
 1016         return (-2);
 1017 }
 1018 
 1019 static int
 1020 g_raid_md_ctl_jmicron(struct g_raid_md_object *md,
 1021     struct gctl_req *req)
 1022 {
 1023         struct g_raid_softc *sc;
 1024         struct g_raid_volume *vol;
 1025         struct g_raid_subdisk *sd;
 1026         struct g_raid_disk *disk;
 1027         struct g_raid_md_jmicron_object *mdi;
 1028         struct g_raid_md_jmicron_perdisk *pd;
 1029         struct g_consumer *cp;
 1030         struct g_provider *pp;
 1031         char arg[16];
 1032         const char *verb, *volname, *levelname, *diskname;
 1033         int *nargs, *force;
 1034         off_t size, sectorsize, strip;
 1035         intmax_t *sizearg, *striparg;
 1036         int numdisks, i, len, level, qual, update;
 1037         int error;
 1038 
 1039         sc = md->mdo_softc;
 1040         mdi = (struct g_raid_md_jmicron_object *)md;
 1041         verb = gctl_get_param(req, "verb", NULL);
 1042         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
 1043         error = 0;
 1044         if (strcmp(verb, "label") == 0) {
 1045 
 1046                 if (*nargs < 4) {
 1047                         gctl_error(req, "Invalid number of arguments.");
 1048                         return (-1);
 1049                 }
 1050                 volname = gctl_get_asciiparam(req, "arg1");
 1051                 if (volname == NULL) {
 1052                         gctl_error(req, "No volume name.");
 1053                         return (-2);
 1054                 }
 1055                 levelname = gctl_get_asciiparam(req, "arg2");
 1056                 if (levelname == NULL) {
 1057                         gctl_error(req, "No RAID level.");
 1058                         return (-3);
 1059                 }
 1060                 if (g_raid_volume_str2level(levelname, &level, &qual)) {
 1061                         gctl_error(req, "Unknown RAID level '%s'.", levelname);
 1062                         return (-4);
 1063                 }
 1064                 numdisks = *nargs - 3;
 1065                 force = gctl_get_paraml(req, "force", sizeof(*force));
 1066                 if (!g_raid_md_jmicron_supported(level, qual, numdisks,
 1067                     force ? *force : 0)) {
 1068                         gctl_error(req, "Unsupported RAID level "
 1069                             "(0x%02x/0x%02x), or number of disks (%d).",
 1070                             level, qual, numdisks);
 1071                         return (-5);
 1072                 }
 1073 
 1074                 /* Search for disks, connect them and probe. */
 1075                 size = 0x7fffffffffffffffllu;
 1076                 sectorsize = 0;
 1077                 for (i = 0; i < numdisks; i++) {
 1078                         snprintf(arg, sizeof(arg), "arg%d", i + 3);
 1079                         diskname = gctl_get_asciiparam(req, arg);
 1080                         if (diskname == NULL) {
 1081                                 gctl_error(req, "No disk name (%s).", arg);
 1082                                 error = -6;
 1083                                 break;
 1084                         }
 1085                         if (strcmp(diskname, "NONE") == 0) {
 1086                                 cp = NULL;
 1087                                 pp = NULL;
 1088                         } else {
 1089                                 g_topology_lock();
 1090                                 cp = g_raid_open_consumer(sc, diskname);
 1091                                 if (cp == NULL) {
 1092                                         gctl_error(req, "Can't open '%s'.",
 1093                                             diskname);
 1094                                         g_topology_unlock();
 1095                                         error = -7;
 1096                                         break;
 1097                                 }
 1098                                 pp = cp->provider;
 1099                         }
 1100                         pd = malloc(sizeof(*pd), M_MD_JMICRON, M_WAITOK | M_ZERO);
 1101                         pd->pd_disk_pos = i;
 1102                         pd->pd_disk_id = arc4random() & JMICRON_DISK_MASK;
 1103                         disk = g_raid_create_disk(sc);
 1104                         disk->d_md_data = (void *)pd;
 1105                         disk->d_consumer = cp;
 1106                         if (cp == NULL)
 1107                                 continue;
 1108                         cp->private = disk;
 1109                         g_topology_unlock();
 1110 
 1111                         /* Read kernel dumping information. */
 1112                         disk->d_kd.offset = 0;
 1113                         disk->d_kd.length = OFF_MAX;
 1114                         len = sizeof(disk->d_kd);
 1115                         g_io_getattr("GEOM::kerneldump", cp, &len, &disk->d_kd);
 1116                         if (disk->d_kd.di.dumper == NULL)
 1117                                 G_RAID_DEBUG1(2, sc,
 1118                                     "Dumping not supported by %s.",
 1119                                     cp->provider->name);
 1120 
 1121                         pd->pd_disk_size = pp->mediasize;
 1122                         if (size > pp->mediasize)
 1123                                 size = pp->mediasize;
 1124                         if (sectorsize < pp->sectorsize)
 1125                                 sectorsize = pp->sectorsize;
 1126                 }
 1127                 if (error != 0)
 1128                         return (error);
 1129 
 1130                 if (sectorsize <= 0) {
 1131                         gctl_error(req, "Can't get sector size.");
 1132                         return (-8);
 1133                 }
 1134 
 1135                 /* Reserve space for metadata. */
 1136                 size -= sectorsize;
 1137 
 1138                 /* Handle size argument. */
 1139                 len = sizeof(*sizearg);
 1140                 sizearg = gctl_get_param(req, "size", &len);
 1141                 if (sizearg != NULL && len == sizeof(*sizearg) &&
 1142                     *sizearg > 0) {
 1143                         if (*sizearg > size) {
 1144                                 gctl_error(req, "Size too big %lld > %lld.",
 1145                                     (long long)*sizearg, (long long)size);
 1146                                 return (-9);
 1147                         }
 1148                         size = *sizearg;
 1149                 }
 1150 
 1151                 /* Handle strip argument. */
 1152                 strip = 131072;
 1153                 len = sizeof(*striparg);
 1154                 striparg = gctl_get_param(req, "strip", &len);
 1155                 if (striparg != NULL && len == sizeof(*striparg) &&
 1156                     *striparg > 0) {
 1157                         if (*striparg < sectorsize) {
 1158                                 gctl_error(req, "Strip size too small.");
 1159                                 return (-10);
 1160                         }
 1161                         if (*striparg % sectorsize != 0) {
 1162                                 gctl_error(req, "Incorrect strip size.");
 1163                                 return (-11);
 1164                         }
 1165                         if (strip > 65535 * sectorsize) {
 1166                                 gctl_error(req, "Strip size too big.");
 1167                                 return (-12);
 1168                         }
 1169                         strip = *striparg;
 1170                 }
 1171 
 1172                 /* Round size down to strip or sector. */
 1173                 if (level == G_RAID_VOLUME_RL_RAID1)
 1174                         size -= (size % sectorsize);
 1175                 else if (level == G_RAID_VOLUME_RL_RAID1E &&
 1176                     (numdisks & 1) != 0)
 1177                         size -= (size % (2 * strip));
 1178                 else
 1179                         size -= (size % strip);
 1180                 if (size <= 0) {
 1181                         gctl_error(req, "Size too small.");
 1182                         return (-13);
 1183                 }
 1184                 if (size > 0xffffffffffffllu * sectorsize) {
 1185                         gctl_error(req, "Size too big.");
 1186                         return (-14);
 1187                 }
 1188 
 1189                 /* We have all we need, create things: volume, ... */
 1190                 mdi->mdio_total_disks = numdisks;
 1191                 mdi->mdio_started = 1;
 1192                 vol = g_raid_create_volume(sc, volname, -1);
 1193                 vol->v_md_data = (void *)(intptr_t)0;
 1194                 vol->v_raid_level = level;
 1195                 vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_NONE;
 1196                 vol->v_strip_size = strip;
 1197                 vol->v_disks_count = numdisks;
 1198                 if (level == G_RAID_VOLUME_RL_RAID0 ||
 1199                     level == G_RAID_VOLUME_RL_CONCAT ||
 1200                     level == G_RAID_VOLUME_RL_SINGLE)
 1201                         vol->v_mediasize = size * numdisks;
 1202                 else if (level == G_RAID_VOLUME_RL_RAID1)
 1203                         vol->v_mediasize = size;
 1204                 else if (level == G_RAID_VOLUME_RL_RAID5)
 1205                         vol->v_mediasize = size * (numdisks - 1);
 1206                 else { /* RAID1E */
 1207                         vol->v_mediasize = ((size * numdisks) / strip / 2) *
 1208                             strip;
 1209                 }
 1210                 vol->v_sectorsize = sectorsize;
 1211                 g_raid_start_volume(vol);
 1212 
 1213                 /* , and subdisks. */
 1214                 TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
 1215                         pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
 1216                         sd = &vol->v_subdisks[pd->pd_disk_pos];
 1217                         sd->sd_disk = disk;
 1218                         sd->sd_offset = 0;
 1219                         sd->sd_size = size;
 1220                         TAILQ_INSERT_TAIL(&disk->d_subdisks, sd, sd_next);
 1221                         if (sd->sd_disk->d_consumer != NULL) {
 1222                                 g_raid_change_disk_state(disk,
 1223                                     G_RAID_DISK_S_ACTIVE);
 1224                                 g_raid_change_subdisk_state(sd,
 1225                                     G_RAID_SUBDISK_S_ACTIVE);
 1226                                 g_raid_event_send(sd, G_RAID_SUBDISK_E_NEW,
 1227                                     G_RAID_EVENT_SUBDISK);
 1228                         } else {
 1229                                 g_raid_change_disk_state(disk, G_RAID_DISK_S_OFFLINE);
 1230                         }
 1231                 }
 1232 
 1233                 /* Write metadata based on created entities. */
 1234                 G_RAID_DEBUG1(0, sc, "Array started.");
 1235                 g_raid_md_write_jmicron(md, NULL, NULL, NULL);
 1236 
 1237                 /* Pickup any STALE/SPARE disks to refill array if needed. */
 1238                 g_raid_md_jmicron_refill(sc);
 1239 
 1240                 g_raid_event_send(vol, G_RAID_VOLUME_E_START,
 1241                     G_RAID_EVENT_VOLUME);
 1242                 return (0);
 1243         }
 1244         if (strcmp(verb, "delete") == 0) {
 1245 
 1246                 /* Check if some volume is still open. */
 1247                 force = gctl_get_paraml(req, "force", sizeof(*force));
 1248                 if (force != NULL && *force == 0 &&
 1249                     g_raid_nopens(sc) != 0) {
 1250                         gctl_error(req, "Some volume is still open.");
 1251                         return (-4);
 1252                 }
 1253 
 1254                 TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
 1255                         if (disk->d_consumer)
 1256                                 jmicron_meta_erase(disk->d_consumer);
 1257                 }
 1258                 g_raid_destroy_node(sc, 0);
 1259                 return (0);
 1260         }
 1261         if (strcmp(verb, "remove") == 0 ||
 1262             strcmp(verb, "fail") == 0) {
 1263                 if (*nargs < 2) {
 1264                         gctl_error(req, "Invalid number of arguments.");
 1265                         return (-1);
 1266                 }
 1267                 for (i = 1; i < *nargs; i++) {
 1268                         snprintf(arg, sizeof(arg), "arg%d", i);
 1269                         diskname = gctl_get_asciiparam(req, arg);
 1270                         if (diskname == NULL) {
 1271                                 gctl_error(req, "No disk name (%s).", arg);
 1272                                 error = -2;
 1273                                 break;
 1274                         }
 1275                         if (strncmp(diskname, "/dev/", 5) == 0)
 1276                                 diskname += 5;
 1277 
 1278                         TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
 1279                                 if (disk->d_consumer != NULL && 
 1280                                     disk->d_consumer->provider != NULL &&
 1281                                     strcmp(disk->d_consumer->provider->name,
 1282                                      diskname) == 0)
 1283                                         break;
 1284                         }
 1285                         if (disk == NULL) {
 1286                                 gctl_error(req, "Disk '%s' not found.",
 1287                                     diskname);
 1288                                 error = -3;
 1289                                 break;
 1290                         }
 1291 
 1292                         if (strcmp(verb, "fail") == 0) {
 1293                                 g_raid_md_fail_disk_jmicron(md, NULL, disk);
 1294                                 continue;
 1295                         }
 1296 
 1297                         pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
 1298 
 1299                         /* Erase metadata on deleting disk. */
 1300                         jmicron_meta_erase(disk->d_consumer);
 1301 
 1302                         /* If disk was assigned, just update statuses. */
 1303                         if (pd->pd_disk_pos >= 0) {
 1304                                 g_raid_change_disk_state(disk, G_RAID_DISK_S_OFFLINE);
 1305                                 g_raid_kill_consumer(sc, disk->d_consumer);
 1306                                 disk->d_consumer = NULL;
 1307                                 TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) {
 1308                                         g_raid_change_subdisk_state(sd,
 1309                                             G_RAID_SUBDISK_S_NONE);
 1310                                         g_raid_event_send(sd, G_RAID_SUBDISK_E_DISCONNECTED,
 1311                                             G_RAID_EVENT_SUBDISK);
 1312                                 }
 1313                         } else {
 1314                                 /* Otherwise -- delete. */
 1315                                 g_raid_change_disk_state(disk, G_RAID_DISK_S_NONE);
 1316                                 g_raid_destroy_disk(disk);
 1317                         }
 1318                 }
 1319 
 1320                 /* Write updated metadata to remaining disks. */
 1321                 g_raid_md_write_jmicron(md, NULL, NULL, NULL);
 1322 
 1323                 /* Check if anything left except placeholders. */
 1324                 if (g_raid_ndisks(sc, -1) ==
 1325                     g_raid_ndisks(sc, G_RAID_DISK_S_OFFLINE))
 1326                         g_raid_destroy_node(sc, 0);
 1327                 else
 1328                         g_raid_md_jmicron_refill(sc);
 1329                 return (error);
 1330         }
 1331         if (strcmp(verb, "insert") == 0) {
 1332                 if (*nargs < 2) {
 1333                         gctl_error(req, "Invalid number of arguments.");
 1334                         return (-1);
 1335                 }
 1336                 update = 0;
 1337                 for (i = 1; i < *nargs; i++) {
 1338                         /* Get disk name. */
 1339                         snprintf(arg, sizeof(arg), "arg%d", i);
 1340                         diskname = gctl_get_asciiparam(req, arg);
 1341                         if (diskname == NULL) {
 1342                                 gctl_error(req, "No disk name (%s).", arg);
 1343                                 error = -3;
 1344                                 break;
 1345                         }
 1346 
 1347                         /* Try to find provider with specified name. */
 1348                         g_topology_lock();
 1349                         cp = g_raid_open_consumer(sc, diskname);
 1350                         if (cp == NULL) {
 1351                                 gctl_error(req, "Can't open disk '%s'.",
 1352                                     diskname);
 1353                                 g_topology_unlock();
 1354                                 error = -4;
 1355                                 break;
 1356                         }
 1357                         pp = cp->provider;
 1358 
 1359                         pd = malloc(sizeof(*pd), M_MD_JMICRON, M_WAITOK | M_ZERO);
 1360                         pd->pd_disk_pos = -3;
 1361                         pd->pd_disk_id = arc4random() & JMICRON_DISK_MASK;
 1362                         pd->pd_disk_size = pp->mediasize;
 1363 
 1364                         disk = g_raid_create_disk(sc);
 1365                         disk->d_consumer = cp;
 1366                         disk->d_md_data = (void *)pd;
 1367                         cp->private = disk;
 1368                         g_topology_unlock();
 1369 
 1370                         /* Read kernel dumping information. */
 1371                         disk->d_kd.offset = 0;
 1372                         disk->d_kd.length = OFF_MAX;
 1373                         len = sizeof(disk->d_kd);
 1374                         g_io_getattr("GEOM::kerneldump", cp, &len, &disk->d_kd);
 1375                         if (disk->d_kd.di.dumper == NULL)
 1376                                 G_RAID_DEBUG1(2, sc,
 1377                                     "Dumping not supported by %s.",
 1378                                     cp->provider->name);
 1379 
 1380                         /* Welcome the "new" disk. */
 1381                         update += g_raid_md_jmicron_start_disk(disk);
 1382                         if (disk->d_state != G_RAID_DISK_S_ACTIVE &&
 1383                             disk->d_state != G_RAID_DISK_S_SPARE) {
 1384                                 gctl_error(req, "Disk '%s' doesn't fit.",
 1385                                     diskname);
 1386                                 g_raid_destroy_disk(disk);
 1387                                 error = -8;
 1388                                 break;
 1389                         }
 1390                 }
 1391 
 1392                 /* Write new metadata if we changed something. */
 1393                 if (update)
 1394                         g_raid_md_write_jmicron(md, NULL, NULL, NULL);
 1395                 return (error);
 1396         }
 1397         gctl_error(req, "Command '%s' is not supported.", verb);
 1398         return (-100);
 1399 }
 1400 
 1401 static int
 1402 g_raid_md_write_jmicron(struct g_raid_md_object *md, struct g_raid_volume *tvol,
 1403     struct g_raid_subdisk *tsd, struct g_raid_disk *tdisk)
 1404 {
 1405         struct g_raid_softc *sc;
 1406         struct g_raid_volume *vol;
 1407         struct g_raid_subdisk *sd;
 1408         struct g_raid_disk *disk;
 1409         struct g_raid_md_jmicron_object *mdi;
 1410         struct g_raid_md_jmicron_perdisk *pd;
 1411         struct jmicron_raid_conf *meta;
 1412         int i, spares;
 1413 
 1414         sc = md->mdo_softc;
 1415         mdi = (struct g_raid_md_jmicron_object *)md;
 1416 
 1417         if (sc->sc_stopping == G_RAID_DESTROY_HARD)
 1418                 return (0);
 1419 
 1420         /* There is only one volume. */
 1421         vol = TAILQ_FIRST(&sc->sc_volumes);
 1422 
 1423         /* Fill global fields. */
 1424         meta = malloc(sizeof(*meta), M_MD_JMICRON, M_WAITOK | M_ZERO);
 1425         strncpy(meta->signature, JMICRON_MAGIC, 2);
 1426         meta->version = JMICRON_VERSION;
 1427         jmicron_meta_put_name(meta, vol->v_name);
 1428         if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID0)
 1429                 meta->type = JMICRON_T_RAID0;
 1430         else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID1)
 1431                 meta->type = JMICRON_T_RAID1;
 1432         else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID1E)
 1433                 meta->type = JMICRON_T_RAID01;
 1434         else if (vol->v_raid_level == G_RAID_VOLUME_RL_CONCAT ||
 1435             vol->v_raid_level == G_RAID_VOLUME_RL_SINGLE)
 1436                 meta->type = JMICRON_T_CONCAT;
 1437         else
 1438                 meta->type = JMICRON_T_RAID5;
 1439         meta->stripe_shift = fls(vol->v_strip_size / 2048);
 1440         meta->flags = JMICRON_F_READY | JMICRON_F_BOOTABLE;
 1441         for (i = 0; i < vol->v_disks_count; i++) {
 1442                 sd = &vol->v_subdisks[i];
 1443                 if (sd->sd_disk == NULL || sd->sd_disk->d_md_data == NULL)
 1444                         meta->disks[i] = 0xffffffff;
 1445                 else {
 1446                         pd = (struct g_raid_md_jmicron_perdisk *)
 1447                             sd->sd_disk->d_md_data;
 1448                         meta->disks[i] = pd->pd_disk_id;
 1449                 }
 1450                 if (sd->sd_state < G_RAID_SUBDISK_S_STALE)
 1451                         meta->flags |= JMICRON_F_BADSEC;
 1452                 if (vol->v_dirty)
 1453                         meta->flags |= JMICRON_F_UNSYNC;
 1454         }
 1455 
 1456         /* Put spares to their slots. */
 1457         spares = 0;
 1458         TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
 1459                 pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
 1460                 if (disk->d_state != G_RAID_DISK_S_SPARE)
 1461                         continue;
 1462                 meta->spare[spares] = pd->pd_disk_id;
 1463                 if (++spares >= 2)
 1464                         break;
 1465         }
 1466 
 1467         /* We are done. Print meta data and store them to disks. */
 1468         if (mdi->mdio_meta != NULL)
 1469                 free(mdi->mdio_meta, M_MD_JMICRON);
 1470         mdi->mdio_meta = meta;
 1471         TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
 1472                 pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
 1473                 if (disk->d_state != G_RAID_DISK_S_ACTIVE &&
 1474                     disk->d_state != G_RAID_DISK_S_SPARE)
 1475                         continue;
 1476                 if (pd->pd_meta != NULL) {
 1477                         free(pd->pd_meta, M_MD_JMICRON);
 1478                         pd->pd_meta = NULL;
 1479                 }
 1480                 pd->pd_meta = jmicron_meta_copy(meta);
 1481                 pd->pd_meta->disk_id = pd->pd_disk_id;
 1482                 if ((sd = TAILQ_FIRST(&disk->d_subdisks)) != NULL) {
 1483                         pd->pd_meta->offset =
 1484                             (sd->sd_offset / 512) / 16;
 1485                         pd->pd_meta->disk_sectors_high =
 1486                             (sd->sd_size / 512) >> 16;
 1487                         pd->pd_meta->disk_sectors_low =
 1488                             (sd->sd_size / 512) & 0xffff;
 1489                         if (sd->sd_state < G_RAID_SUBDISK_S_STALE)
 1490                                 pd->pd_meta->flags &= ~JMICRON_F_BADSEC;
 1491                         else if (sd->sd_state < G_RAID_SUBDISK_S_ACTIVE)
 1492                                 pd->pd_meta->flags |= JMICRON_F_UNSYNC;
 1493                 }
 1494                 G_RAID_DEBUG(1, "Writing JMicron metadata to %s",
 1495                     g_raid_get_diskname(disk));
 1496                 g_raid_md_jmicron_print(pd->pd_meta);
 1497                 jmicron_meta_write(disk->d_consumer, pd->pd_meta);
 1498         }
 1499         return (0);
 1500 }
 1501 
 1502 static int
 1503 g_raid_md_fail_disk_jmicron(struct g_raid_md_object *md,
 1504     struct g_raid_subdisk *tsd, struct g_raid_disk *tdisk)
 1505 {
 1506         struct g_raid_softc *sc;
 1507         struct g_raid_md_jmicron_perdisk *pd;
 1508         struct g_raid_subdisk *sd;
 1509 
 1510         sc = md->mdo_softc;
 1511         pd = (struct g_raid_md_jmicron_perdisk *)tdisk->d_md_data;
 1512 
 1513         /* We can't fail disk that is not a part of array now. */
 1514         if (pd->pd_disk_pos < 0)
 1515                 return (-1);
 1516 
 1517         if (tdisk->d_consumer)
 1518                 jmicron_meta_erase(tdisk->d_consumer);
 1519 
 1520         /* Change states. */
 1521         g_raid_change_disk_state(tdisk, G_RAID_DISK_S_FAILED);
 1522         TAILQ_FOREACH(sd, &tdisk->d_subdisks, sd_next) {
 1523                 g_raid_change_subdisk_state(sd,
 1524                     G_RAID_SUBDISK_S_FAILED);
 1525                 g_raid_event_send(sd, G_RAID_SUBDISK_E_FAILED,
 1526                     G_RAID_EVENT_SUBDISK);
 1527         }
 1528 
 1529         /* Write updated metadata to remaining disks. */
 1530         g_raid_md_write_jmicron(md, NULL, NULL, tdisk);
 1531 
 1532         /* Check if anything left except placeholders. */
 1533         if (g_raid_ndisks(sc, -1) ==
 1534             g_raid_ndisks(sc, G_RAID_DISK_S_OFFLINE))
 1535                 g_raid_destroy_node(sc, 0);
 1536         else
 1537                 g_raid_md_jmicron_refill(sc);
 1538         return (0);
 1539 }
 1540 
 1541 static int
 1542 g_raid_md_free_disk_jmicron(struct g_raid_md_object *md,
 1543     struct g_raid_disk *disk)
 1544 {
 1545         struct g_raid_md_jmicron_perdisk *pd;
 1546 
 1547         pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
 1548         if (pd->pd_meta != NULL) {
 1549                 free(pd->pd_meta, M_MD_JMICRON);
 1550                 pd->pd_meta = NULL;
 1551         }
 1552         free(pd, M_MD_JMICRON);
 1553         disk->d_md_data = NULL;
 1554         return (0);
 1555 }
 1556 
 1557 static int
 1558 g_raid_md_free_jmicron(struct g_raid_md_object *md)
 1559 {
 1560         struct g_raid_md_jmicron_object *mdi;
 1561 
 1562         mdi = (struct g_raid_md_jmicron_object *)md;
 1563         if (!mdi->mdio_started) {
 1564                 mdi->mdio_started = 0;
 1565                 callout_stop(&mdi->mdio_start_co);
 1566                 G_RAID_DEBUG1(1, md->mdo_softc,
 1567                     "root_mount_rel %p", mdi->mdio_rootmount);
 1568                 root_mount_rel(mdi->mdio_rootmount);
 1569                 mdi->mdio_rootmount = NULL;
 1570         }
 1571         if (mdi->mdio_meta != NULL) {
 1572                 free(mdi->mdio_meta, M_MD_JMICRON);
 1573                 mdi->mdio_meta = NULL;
 1574         }
 1575         return (0);
 1576 }
 1577 
 1578 G_RAID_MD_DECLARE(g_raid_md_jmicron);

Cache object: 7090e9e4ef3cedf70741574039e677b1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.