7

Question

Already I can check each snapshot of a filesystem individually, manually.

I would prefer to check all at once (all with a single command or script). Please:

  • can that be done with a script?

The answer should be good for file systems with a space within the name.

Background

From the man page for zfs(8):

zfs holds [-H] [-r] snapshot…

… -r Specifies that a hold with the given tag is applied recursively to the snapshots of all descendent file systems.


I wondered whether recent snapshots are treated as descendants of an older snapshot. No:

Last login: Sat Dec  8 09:02:26 on ttys003
macbookpro08-centrim:~ gjp22$ zfs holds -r gjp22@2012-12-08-081957
NAME                     TAG  TIMESTAMP
macbookpro08-centrim:~ gjp22$ zfs holds -r gjp22@2012-10-28-212255
NAME                     TAG                                           TIMESTAMP
gjp22@2012-10-28-212255  problem with LocalStorage for WOT for Safari  Mon Oct 29  6:44 2012
macbookpro08-centrim:~ gjp22$ zfs hold experiment gjp22@2012-12-08-081957
macbookpro08-centrim:~ gjp22$ zfs holds -r gjp22@2012-10-28-212255
NAME                     TAG                                           TIMESTAMP
gjp22@2012-10-28-212255  problem with LocalStorage for WOT for Safari  Mon Oct 29  6:44 2012
macbookpro08-centrim:~ gjp22$ zfs holds -r gjp22@2012-12-08-081957
NAME                     TAG         TIMESTAMP
gjp22@2012-12-08-081957  experiment  Sat Dec  8  9:04 2012
macbookpro08-centrim:~ gjp22$ zfs holds -r gjp22@2012-10-28-212255
NAME                     TAG                                           TIMESTAMP
gjp22@2012-10-28-212255  problem with LocalStorage for WOT for Safari  Mon Oct 29  6:44 2012
macbookpro08-centrim:~ gjp22$ 

Clarification

I do not plan to combine both checks and destruction in a single command or script. This question is essentially about the checks.

4 Answers 4

9

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

4
  • I love this answer (an upvote from me) but it's not good for file systems with a space within the name. Tested: FreeBSD 12.0-CURRENT #0 r320869: Mon Jul 10 13:57:55 UTC 2017 [email protected]:/usr/obj/usr/src/sys/GENERIC Oct 7, 2017 at 12:37
  • 2
    You're right! Edited to work with spaces.
    – dermetfan
    Oct 8, 2017 at 23:11
  • Superb! pastebin.com/BYrA0cS4 and now … on to #65 Remove all ZFS snapshots in the Internet Archive Wayback Machine … Oct 29, 2017 at 18:15
  • zfs get -Ht snapshot -o name userrefs | xargs zfs holds is far simpler 5 more years later.
    – alaricljs
    Jan 25, 2023 at 0:32
1

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.

2
1

For a pool with multiple file systems

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

Credit to calmh in irc://irc.freenode.net/#zfs but I'm not sure whether the syntax needs a little more work.

For me, with a simple file system hierarchy (only one child) and relatively few snapshots (currently seventeen of the child), the command seems to not reach a conclusion. Example:

macbookpro08-centrim:~ gjp22$ zfs list -H -r -d 1 -t snapshot -o name gjp22 | xargs zfs holds -r
load: 4.94  cmd: zfs 39152 running 17.80u 112.52s
load: 3.73  cmd: zfs 39152 running 55.01u 349.29s
load: 3.15  cmd: zfs 39152 running 167.48u 1061.47s
load: 4.59  cmd: zfs 39152 running 267.57u 1697.49s
load: 5.19  cmd: zfs 39152 running 372.19u 2355.99s
load: 5.29  cmd: zfs 39152 running 432.89u 2736.79s

Borrowing from the other answer, with attention to the child file system alone:

macbookpro08-centrim:~ gjp22$ zfs list -H -r -d 1 -t snapshot -o name gjp22/intrigue | xargs zfs holds
NAME                              TAG  TIMESTAMP
macbookpro08-centrim:~ gjp22$ 

– and that output is almost immediate.

ZFS here is ZEVO Community Edition 1.1.1.

1

The following command will show all snapshots of [pool] (<-replace this with your pool name) that have holds

zfs list -H -o name -t snapshot -r pool | xargs -n1 zfs holds -H

the properties will be listed as property:stuff

with that information we can free the snapshots..

zfs list -H -o name -t snapshot -r pool | xargs -n1 zfs holds -H | awk '{print $1}' | xargs -n1 zfs release property:stuff

(replace 'property:stuff' with whatever is holding your dataset)

..and finally delete them

zfs destroy -r [pool]/[dataset][@snapshot]

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .