geom_vinum platform-independent brokenness

Rick C. Petty rick-freebsd at kiwi-computer.com
Fri Mar 7 23:27:40 UTC 2008


Since no one seems to be working on fixing gvinum, I've decided to
investigate and address some problems I have encountered recently.

***

There is an incompatibility in geom_vinum with respect to i386/amd64.
In particular, the following structure (in geom_vinum_var.h) is stored
as-is on each disk (or provider):

	struct gv_hdr {
        	uint64_t        magic;
	#define GV_MAGIC        22322600044678729LL
	#define GV_NOMAGIC      22322600044678990LL

        	int             config_length;
        	struct gv_label label;
	};

The problem is the "struct gv_label" is not aligned properly against the
int.  On i386 and amd64 system, this corresponds to these offsets:

	i386	amd64	field
	----	-----	-----
	0	0	magic
	8	8	config_length
	-	-	from struct gv_label :
	12	16	sysname
	44	48	name (of drive)
	76	80	date_of_birth
	84	96	last_update
	92	112	drive_size
	=	=
	100	120	= total header size

Because of this, someone who has volumes created with i386 gvinum cannot
put those volumes onto an amd64 system, and vice-versa!

My proposal is to change the type for config_length to either uint32_t or
uint64_t and the fields in the struct timeval to uint32_t (which would be
converted to/from long as necessary).  I think going forward, this should
be our on-disk structure.  The problem is that both i386 and amd64 versions
are currently in existence.  I further propose that we "read" both types of
headers (converting to the in-memory structure) and that the proposed
unambiguous on-disk structure be used in *all* write operations.  That way,
an admin can selectively perform a one-way "upgrade" of their vinum volumes
by calling "gvinum start" followed by "gvinum saveconfig".

This solution needs careful attention because although you can check bytes
12-15 for zero to detect whether it's a legacy amd64 on-disk structure,
it is valid to have sysname be empty (sysname is essentially hostname).
The legacy amd64 partition is also guaranteed to have zeros in particular
places (do to structure misalignment issues), at bytes 12-15, 84-87, 92-95,
100-103, and 108-111.  Because the legacy i386 structure is only 100 bytes,
the zero checks should probably apply only to the first three.

Henceforth, I propose the following algorithm for reads:
	if bytes 12-15 are not all zero:
		assume legacy i386 on-disk structure
	else if byte 16 is not zero:
		assume legacy amd64 on-disk structure
	else if bytes 84-87 and 92-95 are all zero:
		assume legacy amd64 on-disk structure
	else:
		assume legacy i386 on-disk structure

In addition, I propose that magic for the new on-disk structure be changed
slightly from the original magic, in case the new structure is put into a
machine with an older kernel.  I am willing to write all this code and
provide a patch this weekend.  I just wanted to throw this problem at the
GEOM list and get some feedback.


***

Similar to the previous problem, geom_vinum code is very endian-centric.
Although FreeBSD's tier-1 platforms are all little-endian, some care could
be added to the gvinum code to work on big-endian systems.  This problem
is not as bad as the first because the magic will not match on such
systems.  Still, I can imagine a big-endian system that supports the same
drives.  I'm willing to rewrite the read/write header code to use the
appropriate htonl/htons-type macros, unless there are objections.

The good news is that vinum stores its configuration in a text format, so
such a fix would only affect code which reads and writes the gv_hdr.

***

I would like to hear any constructive feedback on these issues before I
dive into the code.  Once I have a diff, should I send-pr or query this
list first?  Also, since I don't have an 8.x system, would a patch against
7x. be acceptable?  I don't imagine there's much difference between the
branches...

-- Rick C. Petty


More information about the freebsd-geom mailing list