From owner-svn-src-all@FreeBSD.ORG Mon Jun 8 02:13:25 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 474EA106564A; Mon, 8 Jun 2009 02:13:25 +0000 (UTC) (envelope-from marcel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 355998FC08; Mon, 8 Jun 2009 02:13:25 +0000 (UTC) (envelope-from marcel@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n582DOhH012543; Mon, 8 Jun 2009 02:13:24 GMT (envelope-from marcel@svn.freebsd.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n582DOwD012542; Mon, 8 Jun 2009 02:13:24 GMT (envelope-from marcel@svn.freebsd.org) Message-Id: <200906080213.n582DOwD012542@svn.freebsd.org> From: Marcel Moolenaar Date: Mon, 8 Jun 2009 02:13:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r193673 - head/sbin/geom/class/part X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 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: Mon, 08 Jun 2009 02:13:25 -0000 Author: marcel Date: Mon Jun 8 02:13:24 2009 New Revision: 193673 URL: http://svn.freebsd.org/changeset/base/193673 Log: Make the size (-s) and start (-b) parameters of the add verb optional. The missing parameter(s) are automatically filled-in. Modified: head/sbin/geom/class/part/geom_part.c Modified: head/sbin/geom/class/part/geom_part.c ============================================================================== --- head/sbin/geom/class/part/geom_part.c Mon Jun 8 01:28:37 2009 (r193672) +++ head/sbin/geom/class/part/geom_part.c Mon Jun 8 02:13:24 2009 (r193673) @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); uint32_t PUBSYM(lib_version) = G_LIB_VERSION; uint32_t PUBSYM(version) = 0; +static char autofill[] = "*"; static char optional[] = ""; static char flags[] = "C"; @@ -68,8 +69,8 @@ static void gpart_show(struct gctl_req * struct g_command PUBSYM(class_commands)[] = { { "add", 0, gpart_issue, { - { 'b', "start", NULL, G_TYPE_ASCLBA }, - { 's', "size", NULL, G_TYPE_ASCLBA }, + { 'b', "start", autofill, G_TYPE_ASCLBA }, + { 's', "size", autofill, G_TYPE_ASCLBA }, { 't', "type", NULL, G_TYPE_STRING }, { 'i', index_param, optional, G_TYPE_ASCNUM }, { 'l', "label", optional, G_TYPE_STRING }, @@ -240,6 +241,121 @@ fmtattrib(struct gprovider *pp) return (buf); } +static int +gpart_autofill(struct gctl_req *req) +{ + struct gmesh mesh; + struct gclass *cp; + struct ggeom *gp; + struct gprovider *pp; + unsigned long long first, last; + unsigned long long size, start; + unsigned long long lba, len, grade; + const char *s; + char *val; + int error, has_size, has_start; + + s = gctl_get_ascii(req, "verb"); + if (strcmp(s, "add") != 0) + return (0); + + s = gctl_get_ascii(req, "size"); + has_size = (*s == '*') ? 0 : 1; + size = (has_size) ? (unsigned long long)atoll(s) : 0ULL; + + s = gctl_get_ascii(req, "start"); + has_start = (*s == '*') ? 0 : 1; + start = (has_start) ? (unsigned long long)atoll(s) : ~0ULL; + + /* No autofill necessary. */ + if (has_size && has_start) + return (0); + + error = geom_gettree(&mesh); + if (error) + return (error); + cp = find_class(&mesh, gctl_get_ascii(req, "class")); + gp = find_geom(cp, gctl_get_ascii(req, "geom")); + first = atoll(find_geomcfg(gp, "first")); + last = atoll(find_geomcfg(gp, "last")); + grade = ~0ULL; + while ((pp = find_provider(gp, first)) != NULL) { + s = find_provcfg(pp, "start"); + if (s == NULL) { + s = find_provcfg(pp, "offset"); + lba = atoll(s) / pp->lg_sectorsize; + } else + lba = atoll(s); + + if (first < lba) { + /* Free space [first, lba> */ + len = lba - first; + if (has_size) { + if (len >= size && len - size < grade) { + start = first; + grade = len - size; + } + } else if (has_start) { + if (start >= first && start < lba) { + size = lba - start; + grade = start - first; + } + } else { + if (grade == ~0ULL || len > size) { + start = first; + size = len; + grade = 0; + } + } + } + + s = find_provcfg(pp, "end"); + if (s == NULL) { + s = find_provcfg(pp, "length"); + first = lba + atoll(s) / pp->lg_sectorsize; + } else + first = atoll(s) + 1; + } + if (first <= last) { + /* Free space [first-last] */ + len = last - first + 1; + if (has_size) { + if (len >= size && len - size < grade) { + start = first; + grade = len - size; + } + } else if (has_start) { + if (start >= first && start <= last) { + size = last - start + 1; + grade = start - first; + } + } else { + if (grade == ~0ULL || len > size) { + start = first; + size = len; + grade = 0; + } + } + } + + if (grade == ~0ULL) + return (ENOSPC); + + if (!has_size) { + asprintf(&val, "%jd", size); + if (val == NULL) + return (ENOMEM); + gctl_change_param(req, "size", -1, val); + } + if (!has_start) { + asprintf(&val, "%jd", start); + if (val == NULL) + return (ENOMEM); + gctl_change_param(req, "start", -1, val); + } + return (0); +} + static void gpart_show_geom(struct ggeom *gp, const char *element) { @@ -531,6 +647,14 @@ gpart_issue(struct gctl_req *req, unsign const char *errstr; int error, status; + /* autofill parameters (if applicable). */ + error = gpart_autofill(req); + if (error) { + warnc(error, "autofill"); + status = EXIT_FAILURE; + goto done; + } + bzero(buf, sizeof(buf)); gctl_rw_param(req, "output", sizeof(buf), buf); errstr = gctl_issue(req);