summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS1
-rw-r--r--etc/mtree/BSD.include.dist2
-rw-r--r--include/Makefile2
-rw-r--r--sbin/geom/class/Makefile1
-rw-r--r--sbin/geom/class/label/Makefile7
-rw-r--r--sbin/geom/class/label/geom_label.c187
-rw-r--r--sbin/geom/class/label/glabel.8182
-rw-r--r--sys/conf/NOTES1
-rw-r--r--sys/conf/files4
-rw-r--r--sys/conf/options1
-rw-r--r--sys/geom/label/g_label.c405
-rw-r--r--sys/geom/label/g_label.h97
-rw-r--r--sys/geom/label/g_label_iso9660.c80
-rw-r--r--sys/geom/label/g_label_msdosfs.c101
-rw-r--r--sys/geom/label/g_label_ufs.c102
-rw-r--r--sys/modules/geom/Makefile1
-rw-r--r--sys/modules/geom/geom_label/Makefile11
17 files changed, 1184 insertions, 1 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 553a8e6..41a7882 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -93,6 +93,7 @@ contrib/pf mlaier Pre-commit review requested.
binutils obrien Insists on BU blocked from unapproved commits
geom_concat pjd Pre-commit review requested.
geom_gate pjd Pre-commit review requested.
+geom_label pjd Pre-commit review requested.
geom_nop pjd Pre-commit review requested.
geom_stripe pjd Pre-commit review requested.
sbin/geom pjd Pre-commit review requested.
diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist
index 590696f..f9a0f7a 100644
--- a/etc/mtree/BSD.include.dist
+++ b/etc/mtree/BSD.include.dist
@@ -84,6 +84,8 @@
..
gate
..
+ label
+ ..
nop
..
stripe
diff --git a/include/Makefile b/include/Makefile
index f4d78dff..130e226 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -35,7 +35,7 @@ LSUBDIRS= cam/scsi dev/an dev/bktr dev/firewire dev/ic dev/iicbus \
dev/ofw dev/ppbus dev/smbus dev/usb dev/wi dev/utopia fs/devfs \
fs/fdescfs fs/fifofs fs/msdosfs fs/ntfs fs/nullfs fs/nwfs fs/portalfs \
fs/procfs fs/smbfs fs/udf fs/umapfs fs/unionfs \
- geom/concat geom/gate geom/nop geom/stripe \
+ geom/concat geom/gate geom/label geom/nop geom/stripe \
isofs/cd9660 netatm/ipatm netatm/sigpvc netatm/spans netatm/uni \
netgraph/atm security/mac_biba security/mac_bsdextended \
security/mac_lomac security/mac_mls security/mac_partition \
diff --git a/sbin/geom/class/Makefile b/sbin/geom/class/Makefile
index 71edcf7..7044661 100644
--- a/sbin/geom/class/Makefile
+++ b/sbin/geom/class/Makefile
@@ -1,6 +1,7 @@
# $FreeBSD$
SUBDIR= concat
+SUBDIR+=label
SUBDIR+=nop
SUBDIR+=stripe
diff --git a/sbin/geom/class/label/Makefile b/sbin/geom/class/label/Makefile
new file mode 100644
index 0000000..cba7ac6
--- /dev/null
+++ b/sbin/geom/class/label/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../misc
+
+CLASS= label
+
+.include <bsd.lib.mk>
diff --git a/sbin/geom/class/label/geom_label.c b/sbin/geom/class/label/geom_label.c
new file mode 100644
index 0000000..bbd6e7f
--- /dev/null
+++ b/sbin/geom/class/label/geom_label.c
@@ -0,0 +1,187 @@
+/*-
+ * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <assert.h>
+#include <libgeom.h>
+#include <geom/label/g_label.h>
+
+#include "core/geom.h"
+#include "misc/subr.h"
+
+
+uint32_t lib_version = G_LIB_VERSION;
+uint32_t version = G_LABEL_VERSION;
+
+static void label_main(struct gctl_req *req, unsigned flags);
+static void label_label(struct gctl_req *req);
+static void label_clear(struct gctl_req *req);
+
+struct g_command class_commands[] = {
+ { "create", G_FLAG_VERBOSE | G_FLAG_LOADKLD, NULL, G_NULL_OPTS },
+ { "destroy", G_FLAG_VERBOSE, NULL,
+ {
+ { 'f', "force", NULL, G_TYPE_NONE },
+ G_OPT_SENTINEL
+ }
+ },
+ { "label", G_FLAG_VERBOSE | G_FLAG_LOADKLD, label_main, G_NULL_OPTS },
+ { "clear", G_FLAG_VERBOSE, label_main, G_NULL_OPTS },
+ G_CMD_SENTINEL
+};
+
+static int verbose = 0;
+
+
+void usage(const char *name);
+void
+usage(const char *name)
+{
+
+ fprintf(stderr, "usage: %s create [-v] <name> <dev>\n", name);
+ fprintf(stderr, " %s destroy [-fv] <name> [name2 [...]]\n", name);
+ fprintf(stderr, " %s label [-v] <name> <dev>\n", name);
+ fprintf(stderr, " %s clear [-v] <dev1> [dev2 [...]]\n", name);
+}
+
+static void
+label_main(struct gctl_req *req, unsigned flags)
+{
+ const char *name;
+
+ if ((flags & G_FLAG_VERBOSE) != 0)
+ verbose = 1;
+
+ name = gctl_get_asciiparam(req, "verb");
+ if (name == NULL) {
+ gctl_error(req, "No '%s' argument.", "verb");
+ return;
+ }
+ if (strcmp(name, "label") == 0)
+ label_label(req);
+ else if (strcmp(name, "clear") == 0)
+ label_clear(req);
+ else
+ gctl_error(req, "Unknown command: %s.", name);
+}
+
+static void
+label_label(struct gctl_req *req)
+{
+ struct g_label_metadata md;
+ const char *name, *label;
+ u_char sector[512];
+ int *nargs, error;
+
+ nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
+ if (nargs == NULL) {
+ gctl_error(req, "No '%s' argument.", "nargs");
+ return;
+ }
+ if (*nargs != 2) {
+ gctl_error(req, "Invalid number of arguments.");
+ return;
+ }
+
+ /*
+ * Clear last sector first to spoil all components if device exists.
+ */
+ name = gctl_get_asciiparam(req, "arg1");
+ if (name == NULL) {
+ gctl_error(req, "No 'arg%u' argument.", 1);
+ return;
+ }
+ error = g_metadata_clear(name, NULL);
+ if (error != 0) {
+ gctl_error(req, "Can't store metadata on %s: %s.", name,
+ strerror(error));
+ return;
+ }
+
+ strlcpy(md.md_magic, G_LABEL_MAGIC, sizeof(md.md_magic));
+ md.md_version = G_LABEL_VERSION;
+ label = gctl_get_asciiparam(req, "arg0");
+ if (label == NULL) {
+ gctl_error(req, "No 'arg%u' argument.", 0);
+ return;
+ }
+ strlcpy(md.md_label, label, sizeof(md.md_label));
+
+ /*
+ * Ok, store metadata.
+ */
+ label_metadata_encode(&md, sector);
+ error = g_metadata_store(name, sector, sizeof(sector));
+ if (error != 0) {
+ fprintf(stderr, "Can't store metadata on %s: %s.\n", name,
+ strerror(error));
+ gctl_error(req, "Not done.");
+ }
+ if (verbose)
+ printf("Metadata value stored on %s.\n", name);
+}
+
+static void
+label_clear(struct gctl_req *req)
+{
+ const char *name;
+ char param[16];
+ unsigned i;
+ int *nargs, error;
+
+ nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
+ if (nargs == NULL) {
+ gctl_error(req, "No '%s' argument.", "nargs");
+ return;
+ }
+ if (*nargs < 1) {
+ gctl_error(req, "Too few arguments.");
+ return;
+ }
+
+ for (i = 0; i < (unsigned)*nargs; i++) {
+ snprintf(param, sizeof(param), "arg%u", i);
+ name = gctl_get_asciiparam(req, param);
+
+ error = g_metadata_clear(name, G_LABEL_MAGIC);
+ if (error != 0) {
+ fprintf(stderr, "Can't clear metadata on %s: %s.\n",
+ name, strerror(error));
+ gctl_error(req, "Not fully done.");
+ continue;
+ }
+ if (verbose)
+ printf("Metadata cleared on %s.\n", name);
+ }
+}
diff --git a/sbin/geom/class/label/glabel.8 b/sbin/geom/class/label/glabel.8
new file mode 100644
index 0000000..8f94505
--- /dev/null
+++ b/sbin/geom/class/label/glabel.8
@@ -0,0 +1,182 @@
+.\" Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd Jul 2, 2004
+.Dt GLABEL 8
+.Os
+.Sh NAME
+.Nm glabel
+.Nd "disk labelization control utility"
+.Sh SYNOPSIS
+.Nm
+.Cm create
+.Op Fl v
+.Ar name
+.Ar dev
+.Nm
+.Cm label
+.Op Fl v
+.Ar name
+.Ar dev
+.Nm
+.Cm destroy
+.Op Fl fv
+.Ar name
+.Op Ar name Op Ar ...
+.Nm
+.Cm clear
+.Op Fl v
+.Ar dev
+.Op Ar dev Op Ar ...
+.Nm
+.Cm list
+.Op Ar prov Op Ar ...
+.Nm
+.Cm load
+.Op Fl v
+.Nm
+.Cm unload
+.Op Fl v
+.Sh DESCRIPTION
+The
+.Nm
+utility is used for GEOM providers labelization.
+A label can be setup on a GEOM provider in two ways:
+.Dq manual
+or
+.Dq automatic .
+When using the
+.Dq manual
+method, no metadata are stored on the devices, so a label has to be configured
+by hand every time it is needed.
+The
+.Dq automatic
+method use on-disk metadata to store label and detect it automatically in the
+future.
+.Pp
+This class also provide volume label detection for file systems.
+Those labels cannot be set with
+.Nm ,
+but must be set with the appropriate file system utility, e.g. for UFS
+the file system label is set with
+.Xr tunefs 8 .
+Currently supported file systems are:
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+UFS1 (directory
+.Pa /dev/ufs/ ) .
+.It
+UFS2 (directory
+.Pa /dev/ufs/ ) .
+.It
+MSDOSFS (FAT12, FAT16, FAT32) (directory
+.Pa /dev/msdosfs/ ) .
+.It
+CD ISO9660 (directory
+.Pa /dev/iso9660/ ) .
+.El
+.Pp
+Non file-system labels are created in the directory
+.Pa /dev/label/ .
+.Pp
+The first argument to
+.Nm
+indicates an action to be performed:
+.Bl -tag -width ".Cm destroy"
+.It Cm create
+Create temporary label
+.Ar name
+for the given provider.
+This is the
+.Dq manual
+method.
+The kernel module
+.Pa geom_label.ko
+will be loaded if it is not loaded already.
+.It Cm label
+Setup a label
+.Ar name
+for the given provider.
+This is the
+.Dq automatic
+method, where metadata are stored in provider's last sector.
+The kernel module
+.Pa geom_label.ko
+will be loaded if it is not loaded already.
+.It Cm destroy
+Turn off the given labels by its
+.Ar name .
+.It Cm clear
+Clear metadata on the given devices.
+.It Cm list
+List all currently configured devices, or list the given devices.
+.It Cm load
+Load
+.Pa geom_label.ko
+kernel module.
+.It Cm unload
+Unload
+.Pa geom_label.ko
+kernel module.
+.El
+.Pp
+Additional options:
+.Bl -tag -width indent
+.It Fl f
+Force the removal of the specified labels.
+.It Fl v
+Be more verbose.
+.El
+.Sh EXAMPLES
+The following example shows how to setup a label for disk da2,
+create a file system on it, and mount it:
+.Bd -literal -offset indent
+glabel label -v usr /dev/da2
+newfs /dev/label/usr
+mount /dev/label/usr /usr
+.Ed
+.Pp
+The next example shows how to setup a label for a UFS file system:
+.Bd -literal -offset indent
+tunefs -L data /dev/da4s1a
+mount /dev/ufs/data /mnt/data
+.Ed
+.Sh DIAGNOSTICS
+Exit status is 0 on success, and 1 if the command fails.
+.Sh SEE ALSO
+.Xr geom 4 ,
+.Xr geom 8 ,
+.Xr mount 8 ,
+.Xr newfs 8 ,
+.Xr tunefs 8
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Fx 5.3 .
+.Sh AUTHORS
+.An Pawel Jakub Dawidek Aq pjd@FreeBSD.org
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 2191e57..2607142 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -125,6 +125,7 @@ options GEOM_CONCAT # Disk concatenation.
options GEOM_FOX # Redundant path mitigation
options GEOM_GATE # Userland services.
options GEOM_GPT # GPT partitioning
+options GEOM_LABEL # Providers labelization.
options GEOM_MBR # DOS/MBR partitioning
options GEOM_NOP # Test class.
options GEOM_PC98 # NEC PC9800 partitioning
diff --git a/sys/conf/files b/sys/conf/files
index 10c2df7..a25b963 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -940,6 +940,10 @@ crypto/rijndael/rijndael-api-fst.c optional geom_bde
crypto/sha2/sha2.c optional geom_bde
geom/concat/g_concat.c optional geom_concat
geom/gate/g_gate.c optional geom_gate
+geom/label/g_label.c optional geom_label
+geom/label/g_label_iso9660.c optional geom_label
+geom/label/g_label_msdosfs.c optional geom_label
+geom/label/g_label_ufs.c optional geom_label
geom/nop/g_nop.c optional geom_nop
geom/stripe/g_stripe.c optional geom_stripe
geom/geom_aes.c optional geom_aes
diff --git a/sys/conf/options b/sys/conf/options
index 1c6c146..d086703 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -71,6 +71,7 @@ GEOM_CONCAT opt_geom.h
GEOM_FOX opt_geom.h
GEOM_GATE opt_geom.h
GEOM_GPT opt_geom.h
+GEOM_LABEL opt_geom.h
GEOM_MBR opt_geom.h
GEOM_MIRROR opt_geom.h
GEOM_NOP opt_geom.h
diff --git a/sys/geom/label/g_label.c b/sys/geom/label/g_label.c
new file mode 100644
index 0000000..2aa9754
--- /dev/null
+++ b/sys/geom/label/g_label.c
@@ -0,0 +1,405 @@
+/*-
+ * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/bio.h>
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+#include <geom/geom.h>
+#include <geom/geom_slice.h>
+#include <geom/label/g_label.h>
+
+
+SYSCTL_DECL(_kern_geom);
+SYSCTL_NODE(_kern_geom, OID_AUTO, label, CTLFLAG_RW, 0, "GEOM_LABEL stuff");
+u_int g_label_debug = 0;
+SYSCTL_UINT(_kern_geom_label, OID_AUTO, debug, CTLFLAG_RW, &g_label_debug, 0,
+ "Debug level");
+
+static int g_label_destroy(struct g_geom *gp, boolean_t force);
+static struct g_geom *g_label_taste(struct g_class *mp, struct g_provider *pp,
+ int flags __unused);
+static void g_label_config(struct gctl_req *req, struct g_class *mp,
+ const char *verb);
+
+struct g_class g_label_class = {
+ .name = G_LABEL_CLASS_NAME,
+ .ctlreq = g_label_config,
+ .taste = g_label_taste
+};
+
+/*
+ * To add a new file system where you want to look for volume labels,
+ * you have to:
+ * 1. Add a file which implements looking for volume labels.
+ * 2. Add an 'extern const struct g_label_desc g_label_<your file system>;'.
+ * 3. Add an element to the table below '&g_label_<your_file_system>,'.
+ */
+const struct g_label_desc *g_labels[] = {
+ &g_label_ufs,
+ &g_label_iso9660,
+ &g_label_msdosfs,
+ NULL
+};
+
+
+static void
+g_label_orphan(struct g_consumer *cp __unused)
+{
+
+ KASSERT(1 == 0, ("%s called?", __func__));
+}
+
+static void
+g_label_start(struct bio *bp __unused)
+{
+
+ KASSERT(1 == 0, ("%s called?", __func__));
+}
+
+static int
+g_label_access(struct g_provider *pp __unused, int dr __unused, int dw __unused,
+ int de __unused)
+{
+
+ KASSERT(1 == 0, ("%s called", __func__));
+ return (EOPNOTSUPP);
+}
+
+static struct g_geom *
+g_label_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp,
+ const char *label, const char *dir, off_t mediasize)
+{
+ struct g_geom *gp;
+ struct g_provider *pp2;
+ struct g_consumer *cp;
+ char name[64];
+
+ g_topology_assert();
+
+ gp = NULL;
+ cp = NULL;
+ snprintf(name, sizeof(name), "%s/%s", dir, label);
+ LIST_FOREACH(gp, &mp->geom, geom) {
+ pp2 = LIST_FIRST(&gp->provider);
+ if (pp2 == NULL)
+ continue;
+ if (strcmp(pp2->name, name) == 0) {
+ G_LABEL_DEBUG(1, "Label %s(%s) already exists (%s).",
+ label, name, pp->name);
+ if (req != NULL) {
+ gctl_error(req, "Provider %s already exists.",
+ name);
+ }
+ return (NULL);
+ }
+ }
+ gp = g_slice_new(mp, 1, pp, &cp, NULL, 0, NULL);
+ if (gp == NULL) {
+ G_LABEL_DEBUG(0, "Cannot create slice %s.", label);
+ if (req != NULL)
+ gctl_error(req, "Cannot create slice %s.", label);
+ return (NULL);
+ }
+ g_access(cp, -1, 0, 0);
+ g_slice_config(gp, 0, G_SLICE_CONFIG_SET, (off_t)0, mediasize,
+ pp->sectorsize, name);
+ G_LABEL_DEBUG(0, "Label for provider %s is %s.", pp->name, name);
+ return (gp);
+}
+
+static int
+g_label_destroy(struct g_geom *gp, boolean_t force)
+{
+ struct g_provider *pp;
+
+ g_topology_assert();
+ pp = LIST_FIRST(&gp->provider);
+ if (pp != NULL && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0)) {
+ if (force) {
+ G_LABEL_DEBUG(0, "Provider %s is still open, so it "
+ "can't be definitely removed.", pp->name);
+ } else {
+ G_LABEL_DEBUG(1,
+ "Provider %s is still open (r%dw%de%d).", pp->name,
+ pp->acr, pp->acw, pp->ace);
+ return (EBUSY);
+ }
+ } else {
+ G_LABEL_DEBUG(0, "Label %s removed.",
+ LIST_FIRST(&gp->provider)->name);
+ }
+ g_slice_spoiled(LIST_FIRST(&gp->consumer));
+ return (0);
+}
+
+static int
+g_label_read_metadata(struct g_consumer *cp, struct g_label_metadata *md)
+{
+ struct g_provider *pp;
+ u_char *buf;
+ int error;
+
+ g_topology_assert();
+
+ pp = cp->provider;
+ g_topology_unlock();
+ buf = g_read_data(cp, pp->mediasize - pp->sectorsize, pp->sectorsize,
+ &error);
+ g_topology_lock();
+ if (buf == NULL)
+ return (error);
+ /* Decode metadata. */
+ label_metadata_decode(buf, md);
+ g_free(buf);
+
+ return (0);
+}
+
+static struct g_geom *
+g_label_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
+{
+ struct g_label_metadata md;
+ struct g_consumer *cp;
+ struct g_geom *gp;
+ int error, i;
+
+ g_trace(G_T_TOPOLOGY, "%s(%s, %s)", __func__, mp->name, pp->name);
+ g_topology_assert();
+
+ G_LABEL_DEBUG(3, "Tasting %s.", pp->name);
+
+ if (strcmp(pp->geom->class->name, mp->name) == 0)
+ return (NULL);
+
+ gp = g_new_geomf(mp, "label:taste");
+ gp->start = g_label_start;
+ gp->access = g_label_access;
+ gp->orphan = g_label_orphan;
+ cp = g_new_consumer(gp);
+ g_attach(cp, pp);
+ error = g_access(cp, 1, 0, 0);
+ if (error != 0)
+ return (NULL);
+
+ do {
+ error = g_label_read_metadata(cp, &md);
+ if (error != 0)
+ break;
+ if (strcmp(md.md_magic, G_LABEL_MAGIC) != 0)
+ break;
+ if (md.md_version > G_LABEL_VERSION) {
+ printf("geom_label.ko module is too old to handle %s.\n",
+ pp->name);
+ break;
+ }
+ g_label_create(NULL, mp, pp, md.md_label, G_LABEL_DIR,
+ pp->mediasize - pp->sectorsize);
+ } while (0);
+ for (i = 0; g_labels[i] != NULL; i++) {
+ char label[64];
+
+ g_topology_unlock();
+ g_labels[i]->ld_taste(cp, label, sizeof(label));
+ g_topology_lock();
+ if (label[0] == '\0')
+ continue;
+ g_label_create(NULL, mp, pp, label, g_labels[i]->ld_dir,
+ pp->mediasize);
+ }
+
+ g_access(cp, -1, 0, 0);
+ g_wither_geom(gp, ENXIO);
+
+ return (NULL);
+}
+
+static void
+g_label_ctl_create(struct gctl_req *req, struct g_class *mp)
+{
+ struct g_provider *pp;
+ const char *name;
+ int *nargs;
+
+ g_topology_assert();
+
+ nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
+ if (nargs == NULL) {
+ gctl_error(req, "No '%s' argument", "nargs");
+ return;
+ }
+ if (*nargs != 2) {
+ gctl_error(req, "Invalid number of argument.");
+ return;
+ }
+ /*
+ * arg1 is the name of provider.
+ */
+ name = gctl_get_asciiparam(req, "arg1");
+ if (name == NULL) {
+ gctl_error(req, "No 'arg%d' argument", 1);
+ return;
+ }
+ if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
+ name += strlen("/dev/");
+ pp = g_provider_by_name(name);
+ if (pp == NULL) {
+ G_LABEL_DEBUG(1, "Provider %s is invalid.", name);
+ gctl_error(req, "Provider %s is invalid.", name);
+ return;
+ }
+ /*
+ * arg0 is the label.
+ */
+ name = gctl_get_asciiparam(req, "arg0");
+ if (name == NULL) {
+ gctl_error(req, "No 'arg%d' argument", 0);
+ return;
+ }
+ g_label_create(req, mp, pp, name, G_LABEL_DIR, pp->mediasize);
+}
+
+static const char *
+g_label_skip_dir(const char *name)
+{
+ char path[64];
+ u_int i;
+
+ if (strncmp(name, "/dev/", strlen("/dev/")) == 0)
+ name += strlen("/dev/");
+ if (strncmp(name, G_LABEL_DIR "/", strlen(G_LABEL_DIR "/")) == 0)
+ name += strlen(G_LABEL_DIR "/");
+ for (i = 0; g_labels[i] != NULL; i++) {
+ snprintf(path, sizeof(path), "%s/", g_labels[i]->ld_dir);
+ if (strncmp(name, path, strlen(path)) == 0) {
+ name += strlen(path);
+ break;
+ }
+ }
+ return (name);
+}
+
+static struct g_geom *
+g_label_find_geom(struct g_class *mp, const char *name)
+{
+ struct g_geom *gp;
+ struct g_provider *pp;
+ const char *pname;
+
+ name = g_label_skip_dir(name);
+ LIST_FOREACH(gp, &mp->geom, geom) {
+ pp = LIST_FIRST(&gp->provider);
+ pname = g_label_skip_dir(pp->name);
+ if (strcmp(pname, name) == 0)
+ return (gp);
+ }
+ return (NULL);
+}
+
+static void
+g_label_ctl_destroy(struct gctl_req *req, struct g_class *mp)
+{
+ int *nargs, *force, error, i;
+ struct g_geom *gp;
+ const char *name;
+ char param[16];
+
+ g_topology_assert();
+
+ nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
+ if (nargs == NULL) {
+ gctl_error(req, "No '%s' argument", "nargs");
+ return;
+ }
+ if (*nargs <= 0) {
+ gctl_error(req, "Missing device(s).");
+ return;
+ }
+ force = gctl_get_paraml(req, "force", sizeof(*force));
+ if (force == NULL) {
+ gctl_error(req, "No 'force' argument");
+ return;
+ }
+
+ for (i = 0; i < *nargs; i++) {
+ snprintf(param, sizeof(param), "arg%d", i);
+ name = gctl_get_asciiparam(req, param);
+ if (name == NULL) {
+ gctl_error(req, "No 'arg%d' argument", i);
+ return;
+ }
+ gp = g_label_find_geom(mp, name);
+ if (gp == NULL) {
+ G_LABEL_DEBUG(1, "Label %s is invalid.", name);
+ gctl_error(req, "Label %s is invalid.", name);
+ return;
+ }
+ error = g_label_destroy(gp, *force);
+ if (error != 0) {
+ gctl_error(req, "Cannot destroy label %s (error=%d).",
+ LIST_FIRST(&gp->provider)->name, error);
+ return;
+ }
+ }
+}
+
+static void
+g_label_config(struct gctl_req *req, struct g_class *mp, const char *verb)
+{
+ uint32_t *version;
+
+ g_topology_assert();
+
+ version = gctl_get_paraml(req, "version", sizeof(*version));
+ if (version == NULL) {
+ gctl_error(req, "No '%s' argument.", "version");
+ return;
+ }
+ if (*version != G_LABEL_VERSION) {
+ gctl_error(req, "Userland and kernel parts are out of sync.");
+ return;
+ }
+
+ if (strcmp(verb, "create") == 0) {
+ g_label_ctl_create(req, mp);
+ return;
+ } else if (strcmp(verb, "destroy") == 0) {
+ g_label_ctl_destroy(req, mp);
+ return;
+ }
+
+ gctl_error(req, "Unknown verb.");
+}
+
+DECLARE_GEOM_CLASS(g_label_class, g_label);
diff --git a/sys/geom/label/g_label.h b/sys/geom/label/g_label.h
new file mode 100644
index 0000000..011cc5e
--- /dev/null
+++ b/sys/geom/label/g_label.h
@@ -0,0 +1,97 @@
+/*-
+ * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _G_LABEL_H_
+#define _G_LABEL_H_
+
+#include <sys/endian.h>
+
+#define G_LABEL_CLASS_NAME "LABEL"
+
+#define G_LABEL_MAGIC "GEOM::LABEL"
+#define G_LABEL_VERSION 0
+#define G_LABEL_DIR "label"
+
+#ifdef _KERNEL
+extern u_int g_label_debug;
+
+#define G_LABEL_DEBUG(lvl, ...) do { \
+ if (g_label_debug >= (lvl)) { \
+ printf("GEOM_LABEL"); \
+ if (g_label_debug > 0) \
+ printf("[%u]", lvl); \
+ printf(": "); \
+ printf(__VA_ARGS__); \
+ printf("\n"); \
+ } \
+} while (0)
+#define G_LABEL_LOGREQ(bp, ...) do { \
+ if (g_label_debug >= 2) { \
+ printf("GEOM_LABEL[2]: "); \
+ printf(__VA_ARGS__); \
+ printf(" "); \
+ g_print_bio(bp); \
+ printf("\n"); \
+ } \
+} while (0)
+
+typedef void g_label_taste_t (struct g_consumer *cp, char *label, size_t size);
+
+struct g_label_desc {
+ g_label_taste_t *ld_taste;
+ char *ld_dir;
+};
+
+/* Supported labels. */
+extern const struct g_label_desc g_label_ufs;
+extern const struct g_label_desc g_label_iso9660;
+extern const struct g_label_desc g_label_msdosfs;
+#endif /* _KERNEL */
+
+struct g_label_metadata {
+ char md_magic[16]; /* Magic value. */
+ uint32_t md_version; /* Version number. */
+ char md_label[16]; /* Label. */
+};
+static __inline void
+label_metadata_encode(const struct g_label_metadata *md, u_char *data)
+{
+
+ bcopy(md->md_magic, data, sizeof(md->md_magic));
+ le32enc(data + 16, md->md_version);
+ bcopy(md->md_label, data + 20, sizeof(md->md_label));
+}
+static __inline void
+label_metadata_decode(const u_char *data, struct g_label_metadata *md)
+{
+
+ bcopy(data, md->md_magic, sizeof(md->md_magic));
+ md->md_version = le32dec(data + 16);
+ bcopy(data + 20, md->md_label, sizeof(md->md_label));
+}
+#endif /* _G_LABEL_H_ */
diff --git a/sys/geom/label/g_label_iso9660.c b/sys/geom/label/g_label_iso9660.c
new file mode 100644
index 0000000..34d9252
--- /dev/null
+++ b/sys/geom/label/g_label_iso9660.c
@@ -0,0 +1,80 @@
+/*-
+ * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <geom/geom.h>
+#include <geom/label/g_label.h>
+
+#define G_LABEL_ISO9660_DIR "iso9660"
+
+#define ISO9660_MAGIC "\x01" "CD001" "\x01\x00"
+#define VOLUME_LEN 32
+
+
+static void
+g_label_iso9660_taste(struct g_consumer *cp, char *label, size_t size)
+{
+ struct g_provider *pp;
+ char *sector, *volume;
+ int i, error;
+
+ g_topology_assert_not();
+ pp = cp->provider;
+ label[0] = '\0';
+
+ sector = (char *)g_read_data(cp, 0x8000, pp->sectorsize, &error);
+ if (sector == NULL || error != 0)
+ return;
+ if (bcmp(sector, ISO9660_MAGIC, sizeof(ISO9660_MAGIC) - 1) != 0) {
+ g_free(sector);
+ return;
+ }
+ G_LABEL_DEBUG(1, "ISO9660 file system detected on %s.", pp->name);
+ volume = sector + 0x28;
+ bzero(label, size);
+ strlcpy(label, volume, MIN(size, VOLUME_LEN));
+ g_free(sector);
+ for (i = size - 1; i > 0; i--) {
+ if (label[i] == '\0')
+ continue;
+ else if (label[i] == ' ')
+ label[i] = '\0';
+ else
+ break;
+ }
+}
+
+const struct g_label_desc g_label_iso9660 = {
+ .ld_taste = g_label_iso9660_taste,
+ .ld_dir = G_LABEL_ISO9660_DIR
+};
diff --git a/sys/geom/label/g_label_msdosfs.c b/sys/geom/label/g_label_msdosfs.c
new file mode 100644
index 0000000..ff0d7c3
--- /dev/null
+++ b/sys/geom/label/g_label_msdosfs.c
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <geom/geom.h>
+#include <geom/label/g_label.h>
+
+#define G_LABEL_MSDOSFS_DIR "msdosfs"
+
+#define FAT12 "FAT12 "
+#define FAT16 "FAT16 "
+#define FAT32 "FAT32 "
+#define VOLUME_LEN 11
+#define NO_NAME "NO NAME "
+
+
+static void
+g_label_msdosfs_taste(struct g_consumer *cp, char *label, size_t size)
+{
+ struct g_provider *pp;
+ char *sector, *volume;
+ int i, error;
+
+ g_topology_assert_not();
+ pp = cp->provider;
+ label[0] = '\0';
+
+ sector = (char *)g_read_data(cp, 0, pp->sectorsize, &error);
+ if (sector == NULL || error != 0)
+ return;
+ if (strncmp(sector + 0x36, FAT12, strlen(FAT12)) == 0) {
+ G_LABEL_DEBUG(1, "MSDOS (FAT12) file system detected on %s.",
+ pp->name);
+ volume = sector + 0x2b;
+ } else if (strncmp(sector + 0x36, FAT16, strlen(FAT16)) == 0) {
+ G_LABEL_DEBUG(1, "MSDOS (FAT16) file system detected on %s.",
+ pp->name);
+ volume = sector + 0x2b;
+ } else if (strncmp(sector + 0x52, FAT32, strlen(FAT32)) == 0) {
+ G_LABEL_DEBUG(1, "MSDOS (FAT32) file system detected on %s.",
+ pp->name);
+ volume = sector + 0x47;
+ } else {
+ g_free(sector);
+ return;
+ }
+ if (strncmp(volume, NO_NAME, VOLUME_LEN) == 0) {
+ g_free(sector);
+ return;
+ }
+ if (volume[0] == '\0') {
+ g_free(sector);
+ return;
+ }
+ bzero(label, size);
+ strlcpy(label, volume, MIN(size, VOLUME_LEN));
+ g_free(sector);
+ for (i = size - 1; i > 0; i--) {
+ if (label[i] == '\0')
+ continue;
+ else if (label[i] == ' ')
+ label[i] = '\0';
+ else
+ break;
+ }
+}
+
+const struct g_label_desc g_label_msdosfs = {
+ .ld_taste = g_label_msdosfs_taste,
+ .ld_dir = G_LABEL_MSDOSFS_DIR
+};
diff --git a/sys/geom/label/g_label_ufs.c b/sys/geom/label/g_label_ufs.c
new file mode 100644
index 0000000..dc188f7
--- /dev/null
+++ b/sys/geom/label/g_label_ufs.c
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 2002, 2003 Gordon Tetlow
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include <geom/geom.h>
+#include <geom/label/g_label.h>
+
+#define G_LABEL_UFS_DIR "ufs"
+
+static const int superblocks[] = SBLOCKSEARCH;
+
+static void
+g_label_ufs_taste(struct g_consumer *cp, char *label, size_t size)
+{
+ struct g_provider *pp;
+ int error, sb, superblock;
+ struct fs *fs;
+
+ g_topology_assert_not();
+ pp = cp->provider;
+ label[0] = '\0';
+ /*
+ * Walk through the standard places that superblocks hide and look
+ * for UFS magic. If we find magic, then check that the size in the
+ * superblock corresponds to the size of the underlying provider.
+ * Finally, look for a volume label and create an appropriate
+ * provider based on that.
+ */
+ for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) {
+ fs = (struct fs *)g_read_data(cp, superblock, SBLOCKSIZE,
+ &error);
+ if (fs == NULL || error != 0)
+ continue;
+ /* Check for magic and make sure things are the right size */
+ if (fs->fs_magic == FS_UFS1_MAGIC) {
+ G_LABEL_DEBUG(1, "UFS1 file system detected on %s.",
+ pp->name);
+ if (fs->fs_old_size * fs->fs_fsize !=
+ (int32_t)pp->mediasize) {
+ g_free(fs);
+ continue;
+ }
+ } else if (fs->fs_magic == FS_UFS2_MAGIC) {
+ G_LABEL_DEBUG(1, "UFS2 file system detected on %s.",
+ pp->name);
+ if (fs->fs_size * fs->fs_fsize !=
+ (int64_t)pp->mediasize) {
+ g_free(fs);
+ continue;
+ }
+ } else {
+ g_free(fs);
+ continue;
+ }
+ /* Check for volume label */
+ if (fs->fs_volname[0] == '\0') {
+ g_free(fs);
+ continue;
+ }
+ strlcpy(label, fs->fs_volname, size);
+ g_free(fs);
+ break;
+ }
+}
+
+const struct g_label_desc g_label_ufs = {
+ .ld_taste = g_label_ufs_taste,
+ .ld_dir = G_LABEL_UFS_DIR
+};
diff --git a/sys/modules/geom/Makefile b/sys/modules/geom/Makefile
index 039ae29..880c082 100644
--- a/sys/modules/geom/Makefile
+++ b/sys/modules/geom/Makefile
@@ -8,6 +8,7 @@ SUBDIR= geom_apple \
geom_fox \
geom_gate \
geom_gpt \
+ geom_label \
geom_mbr \
geom_nop \
geom_pc98 \
diff --git a/sys/modules/geom/geom_label/Makefile b/sys/modules/geom/geom_label/Makefile
new file mode 100644
index 0000000..839a48e
--- /dev/null
+++ b/sys/modules/geom/geom_label/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../geom/label
+
+KMOD= geom_label
+SRCS= g_label.c
+SRCS+= g_label_iso9660.c
+SRCS+= g_label_msdosfs.c
+SRCS+= g_label_ufs.c
+
+.include <bsd.kmod.mk>
OpenPOWER on IntegriCloud