- contribute
- design
- upgrades
- archive
Initial test: stacking squashfs images
Tails filesystem is already using aufs
to provide a read-write filesystem on
top of the read-only squashfs
image.
This system could probably be extended to support mounting multiple squashfs
filesystems on top of each others. Upgrades would be squashfs
images with only
the files that have been modified since the previous releases. This handles file
deletions.
Shipping upgrades could be as simple as shipping those extra squashfs
images.
Debian live supports such stacking already: see in live-boot(7)
the
part about /live/filesystem.module
.
Stacking squashfs images like this would still lack a way of upgrading the kernel and the syslinux. This should also be handled by the automated upgrade process.
Here is a test. First the procedure to create the delta squashfs image, to be
done as root
:
mkdir /mnt/tails-0.7.1
mkdir /mnt/tails-0.7.2
mount -o loop tails-i386-0.7.1.iso /mnt/tails-0.7.1
mount -o loop tails-i386-0.7.2.iso /mnt/tails-0.7.2
mkdir /mnt/tails-0.7.1-root
mkdir /mnt/tails-0.7.2-root
mount -o loop /mnt/tails-0.7.1/live/filesystem.squashfs /mnt/tails-0.7.1-root
mount -o loop /mnt/tails-0.7.2/live/filesystem.squashfs /mnt/tails-0.7.2-root
mkdir /mnt/upgrade-0.7.1-to-0.7.2
mount -t tmpfs tmpfs /mnt/upgrade-0.7.1-to-0.7.2
mkdir /mnt/union
mount -t aufs -o br=/mnt/upgrade-0.7.1-to-0.7.2=rw:/mnt/tails-0.7.1-root=ro none /mnt/union
rsync -avP --delete-after /mnt/tails-0.7.2-root/ /mnt/union/
mksquashfs /mnt/upgrade-0.7.1-to-0.7.2 upgrade-0.7.1-to-0.7.2.squashfs
Compressed size (using default gzip compression) is 82 MB.
Not bad, and the new kernel is included, which can probably be avoided.
Now, let's upgrade an USB stick:
mkdir /media/disk/live
cp /mnt/tails-0.7.1/live/filesystem.squashfs \
upgrade-0.7.1-to-0.7.2.squashfs \
/mnt/tails/0.7.2/live/vmlinuz \
/mnt/tails/0.7.2/live/initrd.img \
/media/disk/live
Then fiddle with GRUB or EXTLINUX.
On boot, the new squashfs gets properly integrated. Whiteouts are not
working. It looks like the live-boot
2.x mount options miss the wh
attribute.
But wait, booting with break=top
and modifying /scripts/live
to replace
roopt=rr
by roopt=rr+wh
is enough to do the trick! Therefore,
we've added the wh
attribute to live-boot
3.x.
Initial test is pretty conclusive!
Discarded options
Appending to squashfs image
mksquashfs
can actually append new files to an existing squashfs
image.
Initial images are created with files in a specific order to improve boot time on cd, but on a USB stick random access is a non-issue.
test if mksquashfs
can append an image that is currently
used without weakening a running system.
Upgrading the system would result in a series of files to be appended to the
current squashfs
image.
This option had been discared because it is not possible to remove files.
Deltas
A possible way to encode deltas for the two previous methods could be:
- For each file that has been modified: a binary delta and a new set of metadata if they have changed.
- A list of deleted files.
And mksquashfs
would be used in the running live system after applying the
delta to create a squashfs
image with the upgrade.
But there is probably things that have been left out of such an early draft.
Binary diff
Plain diff
does not work on binary files.
Binary diffs ([rsync], xdelta, bsdiff, VCDIFF) gives poor
result on live system images because squashfs
images vary
strongly as a whole, even for tiny changes of the files inside.
That situation is unlikely to change (Debian bug #602965) and is even worse
with squashfs-lzma
. Quoting xz
manpage:
Compressed output may vary
The exact compressed output produced from the same uncompressed input
file may vary between XZ Utils versions even if compression options
are identical. This is because the encoder can be improved (faster or
better compression) without affecting the file format. The output can
vary even between different builds of the same XZ Utils version, if
different build options are used.
The above means that implementing --rsyncable to create rsyncable .xz
files is not going to happen without freezing a part of the encoder
implementation, which can then be used with --rsyncable.