How to check that all ZFS snapshots within a pool are without holds before destroying that pool

Solution 1:

Not sure about how this looked back in 2012 but now you can check the userrefs property:

zfs get userrefs

To list all holds in all pools:

zfs get -Ht snapshot userrefs | grep -v $'\t'0 | cut -d $'\t' -f 1 | tr '\n' '\0' | xargs -0 zfs holds

Solution 2:

For a pool with a single file system

zfs list -H -r -d 1 -t snapshot -o name nameoffilesystem | xargs zfs holds

– that is, without -r recursion to the right of the pipe.

Credit to calmh in irc://irc.freenode.net/#zfs

Working example

For a file system with no space in its name:

macbookpro08-centrim:~ gjp22$ zfs list -H -r -d 1 -t snapshot -o name gjp22 | xargs zfs holds
load: 4.82  cmd: zfs 43038 running 0.59u 3.28s
NAME                     TAG                                           TIMESTAMP
gjp22@2012-10-28-212255  problem with LocalStorage for WOT for Safari  Mon Oct 29  6:44 2012
gjp22@2012-12-08-081957  experiment                                    Sat Dec  8  9:04 2012

There was one Control-T to see how things were running.

For completeness, I should state that there is a child of gjp22. But I guess that this example (without attention to descendants) does prove the effectiveness of the command.

Non-working examples

For a file system named Pocket Time Machine (spaces within its name), neither of the following commands succeeds:

zfs list -H -r -d 1 -t snapshot -o name "tall/backups/zhandy/Pocket Time Machine" | xargs zfs holds

zfs list -H -r -d 1 -t snapshot -o name tall/backups/zhandy/Pocket\ Time\ Machine | xargs zfs holds

Output:

'tall/backups/zhandy/Pocket' is not a snapshot
'Time' is not a snapshot
cannot open 'tall/backups/zhandy/Pocket': dataset does not exist
cannot open 'Time': dataset does not exist
cannot open 'Machine@2012-09-18-210251': dataset does not exist
cannot open 'tall/backups/zhandy/Pocket': dataset does not exist
cannot open 'Time': dataset does not exist
cannot open 'Machine@2012-09-23-0330': dataset does not exist

… and so on.

This is implicitly a question within an answer, sorry … someone with good command line knowledge (not me) might be able to smarten this answer without me spinning off to a separate question. I'll seek advice in chat.