Hi Michael,
Am 06.02.2016 um 11:01 schrieb Michael Kjörling:
On 6 Feb 2016 04:18 +0100, from sven@xxxxxxxxxxxxxxxxxxxxx (Sven Eschenberg):
(A secondary header implies that
all changes on both headers need to be atomic and in sync. While
this is doable, LVM clearly shows, that it is not trivial, otherwise
it would certainly be available as feature by now).
I'm not so sure it does imply that. It does certainly imply the need
to know that a, and which one out of the lot, header is most up to
date, but that does not necessarily require writes to both to be done
atomically and in sync. (In fact, truly atomic, in-sync writes to
multiple distinct locations seems a physical impossibility at least in
the case of a single spinning disk, since the write head can only be
in one location at any one time.)
Of course atomicity applies to the transaction as whole. Here atomicity
implies that before starting and afterwards the state is consistent and
that if something goes wrong inbetween, you'll be able to cleanly roll
back or conclude the operation.
This is where the "update counter" and a checksum that I mentioned
earlier comes in. An example of how to actually do this might be to
first discard (or perhaps rather, remove from consideration) any
header which doesn't match its checksum (for integrity purposes), then
use the one with the highest update counter value (taking care to
allow for wraparound) as a starting point for the operation at hand,
then rewrite any previously discarded headers (ideally writing the
checksum last, such that the header remains considered invalid until
it has been fully rewritten).
An update counter+checksum will not do the trick. Let's see (This is has
not been completely thought over and checked) a resize operation that
grows the container:
The backing device grows, possibly without any warning -> We'll need to
keep the secondary header location in the primary header.
Check that both headers are consistent, otherwise fix them first.
Add old location and new planned location of the header into the WAL.
Read secondary header, write secondary header (note in WAL, note the
secondary header at old location will be removed)
safely wipe old header (note in WAL)
Note that primary header's location info on secondary header is about to
be updated, update and note success in WAL.
Check for consistency & clear WAL.
Hopefully I did not miss any step and yes, it is not THAT complicated as
there is no concurrency involved, but the transactions for resizing need
to be crafted carefully.
With a single metadatacopy 90% of the issues don't even exist ;-).
Or maybe even better, rewrite a previously considered invalid header
(if any) first; that should ensure that as long as the storage itself
works properly, if any header is ever valid at the beginning of an
operation, there exists at all times at least one header which is
valid.
By placing the headers far apart from each other, this forces at least
spinning disks to seek, which naturally introduces a sequence point
into the write process; even if the two write requests were to be put
onto the I/O bus at the same instant, one write must complete before
the other can physically begin. (Finally, a good use for the seek
delay in rotational storage!)
This should work equally well for any number of header copies.
_______________________________________________
dm-crypt mailing list
dm-crypt@xxxxxxxx
http://www.saout.de/mailman/listinfo/dm-crypt