From owner-svn-src-projects@FreeBSD.ORG Thu Dec 23 20:23:17 2010 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DAE1E106566B; Thu, 23 Dec 2010 20:23:17 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C8FD78FC08; Thu, 23 Dec 2010 20:23:17 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id oBNKNHp4067982; Thu, 23 Dec 2010 20:23:17 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oBNKNHtw067976; Thu, 23 Dec 2010 20:23:17 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201012232023.oBNKNHtw067976@svn.freebsd.org> From: Alexander Motin Date: Thu, 23 Dec 2010 20:23:17 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r216682 - in projects/graid/head: sbin/geom/class/raid sys/geom/raid X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 23 Dec 2010 20:23:17 -0000 Author: mav Date: Thu Dec 23 20:23:17 2010 New Revision: 216682 URL: http://svn.freebsd.org/changeset/base/216682 Log: Add basic array creation and Intel metadata writing. Now it is possible to create volume readable by BIOS with: graid label Intel test RAID1 ada0 ada1 Modified: projects/graid/head/sbin/geom/class/raid/geom_raid.c projects/graid/head/sys/geom/raid/g_raid.c projects/graid/head/sys/geom/raid/g_raid_ctl.c projects/graid/head/sys/geom/raid/g_raid_md_if.m projects/graid/head/sys/geom/raid/md_intel.c Modified: projects/graid/head/sbin/geom/class/raid/geom_raid.c ============================================================================== --- projects/graid/head/sbin/geom/class/raid/geom_raid.c Thu Dec 23 19:28:50 2010 (r216681) +++ projects/graid/head/sbin/geom/class/raid/geom_raid.c Thu Dec 23 20:23:17 2010 (r216682) @@ -1,5 +1,4 @@ /*- - * Copyright (c) 2004-2009 Pawel Jakub Dawidek * Copyright (c) 2010 Alexander Motin * All rights reserved. * Modified: projects/graid/head/sys/geom/raid/g_raid.c ============================================================================== --- projects/graid/head/sys/geom/raid/g_raid.c Thu Dec 23 19:28:50 2010 (r216681) +++ projects/graid/head/sys/geom/raid/g_raid.c Thu Dec 23 20:23:17 2010 (r216682) @@ -284,8 +284,8 @@ g_raid_volume_str2level(const char *str, else if (strcasecmp(str, "RAID5EE") == 0) *level = G_RAID_VOLUME_RL_RAID5EE; else - return (0); - return (1); + return (-1); + return (0); } static const char * Modified: projects/graid/head/sys/geom/raid/g_raid_ctl.c ============================================================================== --- projects/graid/head/sys/geom/raid/g_raid_ctl.c Thu Dec 23 19:28:50 2010 (r216681) +++ projects/graid/head/sys/geom/raid/g_raid_ctl.c Thu Dec 23 20:23:17 2010 (r216682) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004-2009 Pawel Jakub Dawidek + * Copyright (c) 2010 Alexander Motin * All rights reserved. * * Redistribution and use in source and binary forms, with or without Modified: projects/graid/head/sys/geom/raid/g_raid_md_if.m ============================================================================== --- projects/graid/head/sys/geom/raid/g_raid_md_if.m Thu Dec 23 19:28:50 2010 (r216681) +++ projects/graid/head/sys/geom/raid/g_raid_md_if.m Thu Dec 23 20:23:17 2010 (r216682) @@ -49,14 +49,14 @@ HEADER { # Default implementations of methods. CODE { static int - g_raid_md_create_default(struct g_raid_tr_object *tr) + g_raid_md_create_default(struct g_raid_md_object *md) { return (G_RAID_MD_TASTE_FAIL); } static int - g_raid_md_ctl_default(struct g_raid_tr_object *tr, + g_raid_md_ctl_default(struct g_raid_md_object *md, struct gctl_req *req) { @@ -81,13 +81,13 @@ METHOD int taste { # ctl() - user-level control commands handling method. METHOD int ctl { - struct g_raid_md_object *tr; + struct g_raid_md_object *md; struct gctl_req *req; } DEFAULT g_raid_md_ctl_default; # event() - events handling method. METHOD int event { - struct g_raid_md_object *tr; + struct g_raid_md_object *md; struct g_raid_disk *disk; u_int event; }; Modified: projects/graid/head/sys/geom/raid/md_intel.c ============================================================================== --- projects/graid/head/sys/geom/raid/md_intel.c Thu Dec 23 19:28:50 2010 (r216681) +++ projects/graid/head/sys/geom/raid/md_intel.c Thu Dec 23 20:23:17 2010 (r216682) @@ -120,6 +120,7 @@ struct intel_raid_conf { uint8_t version[6]; #define INTEL_VERSION_1100 "1.1.00" +#define INTEL_VERSION_1200 "1.2.00" #define INTEL_VERSION_1201 "1.2.01" #define INTEL_VERSION_1202 "1.2.02" @@ -161,6 +162,7 @@ struct g_raid_md_intel_object { static g_raid_md_create_t g_raid_md_create_intel; static g_raid_md_taste_t g_raid_md_taste_intel; static g_raid_md_event_t g_raid_md_event_intel; +static g_raid_md_ctl_t g_raid_md_ctl_intel; static g_raid_md_write_t g_raid_md_write_intel; static g_raid_md_free_disk_t g_raid_md_free_disk_intel; static g_raid_md_free_t g_raid_md_free_intel; @@ -169,6 +171,7 @@ static kobj_method_t g_raid_md_intel_met KOBJMETHOD(g_raid_md_create, g_raid_md_create_intel), KOBJMETHOD(g_raid_md_taste, g_raid_md_taste_intel), KOBJMETHOD(g_raid_md_event, g_raid_md_event_intel), + KOBJMETHOD(g_raid_md_ctl, g_raid_md_ctl_intel), KOBJMETHOD(g_raid_md_write, g_raid_md_write_intel), KOBJMETHOD(g_raid_md_free_disk, g_raid_md_free_disk_intel), KOBJMETHOD(g_raid_md_free, g_raid_md_free_intel), @@ -184,42 +187,42 @@ static struct g_raid_md_class g_raid_md_ static struct intel_raid_map * -intel_get_map(struct intel_raid_vol *vol, int i) +intel_get_map(struct intel_raid_vol *mvol, int i) { - struct intel_raid_map *map; + struct intel_raid_map *mmap; - if (i > (vol->migr_state ? 1 : 0)) + if (i > (mvol->migr_state ? 1 : 0)) return (NULL); - map = &vol->map[0]; + mmap = &mvol->map[0]; for (; i > 0; i--) { - map = (struct intel_raid_map *) - &map->disk_idx[map->total_disks]; + mmap = (struct intel_raid_map *) + &mmap->disk_idx[mmap->total_disks]; } - return ((struct intel_raid_map *)map); + return ((struct intel_raid_map *)mmap); } static struct intel_raid_vol * intel_get_volume(struct intel_raid_conf *meta, int i) { - struct intel_raid_vol *vol; - struct intel_raid_map *map; + struct intel_raid_vol *mvol; + struct intel_raid_map *mmap; if (i > 1) return (NULL); - vol = (struct intel_raid_vol *)&meta->disk[meta->total_disks]; + mvol = (struct intel_raid_vol *)&meta->disk[meta->total_disks]; for (; i > 0; i--) { - map = intel_get_map(vol, vol->migr_state ? 1 : 0); - vol = (struct intel_raid_vol *) - &map->disk_idx[map->total_disks]; + mmap = intel_get_map(mvol, mvol->migr_state ? 1 : 0); + mvol = (struct intel_raid_vol *) + &mmap->disk_idx[mmap->total_disks]; } - return (vol); + return (mvol); } static void g_raid_md_intel_print(struct intel_raid_conf *meta) { - struct intel_raid_vol *vol; - struct intel_raid_map *map; + struct intel_raid_vol *mvol; + struct intel_raid_map *mmap; int i, j, k; printf("********* ATA Intel MatrixRAID Metadata *********\n"); @@ -238,34 +241,34 @@ g_raid_md_intel_print(struct intel_raid_ meta->disk[i].id, meta->disk[i].flags); } for (i = 0; i < meta->total_volumes; i++) { - vol = intel_get_volume(meta, i); + mvol = intel_get_volume(meta, i); printf(" ****** Volume %d ******\n", i); - printf(" name %.16s\n", vol->name); - printf(" total_sectors %ju\n", vol->total_sectors); - printf(" state %u\n", vol->state); - printf(" reserved %u\n", vol->reserved); - printf(" curr_migr_unit %u\n", vol->curr_migr_unit); - printf(" checkpoint_id %u\n", vol->checkpoint_id); - printf(" migr_state %u\n", vol->migr_state); - printf(" migr_type %u\n", vol->migr_type); - printf(" dirty %u\n", vol->dirty); + printf(" name %.16s\n", mvol->name); + printf(" total_sectors %ju\n", mvol->total_sectors); + printf(" state %u\n", mvol->state); + printf(" reserved %u\n", mvol->reserved); + printf(" curr_migr_unit %u\n", mvol->curr_migr_unit); + printf(" checkpoint_id %u\n", mvol->checkpoint_id); + printf(" migr_state %u\n", mvol->migr_state); + printf(" migr_type %u\n", mvol->migr_type); + printf(" dirty %u\n", mvol->dirty); - for (j = 0; j < (vol->migr_state ? 2 : 1); j++) { + for (j = 0; j < (mvol->migr_state ? 2 : 1); j++) { printf(" *** Map %d ***\n", j); - map = intel_get_map(vol, j); - printf(" offset %u\n", map->offset); - printf(" disk_sectors %u\n", map->disk_sectors); - printf(" stripe_count %u\n", map->stripe_count); - printf(" stripe_sectors %u\n", map->stripe_sectors); - printf(" status %u\n", map->status); - printf(" type %u\n", map->type); - printf(" total_disks %u\n", map->total_disks); - printf(" total_domains %u\n", map->total_domains); - printf(" failed_disk_num %u\n", map->failed_disk_num); - printf(" ddf %u\n", map->ddf); + mmap = intel_get_map(mvol, j); + printf(" offset %u\n", mmap->offset); + printf(" disk_sectors %u\n", mmap->disk_sectors); + printf(" stripe_count %u\n", mmap->stripe_count); + printf(" stripe_sectors %u\n", mmap->stripe_sectors); + printf(" status %u\n", mmap->status); + printf(" type %u\n", mmap->type); + printf(" total_disks %u\n", mmap->total_disks); + printf(" total_domains %u\n", mmap->total_domains); + printf(" failed_disk_num %u\n", mmap->failed_disk_num); + printf(" ddf %u\n", mmap->ddf); printf(" disk_idx "); - for (k = 0; k < map->total_disks; k++) - printf(" 0x%08x", map->disk_idx[k]); + for (k = 0; k < mmap->total_disks; k++) + printf(" 0x%08x", mmap->disk_idx[k]); printf("\n"); } } @@ -277,11 +280,120 @@ intel_meta_copy(struct intel_raid_conf * { struct intel_raid_conf *nmeta; - nmeta = malloc(meta->config_size, M_MD_INTEL, M_WAITOK | M_ZERO); + nmeta = malloc(meta->config_size, M_MD_INTEL, M_WAITOK); memcpy(nmeta, meta, meta->config_size); return (nmeta); } +static struct intel_raid_conf * +intel_meta_read(struct g_consumer *cp) +{ + struct g_provider *pp; + struct intel_raid_conf *meta; + char *buf; + int error, i, left; + uint32_t checksum, *ptr; + + pp = cp->provider; + + /* Read the anchor sector. */ + buf = g_read_data(cp, + pp->mediasize - pp->sectorsize * 2, pp->sectorsize, &error); + if (buf == NULL) { + G_RAID_DEBUG(1, "Cannot read metadata from %s (error=%d).", + pp->name, error); + return (NULL); + } + meta = (struct intel_raid_conf *)buf; + + /* Check if this is an Intel RAID struct */ + if (strncmp(meta->intel_id, INTEL_MAGIC, strlen(INTEL_MAGIC))) { + G_RAID_DEBUG(1, "Intel signature check failed on %s", pp->name); + g_free(buf); + return (NULL); + } + if (meta->config_size > 65536) { + G_RAID_DEBUG(1, "Intel metadata size looks too big: %d", + meta->config_size); + g_free(buf); + return (NULL); + } + meta = malloc(meta->config_size, M_MD_INTEL, M_WAITOK); + memcpy(meta, buf, pp->sectorsize); + g_free(buf); + + /* Read all the rest, if needed. */ + if (meta->config_size > pp->sectorsize) { + left = (meta->config_size - 1) / pp->sectorsize; + buf = g_read_data(cp, + pp->mediasize - pp->sectorsize * (2 + left), + pp->sectorsize * left, &error); + if (buf == NULL) { + G_RAID_DEBUG(1, "Cannot read remaining metadata" + " part from %s (error=%d).", + pp->name, error); + free(meta, M_MD_INTEL); + return (NULL); + } + memcpy(((char *)meta) + pp->sectorsize, buf, + pp->sectorsize * left); + g_free(buf); + } + + /* Check metadata checksum. */ + for (checksum = 0, ptr = (uint32_t *)meta, i = 0; + i < (meta->config_size / sizeof(uint32_t)); i++) { + checksum += *ptr++; + } + checksum -= meta->checksum; + if (checksum != meta->checksum) { + G_RAID_DEBUG(1, "Intel checksum check failed on %s", pp->name); + free(meta, M_MD_INTEL); + return (NULL); + } + + return (meta); +} + +static int +intel_meta_write(struct g_consumer *cp, struct intel_raid_conf *meta) +{ + struct g_provider *pp; + char *buf; + int error, i, sectors; + uint32_t checksum, *ptr; + + pp = cp->provider; + + /* Recalculate checksum for case if metadata were changed. */ + meta->checksum = 0; + for (checksum = 0, ptr = (uint32_t *)meta, i = 0; + i < (meta->config_size / sizeof(uint32_t)); i++) { + checksum += *ptr++; + } + meta->checksum = checksum; + + /* Create and fill buffer. */ + sectors = (meta->config_size + pp->sectorsize - 1) / pp->sectorsize; + buf = malloc(sectors * pp->sectorsize, M_MD_INTEL, M_WAITOK | M_ZERO); + if (sectors > 1) { + memcpy(buf, ((char *)meta) + pp->sectorsize, + (sectors - 1) * pp->sectorsize); + } + memcpy(buf + (sectors - 1) * pp->sectorsize, meta, pp->sectorsize); + + error = g_write_data(cp, + pp->mediasize - pp->sectorsize * (1 + sectors), + buf, pp->sectorsize * sectors); + if (error != 0) { + G_RAID_DEBUG(1, "Cannot write metadata to %s (error=%d).", + pp->name, error); + } + + free(buf, M_MD_INTEL); + return (error); +} + #if 0 static struct g_raid_disk * g_raid_md_intel_get_disk(struct g_raid_softc *sc, int id) @@ -299,13 +411,13 @@ g_raid_md_intel_get_disk(struct g_raid_s static struct g_raid_volume * g_raid_md_intel_get_volume(struct g_raid_softc *sc, int id) { - struct g_raid_volume *vol; + struct g_raid_volume *mvol; - LIST_FOREACH(vol, &sc->sc_volumes, v_next) { - if ((intptr_t)(vol->v_md_data) == id) + LIST_FOREACH(mvol, &sc->sc_volumes, v_next) { + if ((intptr_t)(mvol->v_md_data) == id) break; } - return (vol); + return (mvol); } static void @@ -319,7 +431,7 @@ g_raid_md_intel_start_disk(struct g_raid struct g_raid_md_intel_perdisk *pd; struct intel_raid_conf *meta, *pdmeta; struct intel_raid_vol *mvol; - struct intel_raid_map *map; + struct intel_raid_map *mmap; int i, j; sc = disk->d_softc; @@ -340,18 +452,18 @@ g_raid_md_intel_start_disk(struct g_raid /* Create subdisks. */ for (i = 0; i < meta->total_volumes; i++) { mvol = intel_get_volume(meta, i); - map = intel_get_map(mvol, 0); - for (j = 0; j < map->total_disks; j++) { - if ((map->disk_idx[j] & INTEL_DI_IDX) == pd->pd_disk_pos) + mmap = intel_get_map(mvol, 0); + for (j = 0; j < mmap->total_disks; j++) { + if ((mmap->disk_idx[j] & INTEL_DI_IDX) == pd->pd_disk_pos) break; } - if (j == map->total_disks) + if (j == mmap->total_disks) continue; vol = g_raid_md_intel_get_volume(sc, i); sd = &vol->v_subdisks[j]; sd->sd_disk = disk; - sd->sd_offset = map->offset * 512; //ZZZ - sd->sd_size = map->disk_sectors; + sd->sd_offset = mmap->offset * 512; //ZZZ + sd->sd_size = mmap->disk_sectors; LIST_INSERT_HEAD(&disk->d_subdisks, sd, sd_next); g_raid_event_send(sd, G_RAID_SUBDISK_E_NEW, G_RAID_EVENT_SUBDISK); @@ -366,7 +478,7 @@ g_raid_md_intel_start(struct g_raid_soft struct g_raid_md_intel_object *mdi; struct intel_raid_conf *meta; struct intel_raid_vol *mvol; - struct intel_raid_map *map; + struct intel_raid_map *mmap; struct g_raid_volume *vol; struct g_raid_disk *disk; int i; @@ -377,23 +489,23 @@ g_raid_md_intel_start(struct g_raid_soft /* Create volumes */ for (i = 0; i < meta->total_volumes; i++) { mvol = intel_get_volume(meta, i); - map = intel_get_map(mvol, 0); + mmap = intel_get_map(mvol, 0); vol = g_raid_create_volume(sc, mvol->name); vol->v_md_data = (void *)(intptr_t)i; - if (map->type == INTEL_T_RAID0) + if (mmap->type == INTEL_T_RAID0) vol->v_raid_level = G_RAID_VOLUME_RL_RAID0; - else if (map->type == INTEL_T_RAID1 && - map->total_disks < 4) + else if (mmap->type == INTEL_T_RAID1 && + mmap->total_disks < 4) vol->v_raid_level = G_RAID_VOLUME_RL_RAID1; - else if (map->type == INTEL_T_RAID1) + else if (mmap->type == INTEL_T_RAID1) vol->v_raid_level = G_RAID_VOLUME_RL_RAID10; - else if (map->type == INTEL_T_RAID5) + else if (mmap->type == INTEL_T_RAID5) vol->v_raid_level = G_RAID_VOLUME_RL_RAID5; else vol->v_raid_level = G_RAID_VOLUME_RL_UNKNOWN; vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_NONE; - vol->v_strip_size = map->stripe_sectors * 512; //ZZZ - vol->v_disks_count = map->total_disks; + vol->v_strip_size = mmap->stripe_sectors * 512; //ZZZ + vol->v_disks_count = mmap->total_disks; vol->v_mediasize = mvol->total_sectors * 512; //ZZZ vol->v_sectorsize = 512; //ZZZ g_raid_start_volume(vol); @@ -500,9 +612,7 @@ g_raid_md_taste_intel(struct g_raid_md_o struct intel_raid_conf *meta; struct g_raid_md_intel_perdisk *pd; struct g_geom *geom; - uint32_t checksum, *ptr; - char *buf, *tmp; - int i, error, serial_len, disk_pos, result; + int error, serial_len, disk_pos, result; char serial[INTEL_SERIAL_LEN]; char name[16]; @@ -511,9 +621,9 @@ g_raid_md_taste_intel(struct g_raid_md_o pp = cp->provider; /* Read metadata from device. */ - meta = malloc(pp->sectorsize * 2, M_MD_INTEL, M_WAITOK | M_ZERO); + meta = NULL; if (g_access(cp, 1, 0, 0) != 0) - goto fail1; + return (G_RAID_MD_TASTE_FAIL); g_topology_unlock(); serial_len = sizeof(serial); error = g_io_getattr("GEOM::ident", cp, &serial_len, serial); @@ -522,35 +632,13 @@ g_raid_md_taste_intel(struct g_raid_md_o pp->name, error); goto fail2; } - buf = g_read_data(cp, - pp->mediasize - pp->sectorsize * 3, pp->sectorsize * 2, - &error); - if (buf == NULL) { - G_RAID_DEBUG(1, "Cannot read metadata from %s (error=%d).", - pp->name, error); - goto fail2; - } + meta = intel_meta_read(cp); g_topology_lock(); g_access(cp, -1, 0, 0); - tmp = (char *)meta; - memcpy(tmp, buf + pp->sectorsize, pp->sectorsize); - memcpy(tmp + pp->sectorsize, buf, pp->sectorsize); - g_free(buf); + if (meta == NULL) + return (G_RAID_MD_TASTE_FAIL); - /* Check if this is a Intel RAID struct */ - if (strncmp(meta->intel_id, INTEL_MAGIC, strlen(INTEL_MAGIC))) { - G_RAID_DEBUG(1, "Intel signature check failed on %s", pp->name); - goto fail1; - } - for (checksum = 0, ptr = (uint32_t *)meta, i = 0; - i < (meta->config_size / sizeof(uint32_t)); i++) { - checksum += *ptr++; - } - checksum -= meta->checksum; - if (checksum != meta->checksum) { - G_RAID_DEBUG(1, "Intel checksum check failed on %s", pp->name); - goto fail1; - } + /* Check this disk position in obtained metadata. */ for (disk_pos = 0; disk_pos < meta->total_disks; disk_pos++) { if (strncmp(meta->disk[disk_pos].serial, serial, serial_len)) { G_RAID_DEBUG(1, "Intel serial mismatch '%s' '%s'", @@ -658,6 +746,188 @@ g_raid_md_event_intel(struct g_raid_md_o } static int +g_raid_md_ctl_intel(struct g_raid_md_object *md, + struct gctl_req *req) +{ + struct g_raid_softc *sc; + struct g_raid_disk *disk; + struct g_raid_md_intel_object *mdi; + struct g_raid_md_intel_perdisk *pd; + struct g_consumer *cp; + struct g_provider *pp; + struct intel_raid_conf *meta; + struct intel_raid_vol *mvol; + struct intel_raid_map *mmap; + char arg[16]; + const char *verb, *volname, *levelname, *diskname; + int *nargs; + uint64_t size, sectorsize; + int numdisks, i, level, qual, serial_len; + int error; + + sc = md->mdo_softc; + mdi = (struct g_raid_md_intel_object *)md; + verb = gctl_get_param(req, "verb", NULL); + nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); + if (strcmp(verb, "label") == 0) { + + if (*nargs < 4) { + gctl_error(req, "Invalid number of arguments."); + return (-1); + } + volname = gctl_get_asciiparam(req, "arg1"); + if (volname == NULL) { + gctl_error(req, "No volume name."); + return (-2); + } + levelname = gctl_get_asciiparam(req, "arg2"); + if (levelname == NULL) { + gctl_error(req, "No RAID level."); + return (-3); + } + if (g_raid_volume_str2level(levelname, &level, &qual)) { + gctl_error(req, "Unknown RAID level '%s'.", levelname); + return (-4); + } + if (level != G_RAID_VOLUME_RL_RAID0 && + level != G_RAID_VOLUME_RL_RAID1 && + level != G_RAID_VOLUME_RL_RAID5 && + level != G_RAID_VOLUME_RL_RAID10) { + gctl_error(req, "Unsupported RAID level."); + return (-5); + } + numdisks = *nargs - 3; + meta = mdi->mdio_meta = malloc(INTEL_MAX_MD_SIZE(numdisks), + M_MD_INTEL, M_WAITOK | M_ZERO); + memcpy(&meta->intel_id[0], INTEL_MAGIC, sizeof(INTEL_MAGIC)); + memcpy(&meta->version[0], INTEL_VERSION_1200, + sizeof(INTEL_VERSION_1200)); + meta->config_size = INTEL_MAX_MD_SIZE(numdisks); + meta->config_id = mdi->mdio_config_id; + meta->generation = 1; + meta->total_disks = numdisks; + meta->total_volumes = 1; + error = 0; + size = 0xffffffffffffffffllu; + sectorsize = 0; + for (i = 0; i < numdisks; i++) { + snprintf(arg, sizeof(arg), "arg%d", i + 3); + diskname = gctl_get_asciiparam(req, arg); + if (diskname == NULL) { + gctl_error(req, "No disk name (%s).", arg); + error = -6; + break; + } + if (strncmp(diskname, "/dev/", 5) == 0) + diskname += 5; + g_topology_lock(); + pp = g_provider_by_name(diskname); + if (pp == NULL) { + gctl_error(req, "Provider '%s' not found.", + diskname); + g_topology_unlock(); + error = -7; + break; + } + cp = g_new_consumer(sc->sc_geom); + if (g_attach(cp, pp) != 0) { + gctl_error(req, "Can't attach provider '%s'.", + diskname); + g_destroy_consumer(cp); + g_topology_unlock(); + error = -7; + break; + } + if (g_access(cp, 1, 1, 1) != 0) { + gctl_error(req, "Can't open provider '%s'.", + diskname); + g_detach(cp); + g_destroy_consumer(cp); + g_topology_unlock(); + error = -7; + break; + } + + pd = malloc(sizeof(*pd), M_MD_INTEL, M_WAITOK | M_ZERO); + pd->pd_disk_pos = i; + disk = g_raid_create_disk(sc); + disk->d_md_data = (void *)pd; + disk->d_consumer = cp; + cp->private = disk; + + g_topology_unlock(); + + serial_len = sizeof(meta->disk[i].serial); + error = g_io_getattr("GEOM::ident", cp, + &serial_len, &meta->disk[i].serial[0]); + if (error != 0) { + gctl_error(req, + "Can't get serial for provider '%s'.", + diskname); + error = -8; + break; + } + meta->disk[i].sectors = pp->mediasize / pp->sectorsize; + if (size > meta->disk[i].sectors) + size = meta->disk[i].sectors; + if (sectorsize < pp->sectorsize) + sectorsize = pp->sectorsize; + meta->disk[i].id = 0xffffffff; + meta->disk[i].flags = INTEL_F_ASSIGNED | INTEL_F_ONLINE; + } + if (error != 0) + return (error); + + /* Reserve some space for metadata. */ + size -= (4096 + sectorsize - 1) / sectorsize + 1; + + size &= ~127; /* Assume stripe size 64K */ + mvol = intel_get_volume(meta, 0); + strlcpy(&mvol->name[0], volname, sizeof(mvol->name)); + if (level == G_RAID_VOLUME_RL_RAID0) + mvol->total_sectors = size * numdisks; + else if (level == G_RAID_VOLUME_RL_RAID5) + mvol->total_sectors = size * (numdisks - 1); + else + mvol->total_sectors = size * (numdisks / 2); + mmap = intel_get_map(mvol, 0); + mmap->offset = 0; + mmap->disk_sectors = size; + mmap->stripe_count = size / 128; + mmap->stripe_sectors = 128; + mmap->status = INTEL_S_READY; + if (level == G_RAID_VOLUME_RL_RAID0) + mmap->type = INTEL_T_RAID0; + else if (level == G_RAID_VOLUME_RL_RAID1 || + level == G_RAID_VOLUME_RL_RAID10) + mmap->type = INTEL_T_RAID1; + else + mmap->type = INTEL_T_RAID5; + mmap->total_disks = numdisks; + if (level == G_RAID_VOLUME_RL_RAID10) + mmap->total_domains = numdisks / 2; + else if (level == G_RAID_VOLUME_RL_RAID1) + mmap->total_domains = numdisks; + else + mmap->total_domains = 1; + mmap->failed_disk_num = ~0; + mmap->ddf = 1; + for (i = 0; i < numdisks; i++) + mmap->disk_idx[i] = i; + g_raid_md_intel_print(meta); + LIST_FOREACH(disk, &sc->sc_disks, d_next) { + pd = (struct g_raid_md_intel_perdisk *)disk->d_md_data; + pd->pd_meta = intel_meta_copy(meta); + intel_meta_write(disk->d_consumer, meta); + } + mdi->mdio_started = 1; + g_raid_md_intel_start(sc); + return (0); + } + return (-100); +} + +static int g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_disk *disk) {