summaryrefslogtreecommitdiffstats
path: root/sbin/geom
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2010-06-21 08:24:50 +0000
committerae <ae@FreeBSD.org>2010-06-21 08:24:50 +0000
commit9f1bacec49f4b54e6b0bc73e3c3f509802f86148 (patch)
tree9dd1dea00f2542fb485d8c429ca1f7be1c43fd76 /sbin/geom
parentd1175426d7bcb8aeacdb7416e281e63e668da297 (diff)
downloadFreeBSD-src-9f1bacec49f4b54e6b0bc73e3c3f509802f86148.zip
FreeBSD-src-9f1bacec49f4b54e6b0bc73e3c3f509802f86148.tar.gz
Remove G_TYPE_ASCLBA type and replace it with G_TYPE_STRING in gpart.
Move code that converts params from humanized numbers to sectors count to subr.c and adjust comment. Add post-processing for "size" and "start offset" params in gpart, now they are properly converted to sectors count with known sector size that can be greater that 512 bytes. Also replace "unsigned long long" type to "off_t" for unify code since it used for medium size in libgeom(3) and DIOCGMEDIASIZE ioctl. PR: bin/146277 Reviewed by: marcel (previous version) Approved by: kib (mentor) MFC after: 1 month
Diffstat (limited to 'sbin/geom')
-rw-r--r--sbin/geom/class/part/geom_part.c204
-rw-r--r--sbin/geom/core/geom.c91
-rw-r--r--sbin/geom/core/geom.h1
-rw-r--r--sbin/geom/misc/subr.c90
-rw-r--r--sbin/geom/misc/subr.h1
5 files changed, 210 insertions, 177 deletions
diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c
index a72155b..cc1145e 100644
--- a/sbin/geom/class/part/geom_part.c
+++ b/sbin/geom/class/part/geom_part.c
@@ -40,6 +40,8 @@ __FBSDID("$FreeBSD$");
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <limits.h>
+#include <inttypes.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
@@ -60,6 +62,9 @@ static char autofill[] = "*";
static char optional[] = "";
static char flags[] = "C";
+static char sstart[32];
+static char ssize[32];
+
static const char const bootcode_param[] = "bootcode";
static const char const index_param[] = "index";
static const char const partcode_param[] = "partcode";
@@ -68,8 +73,7 @@ static struct gclass *find_class(struct gmesh *, const char *);
static struct ggeom * find_geom(struct gclass *, const char *);
static const char *find_geomcfg(struct ggeom *, const char *);
static const char *find_provcfg(struct gprovider *, const char *);
-static struct gprovider *find_provider(struct ggeom *,
- unsigned long long);
+static struct gprovider *find_provider(struct ggeom *, off_t);
static const char *fmtsize(int64_t);
static int gpart_autofill(struct gctl_req *);
static int gpart_autofill_resize(struct gctl_req *);
@@ -84,8 +88,8 @@ static void gpart_write_partcode_vtoc8(struct ggeom *, int, void *);
struct g_command PUBSYM(class_commands)[] = {
{ "add", 0, gpart_issue, {
- { 'b', "start", autofill, G_TYPE_ASCLBA },
- { 's', "size", autofill, G_TYPE_ASCLBA },
+ { 'b', "start", autofill, G_TYPE_STRING },
+ { 's', "size", autofill, G_TYPE_STRING },
{ 't', "type", NULL, G_TYPE_STRING },
{ 'i', index_param, optional, G_TYPE_ASCNUM },
{ 'l', "label", optional, G_TYPE_STRING },
@@ -149,7 +153,7 @@ struct g_command PUBSYM(class_commands)[] = {
"geom", NULL
},
{ "resize", 0, gpart_issue, {
- { 's', "size", autofill, G_TYPE_ASCLBA },
+ { 's', "size", autofill, G_TYPE_STRING },
{ 'i', index_param, NULL, G_TYPE_ASCNUM },
{ 'f', "flags", flags, G_TYPE_STRING },
G_OPT_SENTINEL },
@@ -207,11 +211,11 @@ find_provcfg(struct gprovider *pp, const char *cfg)
}
static struct gprovider *
-find_provider(struct ggeom *gp, unsigned long long minsector)
+find_provider(struct ggeom *gp, off_t minsector)
{
struct gprovider *pp, *bestpp;
const char *s;
- unsigned long long sector, bestsector;
+ off_t sector, bestsector;
bestpp = NULL;
bestsector = 0;
@@ -219,9 +223,10 @@ find_provider(struct ggeom *gp, unsigned long long minsector)
s = find_provcfg(pp, "start");
if (s == NULL) {
s = find_provcfg(pp, "offset");
- sector = atoll(s) / pp->lg_sectorsize;
+ sector =
+ (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
} else
- sector = atoll(s);
+ sector = (off_t)strtoimax(s, NULL, 0);
if (sector < minsector)
continue;
@@ -271,18 +276,12 @@ gpart_autofill_resize(struct gctl_req *req)
struct gclass *cp;
struct ggeom *gp;
struct gprovider *pp;
- unsigned long long last, size, start, new_size;
- unsigned long long lba, new_lba;
+ off_t last, size, start, new_size;
+ off_t lba, new_lba;
const char *s;
char *val;
int error, idx;
- s = gctl_get_ascii(req, "size");
- if (*s == '*')
- new_size = (unsigned long long)atoll(s);
- else
- return (0);
-
s = gctl_get_ascii(req, index_param);
idx = strtol(s, &val, 10);
if (idx < 1 || *s == '\0' || *val != '\0')
@@ -303,8 +302,22 @@ gpart_autofill_resize(struct gctl_req *req)
gp = find_geom(cp, s);
if (gp == NULL)
errx(EXIT_FAILURE, "No such geom: %s.", s);
- last = atoll(find_geomcfg(gp, "last"));
+ pp = LIST_FIRST(&gp->lg_consumer)->lg_provider;
+ if (pp == NULL)
+ errx(EXIT_FAILURE, "Provider for geom %s not found.", s);
+
+ s = gctl_get_ascii(req, "size");
+ if (*s == '*')
+ new_size = 0;
+ else {
+ error = g_parse_lba(s, pp->lg_sectorsize, &new_size);
+ if (error)
+ errc(EXIT_FAILURE, error, "Invalid size param");
+ /* no autofill necessary. */
+ goto done;
+ }
+ last = (off_t)strtoimax(find_geomcfg(gp, "last"), NULL, 0);
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
s = find_provcfg(pp, "index");
if (s == NULL)
@@ -318,18 +331,21 @@ gpart_autofill_resize(struct gctl_req *req)
s = find_provcfg(pp, "start");
if (s == NULL) {
s = find_provcfg(pp, "offset");
- start = atoll(s) / pp->lg_sectorsize;
+ start = (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
} else
- start = atoll(s);
+ start = (off_t)strtoimax(s, NULL, 0);
s = find_provcfg(pp, "end");
if (s == NULL) {
s = find_provcfg(pp, "length");
- lba = start + atoll(s) / pp->lg_sectorsize;
+ lba = start +
+ (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
} else
- lba = atoll(s) + 1;
+ lba = (off_t)strtoimax(s, NULL, 0) + 1;
- if (lba > last)
+ if (lba > last) {
+ geom_deletetree(&mesh);
return (ENOSPC);
+ }
size = lba - start;
pp = find_provider(gp, lba);
if (pp == NULL)
@@ -338,22 +354,25 @@ gpart_autofill_resize(struct gctl_req *req)
s = find_provcfg(pp, "start");
if (s == NULL) {
s = find_provcfg(pp, "offset");
- new_lba = atoll(s) / pp->lg_sectorsize;
+ new_lba =
+ (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
} else
- new_lba = atoll(s);
- /* Is there any free space between current and
+ new_lba = (off_t)strtoimax(s, NULL, 0);
+ /*
+ * Is there any free space between current and
* next providers?
*/
if (new_lba > lba)
new_size = new_lba - start;
- else
+ else {
+ geom_deletetree(&mesh);
return (ENOSPC);
+ }
}
- asprintf(&val, "%llu", new_size);
- if (val == NULL)
- return (ENOMEM);
- gctl_change_param(req, "size", -1, val);
-
+done:
+ snprintf(ssize, sizeof(ssize), "%jd", (intmax_t)new_size);
+ gctl_change_param(req, "size", -1, ssize);
+ geom_deletetree(&mesh);
return (0);
}
@@ -364,11 +383,11 @@ gpart_autofill(struct gctl_req *req)
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;
+ off_t first, last;
+ off_t size, start;
+ off_t lba, len;
+ uintmax_t grade;
const char *s;
- char *val;
int error, has_size, has_start;
s = gctl_get_ascii(req, "verb");
@@ -377,18 +396,6 @@ gpart_autofill(struct gctl_req *req)
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);
@@ -404,22 +411,49 @@ gpart_autofill(struct gctl_req *req)
gp = find_geom(cp, s);
if (gp == NULL)
errx(EXIT_FAILURE, "No such geom: %s.", s);
- first = atoll(find_geomcfg(gp, "first"));
- last = atoll(find_geomcfg(gp, "last"));
+ pp = LIST_FIRST(&gp->lg_consumer)->lg_provider;
+ if (pp == NULL)
+ errx(EXIT_FAILURE, "Provider for geom %s not found.", s);
+
+ s = gctl_get_ascii(req, "size");
+ has_size = (*s == '*') ? 0 : 1;
+ size = 0;
+ if (has_size) {
+ error = g_parse_lba(s, pp->lg_sectorsize, &size);
+ if (error)
+ errc(EXIT_FAILURE, error, "Invalid size param");
+ }
+
+ s = gctl_get_ascii(req, "start");
+ has_start = (*s == '*') ? 0 : 1;
+ start = 0ULL;
+ if (has_start) {
+ error = g_parse_lba(s, pp->lg_sectorsize, &start);
+ if (error)
+ errc(EXIT_FAILURE, error, "Invalid start param");
+ }
+
+ /* No autofill necessary. */
+ if (has_size && has_start)
+ goto done;
+
+ first = (off_t)strtoimax(find_geomcfg(gp, "first"), NULL, 0);
+ last = (off_t)strtoimax(find_geomcfg(gp, "last"), NULL, 0);
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;
+ lba = (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
} else
- lba = atoll(s);
+ lba = (off_t)strtoimax(s, NULL, 0);
if (first < lba) {
/* Free space [first, lba> */
len = lba - first;
if (has_size) {
- if (len >= size && len - size < grade) {
+ if (len >= size &&
+ (uintmax_t)(len - size) < grade) {
start = first;
grade = len - size;
}
@@ -440,15 +474,17 @@ gpart_autofill(struct gctl_req *req)
s = find_provcfg(pp, "end");
if (s == NULL) {
s = find_provcfg(pp, "length");
- first = lba + atoll(s) / pp->lg_sectorsize;
+ first = lba +
+ (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
} else
- first = atoll(s) + 1;
+ first = (off_t)strtoimax(s, NULL, 0) + 1;
}
if (first <= last) {
/* Free space [first-last] */
len = last - first + 1;
if (has_size) {
- if (len >= size && len - size < grade) {
+ if (len >= size &&
+ (uintmax_t)(len - size) < grade) {
start = first;
grade = len - size;
}
@@ -466,21 +502,17 @@ gpart_autofill(struct gctl_req *req)
}
}
- if (grade == ~0ULL)
+ if (grade == ~0ULL) {
+ geom_deletetree(&mesh);
return (ENOSPC);
-
- if (!has_size) {
- asprintf(&val, "%llu", size);
- if (val == NULL)
- return (ENOMEM);
- gctl_change_param(req, "size", -1, val);
- }
- if (!has_start) {
- asprintf(&val, "%llu", start);
- if (val == NULL)
- return (ENOMEM);
- gctl_change_param(req, "start", -1, val);
}
+
+done:
+ snprintf(ssize, sizeof(ssize), "%jd", (intmax_t)size);
+ gctl_change_param(req, "size", -1, ssize);
+ snprintf(sstart, sizeof(sstart), "%jd", (intmax_t)start);
+ gctl_change_param(req, "start", -1, sstart);
+ geom_deletetree(&mesh);
return (0);
}
@@ -489,21 +521,21 @@ gpart_show_geom(struct ggeom *gp, const char *element)
{
struct gprovider *pp;
const char *s, *scheme;
- unsigned long long first, last, sector, end;
- unsigned long long length, secsz;
+ off_t first, last, sector, end;
+ off_t length, secsz;
int idx, wblocks, wname;
scheme = find_geomcfg(gp, "scheme");
s = find_geomcfg(gp, "first");
- first = atoll(s);
+ first = (off_t)strtoimax(s, NULL, 0);
s = find_geomcfg(gp, "last");
- last = atoll(s);
+ last = (off_t)strtoimax(s, NULL, 0);
wblocks = strlen(s);
wname = strlen(gp->lg_name);
pp = LIST_FIRST(&gp->lg_consumer)->lg_provider;
secsz = pp->lg_sectorsize;
- printf("=>%*llu %*llu %*s %s (%s)\n",
- wblocks, first, wblocks, (last - first + 1),
+ printf("=>%*jd %*jd %*s %s (%s)\n",
+ wblocks, (intmax_t)first, wblocks, (intmax_t)(last - first + 1),
wname, gp->lg_name,
scheme, fmtsize(pp->lg_mediasize));
@@ -511,37 +543,37 @@ gpart_show_geom(struct ggeom *gp, const char *element)
s = find_provcfg(pp, "start");
if (s == NULL) {
s = find_provcfg(pp, "offset");
- sector = atoll(s) / secsz;
+ sector = (off_t)strtoimax(s, NULL, 0) / secsz;
} else
- sector = atoll(s);
+ sector = (off_t)strtoimax(s, NULL, 0);
s = find_provcfg(pp, "end");
if (s == NULL) {
s = find_provcfg(pp, "length");
- length = atoll(s) / secsz;
+ length = (off_t)strtoimax(s, NULL, 0) / secsz;
end = sector + length - 1;
} else {
- end = atoll(s);
+ end = (off_t)strtoimax(s, NULL, 0);
length = end - sector + 1;
}
s = find_provcfg(pp, "index");
idx = atoi(s);
if (first < sector) {
- printf(" %*llu %*llu %*s - free - (%s)\n",
- wblocks, first, wblocks, sector - first,
- wname, "",
+ printf(" %*jd %*jd %*s - free - (%s)\n",
+ wblocks, (intmax_t)first, wblocks,
+ (intmax_t)(sector - first), wname, "",
fmtsize((sector - first) * secsz));
}
- printf(" %*llu %*llu %*d %s %s (%s)\n",
- wblocks, sector, wblocks, length,
+ printf(" %*jd %*jd %*d %s %s (%s)\n",
+ wblocks, (intmax_t)sector, wblocks, (intmax_t)length,
wname, idx, find_provcfg(pp, element),
fmtattrib(pp), fmtsize(pp->lg_mediasize));
first = end + 1;
}
if (first <= last) {
length = last - first + 1;
- printf(" %*llu %*llu %*s - free - (%s)\n",
- wblocks, first, wblocks, length,
+ printf(" %*jd %*jd %*s - free - (%s)\n",
+ wblocks, (intmax_t)first, wblocks, (intmax_t)length,
wname, "",
fmtsize(length * secsz));
}
diff --git a/sbin/geom/core/geom.c b/sbin/geom/core/geom.c
index 66f2a8f..49ebdc5 100644
--- a/sbin/geom/core/geom.c
+++ b/sbin/geom/core/geom.c
@@ -259,94 +259,6 @@ set_option(struct gctl_req *req, struct g_option *opt, const char *val)
opt->go_val);
} else
gctl_ro_param(req, opt->go_name, -1, opt->go_val);
- } else if (G_OPT_TYPE(opt) == G_TYPE_ASCLBA) {
- /*
- * LBAs are ugly. The argument is a sector. The size of a
- * sector is context specific (i.e. determined by the media),
- * which we don't know here. But when users enter a value
- * with a SI unit, they really mean the byte-size or byte-
- * offset and not the size or offset in sectors.
- * So how can we map the byte-oriented value into a sector-
- * oriented value if we don't know the sector size in bytes?
- * The approach taken here is:
- * o Sectors are 512 bytes in size. Mostly the case anyway.
- * o When no SI unit is specified the value is in sectors.
- * o With an SI unit the value is in bytes.
- * o The 'b' suffix forces byte interpretation and the 's'
- * suffix forces sector interpretation.
- *
- * Thus:
- * o 2 and 2s mean 2 sectors, and 2b means 2 bytes.
- * o 4k and 4kb mean 4096 bytes, and 4ks means 4096 sectors.
- *
- * "This seemed like a good idea at the time"
- */
- intmax_t mult, unit;
-
- number = strtoimax(val, &s, 0);
- if (s == val)
- errc(EXIT_FAILURE, EINVAL, "argument '%c'",
- opt->go_char);
- mult = 1;
- unit = 512; /* sector */
- if (*s == '\0')
- goto done;
- switch (*s) {
- case 'e': case 'E':
- mult *= 1024;
- /*FALLTHROUGH*/
- case 'p': case 'P':
- mult *= 1024;
- /*FALLTHROUGH*/
- case 't': case 'T':
- mult *= 1024;
- /*FALLTHROUGH*/
- case 'g': case 'G':
- mult *= 1024;
- /*FALLTHROUGH*/
- case 'm': case 'M':
- mult *= 1024;
- /*FALLTHROUGH*/
- case 'k': case 'K':
- mult *= 1024;
- break;
- default:
- goto sfx;
- }
- unit = 1; /* bytes */
- s++;
- if (*s == '\0')
- goto done;
-sfx:
- switch (*s) {
- case 's': case 'S':
- unit = 512; /* sector */
- break;
- case 'b': case 'B':
- unit = 1; /* bytes */
- break;
- default:
- errc(EXIT_FAILURE, EINVAL, "argument '%c': suffix '%c'",
- opt->go_char, *s);
- }
- s++;
- if (*s != '\0')
- errx(EXIT_FAILURE, "argument '%c': junk at end (%s)",
- opt->go_char, s);
-done:
- if (mult * unit < mult || number * mult * unit < number)
- errc(EXIT_FAILURE, ERANGE, "argument '%c'",
- opt->go_char);
- number *= mult * unit;
- if (number % 512)
- errx(EXIT_FAILURE, "argument '%c': "
- "not a valid block address", opt->go_char);
- number /= 512;
- asprintf(&s, "%jd", number);
- if (s == NULL)
- err(EXIT_FAILURE, NULL);
- opt->go_val = s;
- gctl_ro_param(req, opt->go_name, -1, s);
} else if (G_OPT_TYPE(opt) == G_TYPE_STRING) {
gctl_ro_param(req, opt->go_name, -1, val);
} else if (G_OPT_TYPE(opt) == G_TYPE_BOOL) {
@@ -439,8 +351,7 @@ parse_arguments(struct g_command *cmd, struct gctl_req *req, int *argc,
gctl_ro_param(req, opt->go_name,
sizeof(intmax_t), opt->go_val);
} else if (G_OPT_TYPE(opt) == G_TYPE_STRING ||
- G_OPT_TYPE(opt) == G_TYPE_ASCNUM ||
- G_OPT_TYPE(opt) == G_TYPE_ASCLBA) {
+ G_OPT_TYPE(opt) == G_TYPE_ASCNUM) {
if (cmd->gc_argname == NULL ||
opt->go_val == NULL ||
*(char *)opt->go_val != '\0')
diff --git a/sbin/geom/core/geom.h b/sbin/geom/core/geom.h
index 5c25311..424695b 100644
--- a/sbin/geom/core/geom.h
+++ b/sbin/geom/core/geom.h
@@ -39,7 +39,6 @@
#define G_TYPE_STRING 0x02
#define G_TYPE_NUMBER 0x03
#define G_TYPE_ASCNUM 0x04
-#define G_TYPE_ASCLBA 0x05
#define G_TYPE_MASK 0x0f
#define G_TYPE_DONE 0x10
diff --git a/sbin/geom/misc/subr.c b/sbin/geom/misc/subr.c
index e71ec74..7a4786f 100644
--- a/sbin/geom/misc/subr.c
+++ b/sbin/geom/misc/subr.c
@@ -36,6 +36,8 @@ __FBSDID("$FreeBSD$");
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
+#include <limits.h>
+#include <inttypes.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
@@ -107,6 +109,94 @@ bitcount32(uint32_t x)
return (x);
}
+/*
+ * The size of a sector is context specific (i.e. determined by the
+ * media). But when users enter a value with a SI unit, they really
+ * mean the byte-size or byte-offset and not the size or offset in
+ * sectors. We should map the byte-oriented value into a sector-oriented
+ * value when we already know the sector size in bytes. At this time
+ * we can use g_parse_lba() function. It converts user specified
+ * value into sectors with following conditions:
+ * o Sectors size taken as argument from caller.
+ * o When no SI unit is specified the value is in sectors.
+ * o With an SI unit the value is in bytes.
+ * o The 'b' suffix forces byte interpretation and the 's'
+ * suffix forces sector interpretation.
+ *
+ * Thus:
+ * o 2 and 2s mean 2 sectors, and 2b means 2 bytes.
+ * o 4k and 4kb mean 4096 bytes, and 4ks means 4096 sectors.
+ *
+ */
+int
+g_parse_lba(const char *lbastr, unsigned sectorsize, off_t *sectors)
+{
+ off_t number, mult, unit;
+ char *s;
+
+ assert(lbastr != NULL);
+ assert(sectorsize > 0);
+ assert(sectors != NULL);
+
+ number = (off_t)strtoimax(lbastr, &s, 0);
+ if (s == lbastr)
+ return (EINVAL);
+
+ mult = 1;
+ unit = sectorsize;
+ if (*s == '\0')
+ goto done;
+ switch (*s) {
+ case 'e': case 'E':
+ mult *= 1024;
+ /* FALLTHROUGH */
+ case 'p': case 'P':
+ mult *= 1024;
+ /* FALLTHROUGH */
+ case 't': case 'T':
+ mult *= 1024;
+ /* FALLTHROUGH */
+ case 'g': case 'G':
+ mult *= 1024;
+ /* FALLTHROUGH */
+ case 'm': case 'M':
+ mult *= 1024;
+ /* FALLTHROUGH */
+ case 'k': case 'K':
+ mult *= 1024;
+ break;
+ default:
+ goto sfx;
+ }
+ unit = 1; /* bytes */
+ s++;
+ if (*s == '\0')
+ goto done;
+sfx:
+ switch (*s) {
+ case 's': case 'S':
+ unit = sectorsize; /* sector */
+ break;
+ case 'b': case 'B':
+ unit = 1; /* bytes */
+ break;
+ default:
+ return (EINVAL);
+ }
+ s++;
+ if (*s != '\0')
+ return (EINVAL);
+done:
+ if (mult * unit < mult || number * mult * unit < number)
+ return (ERANGE);
+ number *= mult * unit;
+ if (number % sectorsize)
+ return (EINVAL);
+ number /= sectorsize;
+ *sectors = number;
+ return (0);
+}
+
off_t
g_get_mediasize(const char *name)
{
diff --git a/sbin/geom/misc/subr.h b/sbin/geom/misc/subr.h
index c3242a3..2b43bdb 100644
--- a/sbin/geom/misc/subr.h
+++ b/sbin/geom/misc/subr.h
@@ -32,6 +32,7 @@
unsigned g_lcm(unsigned a, unsigned b);
uint32_t bitcount32(uint32_t x);
+int g_parse_lba(const char *lbastr, unsigned sectorsize, off_t *sectors);
off_t g_get_mediasize(const char *name);
unsigned g_get_sectorsize(const char *name);
OpenPOWER on IntegriCloud