Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 23 Dec 2010 20:23:17 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r216682 - in projects/graid/head: sbin/geom/class/raid sys/geom/raid
Message-ID:  <201012232023.oBNKNHtw067976@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <pjd@FreeBSD.org>
  * Copyright (c) 2010 Alexander Motin <mav@FreeBSD.org>
  * 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 <pjd@FreeBSD.org>
+ * Copyright (c) 2010 Alexander Motin <mav@FreeBSD.org>
  * 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)
 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201012232023.oBNKNHtw067976>