aboutsummaryrefslogtreecommitdiff
path: root/sbin/geom
diff options
context:
space:
mode:
authorSimon J. Gerraty <sjg@FreeBSD.org>2014-04-28 07:50:45 +0000
committerSimon J. Gerraty <sjg@FreeBSD.org>2014-04-28 07:50:45 +0000
commit3b8f08459569bf0faa21473e5cec2491e95c9349 (patch)
tree80f45dd81ca716bcd7ca9674581e1fc40b93cd34 /sbin/geom
parent9d2ab4a62d6733c45958627ac113bdbd818d1e2a (diff)
parentb2ba55951383498f252746f618d513139da06e8e (diff)
Notes
Diffstat (limited to 'sbin/geom')
-rw-r--r--sbin/geom/Makefile2
-rw-r--r--sbin/geom/class/eli/geom_eli.c2
-rw-r--r--sbin/geom/class/mirror/geom_mirror.c109
-rw-r--r--sbin/geom/class/mirror/gmirror.833
-rw-r--r--sbin/geom/class/part/geom_part.c49
-rw-r--r--sbin/geom/class/part/gpart.827
6 files changed, 210 insertions, 12 deletions
diff --git a/sbin/geom/Makefile b/sbin/geom/Makefile
index 88b82404e107..ced58425c657 100644
--- a/sbin/geom/Makefile
+++ b/sbin/geom/Makefile
@@ -9,7 +9,7 @@
PROG= geom
SRCS= geom.c geom_label.c geom_part.c subr.c
-NO_MAN=
+MAN=
WARNS?= 2
CFLAGS+=-I${.CURDIR} -I${.CURDIR}/core -DSTATIC_GEOM_CLASSES
diff --git a/sbin/geom/class/eli/geom_eli.c b/sbin/geom/class/eli/geom_eli.c
index 3eee6f249b54..7df4d905f4bc 100644
--- a/sbin/geom/class/eli/geom_eli.c
+++ b/sbin/geom/class/eli/geom_eli.c
@@ -789,7 +789,7 @@ eli_init(struct gctl_req *req)
if (val == 0)
md.md_sectorsize = secsize;
else {
- if (val < 0 || (val % secsize) != 0) {
+ if (val < 0 || (val % secsize) != 0 || !powerof2(val)) {
gctl_error(req, "Invalid sector size.");
return;
}
diff --git a/sbin/geom/class/mirror/geom_mirror.c b/sbin/geom/class/mirror/geom_mirror.c
index 9f0acc67aea3..30f5f8494556 100644
--- a/sbin/geom/class/mirror/geom_mirror.c
+++ b/sbin/geom/class/mirror/geom_mirror.c
@@ -28,6 +28,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <err.h>
#include <errno.h>
#include <paths.h>
#include <stdio.h>
@@ -53,6 +54,7 @@ static void mirror_activate(struct gctl_req *req);
static void mirror_clear(struct gctl_req *req);
static void mirror_dump(struct gctl_req *req);
static void mirror_label(struct gctl_req *req);
+static void mirror_resize(struct gctl_req *req, unsigned flags);
struct g_command class_commands[] = {
{ "activate", G_FLAG_VERBOSE, mirror_main, G_NULL_OPTS,
@@ -80,6 +82,13 @@ struct g_command class_commands[] = {
{ "deactivate", G_FLAG_VERBOSE, NULL, G_NULL_OPTS,
"[-v] name prov ..."
},
+ { "destroy", G_FLAG_VERBOSE, NULL,
+ {
+ { 'f', "force", NULL, G_TYPE_BOOL },
+ G_OPT_SENTINEL
+ },
+ "[-fv] name ..."
+ },
{ "dump", 0, mirror_main, G_NULL_OPTS,
"prov ..."
},
@@ -112,6 +121,13 @@ struct g_command class_commands[] = {
{ "remove", G_FLAG_VERBOSE, NULL, G_NULL_OPTS,
"[-v] name prov ..."
},
+ { "resize", G_FLAG_VERBOSE, mirror_resize,
+ {
+ { 's', "size", "*", G_TYPE_STRING },
+ G_OPT_SENTINEL
+ },
+ "[-s size] [-v] name"
+ },
{ "stop", G_FLAG_VERBOSE, NULL,
{
{ 'f', "force", NULL, G_TYPE_BOOL },
@@ -376,3 +392,96 @@ mirror_activate(struct gctl_req *req)
printf("Provider %s activated.\n", path);
}
}
+
+static struct gclass *
+find_class(struct gmesh *mesh, const char *name)
+{
+ struct gclass *classp;
+
+ LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
+ if (strcmp(classp->lg_name, name) == 0)
+ return (classp);
+ }
+ return (NULL);
+}
+
+static struct ggeom *
+find_geom(struct gclass *classp, const char *name)
+{
+ struct ggeom *gp;
+
+ LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
+ if (strcmp(gp->lg_name, name) == 0)
+ return (gp);
+ }
+ return (NULL);
+}
+
+static void
+mirror_resize(struct gctl_req *req, unsigned flags __unused)
+{
+ struct gmesh mesh;
+ struct gclass *classp;
+ struct ggeom *gp;
+ struct gprovider *pp;
+ struct gconsumer *cp;
+ off_t size;
+ int error, nargs;
+ const char *name;
+ char ssize[30];
+
+ nargs = gctl_get_int(req, "nargs");
+ if (nargs < 1) {
+ gctl_error(req, "Too few arguments.");
+ return;
+ }
+ error = geom_gettree(&mesh);
+ if (error)
+ errc(EXIT_FAILURE, error, "Cannot get GEOM tree");
+ name = gctl_get_ascii(req, "class");
+ if (name == NULL)
+ abort();
+ classp = find_class(&mesh, name);
+ if (classp == NULL)
+ errx(EXIT_FAILURE, "Class %s not found.", name);
+ name = gctl_get_ascii(req, "arg0");
+ if (name == NULL)
+ abort();
+ gp = find_geom(classp, name);
+ if (gp == NULL)
+ errx(EXIT_FAILURE, "No such geom: %s.", name);
+ pp = LIST_FIRST(&gp->lg_provider);
+ if (pp == NULL)
+ errx(EXIT_FAILURE, "Provider of geom %s not found.", name);
+ size = pp->lg_mediasize;
+ name = gctl_get_ascii(req, "size");
+ if (name == NULL)
+ errx(EXIT_FAILURE, "The size is not specified.");
+ if (*name == '*') {
+#define CSZ(c) ((c)->lg_provider->lg_mediasize - \
+ (c)->lg_provider->lg_sectorsize)
+ /* Find the maximum possible size */
+ LIST_FOREACH(cp, &gp->lg_consumer, lg_consumer) {
+ if (CSZ(cp) > size)
+ size = CSZ(cp);
+ }
+ LIST_FOREACH(cp, &gp->lg_consumer, lg_consumer) {
+ if (CSZ(cp) < size)
+ size = CSZ(cp);
+ }
+#undef CSZ
+ if (size == pp->lg_mediasize)
+ errx(EXIT_FAILURE,
+ "Cannot expand provider %s\n",
+ pp->lg_name);
+ } else {
+ error = g_parse_lba(name, pp->lg_sectorsize, &size);
+ if (error)
+ errc(EXIT_FAILURE, error, "Invalid size param");
+ size *= pp->lg_sectorsize;
+ }
+ snprintf(ssize, sizeof(ssize), "%ju", (uintmax_t)size);
+ gctl_change_param(req, "size", -1, ssize);
+ geom_deletetree(&mesh);
+ gctl_issue(req);
+}
diff --git a/sbin/geom/class/mirror/gmirror.8 b/sbin/geom/class/mirror/gmirror.8
index 58ff8afcbc4c..bca5bdba9749 100644
--- a/sbin/geom/class/mirror/gmirror.8
+++ b/sbin/geom/class/mirror/gmirror.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 8, 2009
+.Dd December 27, 2013
.Dt GMIRROR 8
.Os
.Sh NAME
@@ -60,6 +60,11 @@
.Ar name
.Ar prov ...
.Nm
+.Cm resize
+.Op Fl v
+.Op Fl s Ar size
+.Ar name
+.Nm
.Cm insert
.Op Fl hiv
.Op Fl p Ar priority
@@ -81,6 +86,10 @@
.Ar name
.Ar prov ...
.Nm
+.Cm destroy
+.Op Fl fv
+.Ar name ...
+.Nm
.Cm forget
.Op Fl v
.Ar name ...
@@ -193,6 +202,16 @@ balance algorithm.
Rebuild the given mirror components forcibly.
If autosynchronization was not turned off for the given device, this command
should be unnecessary.
+.It Cm resize
+Change the size of the given mirror.
+.Pp
+Additional options include:
+.Bl -tag -width ".Fl s Ar size"
+.It Fl s Ar size
+New size of the mirror is expressed in logical block numbers.
+This option can be omitted, then it will be automatically calculated to
+maximum available size.
+.El
.It Cm insert
Add the given component(s) to the existing mirror.
.Pp
@@ -212,6 +231,14 @@ Activate the given component(s), which were marked as inactive before.
.It Cm deactivate
Mark the given component(s) as inactive, so it will not be automatically
connected to the mirror.
+.It Cm destroy
+Stop the given mirror and clear metadata on all its components.
+.Pp
+Additional options include:
+.Bl -tag -width ".Fl f"
+.It Fl f
+Stop the given mirror even if it is opened.
+.El
.It Cm forget
Forget about components which are not connected.
This command is useful when a disk has failed and cannot be reconnected, preventing the
@@ -300,9 +327,7 @@ gmirror activate data da1
.Sh NOTES
Doing kernel dumps to
.Nm
-providers.
-.Pp
-This is possible, but some conditions have to be met.
+providers is possible, but some conditions have to be met.
First of all, a kernel dump will go only to one component and
.Nm
always chooses the component with the highest priority.
diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c
index 9b3e0e5e451b..ee4b2a939f82 100644
--- a/sbin/geom/class/part/geom_part.c
+++ b/sbin/geom/class/part/geom_part.c
@@ -364,7 +364,11 @@ gpart_autofill_resize(struct gctl_req *req)
}
offset = (pp->lg_stripeoffset / pp->lg_sectorsize) % alignment;
- last = (off_t)strtoimax(find_geomcfg(gp, "last"), NULL, 0);
+ s = find_geomcfg(gp, "last");
+ if (s == NULL)
+ errx(EXIT_FAILURE, "Final block not found for geom %s",
+ gp->lg_name);
+ last = (off_t)strtoimax(s, NULL, 0);
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
s = find_provcfg(pp, "index");
if (s == NULL)
@@ -450,8 +454,19 @@ gpart_autofill(struct gctl_req *req)
if (s == NULL)
abort();
gp = find_geom(cp, s);
- if (gp == NULL)
- errx(EXIT_FAILURE, "No such geom: %s.", s);
+ if (gp == NULL) {
+ if (g_device_path(s) == NULL) {
+ errx(EXIT_FAILURE, "No such geom %s.", s);
+ } else {
+ /*
+ * We don't free memory allocated by g_device_path() as
+ * we are about to exit.
+ */
+ errx(EXIT_FAILURE,
+ "No partitioning scheme found on geom %s. Create one first using 'gpart create'.",
+ s);
+ }
+ }
pp = LIST_FIRST(&gp->lg_consumer)->lg_provider;
if (pp == NULL)
errx(EXIT_FAILURE, "Provider for geom %s not found.", s);
@@ -502,8 +517,16 @@ gpart_autofill(struct gctl_req *req)
if (size > alignment)
size = ALIGNDOWN(size, alignment);
- first = (off_t)strtoimax(find_geomcfg(gp, "first"), NULL, 0);
- last = (off_t)strtoimax(find_geomcfg(gp, "last"), NULL, 0);
+ s = find_geomcfg(gp, "first");
+ if (s == NULL)
+ errx(EXIT_FAILURE, "Starting block not found for geom %s",
+ gp->lg_name);
+ first = (off_t)strtoimax(s, NULL, 0);
+ s = find_geomcfg(gp, "last");
+ if (s == NULL)
+ errx(EXIT_FAILURE, "Final block not found for geom %s",
+ gp->lg_name);
+ last = (off_t)strtoimax(s, NULL, 0);
grade = ~0ULL;
a_first = ALIGNUP(first + offset, alignment);
last = ALIGNDOWN(last + offset, alignment);
@@ -587,12 +610,22 @@ gpart_show_geom(struct ggeom *gp, const char *element, int show_providers)
int idx, wblocks, wname, wmax;
scheme = find_geomcfg(gp, "scheme");
+ if (scheme == NULL)
+ errx(EXIT_FAILURE, "Scheme not found for geom %s", gp->lg_name);
s = find_geomcfg(gp, "first");
+ if (s == NULL)
+ errx(EXIT_FAILURE, "Starting block not found for geom %s",
+ gp->lg_name);
first = (off_t)strtoimax(s, NULL, 0);
s = find_geomcfg(gp, "last");
+ if (s == NULL)
+ errx(EXIT_FAILURE, "Final block not found for geom %s",
+ gp->lg_name);
last = (off_t)strtoimax(s, NULL, 0);
wblocks = strlen(s);
s = find_geomcfg(gp, "state");
+ if (s == NULL)
+ errx(EXIT_FAILURE, "State not found for geom %s", gp->lg_name);
if (s != NULL && *s != 'C')
s = NULL;
wmax = strlen(gp->lg_name);
@@ -748,6 +781,8 @@ gpart_backup(struct gctl_req *req, unsigned int fl __unused)
abort();
pp = LIST_FIRST(&gp->lg_consumer)->lg_provider;
s = find_geomcfg(gp, "last");
+ if (s == NULL)
+ abort();
wblocks = strlen(s);
wtype = 0;
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
@@ -757,6 +792,8 @@ gpart_backup(struct gctl_req *req, unsigned int fl __unused)
wtype = i;
}
s = find_geomcfg(gp, "entries");
+ if (s == NULL)
+ abort();
windex = strlen(s);
printf("%s %s\n", scheme, s);
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
@@ -1177,6 +1214,8 @@ gpart_bootcode(struct gctl_req *req, unsigned int fl)
if (gp == NULL)
errx(EXIT_FAILURE, "No such geom: %s.", s);
s = find_geomcfg(gp, "scheme");
+ if (s == NULL)
+ errx(EXIT_FAILURE, "Scheme not found for geom %s", gp->lg_name);
vtoc8 = 0;
if (strcmp(s, "VTOC8") == 0)
vtoc8 = 1;
diff --git a/sbin/geom/class/part/gpart.8 b/sbin/geom/class/part/gpart.8
index 3ce79a847213..194a19fdf46a 100644
--- a/sbin/geom/class/part/gpart.8
+++ b/sbin/geom/class/part/gpart.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 1, 2013
+.Dd April 2, 2014
.Dt GPART 8
.Os
.Sh NAME
@@ -557,6 +557,16 @@ Interface (EFI).
In such cases, the GPT partitioning scheme is used and the
actual partition type for the system partition can also be specified as
.Qq Li "!c12a7328-f81f-11d2-ba4b-00a0c93ec93b" .
+.It Cm fat16
+A partition that contains a FAT16 filesystem.
+The scheme-specific type is
+.Qq Li "!6"
+for MBR.
+.It Cm fat32
+A partition that contains a FAT32 filesystem.
+The scheme-specific type is
+.Qq Li "!11"
+for MBR.
.It Cm freebsd
A
.Fx
@@ -620,6 +630,16 @@ A partition that is sub-partitioned by a Master Boot Record (MBR).
This type is known as
.Qq Li "!024dee41-33e7-11d3-9d69-0008c781f39f"
by GPT.
+.It Cm ms-basic-data
+A basic data partition (BDP) for Microsoft operating systems.
+In the GPT this type is the equivalent to partition types
+.Cm fat16 , fat32
+and
+.Cm ntfs
+in MBR.
+The scheme-specific type is
+.Qq Li "!ebd0a0a2-b9e5-4433-87c0-68b6b72699c7"
+for GPT.
.It Cm ms-ldm-data
A partition that contains Logical Disk Manager (LDM) volumes.
The scheme-specific types are
@@ -632,6 +652,11 @@ A partition that contains Logical Disk Manager (LDM) database.
The scheme-specific type is
.Qq Li "!5808c8aa-7e8f-42e0-85d2-e1e90434cfb3"
for GPT.
+.It Cm ntfs
+A partition that contains a NTFS or exFAT filesystem.
+The scheme-specific type is
+.Qq Li "!7"
+for MBR.
.El
.Sh ATTRIBUTES
The scheme-specific attributes for EBR: