From owner-svn-src-all@FreeBSD.ORG Thu Jan 31 22:12:26 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 59F389C5; Thu, 31 Jan 2013 22:12:26 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 3236E6E2; Thu, 31 Jan 2013 22:12:26 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id r0VMCQE7046947; Thu, 31 Jan 2013 22:12:26 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id r0VMCP3S046944; Thu, 31 Jan 2013 22:12:25 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201301312212.r0VMCP3S046944@svn.freebsd.org> From: Alexander Motin Date: Thu, 31 Jan 2013 22:12:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r246168 - stable/9/sys/geom/raid X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 31 Jan 2013 22:12:26 -0000 Author: mav Date: Thu Jan 31 22:12:25 2013 New Revision: 246168 URL: http://svnweb.freebsd.org/changeset/base/246168 Log: MFC r245326: Add basic support for Intel Rapid Recover Technology (Intel RRT). It is alike to RAID1, but with dedicating master and recovery disks and providing manual control over synchronization. It allows to use recovery disk as snapshot of the master disk from the time of the last sync. This implementation is not functionaly complete comparing to Windows, but it is better then silent conversion to RAID1 on first boot. Modified: stable/9/sys/geom/raid/g_raid.c stable/9/sys/geom/raid/g_raid.h stable/9/sys/geom/raid/md_intel.c Directory Properties: stable/9/sys/ (props changed) Modified: stable/9/sys/geom/raid/g_raid.c ============================================================================== --- stable/9/sys/geom/raid/g_raid.c Thu Jan 31 22:10:57 2013 (r246167) +++ stable/9/sys/geom/raid/g_raid.c Thu Jan 31 22:12:25 2013 (r246168) @@ -163,6 +163,8 @@ g_raid_disk_state2str(int state) return ("NONE"); case G_RAID_DISK_S_OFFLINE: return ("OFFLINE"); + case G_RAID_DISK_S_DISABLED: + return ("DISABLED"); case G_RAID_DISK_S_FAILED: return ("FAILED"); case G_RAID_DISK_S_STALE_FAILED: @@ -535,7 +537,9 @@ g_raid_report_disk_state(struct g_raid_d if (disk->d_consumer == NULL) return; - if (disk->d_state == G_RAID_DISK_S_FAILED || + if (disk->d_state == G_RAID_DISK_S_DISABLED) { + ; + } else if (disk->d_state == G_RAID_DISK_S_FAILED || disk->d_state == G_RAID_DISK_S_STALE_FAILED) { s = G_STATE_FAILED; } else { Modified: stable/9/sys/geom/raid/g_raid.h ============================================================================== --- stable/9/sys/geom/raid/g_raid.h Thu Jan 31 22:10:57 2013 (r246167) +++ stable/9/sys/geom/raid/g_raid.h Thu Jan 31 22:12:25 2013 (r246168) @@ -140,11 +140,12 @@ struct g_raid_event { }; #define G_RAID_DISK_S_NONE 0x00 /* State is unknown. */ #define G_RAID_DISK_S_OFFLINE 0x01 /* Missing disk placeholder. */ -#define G_RAID_DISK_S_FAILED 0x02 /* Failed. */ -#define G_RAID_DISK_S_STALE_FAILED 0x03 /* Old failed. */ -#define G_RAID_DISK_S_SPARE 0x04 /* Hot-spare. */ -#define G_RAID_DISK_S_STALE 0x05 /* Old disk, unused now. */ -#define G_RAID_DISK_S_ACTIVE 0x06 /* Operational. */ +#define G_RAID_DISK_S_DISABLED 0x02 /* Disabled. */ +#define G_RAID_DISK_S_FAILED 0x03 /* Failed. */ +#define G_RAID_DISK_S_STALE_FAILED 0x04 /* Old failed. */ +#define G_RAID_DISK_S_SPARE 0x05 /* Hot-spare. */ +#define G_RAID_DISK_S_STALE 0x06 /* Old disk, unused now. */ +#define G_RAID_DISK_S_ACTIVE 0x07 /* Operational. */ #define G_RAID_DISK_E_DISCONNECTED 0x01 Modified: stable/9/sys/geom/raid/md_intel.c ============================================================================== --- stable/9/sys/geom/raid/md_intel.c Thu Jan 31 22:10:57 2013 (r246167) +++ stable/9/sys/geom/raid/md_intel.c Thu Jan 31 22:12:25 2013 (r246168) @@ -98,6 +98,8 @@ struct intel_raid_vol { uint8_t cng_master_disk; uint16_t cache_policy; uint8_t cng_state; +#define INTEL_SNGST_NEEDS_UPDATE 1 +#define INTEL_SNGST_MASTER_MISSING 2 uint8_t cng_sub_state; uint32_t filler_0[10]; @@ -130,6 +132,7 @@ struct intel_raid_disk { #define INTEL_F_ASSIGNED 0x02 #define INTEL_F_FAILED 0x04 #define INTEL_F_ONLINE 0x08 +#define INTEL_F_DISABLED 0x80 uint32_t owner_cfg_num; uint32_t sectors_hi; uint32_t filler[3]; @@ -187,6 +190,13 @@ struct g_raid_md_intel_perdisk { struct intel_raid_disk pd_disk_meta; }; +struct g_raid_md_intel_pervolume { + int pv_volume_pos; + int pv_cng; + int pv_cng_man_sync; + int pv_cng_master_disk; +}; + struct g_raid_md_intel_object { struct g_raid_md_object mdio_base; uint32_t mdio_config_id; @@ -206,6 +216,7 @@ static g_raid_md_ctl_t g_raid_md_ctl_int static g_raid_md_write_t g_raid_md_write_intel; static g_raid_md_fail_disk_t g_raid_md_fail_disk_intel; static g_raid_md_free_disk_t g_raid_md_free_disk_intel; +static g_raid_md_free_volume_t g_raid_md_free_volume_intel; static g_raid_md_free_t g_raid_md_free_intel; static kobj_method_t g_raid_md_intel_methods[] = { @@ -216,6 +227,7 @@ static kobj_method_t g_raid_md_intel_met KOBJMETHOD(g_raid_md_write, g_raid_md_write_intel), KOBJMETHOD(g_raid_md_fail_disk, g_raid_md_fail_disk_intel), KOBJMETHOD(g_raid_md_free_disk, g_raid_md_free_disk_intel), + KOBJMETHOD(g_raid_md_free_volume, g_raid_md_free_volume_intel), KOBJMETHOD(g_raid_md_free, g_raid_md_free_intel), { 0, 0 } }; @@ -369,8 +381,15 @@ g_raid_md_intel_print(struct intel_raid_ printf(" ****** Volume %d ******\n", i); printf(" name %.16s\n", mvol->name); printf(" total_sectors %ju\n", mvol->total_sectors); - printf(" state %u\n", mvol->state); + printf(" state 0x%08x\n", mvol->state); printf(" reserved %u\n", mvol->reserved); + printf(" migr_priority %u\n", mvol->migr_priority); + printf(" num_sub_vols %u\n", mvol->num_sub_vols); + printf(" tid %u\n", mvol->tid); + printf(" cng_master_disk %u\n", mvol->cng_master_disk); + printf(" cache_policy %u\n", mvol->cache_policy); + printf(" cng_state %u\n", mvol->cng_state); + printf(" cng_sub_state %u\n", mvol->cng_sub_state); printf(" curr_migr_unit %u\n", mvol->curr_migr_unit); printf(" curr_migr_unit_hi %u\n", mvol->curr_migr_unit_hi); printf(" checkpoint_id %u\n", mvol->checkpoint_id); @@ -699,9 +718,11 @@ static struct g_raid_volume * g_raid_md_intel_get_volume(struct g_raid_softc *sc, int id) { struct g_raid_volume *mvol; + struct g_raid_md_intel_pervolume *pv; TAILQ_FOREACH(mvol, &sc->sc_volumes, v_next) { - if ((intptr_t)(mvol->v_md_data) == id) + pv = mvol->v_md_data; + if (pv->pv_volume_pos == id) break; } return (mvol); @@ -715,6 +736,7 @@ g_raid_md_intel_start_disk(struct g_raid struct g_raid_disk *olddisk, *tmpdisk; struct g_raid_md_object *md; struct g_raid_md_intel_object *mdi; + struct g_raid_md_intel_pervolume *pv; struct g_raid_md_intel_perdisk *pd, *oldpd; struct intel_raid_conf *meta; struct intel_raid_vol *mvol; @@ -732,6 +754,11 @@ g_raid_md_intel_start_disk(struct g_raid disk_pos = intel_meta_find_disk(meta, pd->pd_disk_meta.serial); if (disk_pos < 0) { G_RAID_DEBUG1(1, sc, "Unknown, probably new or stale disk"); + /* Disabled disk is useless for us. */ + if (pd->pd_disk_meta.flags & INTEL_F_DISABLED) { + g_raid_change_disk_state(disk, G_RAID_DISK_S_DISABLED); + return (0); + } /* Failed stale disk is useless for us. */ if (pd->pd_disk_meta.flags & INTEL_F_FAILED) { g_raid_change_disk_state(disk, G_RAID_DISK_S_STALE_FAILED); @@ -826,6 +853,8 @@ nofit: /* Welcome the new disk. */ if (resurrection) g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE); + else if (meta->disk[disk_pos].flags & INTEL_F_DISABLED) + g_raid_change_disk_state(disk, G_RAID_DISK_S_DISABLED); else if (meta->disk[disk_pos].flags & INTEL_F_FAILED) g_raid_change_disk_state(disk, G_RAID_DISK_S_FAILED); else if (meta->disk[disk_pos].flags & INTEL_F_SPARE) @@ -833,8 +862,8 @@ nofit: else g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE); TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) { - mvol = intel_get_volume(meta, - (uintptr_t)(sd->sd_volume->v_md_data)); + pv = sd->sd_volume->v_md_data; + mvol = intel_get_volume(meta, pv->pv_volume_pos); mmap0 = intel_get_map(mvol, 0); if (mvol->migr_state) mmap1 = intel_get_map(mvol, 1); @@ -845,12 +874,17 @@ nofit: /* Stale disk, almost same as new. */ g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_NEW); + } else if (meta->disk[disk_pos].flags & INTEL_F_DISABLED) { + /* Disabled disk, useless. */ + g_raid_change_subdisk_state(sd, + G_RAID_SUBDISK_S_NONE); } else if (meta->disk[disk_pos].flags & INTEL_F_FAILED) { /* Failed disk, almost useless. */ g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_FAILED); } else if (mvol->migr_state == 0) { - if (mmap0->status == INTEL_S_UNINITIALIZED) { + if (mmap0->status == INTEL_S_UNINITIALIZED && + (!pv->pv_cng || pv->pv_cng_master_disk != disk_pos)) { /* Freshly created uninitialized volume. */ g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_UNINITIALIZED); @@ -858,7 +892,8 @@ nofit: /* Freshly inserted disk. */ g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_NEW); - } else if (mvol->dirty) { + } else if (mvol->dirty && (!pv->pv_cng || + pv->pv_cng_master_disk != disk_pos)) { /* Dirty volume (unclean shutdown). */ g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_STALE); @@ -885,7 +920,8 @@ nofit: sd->sd_volume->v_strip_size * mmap0->total_domains; } - } else if (mvol->dirty) { + } else if (mvol->dirty && (!pv->pv_cng || + pv->pv_cng_master_disk != disk_pos)) { /* Dirty volume (unclean shutdown). */ g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_STALE); @@ -1014,6 +1050,7 @@ g_raid_md_intel_start(struct g_raid_soft { struct g_raid_md_object *md; struct g_raid_md_intel_object *mdi; + struct g_raid_md_intel_pervolume *pv; struct g_raid_md_intel_perdisk *pd; struct intel_raid_conf *meta; struct intel_raid_vol *mvol; @@ -1032,7 +1069,13 @@ g_raid_md_intel_start(struct g_raid_soft mvol = intel_get_volume(meta, i); mmap = intel_get_map(mvol, 0); vol = g_raid_create_volume(sc, mvol->name, -1); - vol->v_md_data = (void *)(intptr_t)i; + pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO); + pv->pv_volume_pos = i; + pv->pv_cng = (mvol->state & INTEL_ST_CLONE_N_GO) != 0; + pv->pv_cng_man_sync = (mvol->state & INTEL_ST_CLONE_MAN_SYNC) != 0; + if (mvol->cng_master_disk < mmap->total_disks) + pv->pv_cng_master_disk = mvol->cng_master_disk; + vol->v_md_data = pv; vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_NONE; if (mmap->type == INTEL_T_RAID0) vol->v_raid_level = G_RAID_VOLUME_RL_RAID0; @@ -1450,6 +1493,7 @@ g_raid_md_ctl_intel(struct g_raid_md_obj struct g_raid_subdisk *sd; struct g_raid_disk *disk; struct g_raid_md_intel_object *mdi; + struct g_raid_md_intel_pervolume *pv; struct g_raid_md_intel_perdisk *pd; struct g_consumer *cp; struct g_provider *pp; @@ -1621,7 +1665,9 @@ g_raid_md_ctl_intel(struct g_raid_md_obj /* We have all we need, create things: volume, ... */ mdi->mdio_started = 1; vol = g_raid_create_volume(sc, volname, -1); - vol->v_md_data = (void *)(intptr_t)0; + pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO); + pv->pv_volume_pos = 0; + vol->v_md_data = pv; vol->v_raid_level = level; vol->v_raid_level_qualifier = qual; vol->v_strip_size = strip; @@ -1814,7 +1860,9 @@ g_raid_md_ctl_intel(struct g_raid_md_obj /* We have all we need, create things: volume, ... */ vol = g_raid_create_volume(sc, volname, -1); - vol->v_md_data = (void *)(intptr_t)i; + pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO); + pv->pv_volume_pos = i; + vol->v_md_data = pv; vol->v_raid_level = level; vol->v_raid_level_qualifier = qual; vol->v_strip_size = strip; @@ -2105,6 +2153,7 @@ g_raid_md_write_intel(struct g_raid_md_o struct g_raid_subdisk *sd; struct g_raid_disk *disk; struct g_raid_md_intel_object *mdi; + struct g_raid_md_intel_pervolume *pv; struct g_raid_md_intel_perdisk *pd; struct intel_raid_conf *meta; struct intel_raid_vol *mvol; @@ -2133,7 +2182,11 @@ g_raid_md_write_intel(struct g_raid_md_o pd->pd_disk_meta.flags = INTEL_F_ONLINE | INTEL_F_ASSIGNED; } else if (disk->d_state == G_RAID_DISK_S_FAILED) { - pd->pd_disk_meta.flags = INTEL_F_FAILED | INTEL_F_ASSIGNED; + pd->pd_disk_meta.flags = INTEL_F_FAILED | + INTEL_F_ASSIGNED; + } else if (disk->d_state == G_RAID_DISK_S_DISABLED) { + pd->pd_disk_meta.flags = INTEL_F_FAILED | + INTEL_F_ASSIGNED | INTEL_F_DISABLED; } else { pd->pd_disk_meta.flags = INTEL_F_ASSIGNED; if (pd->pd_disk_meta.id != 0xffffffff) { @@ -2165,12 +2218,13 @@ g_raid_md_write_intel(struct g_raid_md_o vi = 0; version = INTEL_VERSION_1000; TAILQ_FOREACH(vol, &sc->sc_volumes, v_next) { + pv = vol->v_md_data; if (vol->v_stopping) continue; mvol = intel_get_volume(meta, vi); /* New metadata may have different volumes order. */ - vol->v_md_data = (void *)(intptr_t)vi; + pv->pv_volume_pos = vi; for (sdi = 0; sdi < vol->v_disks_count; sdi++) { sd = &vol->v_subdisks[sdi]; @@ -2192,8 +2246,8 @@ g_raid_md_write_intel(struct g_raid_md_o if (meta->attributes & INTEL_ATTR_2TB) cv = INTEL_VERSION_1300; -// else if (dev->status == DEV_CLONE_N_GO) -// cv = INTEL_VERSION_1206; + else if (pv->pv_cng) + cv = INTEL_VERSION_1206; else if (vol->v_disks_count > 4) cv = INTEL_VERSION_1204; else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID5) @@ -2211,6 +2265,17 @@ g_raid_md_write_intel(struct g_raid_md_o strlcpy(&mvol->name[0], vol->v_name, sizeof(mvol->name)); mvol->total_sectors = vol->v_mediasize / sectorsize; + if (pv->pv_cng) { + mvol->state |= INTEL_ST_CLONE_N_GO; + if (pv->pv_cng_man_sync) + mvol->state |= INTEL_ST_CLONE_MAN_SYNC; + mvol->cng_master_disk = pv->pv_cng_master_disk; + if (vol->v_subdisks[pv->pv_cng_master_disk].sd_state == + G_RAID_SUBDISK_S_NONE) + mvol->cng_state = INTEL_SNGST_MASTER_MISSING; + else if (vol->v_state != G_RAID_VOLUME_S_OPTIMAL) + mvol->cng_state = INTEL_SNGST_NEEDS_UPDATE; + } /* Check for any recovery in progress. */ state = G_RAID_SUBDISK_S_ACTIVE; @@ -2403,6 +2468,18 @@ g_raid_md_free_disk_intel(struct g_raid_ } static int +g_raid_md_free_volume_intel(struct g_raid_md_object *md, + struct g_raid_volume *vol) +{ + struct g_raid_md_intel_pervolume *pv; + + pv = (struct g_raid_md_intel_pervolume *)vol->v_md_data; + free(pv, M_MD_INTEL); + vol->v_md_data = NULL; + return (0); +} + +static int g_raid_md_free_intel(struct g_raid_md_object *md) { struct g_raid_md_intel_object *mdi;