Hi Martin,

On 2021-03-29 20:00, Martin Raiber wrote:
On 29.03.2021 19:25 Henning Schild wrote:
Am Mon, 29 Mar 2021 19:30:34 +0300
schrieb Andrei Borzenkov <arvidj...@gmail.com>:

On 29.03.2021 16:16, Claudius Heine wrote:
Hi,

I am currently investigating the possibility to use `btrfs-stream`
files (generated by `btrfs send`) for deploying a image based
update to systems (probably embedded ones).

One of the issues I encountered here is that btrfs-send does not
use any diff algorithm on files that have changed from one snapshot
to the next.
btrfs send works on block level. It sends blocks that differ between
two snapshots.

One way to implement this would be to add some sort of 'patch'
command to the `btrfs-stream` format.
This would require reading complete content of both snapshots instead
if just computing block diff using metadata. Unless I misunderstand
what you mean.
On embedded systems it is common to update complete "firmware" images
as opposed to package based partial updates. You often have two root
filesystems to be able to always fall back to a working state in case
of any sort or error.

Take the picture from
https://sbabic.github.io/swupdate/overview.html#double-copy

and assume that "Application software" is a full blown OS with
everything that makes your device.

That approach offers great "control" but unfortunately can also lead to
great downloads required for an update. The basic idea is to download
the binary-diff between the future and the current rootfs only.
Given a filesystem supports snapshots, it would be great to
"send/receive" them as diffs.

Today most people that do such things with other fss script around with
xdelta etc. But btrfs is more "integrated", so when considering it for
such embedded usecases native support would most likely be better than
hacks on top.

We have several use-cases in mind with btrfs.
  - ro-base with rw overlays
  - binary diff updates against such a ro-base
  - backup/restore with snapshots of certain subvolumes
  - factory reset with wiping certain submodules

regards,
Henning

I think I know what you want to accomplish and I've been doing it for a while 
now. But I don't know what the problem with btrfs send is? Do you want to have 
non-block based diff to make updates smaller? Have you overwritten files 
completely and need to dedupe or reflink them before sending them? 
Theoretically the btrfs send format would be able to support something like 
bsdiff (non-block based diff -- it is just a set of e.g. write commands with 
offset and binary data or using reflink to copy data from one file to another), 
but there currently isn't a tool to create this.

How I've done it is:

  - Create a btrfs image with a rw sys_root_current subvol
  - E.g. debootstrap a Linux system into it
  - Create sys_root_v1 as ro snapshot of sys_root_current

Use that system image on different systems.

On update on the original image:

  - Modify sys_root_current
  - Create ro snapshot sys_root_v2 of sys_root_current
  - Create an btrfs send update that modifies sys_root_v1 to sys_root_v2: btrfs 
send -p sys_root_v1 sys_root_v2 | xz -c > update_v1.btrfs.xz
  - Publish update_v1.btrfs.xz

On the systems:

  - Download update_v1.btrfs.xz (verify signature)
  - Create sys_root_v2 by applying differences to sys_root_v1: cat 
update_v1.btrfs.xz | xz -d -c | btrfs receive /rootfs
  - Rename (exchange) sys_root_current to sys_root_last
  - Create rw snapshot of sys_root_v2 as sys_root_current
  - Reboot into new system

That is mostly the approach we have envisioned. However we also wanted to add the possibility of allowing binary deltas for smaller blobs. (e.g. <60MiB). Because competing mechanisms, that use different mechanisms are based on different file systems like os-tree, or zchunk allow smaller update sizes, by using similar mechanisms.

Os-tree for instance allows to calculate static deltas [1] in order to make the download size of the update smaller. However, currently you cannot really use OS-tree to apply those completely offline.

zchunk allows to split a big image into smaller chunks, and then only the chunks that changed need to be fetched [2]. Again, not really possible offline.

regards,
Claudius

[1] https://ostreedev.github.io/ostree/repository-management/#derived-data---static-deltas-and-the-summary-file
[2] https://github.com/zchunk/zchunk

Reply via email to