md_jmicron.c revision 302408
1492SN/A/*-
21929Sihse * Copyright (c) 2010 Alexander Motin <mav@FreeBSD.org>
3492SN/A * Copyright (c) 2000 - 2008 S��ren Schmidt <sos@FreeBSD.org>
4492SN/A * All rights reserved.
5492SN/A *
6492SN/A * Redistribution and use in source and binary forms, with or without
7492SN/A * modification, are permitted provided that the following conditions
8492SN/A * are met:
9492SN/A * 1. Redistributions of source code must retain the above copyright
10492SN/A *    notice, this list of conditions and the following disclaimer.
11492SN/A * 2. Redistributions in binary form must reproduce the above copyright
12492SN/A *    notice, this list of conditions and the following disclaimer in the
13492SN/A *    documentation and/or other materials provided with the distribution.
14492SN/A *
15492SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
16492SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17492SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18492SN/A * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
19492SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20492SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21492SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22492SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23492SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24492SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25492SN/A * SUCH DAMAGE.
261120Schegar */
271120Schegar
281120Schegar#include <sys/cdefs.h>
291410Sihse__FBSDID("$FreeBSD: stable/11/sys/geom/raid/md_jmicron.c 286615 2015-08-11 03:12:09Z pfg $");
301120Schegar
311120Schegar#include <sys/param.h>
321120Schegar#include <sys/bio.h>
33492SN/A#include <sys/endian.h>
341410Sihse#include <sys/kernel.h>
351410Sihse#include <sys/kobj.h>
361410Sihse#include <sys/limits.h>
371410Sihse#include <sys/lock.h>
38492SN/A#include <sys/malloc.h>
39492SN/A#include <sys/mutex.h>
40492SN/A#include <sys/systm.h>
411410Sihse#include <sys/taskqueue.h>
421120Schegar#include <geom/geom.h>
43837SN/A#include "geom/raid/g_raid.h"
44910Sihse#include "g_raid_md_if.h"
451131Serikj
46492SN/Astatic MALLOC_DEFINE(M_MD_JMICRON, "md_jmicron_data", "GEOM_RAID JMicron metadata");
471120Schegar
481236Sihse#define	JMICRON_MAX_DISKS	8
491120Schegar#define	JMICRON_MAX_SPARE	2
501120Schegar
511120Schegarstruct jmicron_raid_conf {
52968Sihse    u_int8_t		signature[2];
53968Sihse#define	JMICRON_MAGIC		"JM"
54492SN/A
551120Schegar    u_int16_t		version;
561804Serikj#define	JMICRON_VERSION		0x0001
571120Schegar
581120Schegar    u_int16_t		checksum;
591120Schegar    u_int8_t		filler_1[10];
601120Schegar    u_int32_t		disk_id;
611120Schegar    u_int32_t		offset;
621120Schegar    u_int32_t		disk_sectors_high;
631120Schegar    u_int16_t		disk_sectors_low;
641120Schegar    u_int8_t		filler_2[2];
651120Schegar    u_int8_t		name[16];
661120Schegar    u_int8_t		type;
671120Schegar#define	JMICRON_T_RAID0		0
682108Serikj#define	JMICRON_T_RAID1		1
692108Serikj#define	JMICRON_T_RAID01	2
702108Serikj#define	JMICRON_T_CONCAT	3
712108Serikj#define	JMICRON_T_RAID5		5
721223Schegar
731223Schegar    u_int8_t		stripe_shift;
742108Serikj    u_int16_t		flags;
751120Schegar#define	JMICRON_F_READY		0x0001
761120Schegar#define	JMICRON_F_BOOTABLE	0x0002
772108Serikj#define	JMICRON_F_BADSEC	0x0004
781120Schegar#define	JMICRON_F_ACTIVE	0x0010
791120Schegar#define	JMICRON_F_UNSYNC	0x0020
802108Serikj#define	JMICRON_F_NEWEST	0x0040
811600Snaoto
821600Snaoto    u_int8_t		filler_3[4];
832108Serikj    u_int32_t		spare[JMICRON_MAX_SPARE];
841862Serikj    u_int32_t		disks[JMICRON_MAX_DISKS];
852261Serikj#define	JMICRON_DISK_MASK	0xFFFFFFF0
862261Serikj#define	JMICRON_SEG_MASK	0x0000000F
872261Serikj    u_int8_t		filler_4[32];
882399Skvn    u_int8_t		filler_5[384];
892399Skvn};
902399Skvn
912108Serikjstruct g_raid_md_jmicron_perdisk {
921120Schegar	struct jmicron_raid_conf	*pd_meta;
931659Serikj	int				 pd_disk_pos;
942399Skvn	int				 pd_disk_id;
952399Skvn	off_t				 pd_disk_size;
961120Schegar};
971120Schegar
981120Schegarstruct g_raid_md_jmicron_object {
991120Schegar	struct g_raid_md_object	 mdio_base;
1001120Schegar	uint32_t		 mdio_config_id;
1011120Schegar	struct jmicron_raid_conf	*mdio_meta;
1021120Schegar	struct callout		 mdio_start_co;	/* STARTING state timer. */
1031735Sbobv	int			 mdio_total_disks;
1041735Sbobv	int			 mdio_disks_present;
1051735Sbobv	int			 mdio_started;
1062264Serikj	int			 mdio_incomplete;
107492SN/A	struct root_hold_token	*mdio_rootmount; /* Root mount delay token. */
1081120Schegar};
1091120Schegar
1102108Serikjstatic g_raid_md_create_t g_raid_md_create_jmicron;
1112108Serikjstatic g_raid_md_taste_t g_raid_md_taste_jmicron;
1122108Serikjstatic g_raid_md_event_t g_raid_md_event_jmicron;
1132108Serikjstatic g_raid_md_ctl_t g_raid_md_ctl_jmicron;
1142108Serikjstatic g_raid_md_write_t g_raid_md_write_jmicron;
1152108Serikjstatic g_raid_md_fail_disk_t g_raid_md_fail_disk_jmicron;
1162108Serikjstatic g_raid_md_free_disk_t g_raid_md_free_disk_jmicron;
1172108Serikjstatic g_raid_md_free_t g_raid_md_free_jmicron;
1182108Serikj
1192108Serikjstatic kobj_method_t g_raid_md_jmicron_methods[] = {
120492SN/A	KOBJMETHOD(g_raid_md_create,	g_raid_md_create_jmicron),
1212108Serikj	KOBJMETHOD(g_raid_md_taste,	g_raid_md_taste_jmicron),
1222108Serikj	KOBJMETHOD(g_raid_md_event,	g_raid_md_event_jmicron),
1232108Serikj	KOBJMETHOD(g_raid_md_ctl,	g_raid_md_ctl_jmicron),
1242108Serikj	KOBJMETHOD(g_raid_md_write,	g_raid_md_write_jmicron),
125557SN/A	KOBJMETHOD(g_raid_md_fail_disk,	g_raid_md_fail_disk_jmicron),
1262108Serikj	KOBJMETHOD(g_raid_md_free_disk,	g_raid_md_free_disk_jmicron),
1272108Serikj	KOBJMETHOD(g_raid_md_free,	g_raid_md_free_jmicron),
1282108Serikj	{ 0, 0 }
1291961Salanb};
1302108Serikj
1312108Serikjstatic struct g_raid_md_class g_raid_md_jmicron_class = {
1322108Serikj	"JMicron",
1331961Salanb	g_raid_md_jmicron_methods,
1342108Serikj	sizeof(struct g_raid_md_jmicron_object),
1352108Serikj	.mdc_enable = 1,
1361961Salanb	.mdc_priority = 100
1371961Salanb};
1381961Salanb
1392108Serikjstatic void
1402108Serikjg_raid_md_jmicron_print(struct jmicron_raid_conf *meta)
1411961Salanb{
1422108Serikj	int k;
1432108Serikj
1441961Salanb	if (g_raid_debug < 1)
1451120Schegar		return;
1461120Schegar
1471120Schegar	printf("********* ATA JMicron RAID Metadata *********\n");
1481120Schegar	printf("signature           <%c%c>\n", meta->signature[0], meta->signature[1]);
1491223Schegar	printf("version             %04x\n", meta->version);
1501223Schegar	printf("checksum            0x%04x\n", meta->checksum);
1511223Schegar	printf("disk_id             0x%08x\n", meta->disk_id);
1521223Schegar	printf("offset              0x%08x\n", meta->offset);
1531223Schegar	printf("disk_sectors_high   0x%08x\n", meta->disk_sectors_high);
1541223Schegar	printf("disk_sectors_low    0x%04x\n", meta->disk_sectors_low);
1551120Schegar	printf("name                <%.16s>\n", meta->name);
1561120Schegar	printf("type                %d\n", meta->type);
1571120Schegar	printf("stripe_shift        %d\n", meta->stripe_shift);
1581120Schegar	printf("flags               %04x\n", meta->flags);
1591120Schegar	printf("spare              ");
1601223Schegar	for (k = 0; k < JMICRON_MAX_SPARE; k++)
1611223Schegar		printf(" 0x%08x", meta->spare[k]);
1621223Schegar	printf("\n");
1631223Schegar	printf("disks              ");
1641223Schegar	for (k = 0; k < JMICRON_MAX_DISKS; k++)
1651695Stwisti		printf(" 0x%08x", meta->disks[k]);
1661695Stwisti	printf("\n");
1671120Schegar	printf("=================================================\n");
1681961Salanb}
1691961Salanb
1701961Salanbstatic struct jmicron_raid_conf *
1711961Salanbjmicron_meta_copy(struct jmicron_raid_conf *meta)
1721961Salanb{
1731961Salanb	struct jmicron_raid_conf *nmeta;
1741961Salanb
1751961Salanb	nmeta = malloc(sizeof(*meta), M_MD_JMICRON, M_WAITOK);
1761961Salanb	memcpy(nmeta, meta, sizeof(*meta));
1771961Salanb	return (nmeta);
1781961Salanb}
1791961Salanb
1801961Salanbstatic int
1811961Salanbjmicron_meta_total_disks(struct jmicron_raid_conf *meta)
1821961Salanb{
1831961Salanb	int pos;
1841961Salanb
185607SN/A	for (pos = 0; pos < JMICRON_MAX_DISKS; pos++) {
1861120Schegar		if (meta->disks[pos] == 0)
1871120Schegar			break;
1881961Salanb	}
1891120Schegar	return (pos);
190492SN/A}
1911120Schegar
1921120Schegarstatic int
1931790Serikjjmicron_meta_total_spare(struct jmicron_raid_conf *meta)
1941790Serikj{
1951120Schegar	int pos, n;
1961120Schegar
1971120Schegar	n = 0;
1981120Schegar	for (pos = 0; pos < JMICRON_MAX_SPARE; pos++) {
1991120Schegar		if (meta->spare[pos] != 0)
2001120Schegar			n++;
2011120Schegar	}
2021120Schegar	return (n);
2031790Serikj}
2041790Serikj
205492SN/A/*
2061120Schegar * Generate fake Configuration ID based on disk IDs.
2071120Schegar * Note: it will change after each disk set change.
2081120Schegar */
2091120Schegarstatic uint32_t
2101223Schegarjmicron_meta_config_id(struct jmicron_raid_conf *meta)
2111223Schegar{
2121223Schegar	int pos;
2131223Schegar	uint32_t config_id;
2141223Schegar
2151120Schegar	config_id = 0;
2161120Schegar	for (pos = 0; pos < JMICRON_MAX_DISKS; pos++)
2171120Schegar		config_id += meta->disks[pos] << pos;
2181120Schegar	return (config_id);
2191120Schegar}
2201223Schegar
2211223Schegarstatic void
2221223Schegarjmicron_meta_get_name(struct jmicron_raid_conf *meta, char *buf)
2231223Schegar{
2241223Schegar	int i;
2251223Schegar
226492SN/A	strncpy(buf, meta->name, 16);
2271223Schegar	buf[16] = 0;
228492SN/A	for (i = 15; i >= 0; i--) {
2291120Schegar		if (buf[i] > 0x20)
2301120Schegar			break;
2311223Schegar		buf[i] = 0;
2321223Schegar	}
2331223Schegar}
2341223Schegar
2351223Schegarstatic void
2361223Schegarjmicron_meta_put_name(struct jmicron_raid_conf *meta, char *buf)
2371120Schegar{
2381120Schegar
2391120Schegar	memset(meta->name, 0x20, 16);
2401120Schegar	memcpy(meta->name, buf, MIN(strlen(buf), 16));
2411120Schegar}
242492SN/A
2432378Serikjstatic int
2442378Serikjjmicron_meta_find_disk(struct jmicron_raid_conf *meta, uint32_t id)
2452378Serikj{
2462378Serikj	int pos;
2472378Serikj
2482378Serikj	id &= JMICRON_DISK_MASK;
2492378Serikj	for (pos = 0; pos < JMICRON_MAX_DISKS; pos++) {
2502378Serikj		if ((meta->disks[pos] & JMICRON_DISK_MASK) == id)
2512378Serikj			return (pos);
2522378Serikj	}
2532378Serikj	for (pos = 0; pos < JMICRON_MAX_SPARE; pos++) {
2542378Serikj		if ((meta->spare[pos] & JMICRON_DISK_MASK) == id)
2552378Serikj			return (-3);
2562378Serikj	}
2572378Serikj	return (-1);
2582378Serikj}
2592378Serikj
2602378Serikjstatic struct jmicron_raid_conf *
2612378Serikjjmicron_meta_read(struct g_consumer *cp)
2622378Serikj{
2632378Serikj	struct g_provider *pp;
2642378Serikj	struct jmicron_raid_conf *meta;
2652378Serikj	char *buf;
266492SN/A	int error, i;
2672024Serikj	uint16_t checksum, *ptr;
2682072Serikj
2692024Serikj	pp = cp->provider;
2702378Serikj
2712378Serikj	/* Read the anchor sector. */
272643SN/A	buf = g_read_data(cp,
2731120Schegar	    pp->mediasize - pp->sectorsize, pp->sectorsize, &error);
2741120Schegar	if (buf == NULL) {
275492SN/A		G_RAID_DEBUG(1, "Cannot read metadata from %s (error=%d).",
2761550Serikj		    pp->name, error);
2771120Schegar		return (NULL);
278492SN/A	}
2791550Serikj	meta = (struct jmicron_raid_conf *)buf;
2801120Schegar
281492SN/A	/* Check if this is an JMicron RAID struct */
2821550Serikj	if (strncmp(meta->signature, JMICRON_MAGIC, strlen(JMICRON_MAGIC))) {
283492SN/A		G_RAID_DEBUG(1, "JMicron signature check failed on %s", pp->name);
2841120Schegar		g_free(buf);
2851961Salanb		return (NULL);
2861961Salanb	}
2871961Salanb	meta = malloc(sizeof(*meta), M_MD_JMICRON, M_WAITOK);
2881961Salanb	memcpy(meta, buf, min(sizeof(*meta), pp->sectorsize));
2891961Salanb	g_free(buf);
2901961Salanb
2911961Salanb	/* Check metadata checksum. */
2921961Salanb	for (checksum = 0, ptr = (uint16_t *)meta, i = 0; i < 64; i++)
2931961Salanb		checksum += *ptr++;
2941961Salanb	if (checksum != 0) {
2951961Salanb		G_RAID_DEBUG(1, "JMicron checksum check failed on %s", pp->name);
2961961Salanb		free(meta, M_MD_JMICRON);
2971961Salanb		return (NULL);
2981961Salanb	}
2991961Salanb
3001961Salanb	return (meta);
3011961Salanb}
3021961Salanb
3031961Salanbstatic int
3041961Salanbjmicron_meta_write(struct g_consumer *cp, struct jmicron_raid_conf *meta)
3051961Salanb{
3061961Salanb	struct g_provider *pp;
3071961Salanb	char *buf;
3081961Salanb	int error, i;
3091961Salanb	uint16_t checksum, *ptr;
310492SN/A
3112342Sihse	pp = cp->provider;
3122342Sihse
3132119Serikj	/* Recalculate checksum for case if metadata were changed. */
3142342Sihse	meta->checksum = 0;
3152342Sihse	for (checksum = 0, ptr = (uint16_t *)meta, i = 0; i < 64; i++)
316492SN/A		checksum += *ptr++;
3171317Sihse	meta->checksum -= checksum;
3181120Schegar
3192092Serikj	/* Create and fill buffer. */
3202092Serikj	buf = malloc(pp->sectorsize, M_MD_JMICRON, M_WAITOK | M_ZERO);
3212092Serikj	memcpy(buf, meta, sizeof(*meta));
3222092Serikj
3232092Serikj	error = g_write_data(cp,
3242092Serikj	    pp->mediasize - pp->sectorsize, buf, pp->sectorsize);
3252092Serikj	if (error != 0) {
3261223Schegar		G_RAID_DEBUG(1, "Cannot write metadata to %s (error=%d).",
3271223Schegar		    pp->name, error);
3281223Schegar	}
3291223Schegar
3301223Schegar	free(buf, M_MD_JMICRON);
3311223Schegar	return (error);
3321223Schegar}
3331223Schegar
3341223Schegarstatic int
3351223Schegarjmicron_meta_erase(struct g_consumer *cp)
3362264Serikj{
3372264Serikj	struct g_provider *pp;
3382264Serikj	char *buf;
3392264Serikj	int error;
3402264Serikj
3412264Serikj	pp = cp->provider;
3422264Serikj	buf = malloc(pp->sectorsize, M_MD_JMICRON, M_WAITOK | M_ZERO);
3432264Serikj	error = g_write_data(cp,
3441223Schegar	    pp->mediasize - pp->sectorsize, buf, pp->sectorsize);
3451223Schegar	if (error != 0) {
3461223Schegar		G_RAID_DEBUG(1, "Cannot erase metadata on %s (error=%d).",
3471223Schegar		    pp->name, error);
3481550Serikj	}
3491223Schegar	free(buf, M_MD_JMICRON);
3501223Schegar	return (error);
3512352Serikj}
3522352Serikj
3532352Serikjstatic struct g_raid_disk *
3542261Serikjg_raid_md_jmicron_get_disk(struct g_raid_softc *sc, int id)
3552261Serikj{
3562261Serikj	struct g_raid_disk	*disk;
3572342Sihse	struct g_raid_md_jmicron_perdisk *pd;
3582264Serikj
3592264Serikj	TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
3602352Serikj		pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
3611120Schegar		if (pd->pd_disk_pos == id)
3621120Schegar			break;
3631120Schegar	}
3641120Schegar	return (disk);
3651120Schegar}
3662301Sihse
3671120Schegarstatic int
3682301Sihseg_raid_md_jmicron_supported(int level, int qual, int disks, int force)
3692301Sihse{
3701120Schegar
3712301Sihse	if (disks > 8)
3722301Sihse		return (0);
3732016Sneugens	switch (level) {
3742301Sihse	case G_RAID_VOLUME_RL_RAID0:
3751120Schegar		if (disks < 1)
3761120Schegar			return (0);
3771961Salanb		if (!force && (disks < 2 || disks > 6))
3781961Salanb			return (0);
3792052Sredestad		break;
3801961Salanb	case G_RAID_VOLUME_RL_RAID1:
3812052Sredestad		if (disks < 1)
3822052Sredestad			return (0);
3831961Salanb		if (!force && (disks != 2))
3841961Salanb			return (0);
3851961Salanb		break;
3861961Salanb	case G_RAID_VOLUME_RL_RAID1E:
3871961Salanb		if (disks < 2)
3882052Sredestad			return (0);
3891961Salanb		if (!force && (disks != 4))
3901961Salanb			return (0);
3911961Salanb		break;
3921961Salanb	case G_RAID_VOLUME_RL_SINGLE:
3931961Salanb		if (disks != 1)
3941961Salanb			return (0);
3952052Sredestad		if (!force)
3962052Sredestad			return (0);
3972052Sredestad		break;
3982279Serikj	case G_RAID_VOLUME_RL_CONCAT:
3992052Sredestad		if (disks < 2)
4002052Sredestad			return (0);
4012317Serikj		break;
4022317Serikj	case G_RAID_VOLUME_RL_RAID5:
4032317Serikj		if (disks < 3)
4042317Serikj			return (0);
4052317Serikj		if (qual != G_RAID_VOLUME_RLQ_R5LA)
4062317Serikj			return (0);
4072317Serikj		if (!force)
4082317Serikj			return (0);
4092317Serikj		break;
4102317Serikj	default:
4112317Serikj		return (0);
4122317Serikj	}
4132317Serikj	if (level != G_RAID_VOLUME_RL_RAID5 && qual != G_RAID_VOLUME_RLQ_NONE)
4142317Serikj		return (0);
4152052Sredestad	return (1);
4162052Sredestad}
4172052Sredestad
4182096Serikjstatic int
4192317Serikjg_raid_md_jmicron_start_disk(struct g_raid_disk *disk)
4202317Serikj{
4212096Serikj	struct g_raid_softc *sc;
4222052Sredestad	struct g_raid_subdisk *sd, *tmpsd;
4232317Serikj	struct g_raid_disk *olddisk, *tmpdisk;
4241961Salanb	struct g_raid_md_object *md;
4251961Salanb	struct g_raid_md_jmicron_object *mdi;
4261345Sihse	struct g_raid_md_jmicron_perdisk *pd, *oldpd;
4271345Sihse	struct jmicron_raid_conf *meta;
4281345Sihse	int disk_pos, resurrection = 0;
4291345Sihse
4301345Sihse	sc = disk->d_softc;
4311345Sihse	md = sc->sc_md;
4321345Sihse	mdi = (struct g_raid_md_jmicron_object *)md;
4331345Sihse	meta = mdi->mdio_meta;
4341345Sihse	pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
4351345Sihse	olddisk = NULL;
4361345Sihse
4371345Sihse	/* Find disk position in metadata by it's serial. */
4381345Sihse	if (pd->pd_meta != NULL)
4391345Sihse		disk_pos = jmicron_meta_find_disk(meta, pd->pd_disk_id);
4401120Schegar	else
4411345Sihse		disk_pos = -1;
4421345Sihse	if (disk_pos < 0) {
4431345Sihse		G_RAID_DEBUG1(1, sc, "Unknown, probably new or stale disk");
4441345Sihse		/* If we are in the start process, that's all for now. */
4451345Sihse		if (!mdi->mdio_started)
4461345Sihse			goto nofit;
4471345Sihse		/*
4481345Sihse		 * If we have already started - try to get use of the disk.
4492079Siignatyev		 * Try to replace OFFLINE disks first, then FAILED.
4502079Siignatyev		 */
4512079Siignatyev		TAILQ_FOREACH(tmpdisk, &sc->sc_disks, d_next) {
4522079Siignatyev			if (tmpdisk->d_state != G_RAID_DISK_S_OFFLINE &&
4532079Siignatyev			    tmpdisk->d_state != G_RAID_DISK_S_FAILED)
4541641Sihse				continue;
4551641Sihse			/* Make sure this disk is big enough. */
4561641Sihse			TAILQ_FOREACH(sd, &tmpdisk->d_subdisks, sd_next) {
4572017Serikj				if (sd->sd_offset + sd->sd_size + 512 >
4582017Serikj				    pd->pd_disk_size) {
4592017Serikj					G_RAID_DEBUG1(1, sc,
4602013Serikj					    "Disk too small (%ju < %ju)",
4612013Serikj					    pd->pd_disk_size,
4622013Serikj					    sd->sd_offset + sd->sd_size + 512);
4632017Serikj					break;
4642017Serikj				}
4652013Serikj			}
4662013Serikj			if (sd != NULL)
4672013Serikj				continue;
4682017Serikj			if (tmpdisk->d_state == G_RAID_DISK_S_OFFLINE) {
4692017Serikj				olddisk = tmpdisk;
4702013Serikj				break;
4712013Serikj			} else if (olddisk == NULL)
4722017Serikj				olddisk = tmpdisk;
4732013Serikj		}
4741345Sihse		if (olddisk == NULL) {
4751345Sihsenofit:
4762013Serikj			if (disk_pos == -3 || pd->pd_disk_pos == -3) {
4772079Siignatyev				g_raid_change_disk_state(disk,
4781345Sihse				    G_RAID_DISK_S_SPARE);
4791345Sihse				return (1);
4801345Sihse			} else {
4811345Sihse				g_raid_change_disk_state(disk,
4821345Sihse				    G_RAID_DISK_S_STALE);
4831120Schegar				return (0);
4842086Sehelin			}
4851345Sihse		}
4861739Sehelin		oldpd = (struct g_raid_md_jmicron_perdisk *)olddisk->d_md_data;
4872086Sehelin		disk_pos = oldpd->pd_disk_pos;
4881739Sehelin		resurrection = 1;
4891345Sihse	}
4902086Sehelin
4911345Sihse	if (olddisk == NULL) {
4921738Sehelin		/* Find placeholder by position. */
4932086Sehelin		olddisk = g_raid_md_jmicron_get_disk(sc, disk_pos);
4942086Sehelin		if (olddisk == NULL)
4952086Sehelin			panic("No disk at position %d!", disk_pos);
4962086Sehelin		if (olddisk->d_state != G_RAID_DISK_S_OFFLINE) {
4971738Sehelin			G_RAID_DEBUG1(1, sc, "More than one disk for pos %d",
4981345Sihse			    disk_pos);
4992086Sehelin			g_raid_change_disk_state(disk, G_RAID_DISK_S_STALE);
5001120Schegar			return (0);
5011120Schegar		}
5021120Schegar		oldpd = (struct g_raid_md_jmicron_perdisk *)olddisk->d_md_data;
5031120Schegar	}
5041739Sehelin
5052086Sehelin	/* Replace failed disk or placeholder with new disk. */
5061120Schegar	TAILQ_FOREACH_SAFE(sd, &olddisk->d_subdisks, sd_next, tmpsd) {
5071120Schegar		TAILQ_REMOVE(&olddisk->d_subdisks, sd, sd_next);
5082084Serikj		TAILQ_INSERT_TAIL(&disk->d_subdisks, sd, sd_next);
5092084Serikj		sd->sd_disk = disk;
5102084Serikj	}
5112084Serikj	oldpd->pd_disk_pos = -2;
5122084Serikj	pd->pd_disk_pos = disk_pos;
5132084Serikj	/* Update global metadata just in case. */
5142084Serikj	meta->disks[disk_pos] = pd->pd_disk_id;
5152084Serikj
5162084Serikj	/* If it was placeholder -- destroy it. */
5172084Serikj	if (olddisk->d_state == G_RAID_DISK_S_OFFLINE) {
5182084Serikj		g_raid_destroy_disk(olddisk);
5192084Serikj	} else {
5202084Serikj		/* Otherwise, make it STALE_FAILED. */
5212084Serikj		g_raid_change_disk_state(olddisk, G_RAID_DISK_S_STALE_FAILED);
5221120Schegar	}
5231120Schegar
5241120Schegar	/* Welcome the new disk. */
5251120Schegar	g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE);
5261120Schegar	TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) {
5271120Schegar
5281120Schegar		/*
5291120Schegar		 * Different disks may have different sizes/offsets,
5301120Schegar		 * especially in concat mode. Update.
5311236Sihse		 */
5321120Schegar		if (!resurrection) {
5331236Sihse			sd->sd_offset =
5341120Schegar			    (off_t)pd->pd_meta->offset * 16 * 512; //ZZZ
5351120Schegar			sd->sd_size =
5361120Schegar			    (((off_t)pd->pd_meta->disk_sectors_high << 16) +
5371120Schegar			      pd->pd_meta->disk_sectors_low) * 512;
5381120Schegar		}
5391120Schegar
5401120Schegar		if (resurrection) {
5411236Sihse			/* Stale disk, almost same as new. */
5421236Sihse			g_raid_change_subdisk_state(sd,
5431120Schegar			    G_RAID_SUBDISK_S_NEW);
5441236Sihse		} else if ((meta->flags & JMICRON_F_BADSEC) != 0 &&
5451120Schegar		    (pd->pd_meta->flags & JMICRON_F_BADSEC) == 0) {
5461120Schegar			/* Cold-inserted or rebuilding disk. */
5471120Schegar			g_raid_change_subdisk_state(sd,
5481223Schegar			    G_RAID_SUBDISK_S_NEW);
5491223Schegar		} else if (pd->pd_meta->flags & JMICRON_F_UNSYNC) {
5501120Schegar			/* Dirty or resyncing disk.. */
5511120Schegar			g_raid_change_subdisk_state(sd,
5521600Snaoto			    G_RAID_SUBDISK_S_STALE);
5531120Schegar		} else {
5542399Skvn			/* Up to date disk. */
5552399Skvn			g_raid_change_subdisk_state(sd,
5562261Serikj			    G_RAID_SUBDISK_S_ACTIVE);
5572261Serikj		}
5581120Schegar		g_raid_event_send(sd, G_RAID_SUBDISK_E_NEW,
5591120Schegar		    G_RAID_EVENT_SUBDISK);
5602399Skvn	}
5611695Stwisti
5621223Schegar	/* Update status of our need for spare. */
5631120Schegar	if (mdi->mdio_started) {
5641961Salanb		mdi->mdio_incomplete =
5651961Salanb		    (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) <
5661223Schegar		     mdi->mdio_total_disks);
5671120Schegar	}
5681120Schegar
5691120Schegar	return (resurrection);
5701659Serikj}
5711120Schegar
5721550Serikjstatic void
5731550Serikjg_disk_md_jmicron_retaste(void *arg, int pending)
5742378Serikj{
5752378Serikj
5762378Serikj	G_RAID_DEBUG(1, "Array is not complete, trying to retaste.");
5772378Serikj	g_retaste(&g_raid_class);
5782378Serikj	free(arg, M_MD_JMICRON);
5792378Serikj}
5802024Serikj
5812024Serikjstatic void
5821735Sbobvg_raid_md_jmicron_refill(struct g_raid_softc *sc)
5831735Sbobv{
5842378Serikj	struct g_raid_md_object *md;
5852378Serikj	struct g_raid_md_jmicron_object *mdi;
5861120Schegar	struct g_raid_disk *disk;
5871120Schegar	struct task *task;
5881120Schegar	int update, na;
5891735Sbobv
5901735Sbobv	md = sc->sc_md;
5911735Sbobv	mdi = (struct g_raid_md_jmicron_object *)md;
5921735Sbobv	update = 0;
5931130Serikj	do {
5941130Serikj		/* Make sure we miss anything. */
5951130Serikj		na = g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE);
5962284Serikj		if (na == mdi->mdio_total_disks)
5971120Schegar			break;
5981120Schegar
5991120Schegar		G_RAID_DEBUG1(1, md->mdo_softc,
6001120Schegar		    "Array is not complete (%d of %d), "
6011120Schegar		    "trying to refill.", na, mdi->mdio_total_disks);
6021120Schegar
6031120Schegar		/* Try to get use some of STALE disks. */
6041120Schegar		TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
6051120Schegar			if (disk->d_state == G_RAID_DISK_S_STALE) {
6061120Schegar				update += g_raid_md_jmicron_start_disk(disk);
6071120Schegar				if (disk->d_state == G_RAID_DISK_S_ACTIVE)
6081120Schegar					break;
6091120Schegar			}
6102052Sredestad		}
6112052Sredestad		if (disk != NULL)
6122052Sredestad			continue;
6131961Salanb
6142052Sredestad		/* Try to get use some of SPARE disks. */
6151961Salanb		TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
6161120Schegar			if (disk->d_state == G_RAID_DISK_S_SPARE) {
6171120Schegar				update += g_raid_md_jmicron_start_disk(disk);
6181223Schegar				if (disk->d_state == G_RAID_DISK_S_ACTIVE)
6191120Schegar					break;
6201120Schegar			}
6211433Sptbrunet		}
6221433Sptbrunet	} while (disk != NULL);
6231433Sptbrunet
6241236Sihse	/* Write new metadata if we changed something. */
6251223Schegar	if (update)
6261223Schegar		g_raid_md_write_jmicron(md, NULL, NULL, NULL);
6271223Schegar
6281223Schegar	/* Update status of our need for spare. */
6291178Serikj	mdi->mdio_incomplete = (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) <
6301178Serikj	    mdi->mdio_total_disks);
6311223Schegar
6321178Serikj	/* Request retaste hoping to find spare. */
6331882Samurillo	if (mdi->mdio_incomplete) {
6341882Samurillo		task = malloc(sizeof(struct task),
6351929Sihse		    M_MD_JMICRON, M_WAITOK | M_ZERO);
6361882Samurillo		TASK_INIT(task, 0, g_disk_md_jmicron_retaste, task);
6372399Skvn		taskqueue_enqueue(taskqueue_swi, task);
6382399Skvn	}
6392399Skvn}
6402399Skvn
6412399Skvnstatic void
6422399Skvng_raid_md_jmicron_start(struct g_raid_softc *sc)
6432399Skvn{
6442399Skvn	struct g_raid_md_object *md;
6451120Schegar	struct g_raid_md_jmicron_object *mdi;
6461120Schegar	struct g_raid_md_jmicron_perdisk *pd;
6471120Schegar	struct jmicron_raid_conf *meta;
6481515Smchung	struct g_raid_volume *vol;
6491147Smchung	struct g_raid_subdisk *sd;
6502345Smchung	struct g_raid_disk *disk;
6512345Smchung	off_t size;
6522052Sredestad	int j, disk_pos;
6532052Sredestad	char buf[17];
6542052Sredestad
6552345Smchung	md = sc->sc_md;
6562087Serikj	mdi = (struct g_raid_md_jmicron_object *)md;
6572052Sredestad	meta = mdi->mdio_meta;
6581961Salanb
6592378Serikj	/* Create volumes and subdisks. */
6602378Serikj	jmicron_meta_get_name(meta, buf);
6612378Serikj	vol = g_raid_create_volume(sc, buf, -1);
6621961Salanb	size = ((off_t)meta->disk_sectors_high << 16) + meta->disk_sectors_low;
6632052Sredestad	size *= 512; //ZZZ
6642052Sredestad	vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_NONE;
6652052Sredestad	if (meta->type == JMICRON_T_RAID0) {
6662317Serikj		vol->v_raid_level = G_RAID_VOLUME_RL_RAID0;
6672052Sredestad		vol->v_mediasize = size * mdi->mdio_total_disks;
6682317Serikj	} else if (meta->type == JMICRON_T_RAID1) {
6692317Serikj		vol->v_raid_level = G_RAID_VOLUME_RL_RAID1;
6702317Serikj		vol->v_mediasize = size;
6712317Serikj	} else if (meta->type == JMICRON_T_RAID01) {
6722317Serikj		vol->v_raid_level = G_RAID_VOLUME_RL_RAID1E;
6732317Serikj		vol->v_mediasize = size * mdi->mdio_total_disks / 2;
6742317Serikj	} else if (meta->type == JMICRON_T_CONCAT) {
6751961Salanb		if (mdi->mdio_total_disks == 1)
6762279Serikj			vol->v_raid_level = G_RAID_VOLUME_RL_SINGLE;
6772279Serikj		else
6782279Serikj			vol->v_raid_level = G_RAID_VOLUME_RL_CONCAT;
6792279Serikj		vol->v_mediasize = 0;
6802279Serikj	} else if (meta->type == JMICRON_T_RAID5) {
6812279Serikj		vol->v_raid_level = G_RAID_VOLUME_RL_RAID5;
6822279Serikj		vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_R5LA;
6832279Serikj		vol->v_mediasize = size * (mdi->mdio_total_disks - 1);
6842279Serikj	} else {
6852279Serikj		vol->v_raid_level = G_RAID_VOLUME_RL_UNKNOWN;
6862279Serikj		vol->v_mediasize = 0;
6872279Serikj	}
6882279Serikj	vol->v_strip_size = 1024 << meta->stripe_shift; //ZZZ
6892279Serikj	vol->v_disks_count = mdi->mdio_total_disks;
6901961Salanb	vol->v_sectorsize = 512; //ZZZ
6912279Serikj	for (j = 0; j < vol->v_disks_count; j++) {
6922052Sredestad		sd = &vol->v_subdisks[j];
6932052Sredestad		sd->sd_offset = (off_t)meta->offset * 16 * 512; //ZZZ
6942261Serikj		sd->sd_size = size;
6952279Serikj	}
6962279Serikj	g_raid_start_volume(vol);
6972317Serikj
6982052Sredestad	/* Create disk placeholders to store data for later writing. */
6992279Serikj	for (disk_pos = 0; disk_pos < mdi->mdio_total_disks; disk_pos++) {
7002279Serikj		pd = malloc(sizeof(*pd), M_MD_JMICRON, M_WAITOK | M_ZERO);
7012279Serikj		pd->pd_disk_pos = disk_pos;
7022317Serikj		pd->pd_disk_id = meta->disks[disk_pos];
7032317Serikj		disk = g_raid_create_disk(sc);
7041961Salanb		disk->d_md_data = (void *)pd;
7051961Salanb		disk->d_state = G_RAID_DISK_S_OFFLINE;
7061223Schegar		sd = &vol->v_subdisks[disk_pos];
7071223Schegar		sd->sd_disk = disk;
7081120Schegar		TAILQ_INSERT_TAIL(&disk->d_subdisks, sd, sd_next);
7091223Schegar	}
7101223Schegar
7111961Salanb	/* Make all disks found till the moment take their places. */
7121120Schegar	do {
7132096Serikj		TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
7142096Serikj			if (disk->d_state == G_RAID_DISK_S_NONE) {
7152096Serikj				g_raid_md_jmicron_start_disk(disk);
7162317Serikj				break;
7172096Serikj			}
7182096Serikj		}
7192096Serikj	} while (disk != NULL);
7202096Serikj
7212317Serikj	mdi->mdio_started = 1;
7222096Serikj	G_RAID_DEBUG1(0, sc, "Array started.");
7232317Serikj	g_raid_md_write_jmicron(md, NULL, NULL, NULL);
7242096Serikj
7252317Serikj	/* Pickup any STALE/SPARE disks to refill array if needed. */
7262317Serikj	g_raid_md_jmicron_refill(sc);
7272052Sredestad
7282052Sredestad	g_raid_event_send(vol, G_RAID_VOLUME_E_START, G_RAID_EVENT_VOLUME);
7292352Serikj
7301120Schegar	callout_stop(&mdi->mdio_start_co);
7312352Serikj	G_RAID_DEBUG1(1, sc, "root_mount_rel %p", mdi->mdio_rootmount);
7322352Serikj	root_mount_rel(mdi->mdio_rootmount);
7332352Serikj	mdi->mdio_rootmount = NULL;
7342352Serikj}
7351120Schegar
7362264Serikjstatic void
7371120Schegarg_raid_md_jmicron_new_disk(struct g_raid_disk *disk)
7382279Serikj{
7392279Serikj	struct g_raid_softc *sc;
7402279Serikj	struct g_raid_md_object *md;
7412279Serikj	struct g_raid_md_jmicron_object *mdi;
7422279Serikj	struct jmicron_raid_conf *pdmeta;
7432261Serikj	struct g_raid_md_jmicron_perdisk *pd;
7442264Serikj
7451120Schegar	sc = disk->d_softc;
7461961Salanb	md = sc->sc_md;
7471120Schegar	mdi = (struct g_raid_md_jmicron_object *)md;
7482309Serikj	pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
7492378Serikj	pdmeta = pd->pd_meta;
7501120Schegar
7512301Sihse	if (mdi->mdio_started) {
7522034Serikj		if (g_raid_md_jmicron_start_disk(disk))
7532264Serikj			g_raid_md_write_jmicron(md, NULL, NULL, NULL);
7541120Schegar	} else {
7552052Sredestad		/*
7562052Sredestad		 * If we haven't started yet - update common metadata
7571961Salanb		 * to get subdisks details, avoiding data from spare disks.
7582052Sredestad		 */
7592052Sredestad		if (mdi->mdio_meta == NULL ||
7602317Serikj		    jmicron_meta_find_disk(mdi->mdio_meta,
7611120Schegar		     mdi->mdio_meta->disk_id) == -3) {
7621299Serikj			if (mdi->mdio_meta != NULL)
7631299Serikj				free(mdi->mdio_meta, M_MD_JMICRON);
7642284Serikj			mdi->mdio_meta = jmicron_meta_copy(pdmeta);
7651724Serikj			mdi->mdio_total_disks = jmicron_meta_total_disks(pdmeta);
7662013Serikj		}
7672013Serikj		mdi->mdio_meta->flags |= pdmeta->flags & JMICRON_F_BADSEC;
7682013Serikj
7692013Serikj		mdi->mdio_disks_present++;
7702013Serikj		G_RAID_DEBUG1(1, sc, "Matching disk (%d of %d+%d up)",
7712013Serikj		    mdi->mdio_disks_present,
7722378Serikj		    mdi->mdio_total_disks,
7732378Serikj		    jmicron_meta_total_spare(mdi->mdio_meta));
7741348Serikj
7751348Serikj		/* If we collected all needed disks - start array. */
7761348Serikj		if (mdi->mdio_disks_present == mdi->mdio_total_disks +
7771345Sihse		    jmicron_meta_total_spare(mdi->mdio_meta))
7781345Sihse			g_raid_md_jmicron_start(sc);
7791345Sihse	}
7801345Sihse}
7812079Siignatyev
7822079Siignatyevstatic void
7831738Seheling_raid_jmicron_go(void *arg)
7841738Sehelin{
7852264Serikj	struct g_raid_softc *sc;
7861739Sehelin	struct g_raid_md_object *md;
7872086Sehelin	struct g_raid_md_jmicron_object *mdi;
7882086Sehelin
7891750Serikj	sc = arg;
7901750Serikj	md = sc->sc_md;
7912084Serikj	mdi = (struct g_raid_md_jmicron_object *)md;
7922084Serikj	if (!mdi->mdio_started) {
7932084Serikj		G_RAID_DEBUG1(0, sc, "Force array start due to timeout.");
7942084Serikj		g_raid_event_send(sc, G_RAID_NODE_E_START, 0);
7952084Serikj	}
7962084Serikj}
7972261Serikj
7981961Salanbstatic int
7991120Schegarg_raid_md_create_jmicron(struct g_raid_md_object *md, struct g_class *mp,
8001120Schegar    struct g_geom **gp)
8011120Schegar{
8021120Schegar	struct g_raid_softc *sc;
8031120Schegar	struct g_raid_md_jmicron_object *mdi;
8041659Serikj	char name[16];
8052399Skvn
8061223Schegar	mdi = (struct g_raid_md_jmicron_object *)md;
8072378Serikj	mdi->mdio_config_id = arc4random();
8082378Serikj	snprintf(name, sizeof(name), "JMicron-%08x", mdi->mdio_config_id);
8092378Serikj	sc = g_raid_create_node(mp, name, md);
8102378Serikj	if (sc == NULL)
8112378Serikj		return (G_RAID_MD_TASTE_FAIL);
8122378Serikj	md->mdo_softc = sc;
8132378Serikj	*gp = sc->sc_geom;
8142378Serikj	return (G_RAID_MD_TASTE_NEW);
8152378Serikj}
8162378Serikj
8171120Schegarstatic int
8181120Schegarg_raid_md_taste_jmicron(struct g_raid_md_object *md, struct g_class *mp,
8191120Schegar                              struct g_consumer *cp, struct g_geom **gp)
8201120Schegar{
8211961Salanb	struct g_consumer *rcp;
8221120Schegar	struct g_provider *pp;
8231120Schegar	struct g_raid_md_jmicron_object *mdi, *mdi1;
8241120Schegar	struct g_raid_softc *sc;
8251120Schegar	struct g_raid_disk *disk;
8261120Schegar	struct jmicron_raid_conf *meta;
8271223Schegar	struct g_raid_md_jmicron_perdisk *pd;
8281120Schegar	struct g_geom *geom;
8291120Schegar	int disk_pos, result, spare, len;
8301120Schegar	char name[16];
8311961Salanb	uint16_t vendor;
8321961Salanb
8331223Schegar	G_RAID_DEBUG(1, "Tasting JMicron on %s", cp->provider->name);
8341223Schegar	mdi = (struct g_raid_md_jmicron_object *)md;
8351223Schegar	pp = cp->provider;
8361120Schegar
8371120Schegar	/* Read metadata from device. */
8381790Serikj	meta = NULL;
8391120Schegar	g_topology_unlock();
8401120Schegar	vendor = 0xffff;
8411120Schegar	len = sizeof(vendor);
8421120Schegar	if (pp->geom->rank == 1)
8431223Schegar		g_io_getattr("GEOM::hba_vendor", cp, &len, &vendor);
8441120Schegar	meta = jmicron_meta_read(cp);
8451961Salanb	g_topology_lock();
8462378Serikj	if (meta == NULL) {
8472378Serikj		if (g_raid_aggressive_spare) {
8482378Serikj			if (vendor == 0x197b) {
8492378Serikj				G_RAID_DEBUG(1,
8501550Serikj				    "No JMicron metadata, forcing spare.");
8511550Serikj				spare = 2;
8521550Serikj				goto search;
8531550Serikj			} else {
8541317Sihse				G_RAID_DEBUG(1,
8552261Serikj				    "JMicron vendor mismatch 0x%04x != 0x197b",
8562352Serikj				    vendor);
8572279Serikj			}
8582279Serikj		}
8592279Serikj		return (G_RAID_MD_TASTE_FAIL);
8602279Serikj	}
8612279Serikj
8621317Sihse	/* Check this disk position in obtained metadata. */
8632052Sredestad	disk_pos = jmicron_meta_find_disk(meta, meta->disk_id);
8641961Salanb	if (disk_pos == -1) {
8651550Serikj		G_RAID_DEBUG(1, "JMicron disk_id %08x not found",
8661550Serikj		    meta->disk_id);
8671345Sihse		goto fail1;
8681317Sihse	}
8691120Schegar
8701317Sihse	/* Metadata valid. Print it. */
8711317Sihse	g_raid_md_jmicron_print(meta);
8722264Serikj	G_RAID_DEBUG(1, "JMicron disk position %d", disk_pos);
8732264Serikj	spare = (disk_pos == -2) ? 1 : 0;
8742264Serikj
8752264Serikjsearch:
8762264Serikj	/* Search for matching node. */
8771961Salanb	sc = NULL;
8782052Sredestad	mdi1 = NULL;
8792052Sredestad	LIST_FOREACH(geom, &mp->geom, geom) {
8802052Sredestad		sc = geom->softc;
8812052Sredestad		if (sc == NULL)
8821961Salanb			continue;
8832052Sredestad		if (sc->sc_stopping != 0)
8842052Sredestad			continue;
8852052Sredestad		if (sc->sc_md->mdo_class != md->mdo_class)
8861961Salanb			continue;
8871120Schegar		mdi1 = (struct g_raid_md_jmicron_object *)sc->sc_md;
8881223Schegar		if (spare == 2) {
8891317Sihse			if (mdi1->mdio_incomplete)
8901223Schegar				break;
8911120Schegar		} else {
8921317Sihse			if (mdi1->mdio_config_id ==
8932301Sihse			    jmicron_meta_config_id(meta))
8941120Schegar				break;
8951317Sihse		}
8961345Sihse	}
8972079Siignatyev
8981275Sihse	/* Found matching node. */
8992084Serikj	if (geom != NULL) {
9001317Sihse		G_RAID_DEBUG(1, "Found matching array %s", sc->sc_name);
9011317Sihse		result = G_RAID_MD_TASTE_EXISTING;
9022084Serikj
9032084Serikj	} else if (spare) { /* Not found needy node -- left for later. */
9042084Serikj		G_RAID_DEBUG(1, "Spare is not needed at this time");
9052378Serikj		goto fail1;
9062378Serikj
9072261Serikj	} else { /* Not found matching node -- create one. */
9082261Serikj		result = G_RAID_MD_TASTE_NEW;
9092084Serikj		mdi->mdio_config_id = jmicron_meta_config_id(meta);
9102084Serikj		snprintf(name, sizeof(name), "JMicron-%08x",
9111120Schegar		    mdi->mdio_config_id);
9121120Schegar		sc = g_raid_create_node(mp, name, md);
9131120Schegar		md->mdo_softc = sc;
9141317Sihse		geom = sc->sc_geom;
9151317Sihse		callout_init(&mdi->mdio_start_co, 1);
9161317Sihse		callout_reset(&mdi->mdio_start_co, g_raid_start_timeout * hz,
9171817Serikj		    g_raid_jmicron_go, sc);
9181317Sihse		mdi->mdio_rootmount = root_mount_hold("GRAID-JMicron");
9191317Sihse		G_RAID_DEBUG1(1, sc, "root_mount_hold %p", mdi->mdio_rootmount);
9201317Sihse	}
9212084Serikj
9221317Sihse	/* There is no return after this point, so we close passed consumer. */
9231120Schegar	g_access(cp, -1, 0, 0);
9242084Serikj
9251120Schegar	rcp = g_new_consumer(geom);
9261120Schegar	rcp->flags |= G_CF_DIRECT_RECEIVE;
9271120Schegar	g_attach(rcp, pp);
9281120Schegar	if (g_access(rcp, 1, 1, 1) != 0)
9291120Schegar		; //goto fail1;
9301120Schegar
9311120Schegar	g_topology_unlock();
9321236Sihse	sx_xlock(&sc->sc_lock);
9331156Serikj
9341120Schegar	pd = malloc(sizeof(*pd), M_MD_JMICRON, M_WAITOK | M_ZERO);
9351223Schegar	pd->pd_meta = meta;
9361961Salanb	if (spare == 2) {
9371223Schegar		pd->pd_disk_pos = -3;
9381725Sihse		pd->pd_disk_id = arc4random() & JMICRON_DISK_MASK;
9391725Sihse	} else {
9401641Sihse		pd->pd_disk_pos = -1;
9411345Sihse		pd->pd_disk_id = meta->disk_id;
9422301Sihse	}
9431223Schegar	pd->pd_disk_size = pp->mediasize;
9441223Schegar	disk = g_raid_create_disk(sc);
9451223Schegar	disk->d_md_data = (void *)pd;
9461223Schegar	disk->d_consumer = rcp;
9471223Schegar	rcp->private = disk;
948492SN/A
949492SN/A	g_raid_get_disk_info(disk);
9501223Schegar
9511428Serikj	g_raid_md_jmicron_new_disk(disk);
9521120Schegar
9531120Schegar	sx_xunlock(&sc->sc_lock);
9542301Sihse	g_topology_lock();
9552301Sihse	*gp = geom;
9562301Sihse	return (result);
9571223Schegarfail1:
9581223Schegar	free(meta, M_MD_JMICRON);
9591223Schegar	return (G_RAID_MD_TASTE_FAIL);
9601725Sihse}
9611725Sihse
9621725Sihsestatic int
9631345Sihseg_raid_md_event_jmicron(struct g_raid_md_object *md,
9641345Sihse    struct g_raid_disk *disk, u_int event)
9651345Sihse{
9661223Schegar	struct g_raid_softc *sc;
9671223Schegar	struct g_raid_subdisk *sd;
9681223Schegar	struct g_raid_md_jmicron_object *mdi;
9691223Schegar	struct g_raid_md_jmicron_perdisk *pd;
9701223Schegar
9711223Schegar	sc = md->mdo_softc;
9721223Schegar	mdi = (struct g_raid_md_jmicron_object *)md;
9731223Schegar	if (disk == NULL) {
9741223Schegar		switch (event) {
9751223Schegar		case G_RAID_NODE_E_START:
9761223Schegar			if (!mdi->mdio_started)
9771223Schegar				g_raid_md_jmicron_start(sc);
9781223Schegar			return (0);
9791223Schegar		}
9801120Schegar		return (-1);
9811428Serikj	}
9821428Serikj	pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
983492SN/A	switch (event) {
9841428Serikj	case G_RAID_DISK_E_DISCONNECTED:
9851428Serikj		/* If disk was assigned, just update statuses. */
9861120Schegar		if (pd->pd_disk_pos >= 0) {
987837SN/A			g_raid_change_disk_state(disk, G_RAID_DISK_S_OFFLINE);
988837SN/A			if (disk->d_consumer) {
989837SN/A				g_raid_kill_consumer(sc, disk->d_consumer);
9901120Schegar				disk->d_consumer = NULL;
9911120Schegar			}
992837SN/A			TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) {
993837SN/A				g_raid_change_subdisk_state(sd,
9941120Schegar				    G_RAID_SUBDISK_S_NONE);
9951120Schegar				g_raid_event_send(sd, G_RAID_SUBDISK_E_DISCONNECTED,
9962301Sihse				    G_RAID_EVENT_SUBDISK);
9971725Sihse			}
9981725Sihse		} else {
9991120Schegar			/* Otherwise -- delete. */
10001120Schegar			g_raid_change_disk_state(disk, G_RAID_DISK_S_NONE);
10011120Schegar			g_raid_destroy_disk(disk);
10021120Schegar		}
1003492SN/A
10041410Sihse		/* Write updated metadata to all disks. */
10051410Sihse		g_raid_md_write_jmicron(md, NULL, NULL, NULL);
10061410Sihse
10071410Sihse		/* Check if anything left except placeholders. */
10081410Sihse		if (g_raid_ndisks(sc, -1) ==
10091410Sihse		    g_raid_ndisks(sc, G_RAID_DISK_S_OFFLINE))
10101410Sihse			g_raid_destroy_node(sc, 0);
10111410Sihse		else
10121410Sihse			g_raid_md_jmicron_refill(sc);
10131426Sihse		return (0);
10141426Sihse	}
10151426Sihse	return (-2);
10161410Sihse}
10171410Sihse
10181410Sihsestatic int
10191410Sihseg_raid_md_ctl_jmicron(struct g_raid_md_object *md,
10201410Sihse    struct gctl_req *req)
10211410Sihse{
10221426Sihse	struct g_raid_softc *sc;
10231862Serikj	struct g_raid_volume *vol;
10241426Sihse	struct g_raid_subdisk *sd;
10251426Sihse	struct g_raid_disk *disk;
10261120Schegar	struct g_raid_md_jmicron_object *mdi;
10271120Schegar	struct g_raid_md_jmicron_perdisk *pd;
10281120Schegar	struct g_consumer *cp;
10291120Schegar	struct g_provider *pp;
10301120Schegar	char arg[16];
1031492SN/A	const char *verb, *volname, *levelname, *diskname;
1032	int *nargs, *force;
1033	off_t size, sectorsize, strip;
1034	intmax_t *sizearg, *striparg;
1035	int numdisks, i, len, level, qual, update;
1036	int error;
1037
1038	sc = md->mdo_softc;
1039	mdi = (struct g_raid_md_jmicron_object *)md;
1040	verb = gctl_get_param(req, "verb", NULL);
1041	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
1042	error = 0;
1043	if (strcmp(verb, "label") == 0) {
1044
1045		if (*nargs < 4) {
1046			gctl_error(req, "Invalid number of arguments.");
1047			return (-1);
1048		}
1049		volname = gctl_get_asciiparam(req, "arg1");
1050		if (volname == NULL) {
1051			gctl_error(req, "No volume name.");
1052			return (-2);
1053		}
1054		levelname = gctl_get_asciiparam(req, "arg2");
1055		if (levelname == NULL) {
1056			gctl_error(req, "No RAID level.");
1057			return (-3);
1058		}
1059		if (strcasecmp(levelname, "RAID5") == 0)
1060			levelname = "RAID5-LA";
1061		if (g_raid_volume_str2level(levelname, &level, &qual)) {
1062			gctl_error(req, "Unknown RAID level '%s'.", levelname);
1063			return (-4);
1064		}
1065		numdisks = *nargs - 3;
1066		force = gctl_get_paraml(req, "force", sizeof(*force));
1067		if (!g_raid_md_jmicron_supported(level, qual, numdisks,
1068		    force ? *force : 0)) {
1069			gctl_error(req, "Unsupported RAID level "
1070			    "(0x%02x/0x%02x), or number of disks (%d).",
1071			    level, qual, numdisks);
1072			return (-5);
1073		}
1074
1075		/* Search for disks, connect them and probe. */
1076		size = 0x7fffffffffffffffllu;
1077		sectorsize = 0;
1078		for (i = 0; i < numdisks; i++) {
1079			snprintf(arg, sizeof(arg), "arg%d", i + 3);
1080			diskname = gctl_get_asciiparam(req, arg);
1081			if (diskname == NULL) {
1082				gctl_error(req, "No disk name (%s).", arg);
1083				error = -6;
1084				break;
1085			}
1086			if (strcmp(diskname, "NONE") == 0) {
1087				cp = NULL;
1088				pp = NULL;
1089			} else {
1090				g_topology_lock();
1091				cp = g_raid_open_consumer(sc, diskname);
1092				if (cp == NULL) {
1093					gctl_error(req, "Can't open '%s'.",
1094					    diskname);
1095					g_topology_unlock();
1096					error = -7;
1097					break;
1098				}
1099				pp = cp->provider;
1100			}
1101			pd = malloc(sizeof(*pd), M_MD_JMICRON, M_WAITOK | M_ZERO);
1102			pd->pd_disk_pos = i;
1103			pd->pd_disk_id = arc4random() & JMICRON_DISK_MASK;
1104			disk = g_raid_create_disk(sc);
1105			disk->d_md_data = (void *)pd;
1106			disk->d_consumer = cp;
1107			if (cp == NULL)
1108				continue;
1109			cp->private = disk;
1110			g_topology_unlock();
1111
1112			g_raid_get_disk_info(disk);
1113
1114			pd->pd_disk_size = pp->mediasize;
1115			if (size > pp->mediasize)
1116				size = pp->mediasize;
1117			if (sectorsize < pp->sectorsize)
1118				sectorsize = pp->sectorsize;
1119		}
1120		if (error != 0)
1121			return (error);
1122
1123		if (sectorsize <= 0) {
1124			gctl_error(req, "Can't get sector size.");
1125			return (-8);
1126		}
1127
1128		/* Reserve space for metadata. */
1129		size -= sectorsize;
1130
1131		/* Handle size argument. */
1132		len = sizeof(*sizearg);
1133		sizearg = gctl_get_param(req, "size", &len);
1134		if (sizearg != NULL && len == sizeof(*sizearg) &&
1135		    *sizearg > 0) {
1136			if (*sizearg > size) {
1137				gctl_error(req, "Size too big %lld > %lld.",
1138				    (long long)*sizearg, (long long)size);
1139				return (-9);
1140			}
1141			size = *sizearg;
1142		}
1143
1144		/* Handle strip argument. */
1145		strip = 131072;
1146		len = sizeof(*striparg);
1147		striparg = gctl_get_param(req, "strip", &len);
1148		if (striparg != NULL && len == sizeof(*striparg) &&
1149		    *striparg > 0) {
1150			if (*striparg < sectorsize) {
1151				gctl_error(req, "Strip size too small.");
1152				return (-10);
1153			}
1154			if (*striparg % sectorsize != 0) {
1155				gctl_error(req, "Incorrect strip size.");
1156				return (-11);
1157			}
1158			if (strip > 65535 * sectorsize) {
1159				gctl_error(req, "Strip size too big.");
1160				return (-12);
1161			}
1162			strip = *striparg;
1163		}
1164
1165		/* Round size down to strip or sector. */
1166		if (level == G_RAID_VOLUME_RL_RAID1)
1167			size -= (size % sectorsize);
1168		else if (level == G_RAID_VOLUME_RL_RAID1E &&
1169		    (numdisks & 1) != 0)
1170			size -= (size % (2 * strip));
1171		else
1172			size -= (size % strip);
1173		if (size <= 0) {
1174			gctl_error(req, "Size too small.");
1175			return (-13);
1176		}
1177		if (size > 0xffffffffffffllu * sectorsize) {
1178			gctl_error(req, "Size too big.");
1179			return (-14);
1180		}
1181
1182		/* We have all we need, create things: volume, ... */
1183		mdi->mdio_total_disks = numdisks;
1184		mdi->mdio_started = 1;
1185		vol = g_raid_create_volume(sc, volname, -1);
1186		vol->v_md_data = (void *)(intptr_t)0;
1187		vol->v_raid_level = level;
1188		vol->v_raid_level_qualifier = qual;
1189		vol->v_strip_size = strip;
1190		vol->v_disks_count = numdisks;
1191		if (level == G_RAID_VOLUME_RL_RAID0 ||
1192		    level == G_RAID_VOLUME_RL_CONCAT ||
1193		    level == G_RAID_VOLUME_RL_SINGLE)
1194			vol->v_mediasize = size * numdisks;
1195		else if (level == G_RAID_VOLUME_RL_RAID1)
1196			vol->v_mediasize = size;
1197		else if (level == G_RAID_VOLUME_RL_RAID5)
1198			vol->v_mediasize = size * (numdisks - 1);
1199		else { /* RAID1E */
1200			vol->v_mediasize = ((size * numdisks) / strip / 2) *
1201			    strip;
1202		}
1203		vol->v_sectorsize = sectorsize;
1204		g_raid_start_volume(vol);
1205
1206		/* , and subdisks. */
1207		TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
1208			pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
1209			sd = &vol->v_subdisks[pd->pd_disk_pos];
1210			sd->sd_disk = disk;
1211			sd->sd_offset = 0;
1212			sd->sd_size = size;
1213			TAILQ_INSERT_TAIL(&disk->d_subdisks, sd, sd_next);
1214			if (sd->sd_disk->d_consumer != NULL) {
1215				g_raid_change_disk_state(disk,
1216				    G_RAID_DISK_S_ACTIVE);
1217				g_raid_change_subdisk_state(sd,
1218				    G_RAID_SUBDISK_S_ACTIVE);
1219				g_raid_event_send(sd, G_RAID_SUBDISK_E_NEW,
1220				    G_RAID_EVENT_SUBDISK);
1221			} else {
1222				g_raid_change_disk_state(disk, G_RAID_DISK_S_OFFLINE);
1223			}
1224		}
1225
1226		/* Write metadata based on created entities. */
1227		G_RAID_DEBUG1(0, sc, "Array started.");
1228		g_raid_md_write_jmicron(md, NULL, NULL, NULL);
1229
1230		/* Pickup any STALE/SPARE disks to refill array if needed. */
1231		g_raid_md_jmicron_refill(sc);
1232
1233		g_raid_event_send(vol, G_RAID_VOLUME_E_START,
1234		    G_RAID_EVENT_VOLUME);
1235		return (0);
1236	}
1237	if (strcmp(verb, "delete") == 0) {
1238
1239		/* Check if some volume is still open. */
1240		force = gctl_get_paraml(req, "force", sizeof(*force));
1241		if (force != NULL && *force == 0 &&
1242		    g_raid_nopens(sc) != 0) {
1243			gctl_error(req, "Some volume is still open.");
1244			return (-4);
1245		}
1246
1247		TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
1248			if (disk->d_consumer)
1249				jmicron_meta_erase(disk->d_consumer);
1250		}
1251		g_raid_destroy_node(sc, 0);
1252		return (0);
1253	}
1254	if (strcmp(verb, "remove") == 0 ||
1255	    strcmp(verb, "fail") == 0) {
1256		if (*nargs < 2) {
1257			gctl_error(req, "Invalid number of arguments.");
1258			return (-1);
1259		}
1260		for (i = 1; i < *nargs; i++) {
1261			snprintf(arg, sizeof(arg), "arg%d", i);
1262			diskname = gctl_get_asciiparam(req, arg);
1263			if (diskname == NULL) {
1264				gctl_error(req, "No disk name (%s).", arg);
1265				error = -2;
1266				break;
1267			}
1268			if (strncmp(diskname, "/dev/", 5) == 0)
1269				diskname += 5;
1270
1271			TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
1272				if (disk->d_consumer != NULL &&
1273				    disk->d_consumer->provider != NULL &&
1274				    strcmp(disk->d_consumer->provider->name,
1275				     diskname) == 0)
1276					break;
1277			}
1278			if (disk == NULL) {
1279				gctl_error(req, "Disk '%s' not found.",
1280				    diskname);
1281				error = -3;
1282				break;
1283			}
1284
1285			if (strcmp(verb, "fail") == 0) {
1286				g_raid_md_fail_disk_jmicron(md, NULL, disk);
1287				continue;
1288			}
1289
1290			pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
1291
1292			/* Erase metadata on deleting disk. */
1293			jmicron_meta_erase(disk->d_consumer);
1294
1295			/* If disk was assigned, just update statuses. */
1296			if (pd->pd_disk_pos >= 0) {
1297				g_raid_change_disk_state(disk, G_RAID_DISK_S_OFFLINE);
1298				g_raid_kill_consumer(sc, disk->d_consumer);
1299				disk->d_consumer = NULL;
1300				TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) {
1301					g_raid_change_subdisk_state(sd,
1302					    G_RAID_SUBDISK_S_NONE);
1303					g_raid_event_send(sd, G_RAID_SUBDISK_E_DISCONNECTED,
1304					    G_RAID_EVENT_SUBDISK);
1305				}
1306			} else {
1307				/* Otherwise -- delete. */
1308				g_raid_change_disk_state(disk, G_RAID_DISK_S_NONE);
1309				g_raid_destroy_disk(disk);
1310			}
1311		}
1312
1313		/* Write updated metadata to remaining disks. */
1314		g_raid_md_write_jmicron(md, NULL, NULL, NULL);
1315
1316		/* Check if anything left except placeholders. */
1317		if (g_raid_ndisks(sc, -1) ==
1318		    g_raid_ndisks(sc, G_RAID_DISK_S_OFFLINE))
1319			g_raid_destroy_node(sc, 0);
1320		else
1321			g_raid_md_jmicron_refill(sc);
1322		return (error);
1323	}
1324	if (strcmp(verb, "insert") == 0) {
1325		if (*nargs < 2) {
1326			gctl_error(req, "Invalid number of arguments.");
1327			return (-1);
1328		}
1329		update = 0;
1330		for (i = 1; i < *nargs; i++) {
1331			/* Get disk name. */
1332			snprintf(arg, sizeof(arg), "arg%d", i);
1333			diskname = gctl_get_asciiparam(req, arg);
1334			if (diskname == NULL) {
1335				gctl_error(req, "No disk name (%s).", arg);
1336				error = -3;
1337				break;
1338			}
1339
1340			/* Try to find provider with specified name. */
1341			g_topology_lock();
1342			cp = g_raid_open_consumer(sc, diskname);
1343			if (cp == NULL) {
1344				gctl_error(req, "Can't open disk '%s'.",
1345				    diskname);
1346				g_topology_unlock();
1347				error = -4;
1348				break;
1349			}
1350			pp = cp->provider;
1351
1352			pd = malloc(sizeof(*pd), M_MD_JMICRON, M_WAITOK | M_ZERO);
1353			pd->pd_disk_pos = -3;
1354			pd->pd_disk_id = arc4random() & JMICRON_DISK_MASK;
1355			pd->pd_disk_size = pp->mediasize;
1356
1357			disk = g_raid_create_disk(sc);
1358			disk->d_consumer = cp;
1359			disk->d_md_data = (void *)pd;
1360			cp->private = disk;
1361			g_topology_unlock();
1362
1363			g_raid_get_disk_info(disk);
1364
1365			/* Welcome the "new" disk. */
1366			update += g_raid_md_jmicron_start_disk(disk);
1367			if (disk->d_state != G_RAID_DISK_S_ACTIVE &&
1368			    disk->d_state != G_RAID_DISK_S_SPARE) {
1369				gctl_error(req, "Disk '%s' doesn't fit.",
1370				    diskname);
1371				g_raid_destroy_disk(disk);
1372				error = -8;
1373				break;
1374			}
1375		}
1376
1377		/* Write new metadata if we changed something. */
1378		if (update)
1379			g_raid_md_write_jmicron(md, NULL, NULL, NULL);
1380		return (error);
1381	}
1382	gctl_error(req, "Command '%s' is not supported.", verb);
1383	return (-100);
1384}
1385
1386static int
1387g_raid_md_write_jmicron(struct g_raid_md_object *md, struct g_raid_volume *tvol,
1388    struct g_raid_subdisk *tsd, struct g_raid_disk *tdisk)
1389{
1390	struct g_raid_softc *sc;
1391	struct g_raid_volume *vol;
1392	struct g_raid_subdisk *sd;
1393	struct g_raid_disk *disk;
1394	struct g_raid_md_jmicron_object *mdi;
1395	struct g_raid_md_jmicron_perdisk *pd;
1396	struct jmicron_raid_conf *meta;
1397	int i, spares;
1398
1399	sc = md->mdo_softc;
1400	mdi = (struct g_raid_md_jmicron_object *)md;
1401
1402	if (sc->sc_stopping == G_RAID_DESTROY_HARD)
1403		return (0);
1404
1405	/* There is only one volume. */
1406	vol = TAILQ_FIRST(&sc->sc_volumes);
1407
1408	/* Fill global fields. */
1409	meta = malloc(sizeof(*meta), M_MD_JMICRON, M_WAITOK | M_ZERO);
1410	strncpy(meta->signature, JMICRON_MAGIC, 2);
1411	meta->version = JMICRON_VERSION;
1412	jmicron_meta_put_name(meta, vol->v_name);
1413	if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID0)
1414		meta->type = JMICRON_T_RAID0;
1415	else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID1)
1416		meta->type = JMICRON_T_RAID1;
1417	else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID1E)
1418		meta->type = JMICRON_T_RAID01;
1419	else if (vol->v_raid_level == G_RAID_VOLUME_RL_CONCAT ||
1420	    vol->v_raid_level == G_RAID_VOLUME_RL_SINGLE)
1421		meta->type = JMICRON_T_CONCAT;
1422	else
1423		meta->type = JMICRON_T_RAID5;
1424	meta->stripe_shift = fls(vol->v_strip_size / 2048);
1425	meta->flags = JMICRON_F_READY | JMICRON_F_BOOTABLE;
1426	for (i = 0; i < vol->v_disks_count; i++) {
1427		sd = &vol->v_subdisks[i];
1428		if (sd->sd_disk == NULL || sd->sd_disk->d_md_data == NULL)
1429			meta->disks[i] = 0xffffffff;
1430		else {
1431			pd = (struct g_raid_md_jmicron_perdisk *)
1432			    sd->sd_disk->d_md_data;
1433			meta->disks[i] = pd->pd_disk_id;
1434		}
1435		if (sd->sd_state < G_RAID_SUBDISK_S_STALE)
1436			meta->flags |= JMICRON_F_BADSEC;
1437		if (vol->v_dirty)
1438			meta->flags |= JMICRON_F_UNSYNC;
1439	}
1440
1441	/* Put spares to their slots. */
1442	spares = 0;
1443	TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
1444		pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
1445		if (disk->d_state != G_RAID_DISK_S_SPARE)
1446			continue;
1447		meta->spare[spares] = pd->pd_disk_id;
1448		if (++spares >= 2)
1449			break;
1450	}
1451
1452	/* We are done. Print meta data and store them to disks. */
1453	if (mdi->mdio_meta != NULL)
1454		free(mdi->mdio_meta, M_MD_JMICRON);
1455	mdi->mdio_meta = meta;
1456	TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
1457		pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
1458		if (disk->d_state != G_RAID_DISK_S_ACTIVE &&
1459		    disk->d_state != G_RAID_DISK_S_SPARE)
1460			continue;
1461		if (pd->pd_meta != NULL) {
1462			free(pd->pd_meta, M_MD_JMICRON);
1463			pd->pd_meta = NULL;
1464		}
1465		pd->pd_meta = jmicron_meta_copy(meta);
1466		pd->pd_meta->disk_id = pd->pd_disk_id;
1467		if ((sd = TAILQ_FIRST(&disk->d_subdisks)) != NULL) {
1468			pd->pd_meta->offset =
1469			    (sd->sd_offset / 512) / 16;
1470			pd->pd_meta->disk_sectors_high =
1471			    (sd->sd_size / 512) >> 16;
1472			pd->pd_meta->disk_sectors_low =
1473			    (sd->sd_size / 512) & 0xffff;
1474			if (sd->sd_state < G_RAID_SUBDISK_S_STALE)
1475				pd->pd_meta->flags &= ~JMICRON_F_BADSEC;
1476			else if (sd->sd_state < G_RAID_SUBDISK_S_ACTIVE)
1477				pd->pd_meta->flags |= JMICRON_F_UNSYNC;
1478		}
1479		G_RAID_DEBUG(1, "Writing JMicron metadata to %s",
1480		    g_raid_get_diskname(disk));
1481		g_raid_md_jmicron_print(pd->pd_meta);
1482		jmicron_meta_write(disk->d_consumer, pd->pd_meta);
1483	}
1484	return (0);
1485}
1486
1487static int
1488g_raid_md_fail_disk_jmicron(struct g_raid_md_object *md,
1489    struct g_raid_subdisk *tsd, struct g_raid_disk *tdisk)
1490{
1491	struct g_raid_softc *sc;
1492	struct g_raid_md_jmicron_perdisk *pd;
1493	struct g_raid_subdisk *sd;
1494
1495	sc = md->mdo_softc;
1496	pd = (struct g_raid_md_jmicron_perdisk *)tdisk->d_md_data;
1497
1498	/* We can't fail disk that is not a part of array now. */
1499	if (pd->pd_disk_pos < 0)
1500		return (-1);
1501
1502	if (tdisk->d_consumer)
1503		jmicron_meta_erase(tdisk->d_consumer);
1504
1505	/* Change states. */
1506	g_raid_change_disk_state(tdisk, G_RAID_DISK_S_FAILED);
1507	TAILQ_FOREACH(sd, &tdisk->d_subdisks, sd_next) {
1508		g_raid_change_subdisk_state(sd,
1509		    G_RAID_SUBDISK_S_FAILED);
1510		g_raid_event_send(sd, G_RAID_SUBDISK_E_FAILED,
1511		    G_RAID_EVENT_SUBDISK);
1512	}
1513
1514	/* Write updated metadata to remaining disks. */
1515	g_raid_md_write_jmicron(md, NULL, NULL, tdisk);
1516
1517	/* Check if anything left except placeholders. */
1518	if (g_raid_ndisks(sc, -1) ==
1519	    g_raid_ndisks(sc, G_RAID_DISK_S_OFFLINE))
1520		g_raid_destroy_node(sc, 0);
1521	else
1522		g_raid_md_jmicron_refill(sc);
1523	return (0);
1524}
1525
1526static int
1527g_raid_md_free_disk_jmicron(struct g_raid_md_object *md,
1528    struct g_raid_disk *disk)
1529{
1530	struct g_raid_md_jmicron_perdisk *pd;
1531
1532	pd = (struct g_raid_md_jmicron_perdisk *)disk->d_md_data;
1533	if (pd->pd_meta != NULL) {
1534		free(pd->pd_meta, M_MD_JMICRON);
1535		pd->pd_meta = NULL;
1536	}
1537	free(pd, M_MD_JMICRON);
1538	disk->d_md_data = NULL;
1539	return (0);
1540}
1541
1542static int
1543g_raid_md_free_jmicron(struct g_raid_md_object *md)
1544{
1545	struct g_raid_md_jmicron_object *mdi;
1546
1547	mdi = (struct g_raid_md_jmicron_object *)md;
1548	if (!mdi->mdio_started) {
1549		mdi->mdio_started = 0;
1550		callout_stop(&mdi->mdio_start_co);
1551		G_RAID_DEBUG1(1, md->mdo_softc,
1552		    "root_mount_rel %p", mdi->mdio_rootmount);
1553		root_mount_rel(mdi->mdio_rootmount);
1554		mdi->mdio_rootmount = NULL;
1555	}
1556	if (mdi->mdio_meta != NULL) {
1557		free(mdi->mdio_meta, M_MD_JMICRON);
1558		mdi->mdio_meta = NULL;
1559	}
1560	return (0);
1561}
1562
1563G_RAID_MD_DECLARE(jmicron, "JMicron");
1564