summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2014-07-01 13:29:17 +0000
committerae <ae@FreeBSD.org>2014-07-01 13:29:17 +0000
commitb6530ab0a75df248778a68ad2c476a217ce76392 (patch)
tree0f320b4457b4886d9cb130a9a0010f5d378d8e64 /sys/geom
parenta79b0da86bae072e2bc32c6dd62a668b35e0fd52 (diff)
downloadFreeBSD-src-b6530ab0a75df248778a68ad2c476a217ce76392.zip
FreeBSD-src-b6530ab0a75df248778a68ad2c476a217ce76392.tar.gz
MFC r267355:
Add UUIDs for DragonFlyBSD's partition types. MFC r267356: Add DragonFlyBSD's Hammer FS types and type names. MFC r267357: Add aliases for DragonFlyBSD's partition types. MFC r267358: Allow dumping to DragonFlyBSD's swap partition. MFC r267359: Add disklabel64 support to GEOM_PART class. This partitioning scheme is used in DragonFlyBSD. It is similar to BSD disklabel, but has the following improvements: * metadata has own dedicated place and isn't accessible through partitions; * all offsets are 64-bit; * supports 16 partitions by default (has reserved place for more); * has reserved place for backup label (but not yet implemented); * has UUIDs for partitions and partition types; MFC r267360: Add disklabel64 support Relnotes: yes
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/part/g_part.c9
-rw-r--r--sys/geom/part/g_part.h9
-rw-r--r--sys/geom/part/g_part_bsd.c45
-rw-r--r--sys/geom/part/g_part_bsd64.c667
-rw-r--r--sys/geom/part/g_part_gpt.c21
5 files changed, 726 insertions, 25 deletions
diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c
index d5862a0..8429fa0 100644
--- a/sys/geom/part/g_part.c
+++ b/sys/geom/part/g_part.c
@@ -108,6 +108,15 @@ struct g_part_alias_list {
{ "vmware-vmkdiag", G_PART_ALIAS_VMKDIAG },
{ "vmware-reserved", G_PART_ALIAS_VMRESERVED },
{ "vmware-vsanhdr", G_PART_ALIAS_VMVSANHDR },
+ { "dragonfly-label32", G_PART_ALIAS_DFBSD },
+ { "dragonfly-label64", G_PART_ALIAS_DFBSD64 },
+ { "dragonfly-swap", G_PART_ALIAS_DFBSD_SWAP },
+ { "dragonfly-ufs", G_PART_ALIAS_DFBSD_UFS },
+ { "dragonfly-vinum", G_PART_ALIAS_DFBSD_VINUM },
+ { "dragonfly-ccd", G_PART_ALIAS_DFBSD_CCD },
+ { "dragonfly-legacy", G_PART_ALIAS_DFBSD_LEGACY },
+ { "dragonfly-hammer", G_PART_ALIAS_DFBSD_HAMMER },
+ { "dragonfly-hammer2", G_PART_ALIAS_DFBSD_HAMMER2 },
};
SYSCTL_DECL(_kern_geom);
diff --git a/sys/geom/part/g_part.h b/sys/geom/part/g_part.h
index a578735..06522f5 100644
--- a/sys/geom/part/g_part.h
+++ b/sys/geom/part/g_part.h
@@ -75,6 +75,15 @@ enum g_part_alias {
G_PART_ALIAS_VMKDIAG, /* A VMware vmkDiagnostic partition entry */
G_PART_ALIAS_VMRESERVED, /* A VMware reserved partition entry */
G_PART_ALIAS_VMVSANHDR, /* A VMware vSAN header partition entry */
+ G_PART_ALIAS_DFBSD, /* A DfBSD label32 partition entry */
+ G_PART_ALIAS_DFBSD64, /* A DfBSD label64 partition entry */
+ G_PART_ALIAS_DFBSD_SWAP, /* A DfBSD swap partition entry */
+ G_PART_ALIAS_DFBSD_UFS, /* A DfBSD UFS partition entry */
+ G_PART_ALIAS_DFBSD_VINUM, /* A DfBSD Vinum partition entry */
+ G_PART_ALIAS_DFBSD_CCD, /* A DfBSD CCD partition entry */
+ G_PART_ALIAS_DFBSD_LEGACY, /* A DfBSD legacy partition entry */
+ G_PART_ALIAS_DFBSD_HAMMER, /* A DfBSD HAMMER FS partition entry */
+ G_PART_ALIAS_DFBSD_HAMMER2, /* A DfBSD HAMMER2 FS partition entry */
/* Keep the following last */
G_PART_ALIAS_COUNT
};
diff --git a/sys/geom/part/g_part_bsd.c b/sys/geom/part/g_part_bsd.c
index 487bf23..5a5eabd 100644
--- a/sys/geom/part/g_part_bsd.c
+++ b/sys/geom/part/g_part_bsd.c
@@ -112,12 +112,26 @@ static struct g_part_scheme g_part_bsd_scheme = {
};
G_PART_SCHEME_DECLARE(g_part_bsd);
+static struct g_part_bsd_alias {
+ uint8_t type;
+ int alias;
+} bsd_alias_match[] = {
+ { FS_BSDFFS, G_PART_ALIAS_FREEBSD_UFS },
+ { FS_SWAP, G_PART_ALIAS_FREEBSD_SWAP },
+ { FS_ZFS, G_PART_ALIAS_FREEBSD_ZFS },
+ { FS_VINUM, G_PART_ALIAS_FREEBSD_VINUM },
+ { FS_NANDFS, G_PART_ALIAS_FREEBSD_NANDFS },
+ { FS_HAMMER, G_PART_ALIAS_DFBSD_HAMMER },
+ { FS_HAMMER2, G_PART_ALIAS_DFBSD_HAMMER2 },
+};
+
static int
bsd_parse_type(const char *type, uint8_t *fstype)
{
const char *alias;
char *endp;
long lt;
+ int i;
if (type[0] == '!') {
lt = strtol(type + 1, &endp, 0);
@@ -126,30 +140,13 @@ bsd_parse_type(const char *type, uint8_t *fstype)
*fstype = (u_int)lt;
return (0);
}
- alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_NANDFS);
- if (!strcasecmp(type, alias)) {
- *fstype = FS_NANDFS;
- return (0);
- }
- alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_SWAP);
- if (!strcasecmp(type, alias)) {
- *fstype = FS_SWAP;
- return (0);
- }
- alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_UFS);
- if (!strcasecmp(type, alias)) {
- *fstype = FS_BSDFFS;
- return (0);
- }
- alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_VINUM);
- if (!strcasecmp(type, alias)) {
- *fstype = FS_VINUM;
- return (0);
- }
- alias = g_part_alias_name(G_PART_ALIAS_FREEBSD_ZFS);
- if (!strcasecmp(type, alias)) {
- *fstype = FS_ZFS;
- return (0);
+ for (i = 0;
+ i < sizeof(bsd_alias_match) / sizeof(bsd_alias_match[0]); i++) {
+ alias = g_part_alias_name(bsd_alias_match[i].alias);
+ if (strcasecmp(type, alias) == 0) {
+ *fstype = bsd_alias_match[i].type;
+ return (0);
+ }
}
return (EINVAL);
}
diff --git a/sys/geom/part/g_part_bsd64.c b/sys/geom/part/g_part_bsd64.c
new file mode 100644
index 0000000..7586c94
--- /dev/null
+++ b/sys/geom/part/g_part_bsd64.c
@@ -0,0 +1,667 @@
+/*-
+ * Copyright (c) 2014 Andrey V. Elsukov <ae@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 AUTHOR ``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 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/bio.h>
+#include <sys/disklabel.h>
+#include <sys/endian.h>
+#include <sys/gpt.h>
+#include <sys/kernel.h>
+#include <sys/kobj.h>
+#include <sys/limits.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/sbuf.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <geom/geom.h>
+#include <geom/geom_int.h>
+#include <geom/part/g_part.h>
+
+#include "g_part_if.h"
+
+FEATURE(geom_part_bsd64, "GEOM partitioning class for 64-bit BSD disklabels");
+
+/* XXX: move this to sys/disklabel64.h */
+#define DISKMAGIC64 ((uint32_t)0xc4464c59)
+#define MAXPARTITIONS64 16
+#define RESPARTITIONS64 32
+
+struct disklabel64 {
+ char d_reserved0[512]; /* reserved or unused */
+ u_int32_t d_magic; /* the magic number */
+ u_int32_t d_crc; /* crc32() d_magic thru last part */
+ u_int32_t d_align; /* partition alignment requirement */
+ u_int32_t d_npartitions; /* number of partitions */
+ struct uuid d_stor_uuid; /* unique uuid for label */
+
+ u_int64_t d_total_size; /* total size incl everything (bytes) */
+ u_int64_t d_bbase; /* boot area base offset (bytes) */
+ /* boot area is pbase - bbase */
+ u_int64_t d_pbase; /* first allocatable offset (bytes) */
+ u_int64_t d_pstop; /* last allocatable offset+1 (bytes) */
+ u_int64_t d_abase; /* location of backup copy if not 0 */
+
+ u_char d_packname[64];
+ u_char d_reserved[64];
+
+ /*
+ * Note: offsets are relative to the base of the slice, NOT to
+ * d_pbase. Unlike 32 bit disklabels the on-disk format for
+ * a 64 bit disklabel remains slice-relative.
+ *
+ * An uninitialized partition has a p_boffset and p_bsize of 0.
+ *
+ * If p_fstype is not supported for a live partition it is set
+ * to FS_OTHER. This is typically the case when the filesystem
+ * is identified by its uuid.
+ */
+ struct partition64 { /* the partition table */
+ u_int64_t p_boffset; /* slice relative offset, in bytes */
+ u_int64_t p_bsize; /* size of partition, in bytes */
+ u_int8_t p_fstype;
+ u_int8_t p_unused01; /* reserved, must be 0 */
+ u_int8_t p_unused02; /* reserved, must be 0 */
+ u_int8_t p_unused03; /* reserved, must be 0 */
+ u_int32_t p_unused04; /* reserved, must be 0 */
+ u_int32_t p_unused05; /* reserved, must be 0 */
+ u_int32_t p_unused06; /* reserved, must be 0 */
+ struct uuid p_type_uuid;/* mount type as UUID */
+ struct uuid p_stor_uuid;/* unique uuid for storage */
+ } d_partitions[MAXPARTITIONS64];/* actually may be more */
+};
+
+struct g_part_bsd64_table {
+ struct g_part_table base;
+
+ uint32_t d_align;
+ uint64_t d_bbase;
+ uint64_t d_abase;
+ struct uuid d_stor_uuid;
+ char d_reserved0[512];
+ u_char d_packname[64];
+ u_char d_reserved[64];
+};
+
+struct g_part_bsd64_entry {
+ struct g_part_entry base;
+
+ uint8_t fstype;
+ struct uuid type_uuid;
+ struct uuid stor_uuid;
+};
+
+static int g_part_bsd64_add(struct g_part_table *, struct g_part_entry *,
+ struct g_part_parms *);
+static int g_part_bsd64_bootcode(struct g_part_table *, struct g_part_parms *);
+static int g_part_bsd64_create(struct g_part_table *, struct g_part_parms *);
+static int g_part_bsd64_destroy(struct g_part_table *, struct g_part_parms *);
+static void g_part_bsd64_dumpconf(struct g_part_table *, struct g_part_entry *,
+ struct sbuf *, const char *);
+static int g_part_bsd64_dumpto(struct g_part_table *, struct g_part_entry *);
+static int g_part_bsd64_modify(struct g_part_table *, struct g_part_entry *,
+ struct g_part_parms *);
+static const char *g_part_bsd64_name(struct g_part_table *, struct g_part_entry *,
+ char *, size_t);
+static int g_part_bsd64_probe(struct g_part_table *, struct g_consumer *);
+static int g_part_bsd64_read(struct g_part_table *, struct g_consumer *);
+static const char *g_part_bsd64_type(struct g_part_table *, struct g_part_entry *,
+ char *, size_t);
+static int g_part_bsd64_write(struct g_part_table *, struct g_consumer *);
+static int g_part_bsd64_resize(struct g_part_table *, struct g_part_entry *,
+ struct g_part_parms *);
+
+static kobj_method_t g_part_bsd64_methods[] = {
+ KOBJMETHOD(g_part_add, g_part_bsd64_add),
+ KOBJMETHOD(g_part_bootcode, g_part_bsd64_bootcode),
+ KOBJMETHOD(g_part_create, g_part_bsd64_create),
+ KOBJMETHOD(g_part_destroy, g_part_bsd64_destroy),
+ KOBJMETHOD(g_part_dumpconf, g_part_bsd64_dumpconf),
+ KOBJMETHOD(g_part_dumpto, g_part_bsd64_dumpto),
+ KOBJMETHOD(g_part_modify, g_part_bsd64_modify),
+ KOBJMETHOD(g_part_resize, g_part_bsd64_resize),
+ KOBJMETHOD(g_part_name, g_part_bsd64_name),
+ KOBJMETHOD(g_part_probe, g_part_bsd64_probe),
+ KOBJMETHOD(g_part_read, g_part_bsd64_read),
+ KOBJMETHOD(g_part_type, g_part_bsd64_type),
+ KOBJMETHOD(g_part_write, g_part_bsd64_write),
+ { 0, 0 }
+};
+
+static struct g_part_scheme g_part_bsd64_scheme = {
+ "BSD64",
+ g_part_bsd64_methods,
+ sizeof(struct g_part_bsd64_table),
+ .gps_entrysz = sizeof(struct g_part_bsd64_entry),
+ .gps_minent = MAXPARTITIONS64,
+ .gps_maxent = MAXPARTITIONS64
+};
+G_PART_SCHEME_DECLARE(g_part_bsd64);
+
+#define EQUUID(a, b) (memcmp(a, b, sizeof(struct uuid)) == 0)
+static struct uuid bsd64_uuid_unused = GPT_ENT_TYPE_UNUSED;
+static struct uuid bsd64_uuid_dfbsd_swap = GPT_ENT_TYPE_DRAGONFLY_SWAP;
+static struct uuid bsd64_uuid_dfbsd_ufs1 = GPT_ENT_TYPE_DRAGONFLY_UFS1;
+static struct uuid bsd64_uuid_dfbsd_vinum = GPT_ENT_TYPE_DRAGONFLY_VINUM;
+static struct uuid bsd64_uuid_dfbsd_ccd = GPT_ENT_TYPE_DRAGONFLY_CCD;
+static struct uuid bsd64_uuid_dfbsd_legacy = GPT_ENT_TYPE_DRAGONFLY_LEGACY;
+static struct uuid bsd64_uuid_dfbsd_hammer = GPT_ENT_TYPE_DRAGONFLY_HAMMER;
+static struct uuid bsd64_uuid_dfbsd_hammer2 = GPT_ENT_TYPE_DRAGONFLY_HAMMER2;
+static struct uuid bsd64_uuid_freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT;
+static struct uuid bsd64_uuid_freebsd_nandfs = GPT_ENT_TYPE_FREEBSD_NANDFS;
+static struct uuid bsd64_uuid_freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP;
+static struct uuid bsd64_uuid_freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS;
+static struct uuid bsd64_uuid_freebsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM;
+static struct uuid bsd64_uuid_freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS;
+
+struct bsd64_uuid_alias {
+ struct uuid *uuid;
+ uint8_t fstype;
+ int alias;
+};
+static struct bsd64_uuid_alias dfbsd_alias_match[] = {
+ { &bsd64_uuid_dfbsd_swap, FS_SWAP, G_PART_ALIAS_DFBSD_SWAP },
+ { &bsd64_uuid_dfbsd_ufs1, FS_BSDFFS, G_PART_ALIAS_DFBSD_UFS },
+ { &bsd64_uuid_dfbsd_vinum, FS_VINUM, G_PART_ALIAS_DFBSD_VINUM },
+ { &bsd64_uuid_dfbsd_ccd, FS_CCD, G_PART_ALIAS_DFBSD_CCD },
+ { &bsd64_uuid_dfbsd_legacy, FS_OTHER, G_PART_ALIAS_DFBSD_LEGACY },
+ { &bsd64_uuid_dfbsd_hammer, FS_HAMMER, G_PART_ALIAS_DFBSD_HAMMER },
+ { &bsd64_uuid_dfbsd_hammer2, FS_HAMMER2, G_PART_ALIAS_DFBSD_HAMMER2 },
+ { NULL, 0, 0}
+};
+static struct bsd64_uuid_alias fbsd_alias_match[] = {
+ { &bsd64_uuid_freebsd_boot, FS_OTHER, G_PART_ALIAS_FREEBSD_BOOT },
+ { &bsd64_uuid_freebsd_swap, FS_OTHER, G_PART_ALIAS_FREEBSD_SWAP },
+ { &bsd64_uuid_freebsd_ufs, FS_OTHER, G_PART_ALIAS_FREEBSD_UFS },
+ { &bsd64_uuid_freebsd_zfs, FS_OTHER, G_PART_ALIAS_FREEBSD_ZFS },
+ { &bsd64_uuid_freebsd_vinum, FS_OTHER, G_PART_ALIAS_FREEBSD_VINUM },
+ { &bsd64_uuid_freebsd_nandfs, FS_OTHER, G_PART_ALIAS_FREEBSD_NANDFS },
+ { NULL, 0, 0}
+};
+
+static int
+bsd64_parse_type(const char *type, struct g_part_bsd64_entry *entry)
+{
+ struct uuid tmp;
+ const struct bsd64_uuid_alias *uap;
+ const char *alias;
+ char *p;
+ long lt;
+ int error;
+
+ if (type[0] == '!') {
+ if (type[1] == '\0')
+ return (EINVAL);
+ lt = strtol(type + 1, &p, 0);
+ /* The type specified as number */
+ if (*p == '\0') {
+ if (lt <= 0 || lt > 255)
+ return (EINVAL);
+ entry->fstype = lt;
+ entry->type_uuid = bsd64_uuid_unused;
+ return (0);
+ }
+ /* The type specified as uuid */
+ error = parse_uuid(type + 1, &tmp);
+ if (error != 0)
+ return (error);
+ if (EQUUID(&tmp, &bsd64_uuid_unused))
+ return (EINVAL);
+ for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++) {
+ if (EQUUID(&tmp, uap->uuid)) {
+ /* Prefer fstype for known uuids */
+ entry->type_uuid = bsd64_uuid_unused;
+ entry->fstype = uap->fstype;
+ return (0);
+ }
+ }
+ entry->type_uuid = tmp;
+ entry->fstype = FS_OTHER;
+ return (0);
+ }
+ /* The type specified as symbolic alias name */
+ for (uap = &fbsd_alias_match[0]; uap->uuid != NULL; uap++) {
+ alias = g_part_alias_name(uap->alias);
+ if (!strcasecmp(type, alias)) {
+ entry->type_uuid = *uap->uuid;
+ entry->fstype = uap->fstype;
+ return (0);
+ }
+ }
+ for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++) {
+ alias = g_part_alias_name(uap->alias);
+ if (!strcasecmp(type, alias)) {
+ entry->type_uuid = bsd64_uuid_unused;
+ entry->fstype = uap->fstype;
+ return (0);
+ }
+ }
+ return (EINVAL);
+}
+
+static int
+g_part_bsd64_add(struct g_part_table *basetable, struct g_part_entry *baseentry,
+ struct g_part_parms *gpp)
+{
+ struct g_part_bsd64_entry *entry;
+
+ if (gpp->gpp_parms & G_PART_PARM_LABEL)
+ return (EINVAL);
+
+ entry = (struct g_part_bsd64_entry *)baseentry;
+ if (bsd64_parse_type(gpp->gpp_type, entry) != 0)
+ return (EINVAL);
+ kern_uuidgen(&entry->stor_uuid, 1);
+ return (0);
+}
+
+static int
+g_part_bsd64_bootcode(struct g_part_table *basetable, struct g_part_parms *gpp)
+{
+
+ return (EOPNOTSUPP);
+}
+
+#define PALIGN_SIZE (1024 * 1024)
+#define PALIGN_MASK (PALIGN_SIZE - 1)
+#define BLKSIZE (4 * 1024)
+#define BOOTSIZE (32 * 1024)
+#define DALIGN_SIZE (32 * 1024)
+static int
+g_part_bsd64_create(struct g_part_table *basetable, struct g_part_parms *gpp)
+{
+ struct g_part_bsd64_table *table;
+ struct g_part_entry *baseentry;
+ struct g_provider *pp;
+ uint64_t blkmask, pbase;
+ uint32_t blksize, ressize;
+
+ pp = gpp->gpp_provider;
+ if (pp->mediasize < 2* PALIGN_SIZE)
+ return (ENOSPC);
+
+ /*
+ * Use at least 4KB block size. Blksize is stored in the d_align.
+ * XXX: Actually it is used just for calculate d_bbase and used
+ * for better alignment in bsdlabel64(8).
+ */
+ blksize = pp->sectorsize < BLKSIZE ? BLKSIZE: pp->sectorsize;
+ blkmask = blksize - 1;
+ /* Reserve enough space for RESPARTITIONS64 partitions. */
+ ressize = offsetof(struct disklabel64, d_partitions[RESPARTITIONS64]);
+ ressize = (ressize + blkmask) & ~blkmask;
+ /*
+ * Reserve enough space for bootcode and align first allocatable
+ * offset to PALIGN_SIZE.
+ * XXX: Currently DragonFlyBSD has 32KB bootcode, but the size could
+ * be bigger, because it is possible change it (it is equal pbase-bbase)
+ * in the bsdlabel64(8).
+ */
+ pbase = ressize + ((BOOTSIZE + blkmask) & ~blkmask);
+ pbase = (pbase + PALIGN_MASK) & ~PALIGN_MASK;
+ /*
+ * Take physical offset into account and make first allocatable
+ * offset 32KB aligned to the start of the physical disk.
+ * XXX: Actually there are no such restrictions, this is how
+ * DragonFlyBSD behaves.
+ */
+ pbase += DALIGN_SIZE - pp->stripeoffset % DALIGN_SIZE;
+
+ table = (struct g_part_bsd64_table *)basetable;
+ table->d_align = blksize;
+ table->d_bbase = ressize / pp->sectorsize;
+ table->d_abase = ((pp->mediasize - ressize) &
+ ~blkmask) / pp->sectorsize;
+ kern_uuidgen(&table->d_stor_uuid, 1);
+ basetable->gpt_first = pbase / pp->sectorsize;
+ basetable->gpt_last = table->d_abase - 1; /* XXX */
+ /*
+ * Create 'c' partition and make it internal, so user will not be
+ * able use it.
+ */
+ baseentry = g_part_new_entry(basetable, RAW_PART + 1, 0, 0);
+ baseentry->gpe_internal = 1;
+ return (0);
+}
+
+static int
+g_part_bsd64_destroy(struct g_part_table *basetable, struct g_part_parms *gpp)
+{
+ struct g_provider *pp;
+
+ pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
+ if (pp->sectorsize > offsetof(struct disklabel64, d_magic))
+ basetable->gpt_smhead |= 1;
+ else
+ basetable->gpt_smhead |= 3;
+ return (0);
+}
+
+static void
+g_part_bsd64_dumpconf(struct g_part_table *basetable,
+ struct g_part_entry *baseentry, struct sbuf *sb, const char *indent)
+{
+ struct g_part_bsd64_table *table;
+ struct g_part_bsd64_entry *entry;
+ char buf[sizeof(table->d_packname)];
+
+ entry = (struct g_part_bsd64_entry *)baseentry;
+ if (indent == NULL) {
+ /* conftxt: libdisk compatibility */
+ sbuf_printf(sb, " xs BSD64 xt %u", entry->fstype);
+ } else if (entry != NULL) {
+ /* confxml: partition entry information */
+ sbuf_printf(sb, "%s<rawtype>%u</rawtype>\n", indent,
+ entry->fstype);
+ if (!EQUUID(&bsd64_uuid_unused, &entry->type_uuid)) {
+ sbuf_printf(sb, "%s<type_uuid>", indent);
+ sbuf_printf_uuid(sb, &entry->type_uuid);
+ sbuf_printf(sb, "</type_uuid>\n");
+ }
+ sbuf_printf(sb, "%s<stor_uuid>", indent);
+ sbuf_printf_uuid(sb, &entry->stor_uuid);
+ sbuf_printf(sb, "</stor_uuid>\n");
+ } else {
+ /* confxml: scheme information */
+ table = (struct g_part_bsd64_table *)basetable;
+ sbuf_printf(sb, "%s<bootbase>%ju</bootbase>\n", indent,
+ (uintmax_t)table->d_bbase);
+ if (table->d_abase)
+ sbuf_printf(sb, "%s<backupbase>%ju</backupbase>\n",
+ indent, (uintmax_t)table->d_abase);
+ sbuf_printf(sb, "%s<stor_uuid>", indent);
+ sbuf_printf_uuid(sb, &table->d_stor_uuid);
+ sbuf_printf(sb, "</stor_uuid>\n");
+ sbuf_printf(sb, "%s<label>", indent);
+ strncpy(buf, table->d_packname, sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = '\0';
+ g_conf_printf_escaped(sb, "%s", buf);
+ sbuf_printf(sb, "</label>\n");
+ }
+}
+
+static int
+g_part_bsd64_dumpto(struct g_part_table *table, struct g_part_entry *baseentry)
+{
+ struct g_part_bsd64_entry *entry;
+
+ /* Allow dumping to a swap partition. */
+ entry = (struct g_part_bsd64_entry *)baseentry;
+ if (entry->fstype == FS_SWAP ||
+ EQUUID(&entry->type_uuid, &bsd64_uuid_dfbsd_swap) ||
+ EQUUID(&entry->type_uuid, &bsd64_uuid_freebsd_swap))
+ return (1);
+ return (0);
+}
+
+static int
+g_part_bsd64_modify(struct g_part_table *basetable,
+ struct g_part_entry *baseentry, struct g_part_parms *gpp)
+{
+ struct g_part_bsd64_entry *entry;
+
+ if (gpp->gpp_parms & G_PART_PARM_LABEL)
+ return (EINVAL);
+
+ entry = (struct g_part_bsd64_entry *)baseentry;
+ if (gpp->gpp_parms & G_PART_PARM_TYPE)
+ return (bsd64_parse_type(gpp->gpp_type, entry));
+ return (0);
+}
+
+static int
+g_part_bsd64_resize(struct g_part_table *basetable,
+ struct g_part_entry *baseentry, struct g_part_parms *gpp)
+{
+ struct g_part_bsd64_table *table;
+ struct g_provider *pp;
+
+ if (baseentry == NULL) {
+ pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
+ table = (struct g_part_bsd64_table *)basetable;
+ table->d_abase = ((pp->mediasize -
+ table->d_bbase * pp->sectorsize) & ~(table->d_align - 1)) /
+ pp->sectorsize;
+ basetable->gpt_last = table->d_abase - 1;
+ return (0);
+ }
+ baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1;
+ return (0);
+}
+
+static const char *
+g_part_bsd64_name(struct g_part_table *table, struct g_part_entry *baseentry,
+ char *buf, size_t bufsz)
+{
+
+ snprintf(buf, bufsz, "%c", 'a' + baseentry->gpe_index - 1);
+ return (buf);
+}
+
+static int
+g_part_bsd64_probe(struct g_part_table *table, struct g_consumer *cp)
+{
+ struct g_provider *pp;
+ uint32_t v;
+ int error;
+ u_char *buf;
+
+ pp = cp->provider;
+ if (pp->mediasize < 2 * PALIGN_SIZE)
+ return (ENOSPC);
+ v = (pp->sectorsize +
+ offsetof(struct disklabel64, d_magic)) & ~(pp->sectorsize - 1);
+ buf = g_read_data(cp, 0, v, &error);
+ if (buf == NULL)
+ return (error);
+ v = le32dec(buf + offsetof(struct disklabel64, d_magic));
+ g_free(buf);
+ return (v == DISKMAGIC64 ? G_PART_PROBE_PRI_HIGH: ENXIO);
+}
+
+static int
+g_part_bsd64_read(struct g_part_table *basetable, struct g_consumer *cp)
+{
+ struct g_part_bsd64_table *table;
+ struct g_part_bsd64_entry *entry;
+ struct g_part_entry *baseentry;
+ struct g_provider *pp;
+ struct disklabel64 *dlp;
+ uint64_t v64, sz;
+ uint32_t v32;
+ int error, index;
+ u_char *buf;
+
+ pp = cp->provider;
+ table = (struct g_part_bsd64_table *)basetable;
+ v32 = (pp->sectorsize +
+ sizeof(struct disklabel64) - 1) & ~(pp->sectorsize - 1);
+ buf = g_read_data(cp, 0, v32, &error);
+ if (buf == NULL)
+ return (error);
+
+ dlp = (struct disklabel64 *)buf;
+ basetable->gpt_entries = le32toh(dlp->d_npartitions);
+ if (basetable->gpt_entries > MAXPARTITIONS64)
+ goto invalid_label;
+ v32 = le32toh(dlp->d_crc);
+ dlp->d_crc = 0;
+ if (crc32(&dlp->d_magic, offsetof(struct disklabel64,
+ d_partitions[basetable->gpt_entries]) -
+ offsetof(struct disklabel64, d_magic)) != v32)
+ goto invalid_label;
+ table->d_align = le32toh(dlp->d_align);
+ if (table->d_align == 0 || (table->d_align & (pp->sectorsize - 1)))
+ goto invalid_label;
+ if (le64toh(dlp->d_total_size) > pp->mediasize)
+ goto invalid_label;
+ v64 = le64toh(dlp->d_pbase);
+ if (v64 % pp->sectorsize)
+ goto invalid_label;
+ basetable->gpt_first = v64 / pp->sectorsize;
+ v64 = le64toh(dlp->d_pstop);
+ if (v64 % pp->sectorsize)
+ goto invalid_label;
+ basetable->gpt_last = v64 / pp->sectorsize;
+ basetable->gpt_isleaf = 1;
+ v64 = le64toh(dlp->d_bbase);
+ if (v64 % pp->sectorsize)
+ goto invalid_label;
+ table->d_bbase = v64 / pp->sectorsize;
+ v64 = le64toh(dlp->d_abase);
+ if (v64 % pp->sectorsize)
+ goto invalid_label;
+ table->d_abase = v64 / pp->sectorsize;
+ le_uuid_dec(&dlp->d_stor_uuid, &table->d_stor_uuid);
+ for (index = basetable->gpt_entries - 1; index >= 0; index--) {
+ if (index == RAW_PART) {
+ /* Skip 'c' partition. */
+ baseentry = g_part_new_entry(basetable,
+ index + 1, 0, 0);
+ baseentry->gpe_internal = 1;
+ continue;
+ }
+ v64 = le64toh(dlp->d_partitions[index].p_boffset);
+ sz = le64toh(dlp->d_partitions[index].p_bsize);
+ if (sz == 0 && v64 == 0)
+ continue;
+ if (sz == 0 || (v64 % pp->sectorsize) || (sz % pp->sectorsize))
+ goto invalid_label;
+ baseentry = g_part_new_entry(basetable, index + 1,
+ v64 / pp->sectorsize, (v64 + sz) / pp->sectorsize - 1);
+ entry = (struct g_part_bsd64_entry *)baseentry;
+ le_uuid_dec(&dlp->d_partitions[index].p_type_uuid,
+ &entry->type_uuid);
+ le_uuid_dec(&dlp->d_partitions[index].p_stor_uuid,
+ &entry->stor_uuid);
+ entry->fstype = dlp->d_partitions[index].p_fstype;
+ if (index == RAW_PART)
+ baseentry->gpe_internal = 1;
+ }
+ bcopy(dlp->d_reserved0, table->d_reserved0,
+ sizeof(table->d_reserved0));
+ bcopy(dlp->d_packname, table->d_packname, sizeof(table->d_packname));
+ bcopy(dlp->d_reserved, table->d_reserved, sizeof(table->d_reserved));
+ g_free(buf);
+ return (0);
+
+invalid_label:
+ g_free(buf);
+ return (EINVAL);
+}
+
+static const char *
+g_part_bsd64_type(struct g_part_table *basetable, struct g_part_entry *baseentry,
+ char *buf, size_t bufsz)
+{
+ struct g_part_bsd64_entry *entry;
+ struct bsd64_uuid_alias *uap;
+
+ entry = (struct g_part_bsd64_entry *)baseentry;
+ if (entry->fstype != FS_OTHER) {
+ for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++)
+ if (uap->fstype == entry->fstype)
+ return (g_part_alias_name(uap->alias));
+ } else {
+ for (uap = &fbsd_alias_match[0]; uap->uuid != NULL; uap++)
+ if (EQUUID(uap->uuid, &entry->type_uuid))
+ return (g_part_alias_name(uap->alias));
+ for (uap = &dfbsd_alias_match[0]; uap->uuid != NULL; uap++)
+ if (EQUUID(uap->uuid, &entry->type_uuid))
+ return (g_part_alias_name(uap->alias));
+ }
+ if (EQUUID(&bsd64_uuid_unused, &entry->type_uuid))
+ snprintf(buf, bufsz, "!%d", entry->fstype);
+ else {
+ buf[0] = '!';
+ snprintf_uuid(buf + 1, bufsz - 1, &entry->type_uuid);
+ }
+ return (buf);
+}
+
+static int
+g_part_bsd64_write(struct g_part_table *basetable, struct g_consumer *cp)
+{
+ struct g_provider *pp;
+ struct g_part_entry *baseentry;
+ struct g_part_bsd64_entry *entry;
+ struct g_part_bsd64_table *table;
+ struct disklabel64 *dlp;
+ uint32_t v, sz;
+ int error, index;
+
+ pp = cp->provider;
+ table = (struct g_part_bsd64_table *)basetable;
+ sz = (pp->sectorsize +
+ sizeof(struct disklabel64) - 1) & ~(pp->sectorsize - 1);
+ dlp = g_malloc(sz, M_WAITOK | M_ZERO);
+
+ memcpy(dlp->d_reserved0, table->d_reserved0,
+ sizeof(table->d_reserved0));
+ memcpy(dlp->d_packname, table->d_packname, sizeof(table->d_packname));
+ memcpy(dlp->d_reserved, table->d_reserved, sizeof(table->d_reserved));
+ le32enc(&dlp->d_magic, DISKMAGIC64);
+ le32enc(&dlp->d_align, table->d_align);
+ le32enc(&dlp->d_npartitions, basetable->gpt_entries);
+ le_uuid_enc(&dlp->d_stor_uuid, &table->d_stor_uuid);
+ le64enc(&dlp->d_total_size, pp->mediasize);
+ le64enc(&dlp->d_bbase, table->d_bbase * pp->sectorsize);
+ le64enc(&dlp->d_pbase, basetable->gpt_first * pp->sectorsize);
+ le64enc(&dlp->d_pstop, basetable->gpt_last * pp->sectorsize);
+ le64enc(&dlp->d_abase, table->d_abase * pp->sectorsize);
+
+ LIST_FOREACH(baseentry, &basetable->gpt_entry, gpe_entry) {
+ if (baseentry->gpe_deleted)
+ continue;
+ index = baseentry->gpe_index - 1;
+ entry = (struct g_part_bsd64_entry *)baseentry;
+ if (index == RAW_PART)
+ continue;
+ le64enc(&dlp->d_partitions[index].p_boffset,
+ baseentry->gpe_start * pp->sectorsize);
+ le64enc(&dlp->d_partitions[index].p_bsize, pp->sectorsize *
+ (baseentry->gpe_end - baseentry->gpe_start + 1));
+ dlp->d_partitions[index].p_fstype = entry->fstype;
+ le_uuid_enc(&dlp->d_partitions[index].p_type_uuid,
+ &entry->type_uuid);
+ le_uuid_enc(&dlp->d_partitions[index].p_stor_uuid,
+ &entry->stor_uuid);
+ }
+ /* Calculate checksum. */
+ v = offsetof(struct disklabel64,
+ d_partitions[basetable->gpt_entries]) -
+ offsetof(struct disklabel64, d_magic);
+ le32enc(&dlp->d_crc, crc32(&dlp->d_magic, v));
+ error = g_write_data(cp, 0, dlp, sz);
+ g_free(dlp);
+ return (error);
+}
+
diff --git a/sys/geom/part/g_part_gpt.c b/sys/geom/part/g_part_gpt.c
index 4af2868..46841f4 100644
--- a/sys/geom/part/g_part_gpt.c
+++ b/sys/geom/part/g_part_gpt.c
@@ -181,6 +181,15 @@ static struct uuid gpt_uuid_netbsd_raid = GPT_ENT_TYPE_NETBSD_RAID;
static struct uuid gpt_uuid_netbsd_swap = GPT_ENT_TYPE_NETBSD_SWAP;
static struct uuid gpt_uuid_mbr = GPT_ENT_TYPE_MBR;
static struct uuid gpt_uuid_unused = GPT_ENT_TYPE_UNUSED;
+static struct uuid gpt_uuid_dfbsd_swap = GPT_ENT_TYPE_DRAGONFLY_SWAP;
+static struct uuid gpt_uuid_dfbsd_ufs1 = GPT_ENT_TYPE_DRAGONFLY_UFS1;
+static struct uuid gpt_uuid_dfbsd_vinum = GPT_ENT_TYPE_DRAGONFLY_VINUM;
+static struct uuid gpt_uuid_dfbsd_ccd = GPT_ENT_TYPE_DRAGONFLY_CCD;
+static struct uuid gpt_uuid_dfbsd_legacy = GPT_ENT_TYPE_DRAGONFLY_LEGACY;
+static struct uuid gpt_uuid_dfbsd_hammer = GPT_ENT_TYPE_DRAGONFLY_HAMMER;
+static struct uuid gpt_uuid_dfbsd_hammer2 = GPT_ENT_TYPE_DRAGONFLY_HAMMER2;
+static struct uuid gpt_uuid_dfbsd_label32 = GPT_ENT_TYPE_DRAGONFLY_LABEL32;
+static struct uuid gpt_uuid_dfbsd_label64 = GPT_ENT_TYPE_DRAGONFLY_LABEL64;
static struct g_part_uuid_alias {
struct uuid *uuid;
@@ -222,6 +231,15 @@ static struct g_part_uuid_alias {
{ &gpt_uuid_netbsd_lfs, G_PART_ALIAS_NETBSD_LFS, 0 },
{ &gpt_uuid_netbsd_raid, G_PART_ALIAS_NETBSD_RAID, 0 },
{ &gpt_uuid_netbsd_swap, G_PART_ALIAS_NETBSD_SWAP, 0 },
+ { &gpt_uuid_dfbsd_swap, G_PART_ALIAS_DFBSD_SWAP, 0 },
+ { &gpt_uuid_dfbsd_ufs1, G_PART_ALIAS_DFBSD_UFS, 0 },
+ { &gpt_uuid_dfbsd_vinum, G_PART_ALIAS_DFBSD_VINUM, 0 },
+ { &gpt_uuid_dfbsd_ccd, G_PART_ALIAS_DFBSD_CCD, 0 },
+ { &gpt_uuid_dfbsd_legacy, G_PART_ALIAS_DFBSD_LEGACY, 0 },
+ { &gpt_uuid_dfbsd_hammer, G_PART_ALIAS_DFBSD_HAMMER, 0 },
+ { &gpt_uuid_dfbsd_hammer2, G_PART_ALIAS_DFBSD_HAMMER2, 0 },
+ { &gpt_uuid_dfbsd_label32, G_PART_ALIAS_DFBSD, 0xa5 },
+ { &gpt_uuid_dfbsd_label64, G_PART_ALIAS_DFBSD64, 0xa5 },
{ NULL, 0, 0 }
};
@@ -706,7 +724,8 @@ g_part_gpt_dumpto(struct g_part_table *table, struct g_part_entry *baseentry)
entry = (struct g_part_gpt_entry *)baseentry;
return ((EQUUID(&entry->ent.ent_type, &gpt_uuid_freebsd_swap) ||
- EQUUID(&entry->ent.ent_type, &gpt_uuid_linux_swap)) ? 1 : 0);
+ EQUUID(&entry->ent.ent_type, &gpt_uuid_linux_swap) ||
+ EQUUID(&entry->ent.ent_type, &gpt_uuid_dfbsd_swap)) ? 1 : 0);
}
static int
OpenPOWER on IntegriCloud