Date: Thu, 13 Jan 2011 17:29:05 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r217363 - in projects/graid/head: sbin/geom/class/raid sys/geom/raid Message-ID: <201101131729.p0DHT5n5058009@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mav Date: Thu Jan 13 17:29:05 2011 New Revision: 217363 URL: http://svn.freebsd.org/changeset/base/217363 Log: Implement `graid remove` command that drops specified disk from array. 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.h 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 Jan 13 17:04:02 2011 (r217362) +++ projects/graid/head/sbin/geom/class/raid/geom_raid.c Thu Jan 13 17:29:05 2011 (r217363) @@ -59,6 +59,12 @@ struct g_command class_commands[] = { }, "[-S size] [-s stripsize] format name level prov ..." }, + { "insert", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, + "[-v] name prov" + }, + { "remove", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, + "[-v] name prov" + }, { "stop", G_FLAG_VERBOSE, NULL, { { 'f', "force", NULL, G_TYPE_BOOL }, Modified: projects/graid/head/sys/geom/raid/g_raid.c ============================================================================== --- projects/graid/head/sys/geom/raid/g_raid.c Thu Jan 13 17:04:02 2011 (r217362) +++ projects/graid/head/sys/geom/raid/g_raid.c Thu Jan 13 17:29:05 2011 (r217363) @@ -159,10 +159,6 @@ g_raid_subdisk_state2str(int state) return ("STALE"); case G_RAID_SUBDISK_S_SYNCHRONIZING: return ("SYNCHRONIZING"); - case G_RAID_SUBDISK_S_DISCONNECTED: - return ("DISCONNECTED"); - case G_RAID_SUBDISK_S_DESTROY: - return ("DESTROY"); default: return ("INVALID"); } Modified: projects/graid/head/sys/geom/raid/g_raid.h ============================================================================== --- projects/graid/head/sys/geom/raid/g_raid.h Thu Jan 13 17:04:02 2011 (r217362) +++ projects/graid/head/sys/geom/raid/g_raid.h Thu Jan 13 17:29:05 2011 (r217363) @@ -112,6 +112,7 @@ struct g_raid_event { #define G_RAID_DISK_S_SPARE 0x02 #define G_RAID_DISK_S_OFFLINE 0x03 #define G_RAID_DISK_S_STALE 0x04 +#define G_RAID_DISK_S_FAILED 0x05 #define G_RAID_DISK_E_DISCONNECTED 0x01 @@ -132,8 +133,6 @@ struct g_raid_disk { #define G_RAID_SUBDISK_S_ACTIVE 0x02 #define G_RAID_SUBDISK_S_STALE 0x03 #define G_RAID_SUBDISK_S_SYNCHRONIZING 0x04 -#define G_RAID_SUBDISK_S_DISCONNECTED 0x05 -#define G_RAID_SUBDISK_S_DESTROY 0x06 #define G_RAID_SUBDISK_E_NEW 0x01 #define G_RAID_SUBDISK_E_DISCONNECTED 0x02 Modified: projects/graid/head/sys/geom/raid/md_intel.c ============================================================================== --- projects/graid/head/sys/geom/raid/md_intel.c Thu Jan 13 17:04:02 2011 (r217362) +++ projects/graid/head/sys/geom/raid/md_intel.c Thu Jan 13 17:29:05 2011 (r217363) @@ -426,6 +426,26 @@ intel_meta_write(struct g_consumer *cp, return (error); } +static int +intel_meta_erase(struct g_consumer *cp) +{ + struct g_provider *pp; + char *buf; + int error; + + pp = cp->provider; + buf = malloc(pp->sectorsize, M_MD_INTEL, M_WAITOK | M_ZERO); + error = g_write_data(cp, + pp->mediasize - 2 * pp->sectorsize, + buf, pp->sectorsize); + if (error != 0) { + G_RAID_DEBUG(1, "Cannot erase metadata on %s (error=%d).", + pp->name, error); + } + free(buf, M_MD_INTEL); + return (error); +} + static struct g_raid_disk * g_raid_md_intel_get_disk(struct g_raid_softc *sc, int id) { @@ -881,6 +901,7 @@ g_raid_md_ctl_intel(struct g_raid_md_obj mdi = (struct g_raid_md_intel_object *)md; verb = gctl_get_param(req, "verb", NULL); nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); + error = 0; if (strcmp(verb, "label") == 0) { if (*nargs < 4) { @@ -911,7 +932,6 @@ g_raid_md_ctl_intel(struct g_raid_md_obj /* Search for disks, connect them and probe. */ numdisks = *nargs - 3; - error = 0; size = 0xffffffffffffffffllu; sectorsize = 0; for (i = 0; i < numdisks; i++) { @@ -1050,6 +1070,69 @@ g_raid_md_ctl_intel(struct g_raid_md_obj g_raid_md_write_intel(md); return (0); } + if (strcmp(verb, "remove") == 0) { + if (*nargs < 2) { + gctl_error(req, "Invalid number of arguments."); + return (-1); + } + for (i = 1; i < *nargs; i++) { + snprintf(arg, sizeof(arg), "arg%d", i); + diskname = gctl_get_asciiparam(req, arg); + if (diskname == NULL) { + gctl_error(req, "No disk name (%s).", arg); + error = -2; + break; + } + if (strncmp(diskname, "/dev/", 5) == 0) + diskname += 5; + + LIST_FOREACH(disk, &sc->sc_disks, d_next) { + if (disk->d_consumer != NULL && + disk->d_consumer->provider != NULL && + strcmp(disk->d_consumer->provider->name, + diskname) == 0) + break; + } + if (disk == NULL) { + gctl_error(req, "Disk '%s' not found.", + diskname); + error = -3; + break; + } + pd = (struct g_raid_md_intel_perdisk *)disk->d_md_data; + + /* Erase metadata on deleting disk. */ + intel_meta_erase(disk->d_consumer); + + /* If disk was assigned, just update statuses. */ + if (pd->pd_disk_pos >= 0) { + g_raid_change_disk_state(disk, G_RAID_DISK_S_OFFLINE); + if (disk->d_consumer) { + g_topology_lock(); + g_raid_kill_consumer(sc, disk->d_consumer); + g_topology_unlock(); + disk->d_consumer = NULL; + } + LIST_FOREACH(sd, &disk->d_subdisks, sd_next) { + g_raid_event_send(sd, G_RAID_SUBDISK_E_DISCONNECTED, + G_RAID_EVENT_SUBDISK); + } + } else { + /* Otherwise -- delete. */ + g_raid_change_disk_state(disk, G_RAID_DISK_S_NONE); + g_raid_destroy_disk(disk); + } + } + + /* Write updated metadata to remaining disks. */ + g_raid_md_write_intel(md); + + /* Check if anything left. */ + if (g_raid_ndisks(sc, G_RAID_DISK_S_NONE) == 0 && + g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) == 0) + g_raid_destroy_node(sc, 0); + return (error); + } return (-100); } @@ -1067,7 +1150,7 @@ g_raid_md_write_intel(struct g_raid_md_o struct intel_raid_map *mmap; off_t sectorsize = 512; const char *version, *cv; - int i, vi, sdi, numdisks; + int vi, sdi, numdisks, len; sc = md->mdo_softc; mdi = (struct g_raid_md_intel_object *)md; @@ -1077,12 +1160,25 @@ g_raid_md_write_intel(struct g_raid_md_o /* Count number of disks. */ numdisks = 0; - i = 0; LIST_FOREACH(disk, &sc->sc_disks, d_next) { pd = (struct g_raid_md_intel_perdisk *)disk->d_md_data; - if (pd->pd_disk_pos >= 0) { - numdisks++; - pd->pd_disk_pos = i++; + if (pd->pd_disk_pos < 0) + continue; + numdisks++; + if (disk->d_state == G_RAID_DISK_S_ACTIVE) { + pd->pd_disk_meta.flags |= INTEL_F_ASSIGNED; + pd->pd_disk_meta.flags |= INTEL_F_ONLINE; + } else if (disk->d_state == G_RAID_DISK_S_FAILED) { + pd->pd_disk_meta.flags &= ~INTEL_F_ASSIGNED; + pd->pd_disk_meta.flags |= INTEL_F_DOWN; + } else { + pd->pd_disk_meta.flags &= ~INTEL_F_ONLINE; + if (pd->pd_disk_meta.id != 0xffffffff) { + pd->pd_disk_meta.id = 0xffffffff; + len = strlen(pd->pd_disk_meta.serial); + len = min(len, INTEL_SERIAL_LEN - 3); + strcpy(pd->pd_disk_meta.serial + len, ":0"); + } } } @@ -1097,7 +1193,7 @@ g_raid_md_write_intel(struct g_raid_md_o meta->total_disks = numdisks; LIST_FOREACH(disk, &sc->sc_disks, d_next) { pd = (struct g_raid_md_intel_perdisk *)disk->d_md_data; - if ((pd->pd_disk_meta.flags & INTEL_F_ASSIGNED) == 0) + if (pd->pd_disk_pos < 0) continue; meta->disk[pd->pd_disk_pos] = pd->pd_disk_meta; } @@ -1170,13 +1266,18 @@ g_raid_md_write_intel(struct g_raid_md_o mmap->total_domains = vol->v_disks_count; else mmap->total_domains = 1; - mmap->failed_disk_num = ~0; + mmap->failed_disk_num = 0xff; mmap->ddf = 1; for (sdi = 0; sdi < vol->v_disks_count; sdi++) { sd = &vol->v_subdisks[sdi]; pd = (struct g_raid_md_intel_perdisk *) sd->sd_disk->d_md_data; mmap->disk_idx[sdi] = pd->pd_disk_pos; +// if (sd->sd_state == G_RAID_SUBDISK_S_NONE) { +// mmap->disk_idx[sdi] |= INTEL_DI_RBLD; +// if (mmap->failed_disk_num == 0xff) +// mmap->failed_disk_num = sdi; +// } } vi++; } @@ -1192,6 +1293,8 @@ g_raid_md_write_intel(struct g_raid_md_o mdi->mdio_meta = meta; LIST_FOREACH(disk, &sc->sc_disks, d_next) { pd = (struct g_raid_md_intel_perdisk *)disk->d_md_data; + if (disk->d_state != G_RAID_DISK_S_ACTIVE) + continue; if (pd->pd_meta != NULL) { free(pd->pd_meta, M_MD_INTEL); pd->pd_meta = NULL;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201101131729.p0DHT5n5058009>