From owner-freebsd-hackers@FreeBSD.ORG Fri Jun 6 09:38:57 2014 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx2.freebsd.org (mx2.freebsd.org [IPv6:2001:1900:2254:206a::19:2]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 9FB97F78; Fri, 6 Jun 2014 09:38:57 +0000 (UTC) Received: from butcher-nb.yandex.net (hub.freebsd.org [IPv6:2001:1900:2254:206c::16:88]) by mx2.freebsd.org (Postfix) with ESMTP id A38C13412; Fri, 6 Jun 2014 09:38:55 +0000 (UTC) Message-ID: <53918C0B.5060706@FreeBSD.org> Date: Fri, 06 Jun 2014 13:38:19 +0400 From: "Andrey V. Elsukov" User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:24.0) Gecko/20100101 Thunderbird/24.5.0 MIME-Version: 1.0 To: freebsd-geom@FreeBSD.org, FreeBSD Hackers Subject: [RFC][RFT] disklabel64 support for GEOM_PART X-Enigmail-Version: 1.6 Content-Type: multipart/mixed; boundary="------------040101090305050600040806" X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 06 Jun 2014 09:38:57 -0000 This is a multi-part message in MIME format. --------------040101090305050600040806 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Hi All, I've added disklabel64 support for GEOM_PART class. This partitioning scheme is used in DragonFlyBSD. It has the following features: * no part of its metadata is addressable via a partition access; * all offsets are 64-bit; * supports 16 partitions by default (can be extended) * has reserved location for backup label (not yet implemented). If you are able to test compatibility of our implementation and dragonfly's, I'd like to see the results. Currently we have no bootcode that supports this type of disklabel, so it can be only used for data partitions or for access to DragonflyBSD's UFS partitions. There are two patches. The first one add dflybsd's partition types, the second is the disklabel64 implementation. Also, I published them in our phabricator: https://phabric.freebsd.org/D168 https://phabric.freebsd.org/D169 -- WBR, Andrey V. Elsukov --------------040101090305050600040806 Content-Type: text/plain; charset=UTF-8; name="bsd64.diff.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="bsd64.diff.txt" Index: head/sys/geom/part/g_part_bsd64.c =================================================================== --- head/sys/geom/part/g_part_bsd64.c (revision 0) +++ head/sys/geom/part/g_part_bsd64.c (working copy) @@ -0,0 +1,666 @@ +/*- + * Copyright (c) 2014 Andrey V. Elsukov + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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%u\n", indent, + entry->fstype); + if (!EQUUID(&bsd64_uuid_unused, &entry->type_uuid)) { + sbuf_printf(sb, "%s", indent); + sbuf_printf_uuid(sb, &entry->type_uuid); + sbuf_printf(sb, "\n"); + } + sbuf_printf(sb, "%s", indent); + sbuf_printf_uuid(sb, &entry->stor_uuid); + sbuf_printf(sb, "\n"); + } else { + /* confxml: scheme information */ + table = (struct g_part_bsd64_table *)basetable; + sbuf_printf(sb, "%s%ju\n", indent, + (uintmax_t)table->d_bbase); + if (table->d_abase) + sbuf_printf(sb, "%s%ju\n", + indent, (uintmax_t)table->d_abase); + sbuf_printf(sb, "%s", indent); + sbuf_printf_uuid(sb, &table->d_stor_uuid); + sbuf_printf(sb, "\n"); + sbuf_printf(sb, "%s\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); +} Property changes on: head/sys/geom/part/g_part_bsd64.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/conf/NOTES =================================================================== --- head/sys/conf/NOTES (revision 267040) +++ head/sys/conf/NOTES (working copy) @@ -162,6 +162,7 @@ options GEOM_MULTIPATH # Disk multipath options GEOM_NOP # Test class. options GEOM_PART_APM # Apple partitioning options GEOM_PART_BSD # BSD disklabel +options GEOM_PART_BSD64 # BSD disklabel64 options GEOM_PART_EBR # Extended Boot Records options GEOM_PART_EBR_COMPAT # Backward compatible partition names options GEOM_PART_GPT # GPT partitioning Index: head/sys/conf/files =================================================================== --- head/sys/conf/files (revision 267040) +++ head/sys/conf/files (working copy) @@ -2756,6 +2756,7 @@ geom/part/g_part.c standard geom/part/g_part_if.m standard geom/part/g_part_apm.c optional geom_part_apm geom/part/g_part_bsd.c optional geom_part_bsd +geom/part/g_part_bsd64.c optional geom_part_bsd64 geom/part/g_part_ebr.c optional geom_part_ebr geom/part/g_part_gpt.c optional geom_part_gpt geom/part/g_part_ldm.c optional geom_part_ldm Index: head/sys/conf/options =================================================================== --- head/sys/conf/options (revision 267040) +++ head/sys/conf/options (working copy) @@ -111,6 +111,7 @@ GEOM_MULTIPATH opt_geom.h GEOM_NOP opt_geom.h GEOM_PART_APM opt_geom.h GEOM_PART_BSD opt_geom.h +GEOM_PART_BSD64 opt_geom.h GEOM_PART_EBR opt_geom.h GEOM_PART_EBR_COMPAT opt_geom.h GEOM_PART_GPT opt_geom.h Index: head/sys/modules/geom/geom_part/Makefile =================================================================== --- head/sys/modules/geom/geom_part/Makefile (revision 267040) +++ head/sys/modules/geom/geom_part/Makefile (working copy) @@ -2,6 +2,7 @@ SUBDIR= geom_part_apm \ geom_part_bsd \ + geom_part_bsd64 \ geom_part_ebr \ geom_part_gpt \ geom_part_ldm \ Index: head/sys/modules/geom/geom_part/geom_part_bsd64/Makefile =================================================================== --- head/sys/modules/geom/geom_part/geom_part_bsd64/Makefile (revision 0) +++ head/sys/modules/geom/geom_part/geom_part_bsd64/Makefile (working copy) @@ -0,0 +1,12 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../../geom/part + +KMOD= geom_part_bsd64 +SRCS= g_part_bsd64.c + +SRCS+= bus_if.h device_if.h g_part_if.h + +MFILES= kern/bus_if.m kern/device_if.m geom/part/g_part_if.m + +.include Property changes on: head/sys/modules/geom/geom_part/geom_part_bsd64/Makefile ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: head/sbin/geom/class/part/gpart.8 =================================================================== --- head/sbin/geom/class/part/gpart.8 (revision 267040) +++ head/sbin/geom/class/part/gpart.8 (working copy) @@ -491,6 +491,12 @@ called Requires the .Cm GEOM_PART_BSD kernel option. +.It Cm BSD64 +64-bit implementation of BSD disklabel used in DragonFlyBSD to subdivide MBR +or GPT partitions. +Requires the +.Cm GEOM_PART_BSD64 +kernel option. .It Cm LDM The Logical Disk Manager is an implementation of volume manager for Microsoft Windows NT. --------------040101090305050600040806 Content-Type: text/plain; charset=UTF-8; name="dfbsd-types.diff.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="dfbsd-types.diff.txt" Index: head/sys/sys/disklabel.h =================================================================== --- head/sys/sys/disklabel.h (revision 267040) +++ head/sys/sys/disklabel.h (working copy) @@ -229,6 +229,8 @@ static const char *dktypenames[] = { #define FS_NTFS 18 /* Windows/NT file system */ #define FS_CCD 20 /* concatenated disk component */ #define FS_JFS2 21 /* IBM JFS2 */ +#define FS_HAMMER 22 /* DragonFlyBSD Hammer FS */ +#define FS_HAMMER2 23 /* DragonFlyBSD Hammer2 FS */ #define FS_UDF 24 /* UDF */ #define FS_EFS 26 /* SGI's Extent File system */ #define FS_ZFS 27 /* Sun's ZFS */ @@ -258,8 +260,8 @@ static const char *fstypenames[] = { "?", "ccd", "jfs", - "?", - "?", + "HAMMER", + "HAMMER2", "UDF", "?", "EFS", Index: head/sys/sys/gpt.h =================================================================== --- head/sys/sys/gpt.h (revision 267040) +++ head/sys/sys/gpt.h (working copy) @@ -161,6 +161,25 @@ struct gpt_ent { #define GPT_ENT_TYPE_NETBSD_CGD \ {0x2db519ec,0xb10f,0x11dc,0xb9,0x9b,{0x00,0x19,0xd1,0x87,0x96,0x48}} +#define GPT_ENT_TYPE_DRAGONFLY_LABEL32 \ + {0x9d087404,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_SWAP \ + {0x9d58fdbd,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_UFS1 \ + {0x9d94ce7c,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_VINUM \ + {0x9dd4478f,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_CCD \ + {0xdbd5211b,0x1ca5,0x11dc,0x88,0x17,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_LABEL64 \ + {0x3d48ce54,0x1d16,0x11dc,0x86,0x96,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_LEGACY \ + {0xbd215ab2,0x1d16,0x11dc,0x86,0x96,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_HAMMER \ + {0x61dc63ac,0x6e38,0x11dc,0x85,0x13,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} +#define GPT_ENT_TYPE_DRAGONFLY_HAMMER2 \ + {0x5cbb9ad1,0x862d,0x11dc,0xa9,0x4d,{0x01,0x30,0x1b,0xb8,0xa9,0xf5}} + /* * Boot partition used by GRUB 2. */ Index: head/sys/geom/part/g_part.c =================================================================== --- head/sys/geom/part/g_part.c (revision 267040) +++ head/sys/geom/part/g_part.c (working copy) @@ -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); Index: head/sys/geom/part/g_part.h =================================================================== --- head/sys/geom/part/g_part.h (revision 267040) +++ head/sys/geom/part/g_part.h (working copy) @@ -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 }; Index: head/sys/geom/part/g_part_bsd.c =================================================================== --- head/sys/geom/part/g_part_bsd.c (revision 267040) +++ head/sys/geom/part/g_part_bsd.c (working copy) @@ -112,6 +112,19 @@ 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) { @@ -118,6 +131,7 @@ 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,31 +140,14 @@ 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); + 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); + } } - 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); - } return (EINVAL); } Index: head/sys/geom/part/g_part_gpt.c =================================================================== --- head/sys/geom/part/g_part_gpt.c (revision 267040) +++ head/sys/geom/part/g_part_gpt.c (working copy) @@ -181,6 +181,15 @@ static struct uuid gpt_uuid_netbsd_raid = GPT_ENT_ 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 } }; --------------040101090305050600040806--