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