How to validate a ZFS snapshot image residing on a backup system

backupzfs

I'm running a FreeBSD host with ZFS.

Let's pretend that I am storing a series of incremental ZFS snapshot images on a remote host using zfs send:

zfs send -i zpool/data/foo@04hoursago zpool/data/foo@10hoursago > /nfs/backups/foo.zfs

Or perhaps I want to send the stream through an FTP server:

% ftp backup
ftp> put "| zfs send -i zpool/data/foo@04hoursago zpool/data/foo@10hoursago" /backups/foo.zfs

I would like to validate this remote image. I'd like to print a list of snapshots that are in this image, or optionally extract a checksum or other metadata to help check that the image is valid and contains the snapshots like I expected.

How can I query the image file and see what is inside?

I have tried zfs receive with the -nv (no-op and verbose) flags to list the snapshots within the image, but this may not work on a live system:

# zfs receive -nv zpool < /nfs/backups/foo.zfs
cannot receive new filesystem stream: destination 'zpool' exists
must specify -F to overwrite it
# zfs receive -nv -F zpool < /nfs/backups/foo.zfs
cannot receive new filesystem stream: destination has snapshots (eg. zpool@09hoursago)
must destroy them to overwrite it

Best Answer

More modern versions of ZFS provide a command named zstreamdump which can provide human-readable information from a stream (or image) created using zfs send.

This is an example using the commandline:

host # zstreamdump < foo.zfs 
BEGIN record
    ...
    toname = zpool/data/foo@04hoursago
    END checksum = 123123123123123123/123123123123123123/asdasdasdasdasd/zxczxczxczxczxc
    ...
    Total write size = 54784 (0xd600)

And an example from FTP:

ftp> get /backups/foo.zfs "| zstreamdump"
BEGIN record
 hdrtype = 1
 ...
 toname = zpool/data/foo@04hoursago
 END checksum = 123123123123123123/123123123123123123/asdasdasdasdasd/zxczxczxczxczxc
 ...

This provides me with the name of the actual snapshot, and a checksum of that snapshot. It will not provide me with a list of files within the snapshot of course, because that information exists at a different layer.

I have not actually tried this on an incremental snapshot created using zfs send -i, but this may be what I want.