svn commit: r356060 - head/usr.sbin/fstyp
Pedro F. Giffuni
pfg at FreeBSD.org
Tue Dec 24 19:00:21 UTC 2019
Author: pfg
Date: Tue Dec 24 19:00:20 2019
New Revision: 356060
URL: https://svnweb.freebsd.org/changeset/base/356060
Log:
sbin/fstyp: recgonize Dragonfly's hammer and hammer2.
This is based on DragonFly's implementation from about 2019-09-13. It
only contains the basic code and header information to identify the
disks.
Relnotes: yes
Differential Revision: https://reviews.freebsd.org/D13369
Added:
head/usr.sbin/fstyp/hammer.c (contents, props changed)
head/usr.sbin/fstyp/hammer2.c (contents, props changed)
head/usr.sbin/fstyp/hammer2_disk.h (contents, props changed)
head/usr.sbin/fstyp/hammer_disk.h (contents, props changed)
Modified:
head/usr.sbin/fstyp/Makefile
head/usr.sbin/fstyp/fstyp.8
head/usr.sbin/fstyp/fstyp.c
head/usr.sbin/fstyp/fstyp.h
Modified: head/usr.sbin/fstyp/Makefile
==============================================================================
--- head/usr.sbin/fstyp/Makefile Tue Dec 24 18:38:06 2019 (r356059)
+++ head/usr.sbin/fstyp/Makefile Tue Dec 24 19:00:20 2019 (r356060)
@@ -3,7 +3,8 @@
.include <src.opts.mk>
PROG= fstyp
-SRCS= apfs.c cd9660.c exfat.c ext2fs.c fstyp.c geli.c hfsplus.c msdosfs.c ntfs.c ufs.c
+SRCS= apfs.c cd9660.c exfat.c ext2fs.c fstyp.c geli.c hammer.c \
+ hammer2.c hfsplus.c msdosfs.c ntfs.c ufs.c
.if ${MK_ZFS} != "no"
SRCS += zfs.c
Modified: head/usr.sbin/fstyp/fstyp.8
==============================================================================
--- head/usr.sbin/fstyp/fstyp.8 Tue Dec 24 18:38:06 2019 (r356059)
+++ head/usr.sbin/fstyp/fstyp.8 Tue Dec 24 19:00:20 2019 (r356060)
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 26, 2017
+.Dd December 24, 2019
.Dt FSTYP 8
.Os
.Sh NAME
@@ -67,6 +67,10 @@ exfat
ext2fs
.It
geli
+.It
+hammer
+.It
+hammer2
.It
msdosfs
.It
Modified: head/usr.sbin/fstyp/fstyp.c
==============================================================================
--- head/usr.sbin/fstyp/fstyp.c Tue Dec 24 18:38:06 2019 (r356059)
+++ head/usr.sbin/fstyp/fstyp.c Tue Dec 24 19:00:20 2019 (r356060)
@@ -69,6 +69,8 @@ static struct {
{ "exfat", &fstyp_exfat, false, EXFAT_ENC },
{ "ext2fs", &fstyp_ext2fs, false, NULL },
{ "geli", &fstyp_geli, true, NULL },
+ { "hammer", &fstyp_hammer, true, NULL },
+ { "hammer2", &fstyp_hammer2, true, NULL },
{ "hfs+", &fstyp_hfsp, false, NULL },
{ "msdosfs", &fstyp_msdosfs, false, NULL },
{ "ntfs", &fstyp_ntfs, false, NTFS_ENC },
Modified: head/usr.sbin/fstyp/fstyp.h
==============================================================================
--- head/usr.sbin/fstyp/fstyp.h Tue Dec 24 18:38:06 2019 (r356059)
+++ head/usr.sbin/fstyp/fstyp.h Tue Dec 24 19:00:20 2019 (r356060)
@@ -55,6 +55,8 @@ int fstyp_cd9660(FILE *fp, char *label, size_t size);
int fstyp_exfat(FILE *fp, char *label, size_t size);
int fstyp_ext2fs(FILE *fp, char *label, size_t size);
int fstyp_geli(FILE *fp, char *label, size_t size);
+int fstyp_hammer(FILE *fp, char *label, size_t size);
+int fstyp_hammer2(FILE *fp, char *label, size_t size);
int fstyp_hfsp(FILE *fp, char *label, size_t size);
int fstyp_msdosfs(FILE *fp, char *label, size_t size);
int fstyp_ntfs(FILE *fp, char *label, size_t size);
Added: head/usr.sbin/fstyp/hammer.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/usr.sbin/fstyp/hammer.c Tue Dec 24 19:00:20 2019 (r356060)
@@ -0,0 +1,198 @@
+/*-
+ * Copyright (c) 2016 The DragonFly Project
+ * All rights reserved.
+ *
+ * This software was developed by Edward Tomasz Napierala under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <assert.h>
+
+#include <sys/types.h>
+
+#include "hammer_disk.h"
+
+#include "fstyp.h"
+
+static hammer_volume_ondisk_t
+__read_ondisk(FILE *fp)
+{
+ hammer_volume_ondisk_t ondisk;
+
+ ondisk = read_buf(fp, 0, sizeof(*ondisk));
+ if (ondisk == NULL)
+ err(1, "failed to read ondisk");
+
+ return (ondisk);
+}
+
+static int
+__test_ondisk(const hammer_volume_ondisk_t ondisk)
+{
+ static int count = 0;
+ static hammer_uuid_t fsid, fstype;
+ static char label[64];
+
+ if (ondisk->vol_signature != HAMMER_FSBUF_VOLUME &&
+ ondisk->vol_signature != HAMMER_FSBUF_VOLUME_REV)
+ return (1);
+ if (ondisk->vol_rootvol != HAMMER_ROOT_VOLNO)
+ return (2);
+ if (ondisk->vol_no < 0 || ondisk->vol_no > HAMMER_MAX_VOLUMES - 1)
+ return (3);
+ if (ondisk->vol_count < 1 || ondisk->vol_count > HAMMER_MAX_VOLUMES)
+ return (4);
+
+ if (count == 0) {
+ count = ondisk->vol_count;
+ assert(count != 0);
+ memcpy(&fsid, &ondisk->vol_fsid, sizeof(fsid));
+ memcpy(&fstype, &ondisk->vol_fstype, sizeof(fstype));
+ strncpy(label, ondisk->vol_label, sizeof(label));
+ } else {
+ if (ondisk->vol_count != count)
+ return (5);
+ if (memcmp(&ondisk->vol_fsid, &fsid, sizeof(fsid)))
+ return (6);
+ if (memcmp(&ondisk->vol_fstype, &fstype, sizeof(fstype)))
+ return (7);
+ if (strncmp(ondisk->vol_label, label, sizeof(label)))
+ return (8);
+ }
+
+ return (0);
+}
+
+int
+fstyp_hammer(FILE *fp, char *label, size_t size)
+{
+ hammer_volume_ondisk_t ondisk;
+ int error = 1;
+
+ ondisk = __read_ondisk(fp);
+ if (ondisk->vol_no != HAMMER_ROOT_VOLNO)
+ goto done;
+ if (ondisk->vol_count != 1)
+ goto done;
+ if (__test_ondisk(ondisk))
+ goto done;
+
+ strlcpy(label, ondisk->vol_label, size);
+ error = 0;
+done:
+ free(ondisk);
+ return (error);
+}
+
+static int
+__test_volume(const char *volpath)
+{
+ hammer_volume_ondisk_t ondisk;
+ FILE *fp;
+ int volno = -1;
+
+ if ((fp = fopen(volpath, "r")) == NULL)
+ err(1, "failed to open %s", volpath);
+
+ ondisk = __read_ondisk(fp);
+ fclose(fp);
+ if (__test_ondisk(ondisk))
+ goto done;
+
+ volno = ondisk->vol_no;
+done:
+ free(ondisk);
+ return (volno);
+}
+
+static int
+__fsvtyp_hammer(const char *blkdevs, char *label, size_t size, int partial)
+{
+ hammer_volume_ondisk_t ondisk;
+ FILE *fp;
+ char *dup, *p, *volpath, x[HAMMER_MAX_VOLUMES];
+ int i, volno, error = 1;
+
+ memset(x, 0, sizeof(x));
+ dup = strdup(blkdevs);
+ p = dup;
+
+ while (p) {
+ volpath = p;
+ if ((p = strchr(p, ':')) != NULL)
+ *p++ = '\0';
+ if ((volno = __test_volume(volpath)) == -1)
+ break;
+ x[volno]++;
+ }
+
+ if ((fp = fopen(volpath, "r")) == NULL)
+ err(1, "failed to open %s", volpath);
+ ondisk = __read_ondisk(fp);
+ fclose(fp);
+
+ free(dup);
+
+ if (volno == -1)
+ goto done;
+ if (partial)
+ goto success;
+
+ for (i = 0; i < HAMMER_MAX_VOLUMES; i++)
+ if (x[i] > 1)
+ goto done;
+ for (i = 0; i < HAMMER_MAX_VOLUMES; i++)
+ if (x[i] == 0)
+ break;
+ if (ondisk->vol_count != i)
+ goto done;
+ for (; i < HAMMER_MAX_VOLUMES; i++)
+ if (x[i] != 0)
+ goto done;
+success:
+ strlcpy(label, ondisk->vol_label, size);
+ error = 0;
+done:
+ free(ondisk);
+ return (error);
+}
+
+int
+fsvtyp_hammer(const char *blkdevs, char *label, size_t size)
+{
+ return (__fsvtyp_hammer(blkdevs, label, size, 0));
+}
+
+int
+fsvtyp_hammer_partial(const char *blkdevs, char *label, size_t size)
+{
+ return (__fsvtyp_hammer(blkdevs, label, size, 1));
+}
Added: head/usr.sbin/fstyp/hammer2.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/usr.sbin/fstyp/hammer2.c Tue Dec 24 19:00:20 2019 (r356060)
@@ -0,0 +1,152 @@
+/*-
+ * Copyright (c) 2017-2019 The DragonFly Project
+ * All rights reserved.
+ *
+ * This software was developed by Edward Tomasz Napierala under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+
+#include <sys/types.h>
+
+#include "hammer2_disk.h"
+
+#include "fstyp.h"
+
+static hammer2_volume_data_t*
+__read_voldata(FILE *fp)
+{
+ hammer2_volume_data_t *voldata;
+
+ voldata = read_buf(fp, 0, sizeof(*voldata));
+ if (voldata == NULL)
+ err(1, "failed to read volume data");
+
+ return (voldata);
+}
+
+static int
+__test_voldata(const hammer2_volume_data_t *voldata)
+{
+ if (voldata->magic != HAMMER2_VOLUME_ID_HBO &&
+ voldata->magic != HAMMER2_VOLUME_ID_ABO)
+ return (1);
+
+ return (0);
+}
+
+static int
+__read_label(FILE *fp, char *label, size_t size)
+{
+ hammer2_blockref_t broot, best, *bref;
+ hammer2_media_data_t *vols[HAMMER2_NUM_VOLHDRS], *media;
+ hammer2_off_t io_off, io_base;
+ size_t bytes, io_bytes, boff;
+ int i, best_i, error = 0;
+
+ best_i = -1;
+ memset(&best, 0, sizeof(best));
+
+ for (i = 0; i < HAMMER2_NUM_VOLHDRS; i++) {
+ memset(&broot, 0, sizeof(broot));
+ broot.type = HAMMER2_BREF_TYPE_VOLUME;
+ broot.data_off = (i * HAMMER2_ZONE_BYTES64) | HAMMER2_PBUFRADIX;
+ vols[i] = read_buf(fp, broot.data_off & ~HAMMER2_OFF_MASK_RADIX,
+ sizeof(*vols[i]));
+ broot.mirror_tid = vols[i]->voldata.mirror_tid;
+ if (best_i < 0 || best.mirror_tid < broot.mirror_tid) {
+ best_i = i;
+ best = broot;
+ }
+ }
+ if (best_i == -1) {
+ warnx("Failed to find volume header from zones");
+ error = 1;
+ goto done;
+ }
+
+ bref = &vols[best_i]->voldata.sroot_blockset.blockref[0];
+ if (bref->type != HAMMER2_BREF_TYPE_INODE) {
+ warnx("Superroot blockref type is not inode");
+ error = 2;
+ goto done;
+ }
+
+ bytes = bref->data_off & HAMMER2_OFF_MASK_RADIX;
+ if (bytes)
+ bytes = (size_t)1 << bytes;
+ if (bytes != sizeof(hammer2_inode_data_t)) {
+ warnx("Superroot blockref size does not match inode size");
+ error = 3;
+ goto done;
+ }
+
+ io_off = bref->data_off & ~HAMMER2_OFF_MASK_RADIX;
+ io_base = io_off & ~(hammer2_off_t)(HAMMER2_MINIOSIZE - 1);
+ boff = io_off - io_base;
+
+ io_bytes = HAMMER2_MINIOSIZE;
+ while (io_bytes + boff < bytes)
+ io_bytes <<= 1;
+ if (io_bytes > sizeof(*media)) {
+ warnx("Invalid I/O bytes");
+ error = 4;
+ goto done;
+ }
+
+ media = read_buf(fp, io_base, io_bytes);
+ if (boff)
+ memcpy(media, (char*)media + boff, bytes);
+
+ strlcpy(label, (char*)media->ipdata.filename, size);
+ free(media);
+done:
+ for (i = 0; i < HAMMER2_NUM_VOLHDRS; i++)
+ free(vols[i]);
+
+ return (error);
+}
+
+int
+fstyp_hammer2(FILE *fp, char *label, size_t size)
+{
+ hammer2_volume_data_t *voldata;
+ int error = 1;
+
+ voldata = __read_voldata(fp);
+ if (__test_voldata(voldata))
+ goto done;
+
+ error = __read_label(fp, label, size);
+done:
+ free(voldata);
+ return (error);
+}
Added: head/usr.sbin/fstyp/hammer2_disk.h
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/usr.sbin/fstyp/hammer2_disk.h Tue Dec 24 19:00:20 2019 (r356060)
@@ -0,0 +1,1390 @@
+/*-
+ * Copyright (c) 2011-2018 The DragonFly Project. All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon at dragonflybsd.org>
+ * by Venkatesh Srinivas <vsrinivas at dragonflybsd.org>
+ *
+ * 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.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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 _HAMMER2_DISK_H_
+#define _HAMMER2_DISK_H_
+
+#ifndef _SYS_UUID_H_
+#include <sys/uuid.h>
+#endif
+#ifndef _SYS_DMSG_H_
+/*
+ * dmsg_hdr must be 64 bytes
+ */
+struct dmsg_hdr {
+ uint16_t magic; /* 00 sanity, synchro, endian */
+ uint16_t reserved02; /* 02 */
+ uint32_t salt; /* 04 random salt helps w/crypto */
+
+ uint64_t msgid; /* 08 message transaction id */
+ uint64_t circuit; /* 10 circuit id or 0 */
+ uint64_t reserved18; /* 18 */
+
+ uint32_t cmd; /* 20 flags | cmd | hdr_size / ALIGN */
+ uint32_t aux_crc; /* 24 auxillary data crc */
+ uint32_t aux_bytes; /* 28 auxillary data length (bytes) */
+ uint32_t error; /* 2C error code or 0 */
+ uint64_t aux_descr; /* 30 negotiated OOB data descr */
+ uint32_t reserved38; /* 38 */
+ uint32_t hdr_crc; /* 3C (aligned) extended header crc */
+};
+
+typedef struct dmsg_hdr dmsg_hdr_t;
+#endif
+
+/*
+ * The structures below represent the on-disk media structures for the HAMMER2
+ * filesystem. Note that all fields for on-disk structures are naturally
+ * aligned. The host endian format is typically used - compatibility is
+ * possible if the implementation detects reversed endian and adjusts accesses
+ * accordingly.
+ *
+ * HAMMER2 primarily revolves around the directory topology: inodes,
+ * directory entries, and block tables. Block device buffer cache buffers
+ * are always 64KB. Logical file buffers are typically 16KB. All data
+ * references utilize 64-bit byte offsets.
+ *
+ * Free block management is handled independently using blocks reserved by
+ * the media topology.
+ */
+
+/*
+ * The data at the end of a file or directory may be a fragment in order
+ * to optimize storage efficiency. The minimum fragment size is 1KB.
+ * Since allocations are in powers of 2 fragments must also be sized in
+ * powers of 2 (1024, 2048, ... 65536).
+ *
+ * For the moment the maximum allocation size is HAMMER2_PBUFSIZE (64K),
+ * which is 2^16. Larger extents may be supported in the future. Smaller
+ * fragments might be supported in the future (down to 64 bytes is possible),
+ * but probably will not be.
+ *
+ * A full indirect block use supports 512 x 128-byte blockrefs in a 64KB
+ * buffer. Indirect blocks down to 1KB are supported to keep small
+ * directories small.
+ *
+ * A maximally sized file (2^64-1 bytes) requires ~6 indirect block levels
+ * using 64KB indirect blocks (128 byte refs, 512 or radix 9 per indblk).
+ *
+ * 16(datablk) + 9 + 9 + 9 + 9 + 9 + 9 = ~70.
+ * 16(datablk) + 7 + 9 + 9 + 9 + 9 + 9 = ~68. (smaller top level indblk)
+ *
+ * The actual depth depends on copies redundancy and whether the filesystem
+ * has chosen to use a smaller indirect block size at the top level or not.
+ */
+#define HAMMER2_ALLOC_MIN 1024 /* minimum allocation size */
+#define HAMMER2_RADIX_MIN 10 /* minimum allocation size 2^N */
+#define HAMMER2_ALLOC_MAX 65536 /* maximum allocation size */
+#define HAMMER2_RADIX_MAX 16 /* maximum allocation size 2^N */
+#define HAMMER2_RADIX_KEY 64 /* number of bits in key */
+
+/*
+ * MINALLOCSIZE - The minimum allocation size. This can be smaller
+ * or larger than the minimum physical IO size.
+ *
+ * NOTE: Should not be larger than 1K since inodes
+ * are 1K.
+ *
+ * MINIOSIZE - The minimum IO size. This must be less than
+ * or equal to HAMMER2_LBUFSIZE.
+ *
+ * HAMMER2_LBUFSIZE - Nominal buffer size for I/O rollups.
+ *
+ * HAMMER2_PBUFSIZE - Topological block size used by files for all
+ * blocks except the block straddling EOF.
+ *
+ * HAMMER2_SEGSIZE - Allocation map segment size, typically 4MB
+ * (space represented by a level0 bitmap).
+ */
+
+#define HAMMER2_SEGSIZE (1 << HAMMER2_FREEMAP_LEVEL0_RADIX)
+#define HAMMER2_SEGRADIX HAMMER2_FREEMAP_LEVEL0_RADIX
+
+#define HAMMER2_PBUFRADIX 16 /* physical buf (1<<16) bytes */
+#define HAMMER2_PBUFSIZE 65536
+#define HAMMER2_LBUFRADIX 14 /* logical buf (1<<14) bytes */
+#define HAMMER2_LBUFSIZE 16384
+
+/*
+ * Generally speaking we want to use 16K and 64K I/Os
+ */
+#define HAMMER2_MINIORADIX HAMMER2_LBUFRADIX
+#define HAMMER2_MINIOSIZE HAMMER2_LBUFSIZE
+
+#define HAMMER2_IND_BYTES_MIN 4096
+#define HAMMER2_IND_BYTES_NOM HAMMER2_LBUFSIZE
+#define HAMMER2_IND_BYTES_MAX HAMMER2_PBUFSIZE
+#define HAMMER2_IND_RADIX_MIN 12
+#define HAMMER2_IND_RADIX_NOM HAMMER2_LBUFRADIX
+#define HAMMER2_IND_RADIX_MAX HAMMER2_PBUFRADIX
+#define HAMMER2_IND_COUNT_MIN (HAMMER2_IND_BYTES_MIN / \
+ sizeof(hammer2_blockref_t))
+#define HAMMER2_IND_COUNT_MAX (HAMMER2_IND_BYTES_MAX / \
+ sizeof(hammer2_blockref_t))
+
+/*
+ * In HAMMER2, arrays of blockrefs are fully set-associative, meaning that
+ * any element can occur at any index and holes can be anywhere. As a
+ * future optimization we will be able to flag that such arrays are sorted
+ * and thus optimize lookups, but for now we don't.
+ *
+ * Inodes embed either 512 bytes of direct data or an array of 4 blockrefs,
+ * resulting in highly efficient storage for files <= 512 bytes and for files
+ * <= 512KB. Up to 4 directory entries can be referenced from a directory
+ * without requiring an indirect block.
+ *
+ * Indirect blocks are typically either 4KB (64 blockrefs / ~4MB represented),
+ * or 64KB (1024 blockrefs / ~64MB represented).
+ */
+#define HAMMER2_SET_RADIX 2 /* radix 2 = 4 entries */
+#define HAMMER2_SET_COUNT (1 << HAMMER2_SET_RADIX)
+#define HAMMER2_EMBEDDED_BYTES 512 /* inode blockset/dd size */
+#define HAMMER2_EMBEDDED_RADIX 9
+
+#define HAMMER2_PBUFMASK (HAMMER2_PBUFSIZE - 1)
+#define HAMMER2_LBUFMASK (HAMMER2_LBUFSIZE - 1)
+#define HAMMER2_SEGMASK (HAMMER2_SEGSIZE - 1)
+
+#define HAMMER2_LBUFMASK64 ((hammer2_off_t)HAMMER2_LBUFMASK)
+#define HAMMER2_PBUFSIZE64 ((hammer2_off_t)HAMMER2_PBUFSIZE)
+#define HAMMER2_PBUFMASK64 ((hammer2_off_t)HAMMER2_PBUFMASK)
+#define HAMMER2_SEGSIZE64 ((hammer2_off_t)HAMMER2_SEGSIZE)
+#define HAMMER2_SEGMASK64 ((hammer2_off_t)HAMMER2_SEGMASK)
+
+#define HAMMER2_UUID_STRING "5cbb9ad1-862d-11dc-a94d-01301bb8a9f5"
+
+/*
+ * A 4MB segment is reserved at the beginning of each 2GB zone. This segment
+ * contains the volume header (or backup volume header), the free block
+ * table, and possibly other information in the future. A 4MB segment for
+ * freemap is reserved at the beginning of every 1GB.
+ *
+ * 4MB = 64 x 64K blocks. Each 4MB segment is broken down as follows:
+ *
+ * ==========
+ * 0 volume header (for the first four 2GB zones)
+ * 1 freemap00 level1 FREEMAP_LEAF (256 x 128B bitmap data per 1GB)
+ * 2 level2 FREEMAP_NODE (256 x 128B indirect block per 256GB)
+ * 3 level3 FREEMAP_NODE (256 x 128B indirect block per 64TB)
+ * 4 level4 FREEMAP_NODE (256 x 128B indirect block per 16PB)
+ * 5 level5 FREEMAP_NODE (256 x 128B indirect block per 4EB)
+ * 6 freemap01 level1 (rotation)
+ * 7 level2
+ * 8 level3
+ * 9 level4
+ * 10 level5
+ * 11 freemap02 level1 (rotation)
+ * 12 level2
+ * 13 level3
+ * 14 level4
+ * 15 level5
+ * 16 freemap03 level1 (rotation)
+ * 17 level2
+ * 18 level3
+ * 19 level4
+ * 20 level5
+ * 21 freemap04 level1 (rotation)
+ * 22 level2
+ * 23 level3
+ * 24 level4
+ * 25 level5
+ * 26 freemap05 level1 (rotation)
+ * 27 level2
+ * 28 level3
+ * 29 level4
+ * 30 level5
+ * 31 freemap06 level1 (rotation)
+ * 32 level2
+ * 33 level3
+ * 34 level4
+ * 35 level5
+ * 36 freemap07 level1 (rotation)
+ * 37 level2
+ * 38 level3
+ * 39 level4
+ * 40 level5
+ * 41 unused
+ * .. unused
+ * 63 unused
+ * ==========
+ *
+ * The first four 2GB zones contain volume headers and volume header backups.
+ * After that the volume header block# is reserved for future use. Similarly,
+ * there are many blocks related to various Freemap levels which are not
+ * used in every segment and those are also reserved for future use.
+ * Note that each FREEMAP_LEAF or FREEMAP_NODE uses 32KB out of 64KB slot.
+ *
+ * Freemap (see the FREEMAP document)
+ *
+ * The freemap utilizes blocks #1-40 in 8 sets of 5 blocks. Each block in
+ * a set represents a level of depth in the freemap topology. Eight sets
+ * exist to prevent live updates from disturbing the state of the freemap
+ * were a crash/reboot to occur. That is, a live update is not committed
+ * until the update's flush reaches the volume root. There are FOUR volume
+ * roots representing the last four synchronization points, so the freemap
+ * must be consistent no matter which volume root is chosen by the mount
+ * code.
+ *
+ * Each freemap set is 5 x 64K blocks and represents the 1GB, 256GB, 64TB,
+ * 16PB and 4EB indirect map. The volume header itself has a set of 4 freemap
+ * blockrefs representing another 2 bits, giving us a total 64 bits of
+ * representable address space.
+ *
+ * The Level 0 64KB block represents 1GB of storage represented by 32KB
+ * (256 x struct hammer2_bmap_data). Each structure represents 4MB of storage
+ * and has a 512 bit bitmap, using 2 bits to represent a 16KB chunk of
+ * storage. These 2 bits represent the following states:
+ *
+ * 00 Free
+ * 01 (reserved) (Possibly partially allocated)
+ * 10 Possibly free
+ * 11 Allocated
+ *
+ * One important thing to note here is that the freemap resolution is 16KB,
+ * but the minimum storage allocation size is 1KB. The hammer2 vfs keeps
+ * track of sub-allocations in memory, which means that on a unmount or reboot
+ * the entire 16KB of a partially allocated block will be considered fully
+ * allocated. It is possible for fragmentation to build up over time, but
+ * defragmentation is fairly easy to accomplish since all modifications
+ * allocate a new block.
+ *
+ * The Second thing to note is that due to the way snapshots and inode
+ * replication works, deleting a file cannot immediately free the related
+ * space. Furthermore, deletions often do not bother to traverse the
+ * block subhierarchy being deleted. And to go even further, whole
+ * sub-directory trees can be deleted simply by deleting the directory inode
+ * at the top. So even though we have a symbol to represent a 'possibly free'
+ * block (binary 10), only the bulk free scanning code can actually use it.
+ * Normal 'rm's or other deletions do not.
+ *
+ * WARNING! ZONE_SEG and VOLUME_ALIGN must be a multiple of 1<<LEVEL0_RADIX
+ * (i.e. a multiple of 4MB). VOLUME_ALIGN must be >= ZONE_SEG.
+ *
+ * In Summary:
+ *
+ * (1) Modifications to freemap blocks 'allocate' a new copy (aka use a block
+ * from the next set). The new copy is reused until a flush occurs at
+ * which point the next modification will then rotate to the next set.
+ */
+#define HAMMER2_VOLUME_ALIGN (8 * 1024 * 1024)
+#define HAMMER2_VOLUME_ALIGN64 ((hammer2_off_t)HAMMER2_VOLUME_ALIGN)
+#define HAMMER2_VOLUME_ALIGNMASK (HAMMER2_VOLUME_ALIGN - 1)
+#define HAMMER2_VOLUME_ALIGNMASK64 ((hammer2_off_t)HAMMER2_VOLUME_ALIGNMASK)
+
+#define HAMMER2_NEWFS_ALIGN (HAMMER2_VOLUME_ALIGN)
+#define HAMMER2_NEWFS_ALIGN64 ((hammer2_off_t)HAMMER2_VOLUME_ALIGN)
+#define HAMMER2_NEWFS_ALIGNMASK (HAMMER2_VOLUME_ALIGN - 1)
+#define HAMMER2_NEWFS_ALIGNMASK64 ((hammer2_off_t)HAMMER2_NEWFS_ALIGNMASK)
+
+#define HAMMER2_ZONE_BYTES64 (2LLU * 1024 * 1024 * 1024)
+#define HAMMER2_ZONE_MASK64 (HAMMER2_ZONE_BYTES64 - 1)
+#define HAMMER2_ZONE_SEG (4 * 1024 * 1024)
+#define HAMMER2_ZONE_SEG64 ((hammer2_off_t)HAMMER2_ZONE_SEG)
+#define HAMMER2_ZONE_BLOCKS_SEG (HAMMER2_ZONE_SEG / HAMMER2_PBUFSIZE)
+
+#define HAMMER2_ZONE_FREEMAP_INC 5 /* 5 deep */
+
+#define HAMMER2_ZONE_VOLHDR 0 /* volume header or backup */
+#define HAMMER2_ZONE_FREEMAP_00 1 /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_01 6 /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_02 11 /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_03 16 /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_04 21 /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_05 26 /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_06 31 /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_07 36 /* normal freemap rotation */
+#define HAMMER2_ZONE_FREEMAP_END 41 /* (non-inclusive) */
+
+#define HAMMER2_ZONE_UNUSED41 41
+#define HAMMER2_ZONE_UNUSED42 42
+#define HAMMER2_ZONE_UNUSED43 43
+#define HAMMER2_ZONE_UNUSED44 44
+#define HAMMER2_ZONE_UNUSED45 45
+#define HAMMER2_ZONE_UNUSED46 46
+#define HAMMER2_ZONE_UNUSED47 47
+#define HAMMER2_ZONE_UNUSED48 48
+#define HAMMER2_ZONE_UNUSED49 49
+#define HAMMER2_ZONE_UNUSED50 50
+#define HAMMER2_ZONE_UNUSED51 51
+#define HAMMER2_ZONE_UNUSED52 52
+#define HAMMER2_ZONE_UNUSED53 53
+#define HAMMER2_ZONE_UNUSED54 54
+#define HAMMER2_ZONE_UNUSED55 55
+#define HAMMER2_ZONE_UNUSED56 56
+#define HAMMER2_ZONE_UNUSED57 57
+#define HAMMER2_ZONE_UNUSED58 58
+#define HAMMER2_ZONE_UNUSED59 59
+#define HAMMER2_ZONE_UNUSED60 60
+#define HAMMER2_ZONE_UNUSED61 61
+#define HAMMER2_ZONE_UNUSED62 62
+#define HAMMER2_ZONE_UNUSED63 63
+#define HAMMER2_ZONE_END 64 /* non-inclusive */
+
+#define HAMMER2_NFREEMAPS 8 /* FREEMAP_00 - FREEMAP_07 */
+
+ /* relative to FREEMAP_x */
+#define HAMMER2_ZONEFM_LEVEL1 0 /* 1GB leafmap */
+#define HAMMER2_ZONEFM_LEVEL2 1 /* 256GB indmap */
+#define HAMMER2_ZONEFM_LEVEL3 2 /* 64TB indmap */
+#define HAMMER2_ZONEFM_LEVEL4 3 /* 16PB indmap */
+#define HAMMER2_ZONEFM_LEVEL5 4 /* 4EB indmap */
+/* LEVEL6 is a set of 4 blockrefs in the volume header 16EB */
+
+/*
+ * Freemap radix. Assumes a set-count of 4, 128-byte blockrefs,
+ * 32KB indirect block for freemap (LEVELN_PSIZE below).
+ *
+ * Leaf entry represents 4MB of storage broken down into a 512-bit
+ * bitmap, 2-bits per entry. So course bitmap item represents 16KB.
+ */
+#if HAMMER2_SET_COUNT != 4
+#error "hammer2_disk.h - freemap assumes SET_COUNT is 4"
+#endif
+#define HAMMER2_FREEMAP_LEVEL6_RADIX 64 /* 16EB (end) */
+#define HAMMER2_FREEMAP_LEVEL5_RADIX 62 /* 4EB */
+#define HAMMER2_FREEMAP_LEVEL4_RADIX 54 /* 16PB */
+#define HAMMER2_FREEMAP_LEVEL3_RADIX 46 /* 64TB */
+#define HAMMER2_FREEMAP_LEVEL2_RADIX 38 /* 256GB */
+#define HAMMER2_FREEMAP_LEVEL1_RADIX 30 /* 1GB */
+#define HAMMER2_FREEMAP_LEVEL0_RADIX 22 /* 4MB (128by in l-1 leaf) */
+
+#define HAMMER2_FREEMAP_LEVELN_PSIZE 32768 /* physical bytes */
+
+#define HAMMER2_FREEMAP_LEVEL5_SIZE ((hammer2_off_t)1 << \
+ HAMMER2_FREEMAP_LEVEL5_RADIX)
+#define HAMMER2_FREEMAP_LEVEL4_SIZE ((hammer2_off_t)1 << \
+ HAMMER2_FREEMAP_LEVEL4_RADIX)
+#define HAMMER2_FREEMAP_LEVEL3_SIZE ((hammer2_off_t)1 << \
+ HAMMER2_FREEMAP_LEVEL3_RADIX)
+#define HAMMER2_FREEMAP_LEVEL2_SIZE ((hammer2_off_t)1 << \
+ HAMMER2_FREEMAP_LEVEL2_RADIX)
+#define HAMMER2_FREEMAP_LEVEL1_SIZE ((hammer2_off_t)1 << \
+ HAMMER2_FREEMAP_LEVEL1_RADIX)
+#define HAMMER2_FREEMAP_LEVEL0_SIZE ((hammer2_off_t)1 << \
+ HAMMER2_FREEMAP_LEVEL0_RADIX)
+
+#define HAMMER2_FREEMAP_LEVEL5_MASK (HAMMER2_FREEMAP_LEVEL5_SIZE - 1)
+#define HAMMER2_FREEMAP_LEVEL4_MASK (HAMMER2_FREEMAP_LEVEL4_SIZE - 1)
+#define HAMMER2_FREEMAP_LEVEL3_MASK (HAMMER2_FREEMAP_LEVEL3_SIZE - 1)
+#define HAMMER2_FREEMAP_LEVEL2_MASK (HAMMER2_FREEMAP_LEVEL2_SIZE - 1)
+#define HAMMER2_FREEMAP_LEVEL1_MASK (HAMMER2_FREEMAP_LEVEL1_SIZE - 1)
+#define HAMMER2_FREEMAP_LEVEL0_MASK (HAMMER2_FREEMAP_LEVEL0_SIZE - 1)
+
+#define HAMMER2_FREEMAP_COUNT (int)(HAMMER2_FREEMAP_LEVELN_PSIZE / \
+ sizeof(hammer2_bmap_data_t))
+
+/*
+ * XXX I made a mistake and made the reserved area begin at each LEVEL1 zone,
+ * which is on a 1GB demark. This will eat a little more space but for
+ * now we retain compatibility and make FMZONEBASE every 1GB
+ */
+#define H2FMZONEBASE(key) ((key) & ~HAMMER2_FREEMAP_LEVEL1_MASK)
+#define H2FMBASE(key, radix) ((key) & ~(((hammer2_off_t)1 << (radix)) - 1))
+
+/*
+ * 16KB bitmap granularity (x2 bits per entry).
+ */
+#define HAMMER2_FREEMAP_BLOCK_RADIX 14
+#define HAMMER2_FREEMAP_BLOCK_SIZE (1 << HAMMER2_FREEMAP_BLOCK_RADIX)
+#define HAMMER2_FREEMAP_BLOCK_MASK (HAMMER2_FREEMAP_BLOCK_SIZE - 1)
+
+/*
+ * bitmap[] structure. 2 bits per HAMMER2_FREEMAP_BLOCK_SIZE.
+ *
+ * 8 x 64-bit elements, 2 bits per block.
+ * 32 blocks (radix 5) per element.
+ * representing INDEX_SIZE bytes worth of storage per element.
+ */
+
+typedef uint64_t hammer2_bitmap_t;
+
+#define HAMMER2_BMAP_ALLONES ((hammer2_bitmap_t)-1)
+#define HAMMER2_BMAP_ELEMENTS 8
+#define HAMMER2_BMAP_BITS_PER_ELEMENT 64
+#define HAMMER2_BMAP_INDEX_RADIX 5 /* 32 blocks per element */
+#define HAMMER2_BMAP_BLOCKS_PER_ELEMENT (1 << HAMMER2_BMAP_INDEX_RADIX)
+
+#define HAMMER2_BMAP_INDEX_SIZE (HAMMER2_FREEMAP_BLOCK_SIZE * \
+ HAMMER2_BMAP_BLOCKS_PER_ELEMENT)
+#define HAMMER2_BMAP_INDEX_MASK (HAMMER2_BMAP_INDEX_SIZE - 1)
+
+#define HAMMER2_BMAP_SIZE (HAMMER2_BMAP_INDEX_SIZE * \
+ HAMMER2_BMAP_ELEMENTS)
+#define HAMMER2_BMAP_MASK (HAMMER2_BMAP_SIZE - 1)
+
+/*
+ * Two linear areas can be reserved after the initial 4MB segment in the base
+ * zone (the one starting at offset 0). These areas are NOT managed by the
+ * block allocator and do not fall under HAMMER2 crc checking rules based
+ * at the volume header (but can be self-CRCd internally, depending).
+ */
+#define HAMMER2_BOOT_MIN_BYTES HAMMER2_VOLUME_ALIGN
+#define HAMMER2_BOOT_NOM_BYTES (64*1024*1024)
+#define HAMMER2_BOOT_MAX_BYTES (256*1024*1024)
+
+#define HAMMER2_REDO_MIN_BYTES HAMMER2_VOLUME_ALIGN
+#define HAMMER2_REDO_NOM_BYTES (256*1024*1024)
+#define HAMMER2_REDO_MAX_BYTES (1024*1024*1024)
+
+/*
+ * Most HAMMER2 types are implemented as unsigned 64-bit integers.
+ * Transaction ids are monotonic.
+ *
+ * We utilize 32-bit iSCSI CRCs.
+ */
+typedef uint64_t hammer2_tid_t;
+typedef uint64_t hammer2_off_t;
+typedef uint64_t hammer2_key_t;
+typedef uint32_t hammer2_crc32_t;
+
+/*
+ * Miscellanious ranges (all are unsigned).
+ */
+#define HAMMER2_TID_MIN 1ULL
+#define HAMMER2_TID_MAX 0xFFFFFFFFFFFFFFFFULL
+#define HAMMER2_KEY_MIN 0ULL
+#define HAMMER2_KEY_MAX 0xFFFFFFFFFFFFFFFFULL
+#define HAMMER2_OFFSET_MIN 0ULL
+#define HAMMER2_OFFSET_MAX 0xFFFFFFFFFFFFFFFFULL
+
+/*
+ * HAMMER2 data offset special cases and masking.
+ *
+ * All HAMMER2 data offsets have to be broken down into a 64K buffer base
+ * offset (HAMMER2_OFF_MASK_HI) and a 64K buffer index (HAMMER2_OFF_MASK_LO).
+ *
+ * Indexes into physical buffers are always 64-byte aligned. The low 6 bits
+ * of the data offset field specifies how large the data chunk being pointed
+ * to as a power of 2. The theoretical minimum radix is thus 6 (The space
+ * needed in the low bits of the data offset field). However, the practical
+ * minimum allocation chunk size is 1KB (a radix of 10), so HAMMER2 sets
+ * HAMMER2_RADIX_MIN to 10. The maximum radix is currently 16 (64KB), but
+ * we fully intend to support larger extents in the future.
+ *
+ * WARNING! A radix of 0 (such as when data_off is all 0's) is a special
+ * case which means no data associated with the blockref, and
+ * not the '1 byte' it would otherwise calculate to.
+ */
+#define HAMMER2_OFF_BAD ((hammer2_off_t)-1)
+#define HAMMER2_OFF_MASK 0xFFFFFFFFFFFFFFC0ULL
+#define HAMMER2_OFF_MASK_LO (HAMMER2_OFF_MASK & HAMMER2_PBUFMASK64)
+#define HAMMER2_OFF_MASK_HI (~HAMMER2_PBUFMASK64)
+#define HAMMER2_OFF_MASK_RADIX 0x000000000000003FULL
+#define HAMMER2_MAX_COPIES 6
+
+/*
+ * HAMMER2 directory support and pre-defined keys
+ */
+#define HAMMER2_DIRHASH_VISIBLE 0x8000000000000000ULL
+#define HAMMER2_DIRHASH_USERMSK 0x7FFFFFFFFFFFFFFFULL
+#define HAMMER2_DIRHASH_LOMASK 0x0000000000007FFFULL
+#define HAMMER2_DIRHASH_HIMASK 0xFFFFFFFFFFFF0000ULL
+#define HAMMER2_DIRHASH_FORCED 0x0000000000008000ULL /* bit forced on */
+
+#define HAMMER2_SROOT_KEY 0x0000000000000000ULL /* volume to sroot */
+#define HAMMER2_BOOT_KEY 0xd9b36ce135528000ULL /* sroot to BOOT PFS */
+
+/************************************************************************
+ * DMSG SUPPORT *
+ ************************************************************************
+ * LNK_VOLCONF
+ *
+ * All HAMMER2 directories directly under the super-root on your local
+ * media can be mounted separately, even if they share the same physical
+ * device.
+ *
+ * When you do a HAMMER2 mount you are effectively tying into a HAMMER2
+ * cluster via local media. The local media does not have to participate
+ * in the cluster, other than to provide the hammer2_volconf[] array and
+ * root inode for the mount.
+ *
+ * This is important: The mount device path you specify serves to bootstrap
+ * your entry into the cluster, but your mount will make active connections
+ * to ALL copy elements in the hammer2_volconf[] array which match the
+ * PFSID of the directory in the super-root that you specified. The local
+ * media path does not have to be mentioned in this array but becomes part
+ * of the cluster based on its type and access rights. ALL ELEMENTS ARE
+ * TREATED ACCORDING TO TYPE NO MATTER WHICH ONE YOU MOUNT FROM.
+ *
+ * The actual cluster may be far larger than the elements you list in the
+ * hammer2_volconf[] array. You list only the elements you wish to
+ * directly connect to and you are able to access the rest of the cluster
+ * indirectly through those connections.
+ *
+ * WARNING! This structure must be exactly 128 bytes long for its config
+ * array to fit in the volume header.
+ */
+struct hammer2_volconf {
+ uint8_t copyid; /* 00 copyid 0-255 (must match slot) */
+ uint8_t inprog; /* 01 operation in progress, or 0 */
+ uint8_t chain_to; /* 02 operation chaining to, or 0 */
+ uint8_t chain_from; /* 03 operation chaining from, or 0 */
+ uint16_t flags; /* 04-05 flags field */
+ uint8_t error; /* 06 last operational error */
+ uint8_t priority; /* 07 priority and round-robin flag */
+ uint8_t remote_pfs_type;/* 08 probed direct remote PFS type */
+ uint8_t reserved08[23]; /* 09-1F */
+ uuid_t pfs_clid; /* 20-2F copy target must match this uuid */
+ uint8_t label[16]; /* 30-3F import/export label */
+ uint8_t path[64]; /* 40-7F target specification string or key */
+} __packed;
+
+typedef struct hammer2_volconf hammer2_volconf_t;
+
+#define DMSG_VOLF_ENABLED 0x0001
+#define DMSG_VOLF_INPROG 0x0002
+#define DMSG_VOLF_CONN_RR 0x80 /* round-robin at same priority */
+#define DMSG_VOLF_CONN_EF 0x40 /* media errors flagged */
+#define DMSG_VOLF_CONN_PRI 0x0F /* select priority 0-15 (15=best) */
+
+struct dmsg_lnk_hammer2_volconf {
+ dmsg_hdr_t head;
+ hammer2_volconf_t copy; /* copy spec */
+ int32_t index;
+ int32_t unused01;
+ uuid_t mediaid;
+ int64_t reserved02[32];
+} __packed;
+
+typedef struct dmsg_lnk_hammer2_volconf dmsg_lnk_hammer2_volconf_t;
+
+#define DMSG_LNK_HAMMER2_VOLCONF DMSG_LNK(DMSG_LNK_CMD_HAMMER2_VOLCONF, \
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list