Make the size (-s) and start (-b) parameters of the add verb optional.
The missing parameter(s) are automatically filled-in.
This commit is contained in:
parent
40420f94ac
commit
87bc9febc2
@ -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 *, unsigned int);
|
||||
|
||||
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, unsigned int fl __unused)
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user