#876675 snapper: Avoid filling up btrfs, as it break the system?

Package:
snapper
Source:
snapper
Description:
Linux filesystem snapshot management tool
Submitter:
Petter Reinholdtsen
Date:
2021-03-14 16:06:10 UTC
Severity:
important
#876675#5
Date:
2017-09-24 19:11:20 UTC
From:
To:
Hi.  I use the FreedomBox with btrfs, and it is configured to use
snapper to take regular file system snapshots.  But as you can see from
<URL: https://bugs.debian.org/876514 >, this can bring down the system
if the btrfs file system fill up.

Could snapper be changed to restrict the amount of snapshots kept in
each category based on amount of free space on the file system, to avoid
filling up the disk with snapshots?

It would be great if snapper also provided a way to easily figure out
how much disk space a given snapshot uses.

Btw, are you aware of <URL: https://tracker.debian.org/pkg/zfsnap >,
which uses an interesting way to name snapshots (with timestamp and
duration), which make it quite easy to administrate the snapshots from
the command line.  Perhaps something similar could be done by snapper?

#876675#10
Date:
2017-09-26 09:07:42 UTC
From:
To:
Hi,

Unfortunately, no. However, you can limit snapshots by "numbers".

One btrfs guy says it's hard to do such behavior since btrfs snapshots
share same blocks as those snapshot data, so not sure how to keep
amount of disk by deleting old snapshots.

Said above, most of snapshots share same blocks, it's hard I guess.

Could you give me some examples, please?

#876675#15
Date:
2017-10-15 05:29:26 UTC
From:
To:
[Hideki Yamane]

Any hope to have such feature implemented, as snapper in its current
form is dangerous as long as btrfs start blocking processes when the
disk is full. :(

One way would be to not take snapshots if df show less than X % free
space.  Another would be to start removing old snapshots until df show
more than X % free space before doing any snapshots.  The point is that
for me it is better to not take snapshots than to bring down the entire
service. :)

A way to do this is documented in
<URL: https://raw.githubusercontent.com/agronick/btrfs-size/master/btrfs-size.sh >.

#876675#20
Date:
2017-11-22 08:36:33 UTC
From:
To:
Hi,

I've run into the same problem. btrfs partition was full of snapper
snapshots and has made the system unbootable.
what about decrease default number of snapshots?

I see in Debian wiki it's recommended not to have more than 12
snapshots [1].

1. https://wiki.debian.org/Btrfs

#876675#25
Date:
2018-04-04 05:24:27 UTC
From:
To:
severity 876675 important
tags 876675 + patch
thanks

The biggest reason why snapper fills up disk with snapshots is because
the number algorithm does not cleanup automatically.  When apt snapshots
are taken by this package's apt hooks, number algorithm is used.
However, unlike timeline algorithms that are periodically cleaned up by
snapperd, numeric snapshots are not (even after saying number cleanup to
'yes'). Even after configuring snapperd to keep very few apt snapshots,
this still fills up the disk eventually.

The solution to this part is to trigger a number cleanup after every
snapshot. The fix is available as part of patch in
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=880144 . Hence, adding
patch tag. Please consider accepting the simple patch to fix both bugs.

Bumping priority as this as it effects all FreedomBox machines that use
snapper.

Thanks,

#876675#34
Date:
2018-09-02 04:56:00 UTC
From:
To:
[Sunil Mohan Adapa]

I suspect you talk about the second patch in bug #880144, ie this:

diff --git a/debian/80snapper b/debian/80snapper
index 0007402..ddf1f8b 100644
--- a/debian/80snapper
+++ b/debian/80snapper
@@ -1,3 +1,3 @@
 # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=770938
-  DPkg::Pre-Invoke  { "if [ -x /usr/bin/snapper -a -e /etc/snapper/configs/root ]; then rm /var/tmp/snapper-apt || true ; snapper create -d apt -c number -t pre -p > /var/tmp/snapper-apt || true ; fi"; };
-  DPkg::Post-Invoke { "if [ -x /usr/bin/snapper -a -e /var/tmp/snapper-apt ]; then snapper create -d apt -c number -t post --pre-number=`cat /var/tmp/snapper-apt` || true ; fi"; };
+  DPkg::Pre-Invoke  { "if [ -e /etc/default/snapper ]; then . /etc/default/snapper; fi; if [ -x /usr/bin/snapper -a ! x$DISABLE_APT_SNAPSHOT = 'xyes' -a -e /etc/snapper/configs/root ]; then rm /var/tmp/snapper-apt || true ; snapper create -d apt -c number -t pre -p > /var/tmp/snapper-apt || true ; snapper cleanup number || true ; fi"; };
+  DPkg::Post-Invoke { "if [ -e /etc/default/snapper ]; then . /etc/default/snapper; fi; if [ -x /usr/bin/snapper -a ! x$DISABLE_APT_SNAPSHOT = 'xyes' -a -e /var/tmp/snapper-apt ]; then snapper create -d apt -c number -t post --pre-number=`cat /var/tmp/snapper-apt` || true ; snapper cleanup number || true ; fi"; };

It has already been applied in the snapper git repository.  Did it
help with this issue too?

#876675#37
Date:
2019-01-06 04:44:39 UTC
From:
To:
control: tags -1 -patch

Hi,

 I've found that snapper has two useful configuration now.
 See https://manpages.debian.org/unstable/snapper/snapper-configs.5.en.html

 If it works correctly, snapper should care free space when taking
 a snapshot. Then, we can close this bug as avoiding full of snapshots
 eat your disks.

 Now I've confirmed that the number clean algorithm works well.

 I've tested it and stuck, then reset and btrfs corrupted... ;(

#876675#44
Date:
2019-01-06 04:48:45 UTC
From:
To:
 Its number is decided by snapper upstream, so if you have a question
 about it, please ask them. And I doubt whether it's true as Nicholas
 noted "Need to find the source for this on linux-btrfs".

#876675#49
Date:
2021-03-14 16:03:15 UTC
From:
To:
Hi,

If you wish to check the diskspace used by the btrfs subvolume, you are
suppose to use qgroup thing as mentiond. That is not safe to use.

But if the objective is to avoid filling up the disk. may be abit
simpler approach may help.  Let me explain.

FYI:
If the base of Btrfs is at $BTRFS_BASE, somthing like the following
should be OK as shell code. (__echo is a shell function)

The idea is set limit for minimum absolute disk size and minumum free
desk space percentage.  I am testing idea with free 10% (FMIN=10) disk
space with the following code.

```
  # disk size sanity check without quota consideration
  BSS_STAT_TOTAL=$(stat -f -c %b "$BTRFS_BASE")
  # Even on 4k block system, disk with 200 blocks is less than 1MB
  if [ "$BSS_STAT_TOTAL" -le 200 ]; then
    __echo 0 "Total disk size: $BSS_STAT_TOTAL blocks (too small,
minimum required 200)"
    __echo 0 "skip snapshot: BASE=$BTRFS_BASE TIME=${NOW_TSTR}
TYPE=${BSS_TYPE}"
    exit 1
  fi
  BSS_STAT_UNIT=$((BSS_STAT_TOTAL/100))
  BSS_STAT_FREE=$(stat -f -c %f "$BTRFS_BASE")
  BSS_FREE_UNIT=$((BSS_STAT_FREE/BSS_STAT_UNIT))
  if [ "$BSS_FREE_UNIT" -le "$BSS_FMIN" ]; then
    __echo 0 "Free disk space: $BSS_FREE_UNIT%  (too small, minimum
required FMIN=$BSS_FMIN%)"
    __echo 0 "skip snapshot: BASE=$BTRFS_BASE TIME=${NOW_TSTR}
TYPE=${BSS_TYPE}"
    exit 1
  else
    __echo 2 "Free disk space: $BSS_FREE_UNIT%  (enough, minimum
required FMIN=$BSS_FMIN%)"
  fi
  # make snapshot
  $NOOP $SUDO mkdir -p "$BSS_DIR_BASE" >/dev/null
  while [ -d "$BSS_DIR_BASE/${NOW_TSTR}.${BSS_TYPE}" ]; do
    sleep "1s"
    NOW_TSTR=$(date -u --iso=second)
  done
  __echo 2 "make snapshot: BASE=$BTRFS_BASE TIME=${NOW_TSTR}
TYPE=${BSS_TYPE}"
  # shellcheck disable=SC2086
  $NOOP $BSV snapshot -r "$BTRFS_BASE"
"$BSS_DIR_BASE/${NOW_TSTR}.${BSS_TYPE}"

```
(This is what I do here for my own needs here and playing with data
aging parameters.)

I think snapper can do the similar.

#876675#52
Date:
2021-03-14 16:03:15 UTC
From:
To:
Hi,

If you wish to check the diskspace used by the btrfs subvolume, you are
suppose to use qgroup thing as mentiond. That is not safe to use.

But if the objective is to avoid filling up the disk. may be abit
simpler approach may help.  Let me explain.

FYI:
If the base of Btrfs is at $BTRFS_BASE, somthing like the following
should be OK as shell code. (__echo is a shell function)

The idea is set limit for minimum absolute disk size and minumum free
desk space percentage.  I am testing idea with free 10% (FMIN=10) disk
space with the following code.

```
  # disk size sanity check without quota consideration
  BSS_STAT_TOTAL=$(stat -f -c %b "$BTRFS_BASE")
  # Even on 4k block system, disk with 200 blocks is less than 1MB
  if [ "$BSS_STAT_TOTAL" -le 200 ]; then
    __echo 0 "Total disk size: $BSS_STAT_TOTAL blocks (too small,
minimum required 200)"
    __echo 0 "skip snapshot: BASE=$BTRFS_BASE TIME=${NOW_TSTR}
TYPE=${BSS_TYPE}"
    exit 1
  fi
  BSS_STAT_UNIT=$((BSS_STAT_TOTAL/100))
  BSS_STAT_FREE=$(stat -f -c %f "$BTRFS_BASE")
  BSS_FREE_UNIT=$((BSS_STAT_FREE/BSS_STAT_UNIT))
  if [ "$BSS_FREE_UNIT" -le "$BSS_FMIN" ]; then
    __echo 0 "Free disk space: $BSS_FREE_UNIT%  (too small, minimum
required FMIN=$BSS_FMIN%)"
    __echo 0 "skip snapshot: BASE=$BTRFS_BASE TIME=${NOW_TSTR}
TYPE=${BSS_TYPE}"
    exit 1
  else
    __echo 2 "Free disk space: $BSS_FREE_UNIT%  (enough, minimum
required FMIN=$BSS_FMIN%)"
  fi
  # make snapshot
  $NOOP $SUDO mkdir -p "$BSS_DIR_BASE" >/dev/null
  while [ -d "$BSS_DIR_BASE/${NOW_TSTR}.${BSS_TYPE}" ]; do
    sleep "1s"
    NOW_TSTR=$(date -u --iso=second)
  done
  __echo 2 "make snapshot: BASE=$BTRFS_BASE TIME=${NOW_TSTR}
TYPE=${BSS_TYPE}"
  # shellcheck disable=SC2086
  $NOOP $BSV snapshot -r "$BTRFS_BASE"
"$BSS_DIR_BASE/${NOW_TSTR}.${BSS_TYPE}"

```
(This is what I do here for my own needs here and playing with data
aging parameters.)

I think snapper can do the similar.