From owner-svn-src-projects@FreeBSD.ORG Fri Jan 28 13:48:22 2011 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EE4C8106564A; Fri, 28 Jan 2011 13:48:22 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id DE26C8FC1C; Fri, 28 Jan 2011 13:48:22 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p0SDmMm9081304; Fri, 28 Jan 2011 13:48:22 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p0SDmMhw081302; Fri, 28 Jan 2011 13:48:22 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201101281348.p0SDmMhw081302@svn.freebsd.org> From: Alexander Motin Date: Fri, 28 Jan 2011 13:48:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r218016 - projects/graid/head/sys/geom/raid X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 28 Jan 2011 13:48:23 -0000 Author: mav Date: Fri Jan 28 13:48:22 2011 New Revision: 218016 URL: http://svn.freebsd.org/changeset/base/218016 Log: Add `graid label` ability to create arrays missing some disks by specifying NONE instead of their names. It can be used, for example, to migrate from non-RAID setup to RAID1 or if further redundant disks are not available at the moment. Add some checks to validate subdisk sizes. Creating too small subdisk could cause crash, while for too large it may be impossible to write metadata. Modified: projects/graid/head/sys/geom/raid/md_intel.c Modified: projects/graid/head/sys/geom/raid/md_intel.c ============================================================================== --- projects/graid/head/sys/geom/raid/md_intel.c Fri Jan 28 11:56:14 2011 (r218015) +++ projects/graid/head/sys/geom/raid/md_intel.c Fri Jan 28 13:48:22 2011 (r218016) @@ -1229,6 +1229,11 @@ g_raid_md_ctl_intel(struct g_raid_md_obj error = -6; break; } + if (strcmp(diskname, "NONE") == 0) { + cp = NULL; + pp = NULL; + goto makedisk; + } if (strncmp(diskname, "/dev/", 5) == 0) diskname += 5; g_topology_lock(); @@ -1258,12 +1263,19 @@ g_raid_md_ctl_intel(struct g_raid_md_obj error = -7; break; } - +makedisk: 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; + if (cp == NULL) { + strcpy(&pd->pd_disk_meta.serial[0], "NONE"); + pd->pd_disk_meta.id = 0; + pd->pd_disk_meta.id = 0xffffffff; + pd->pd_disk_meta.flags = INTEL_F_ASSIGNED; + continue; + } cp->private = disk; g_topology_unlock(); @@ -1331,7 +1343,20 @@ g_raid_md_ctl_intel(struct g_raid_md_obj } strip = *striparg; } - size -= (size % strip); + + /* Round size down to strip or sector. */ + if (level == G_RAID_VOLUME_RL_RAID1) + size -= (size % sectorsize); + else + size -= (size % strip); + if (size <= 0) { + gctl_error(req, "Size too small."); + return (-13); + } + if (size > 0xffffffffllu * sectorsize) { + gctl_error(req, "Size too big."); + return (-14); + } /* We have all we need, create things: volume, ... */ mdi->mdio_started = 1; @@ -1343,9 +1368,11 @@ g_raid_md_ctl_intel(struct g_raid_md_obj vol->v_disks_count = numdisks; if (level == G_RAID_VOLUME_RL_RAID0) vol->v_mediasize = size * numdisks; + else if (level == G_RAID_VOLUME_RL_RAID1) + vol->v_mediasize = size; else if (level == G_RAID_VOLUME_RL_RAID5) vol->v_mediasize = size * (numdisks - 1); - else + else /* RAID10 */ vol->v_mediasize = size * (numdisks / 2); vol->v_sectorsize = sectorsize; g_raid_start_volume(vol); @@ -1358,14 +1385,23 @@ g_raid_md_ctl_intel(struct g_raid_md_obj sd->sd_offset = 0; sd->sd_size = size; TAILQ_INSERT_TAIL(&disk->d_subdisks, sd, sd_next); - g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE); - g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_ACTIVE); - g_raid_event_send(sd, G_RAID_SUBDISK_E_NEW, - G_RAID_EVENT_SUBDISK); + if (sd->sd_disk->d_consumer != NULL) { + g_raid_change_disk_state(disk, + G_RAID_DISK_S_ACTIVE); + g_raid_change_subdisk_state(sd, + G_RAID_SUBDISK_S_ACTIVE); + g_raid_event_send(sd, G_RAID_SUBDISK_E_NEW, + G_RAID_EVENT_SUBDISK); + } else { + g_raid_change_disk_state(disk, G_RAID_DISK_S_OFFLINE); + } } /* Write metadata based on created entities. */ g_raid_md_write_intel(md, NULL, NULL, NULL); + + /* Pickup any STALE/SPARE disks to refill array if needed. */ + g_raid_md_intel_refill(sc); return (0); } if (strcmp(verb, "add") == 0) { @@ -1476,14 +1512,24 @@ g_raid_md_ctl_intel(struct g_raid_md_obj } strip = *striparg; } + + /* Round offset up to strip. */ size -= ((strip - off) % strip); off += ((strip - off) % strip); - size -= (size % strip); + /* Round size down to strip or sector. */ + if (level == G_RAID_VOLUME_RL_RAID1) + size -= (size % sectorsize); + else + size -= (size % strip); if (size <= 0) { - gctl_error(req, "No free space."); + gctl_error(req, "Size too small."); return (-13); } + if (size > 0xffffffffllu * sectorsize) { + gctl_error(req, "Size too big."); + return (-14); + } /* We have all we need, create things: volume, ... */ vol = g_raid_create_volume(sc, volname); @@ -1494,9 +1540,11 @@ g_raid_md_ctl_intel(struct g_raid_md_obj vol->v_disks_count = numdisks; if (level == G_RAID_VOLUME_RL_RAID0) vol->v_mediasize = size * numdisks; + else if (level == G_RAID_VOLUME_RL_RAID1) + vol->v_mediasize = size; else if (level == G_RAID_VOLUME_RL_RAID5) vol->v_mediasize = size * (numdisks - 1); - else + else /* RAID10 */ vol->v_mediasize = size * (numdisks / 2); vol->v_sectorsize = sectorsize; g_raid_start_volume(vol);