Difference between revisions of "Linux: incremental backup using rsync on btrfs with snapshots"

From Luky-Wiki
Jump to: navigation, search
("filesystem df")
(File system extend)
 
(32 intermediate revisions by the same user not shown)
Line 1: Line 1:
My production data are backed up by [http://www.bacula.org bacula]. This is good for data "online" all the time, but it is not so convent for my notebook and media PC. Till now I was using only simple rsync script to "copy" everything important to USB drive or iSCSI LUN. This solution was working fine but hat one catch. There is no way how to retrieve older version of files.
+
My production data are backed up by [http://www.bacula.org bacula]. This is good for data "online" all the time, but it is not so convent for my notebook and media PC. Till now I was using only simple rsync script to "copy" everything important to USB drive or iSCSI LUN. It was working fine but hat one catch. There is no way how to retrieve older version of files.
  
I would like to have possibility to retrieve also older versions of files so i combined my rsync backup with btrfs and snapshot feature. Here is result:
+
I would like to have possibility to retrieve also older versions of files so I combined my rsync backup with btrfs and snapshot feature. Here is result:
 
== Before first backup ==
 
== Before first backup ==
 
I am using iSCSI lun as target for backup. Skip iSCSI part if you are using USB drive.
 
I am using iSCSI lun as target for backup. Skip iSCSI part if you are using USB drive.
Line 19: Line 19:
  
 
=== iSCSI discovery and login ===
 
=== iSCSI discovery and login ===
It is necessary to discover iSCSI target and log to it before system can access drive. It can be performed by following commands:
+
It is necessary to discover iSCSI target and log to it before system can access drive. It can be performed by following commands (replace "narnia-nas" and name of target with name used by your storage):
 
<pre>
 
<pre>
# iscsiadm -m discovery -t st -p prue-nas
+
# iscsiadm -m discovery -t st -p narnia-nas
10.xx.xx.5:3260,0 iqn.2000-01.com.synology:prue-nas.phoebe
+
10.x.x.x:3260,1 iqn.2000-01.com.synology:narnia-nas.lukas
10.xx.xx.5:3260,0 iqn.2000-01.com.synology:prue-nas.lukas
 
  
# iscsiadm -m node -T iqn.2000-01.com.synology:prue-nas.phoebe --login
+
# iscsiadm -m node -T iqn.2000-01.com.synology:narnia-nas.lukas --login
Logging in to [iface: default, target: iqn.2000-01.com.synology:prue-nas.phoebe, portal: 10.xx.xx.5,3260]
+
Logging in to [iface: default, target: iqn.2000-01.com.synology:narnia-nas.lukas, portal: 10.x.x.x,3260] (multiple)
Login to [iface: default, target: iqn.2000-01.com.synology:prue-nas.phoebe, portal: 10.xx.xx.5,3260] successful.
+
Login to [iface: default, target: iqn.2000-01.com.synology:narnia-nas.lukas, portal: 10.x.x.x,3260] successful.
 
</pre>
 
</pre>
There should be new disk once kernel detect it:
+
 
 +
There should be new disk once kernel detect it (snip from dmesg command):
 
<pre>
 
<pre>
scsi8 : iSCSI Initiator over TCP/IP
+
scsi host4: iSCSI Initiator over TCP/IP
scsi 8:0:0:0: Direct-Access    SYNOLOGY iSCSI Storage    3.1 PQ: 0 ANSI: 5
+
scsi 4:0:0:0: Direct-Access    SYNOLOGY iSCSI Storage    4.0 PQ: 0 ANSI: 5
sd 8:0:0:0: Attached scsi generic sg2 type 0
+
sd 4:0:0:0: Attached scsi generic sg2 type 0
sd 8:0:0:0: [sdb] 104857600 512-byte logical blocks: (53.6 GB/50.0 GiB)
+
sd 4:0:0:0: [sdb] 209715200 512-byte logical blocks: (107 GB/100 GiB)
sd 8:0:0:0: [sdb] Write Protect is off
+
sd 4:0:0:0: [sdb] Write Protect is off
sd 8:0:0:0: [sdb] Mode Sense: 3b 00 00 00
+
sd 4:0:0:0: [sdb] Mode Sense: 43 00 10 08
sd 8:0:0:0: [sdb] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
+
sd 4:0:0:0: [sdb] Write cache: enabled, read cache: enabled, supports DPO and FUA
sdb: unknown partition table
+
sd 4:0:0:0: [sdb] Attached SCSI disk
sd 8:0:0:0: [sdb] Attached SCSI disk
 
 
</pre>
 
</pre>
 +
 
<pre>
 
<pre>
 
# lsscsi | grep SYN
 
# lsscsi | grep SYN
[6:0:0:0]    disk    SYNOLOGY iSCSI Storage    3.1   /dev/sdb  
+
[4:0:0:0]    disk    SYNOLOGY iSCSI Storage    4.0   /dev/sdb  
 
</pre>
 
</pre>
  
Line 49: Line 49:
 
I prefer disk labels as device file may change over time. '''Make sure you select correct device''':
 
I prefer disk labels as device file may change over time. '''Make sure you select correct device''':
 
<pre>
 
<pre>
# mkfs.btrfs -L phoebe-backup /dev/sdb
+
# mkfs.btrfs -L lukas-backup /dev/sdb
 +
btrfs-progs v4.0
 +
See http://btrfs.wiki.kernel.org for more information.
  
 +
Performing full device TRIM (100.00GiB) ...
 
Turning ON incompat feature 'extref': increased hardlink limit per file to 65536
 
Turning ON incompat feature 'extref': increased hardlink limit per file to 65536
fs created label phoebe-backup on /dev/sdb
+
Turning ON incompat feature 'skinny-metadata': reduced-size metadata extent refs
nodesize 16384 leafsize 16384 sectorsize 4096 size 50.00GiB
+
fs created label lukas-backup on /dev/sdb
Btrfs v3.12
+
nodesize 16384 leafsize 16384 sectorsize 4096 size 100.00GiB
 
</pre>
 
</pre>
 +
''Note: TRIM on iSCSI LUN is feature of DSM 6.0 running on selected models of NAS from Synology. It may be available also on NAS devices from different vendors.''
  
 
=== FS first time mounted ===
 
=== FS first time mounted ===
File system will be mounted by script therefore it is not necessary for system itself to mount it during boot up. To reflect this entry in <code>/etc/fstab</code> should looks like:
+
File system will be mounted by script therefore it is not necessary for system itself to mount it during boot up. Entry in <code>/etc/fstab</code> should looks like:
 
<pre>
 
<pre>
# data backup
+
# backup
LABEL=phoebe-backup /mnt/backup btrfs noauto 0 0
+
LABEL=lukas-backup /mnt/backup btrfs noauto 0 0
 
</pre>
 
</pre>
  
Btrfs can be managed only while it is mounted.
+
Btrfs can be managed only while it is mounted so it is necessary to mount it first.
 
<pre>
 
<pre>
 
mkdir -p /mnt/backup
 
mkdir -p /mnt/backup
mount /mnt/backup
+
chmod  0 /mnt/backup
 +
mount   /mnt/backup
 
</pre>
 
</pre>
  
Line 76: Line 81:
 
btrfs quota enable /mnt/backup
 
btrfs quota enable /mnt/backup
 
</pre>
 
</pre>
'''Note:''' enable quota before placing data on fs otherwise it will take some time to collect (scan) it
+
'''Note:''' enable quota before placing data on fs otherwise it will take some time to collect (scan) it.
  
 
I prefer to use separate subvolume for backup. With this configuration it is possible to use one filesystem as target for different backups:
 
I prefer to use separate subvolume for backup. With this configuration it is possible to use one filesystem as target for different backups:
 
<pre>
 
<pre>
# btrfs sub create /mnt/backup/phoebe
+
# btrfs sub create /mnt/backup/lukas
Create subvolume '/mnt/backup/phoebe'
+
Create subvolume '/mnt/backup/lukas'
 
</pre>
 
</pre>
  
 
=== Umount & logoff ===
 
=== Umount & logoff ===
My script is handling iSCSI initiator and mounting of fs. To have clean start I executed following commands at this point:
+
My script is handling iSCSI and mounting of file system. It is necessary to unmount file system and disconnect from NAS in order to have "clean" start.
 
<pre>
 
<pre>
# umount /mnt/backup/
+
# umount -v /mnt/backup/
 +
umount: /mnt/backup/ unmounted
 +
</pre>
  
# iscsiadm -m node -T iqn.2000-01.com.synology:prue-nas.phoebe --logout
+
<pre>
Logging out of session [sid: 1, target: iqn.2000-01.com.synology:prue-nas.phoebe, portal: 10.xx.xx.5,3260]
+
# iscsiadm -m node -T iqn.2000-01.com.synology:narnia-nas.lukas --logout
Logout of [sid: 1, target: iqn.2000-01.com.synology:prue-nas.phoebe, portal: 10.xx.xx.5,3260] successful.
+
Logging out of session [sid: 2, target: iqn.2000-01.com.synology:narnia-nas.lukas, portal: 10.x.x.x,3260]
 +
Logout of [sid: 2, target: iqn.2000-01.com.synology:narnia-nas.lukas, portal: 10.x.x.x,3260] successful.
 
</pre>
 
</pre>
  
 
== Backup script ==
 
== Backup script ==
== Useful btrfs commands ==
+
This script don't try to be smart. It simply execute commands and end immediately if failure occur. If failure occur while executing <code>rsync</code> then snapshot is marked as "incomplete".
=== "No space left on device." What ? ===
+
 
First of all don't panic :o) At second don't use "df" command or it's derivatives. Btrfs have specific space management so "df" command can show misleading values.
+
'''Note: don't use this script directly. It is created to fulfill my needs and it may be necessary to modify it before you can use it in your environment.'''
 +
<pre>
 +
#!/bin/bash
 +
 
 +
echo
 +
echo "To verify using \"--checksum\" execute:"
 +
echo "${0} verify"
 +
echo
 +
sleep 5
 +
 
 +
if [ "${1}" == "verify" ]
 +
then
 +
        echo "... verify mode selected"
 +
        opt="--checksum"
 +
else
 +
        echo "... normal mode selected"
 +
        opt=""
 +
fi
 +
 
 +
sleep 5
 +
echo
 +
echo
 +
 
 +
echo "Discovering narnia-nas ..."
 +
iscsiadm -m discovery -t st -p narnia-nas || exit 1
 +
echo
 +
 
 +
echo "Connecting to narnia-nas ..."
 +
iscsiadm -m node -T iqn.2000-01.com.synology:narnia-nas.lukas --login || exit 2
 +
echo
 +
 
 +
echo "Sleeping ... kernel need some time to detect new devices"
 +
sleep 10
 +
echo
 +
 
 +
echo "Mounting backup fs ..."
 +
mount -v /mnt/backup || exit 3
 +
echo
 +
 
 +
echo "Copying data ..."
 +
# output of following commands is saved along with backup
 +
(  echo; echo "lsusb:" ; lsusb;
 +
  echo; echo "lsscsi:"; lsscsi;
 +
  echo; echo "lshw:"  ; lshw -short;
 +
  echo; echo "date:"  ; date;
 +
  echo; echo "dpkg -l"; dpkg -l;
 +
  echo; echo "# EOF" ;
 +
) > /_lastbackup_iscsi
 +
echo
 +
 
 +
# copy data to backup location
 +
rsync ${opt} --archive --delete --delete-excluded --human-readable --stats --progress \
 +
--exclude=/cdrom --exclude=/dev --exclude=/media --exclude=/mnt --exclude=/proc --exclude=/run \
 +
--exclude=/sys --exclude=/tmp \
 +
--exclude=/btrfs \
 +
--exclude=/root/hekate-certificates \
 +
--exclude=/home/lukas/.cache/google-chrome \
 +
--exclude=/home/lukas/.cache/mozilla/firefox \
 +
--exclude=/home/lukas/.cache/thumbnails \
 +
--exclude=/data/VMs/no-backup \
 +
--exclude=/data/swap \
 +
/ /mnt/backup/lukas/
 +
 
 +
RC=$?
 +
 
 +
echo
 +
echo "Done with rc: ${RC}"
 +
echo
  
Example:
+
echo "Flushing file system buffers ..."
* you have btrfs on two 10GB devices with one "single" subvolume and second one using "raid1"
+
time sync
 +
btrfs filesystem sync /mnt/backup
 +
time sync
 +
echo
  
Simple data usage:
+
echo "Creating snapshot of backup ..."
* If you try to write to "single" subvolume then you may write up to 20GB of data (2x10GB, not counting metadata)
+
if [ "${RC}" -eq 0 ]
* If you try to write to "raid1" subvolume then you may write up to 10GB of data (again not counting metadata)
+
then
 +
btrfs sub snap -r /mnt/backup/lukas "/mnt/backup/lukas_$(LANG=C date +%Y-%m-%d_%s)"                  || exit 4
 +
else
 +
btrfs sub snap -r /mnt/backup/lukas "/mnt/backup/lukas_$(LANG=C date +%Y-%m-%d_%s)_incomplete_${RC}" || exit 5
 +
fi
 +
echo
  
At this point it looks simple but check this:
+
echo "Hit enter to continue ... "
* You stored 5GB of data to "single" subvolume and another set of 5GB data to "raid1" subvolume. What will be space left on fs ?
+
read
  
That's tricky question but here is answer:
+
echo "Umounting backup filesystem ..."
* 5GB of "raid1" mean that there is 5GB of 10GB occupied on both devices
+
umount -v /mnt/backup || exit 6
* 5GB of "single" mean two things. If everything is balanced properly then 2.5GB of space is taken from both devices. If not then up to 5GB is on one device and rest on second one.
+
echo
  
This mean:
+
echo "Disconecting from narnia-nas ..."
* you may store up to 2.5GB of "raid1" or up to 5GB in "single" subvolume
+
iscsiadm -m node -T iqn.2000-01.com.synology:narnia-nas.lukas --logout || exit 7
 +
echo
  
Now you understand why df can't tell you utilization details correctly ?
+
echo "Done :o)"
 +
echo
  
Additional problems may occur if data and metadata are way to fragmented. Refer to official wiki for more details: [https://btrfs.wiki.kernel.org/index.php/FAQ#Help.21_I_ran_out_of_disk_space.21 Help! I ran out of disk space!]
+
# EOF
 +
</pre>
 +
 
 +
md5sum: e075be22b429a2be4b3dbf2fbb467ab9
 +
 
 +
== Useful btrfs commands ==
 
=== "filesystem df" ===
 
=== "filesystem df" ===
To explain details btrfs have "btrfs filesystem df" command:
+
BTRFS use different data layout compared to file systems like ext{2,3,4}. Data and metadata are organized to pools and pools are allocated from raw device. There are several different pools and each one have it's own utilization. Therefore it is not easy to provide "numbers" for <code>df</code> command. If you ran out of space or you are unsure what is causing disk utilization then review output of following command:  
 
<pre>
 
<pre>
 
# btrfs filesystem df /mnt/backup/
 
# btrfs filesystem df /mnt/backup/
Data, single: total=33.01GiB, used=32.99GiB
+
 
 +
Data, single: total=79.01GiB, used=78.66GiB
 +
 
 
System, DUP: total=8.00MiB, used=16.00KiB
 
System, DUP: total=8.00MiB, used=16.00KiB
System, single: total=4.00MiB, used=0.00
+
System, single: total=4.00MiB, used=0.00B
Metadata, DUP: total=1.25GiB, used=939.14MiB
+
 
Metadata, single: total=8.00MiB, used=0.00
+
Metadata, DUP: total=1.00GiB, used=440.55MiB
 +
Metadata, single: total=8.00MiB, used=0.00B
 +
 
 +
GlobalReserve, single: total=160.00MiB, used=0.00B
 
</pre>
 
</pre>
 +
''Note1: I put empty lines to output in order to visually separate pools''
  
Space is allocated in chunks. This mean that "total" show size of allocated chunks and "used" real usage.
+
''Note2: Data -> user data, System -> stuff related to "super block", Metadata -> Metadata :o) , GlobalReserve -> FS reserve to prevent deadlock''
  
How to check size of subvolume or snapshot ? It is not possible without quota. If you don't have enabled yet then enable it and make sure you ran initial scan otherwise it may show you wrong details.
+
=== how to identify space consumers ===
 +
Files and blocks of files can be shared between volumes (and snapshots). Standard Linux tools don't understand underlying data layout so it is not easy to find space consumers using this tools. It is necessary to use btrfs native commands in order to get accurate numbers. Example of usage:
  
First of all it is necessary to check subvolume/snapshot id:
+
* First step is to get ID of subvolumes:
 
<pre>
 
<pre>
 
# btrfs sub list /mnt/backup/
 
# btrfs sub list /mnt/backup/
ID 256 gen 200 top level 5 path phoebe
+
ID 257 gen 44 top level 5 path lukas
ID 293 gen 98  top level 5 path phoebe_2014-02-21_1392991593
+
ID 337 gen 30 top level 5 path lukas_2016-09-11_1473624103
ID 294 gen 171 top level 5 path phoebe_2014-02-21_1392994197
+
ID 345 gen 35 top level 5 path lukas_2016-09-11_1473624272
ID 295 gen 179 top level 5 path phoebe_2014-02-21_1392997683
+
ID 349 gen 39 top level 5 path lukas_2016-09-11_1473624385
ID 296 gen 183 top level 5 path phoebe_2014-02-21_1392998450
+
ID 350 gen 42 top level 5 path lukas_2016-09-11_1473624546
 
</pre>
 
</pre>
  
Second step is list of quota groups:
+
* Second step is list of quota groups:
 
<pre>
 
<pre>
# # btrfs qgroup show /mnt/backup/
+
# btrfs qgroup show /mnt/backup/
qgroupid rfer       excl      
+
qgroupid         rfer         excl  
-------- ----       ----  
+
--------         ----         ----  
0/5     16384      16384
+
0/5         16.00KiB    16.00KiB
0/256    43434659840 7568146432
+
0/257        78.41GiB    42.92MiB
0/293    35893178368 446140416 
+
0/337        78.84GiB      7.37GiB
0/294    35894276096 7098368   
+
0/345        78.42GiB    48.53MiB
0/295    35895332864 147456      
+
0/349        78.42GiB     46.27MiB
0/296    35895332864 147456      
+
0/350        78.43GiB     37.96MiB
 
</pre>
 
</pre>
  
First number represent subvolume id (yes, snapshot is also subvolume). Second one is size of it (in mean of all data accessible via subvolume). Third one show data exclusively stored in this group. This is actually difference between subvolumes (snapshots) which can be recovered by removing it.
+
First number represent subvolume id (snapshot is also subvolume). Second one is size of it (in mean of all data accessible via subvolume). Third one show data exclusively stored in this group. This size can be recovered by removing subvolume / snapshot.
 +
 
 +
As a example -> By removing "0/337 " I can get back 7.37GiB of space.
 +
 
 +
=== Subvolume (snapshot) remove ===
 +
 
 +
Snapshots and subvolumes are removed in same way:
  
Values in last table are in bytes so after converting you can see:
 
 
<pre>
 
<pre>
0/5    0M      0M
+
# btrfs sub delete /mnt/backup/lukas_2016-09-11_1473624103/
0/256  41422M  7217M
+
Delete subvolume (no-commit): '/mnt/backup/lukas_2016-09-11_1473624103'
0/293  34230M  425M
 
0/294  34231M  6M
 
0/295  34232M  0M
 
0/296  34232M  0M
 
 
</pre>
 
</pre>
  
By removing "0/293" I can get back 425M (of course in future it will be bigger value :o) ).
+
It may take some time till BTRFS release all data used by snapshot or subvolume.
 
 
=== Subvolume (snapshot) remove ===
 
  
Snapshots and subvolumes are removed in same way:
+
=== File system extend ===
 +
I am using iSCSI LUN so I can extend it. Here is way how to extend also BTRFS on it:
  
 
<pre>
 
<pre>
# btrfs sub delete /mnt/backup/phoebe_2014-02-21_1392988539
+
# btrfs filesystem resize max /mnt/backup/
Delete subvolume '/mnt/backup/phoebe_2014-02-21_1392988539'
+
Resize '/mnt/backup/' of 'max'
 
</pre>
 
</pre>
  
It may take some time to release all space allocated by snapshot or subvolume.
+
This command will extend all attached devices in btrfs to reflect maximum HW size (for example after LUN resize).

Latest revision as of 22:20, 11 September 2016

My production data are backed up by bacula. This is good for data "online" all the time, but it is not so convent for my notebook and media PC. Till now I was using only simple rsync script to "copy" everything important to USB drive or iSCSI LUN. It was working fine but hat one catch. There is no way how to retrieve older version of files.

I would like to have possibility to retrieve also older versions of files so I combined my rsync backup with btrfs and snapshot feature. Here is result:

Before first backup

I am using iSCSI lun as target for backup. Skip iSCSI part if you are using USB drive.

iSCSI configuration

It is important to password protect Target. Otherwise any device on local network can overwrite it. Also I highly recommend Header and Data digest. There is possibility of data corruption without it.

Configuration of iSCSI initiator is stored in /etc/iscsi/iscsid.conf. Following lines are mandatory:

node.session.auth.authmethod = CHAP
node.session.auth.username = <user>
node.session.auth.password = <pass>

node.conn[0].iscsi.HeaderDigest = CRC32C
node.conn[0].iscsi.DataDigest = CRC32C

All others can be left in "default" configuration.

iSCSI discovery and login

It is necessary to discover iSCSI target and log to it before system can access drive. It can be performed by following commands (replace "narnia-nas" and name of target with name used by your storage):

# iscsiadm -m discovery -t st -p narnia-nas
10.x.x.x:3260,1 iqn.2000-01.com.synology:narnia-nas.lukas

# iscsiadm -m node -T iqn.2000-01.com.synology:narnia-nas.lukas --login
Logging in to [iface: default, target: iqn.2000-01.com.synology:narnia-nas.lukas, portal: 10.x.x.x,3260] (multiple)
Login to [iface: default, target: iqn.2000-01.com.synology:narnia-nas.lukas, portal: 10.x.x.x,3260] successful.

There should be new disk once kernel detect it (snip from dmesg command):

scsi host4: iSCSI Initiator over TCP/IP
scsi 4:0:0:0: Direct-Access     SYNOLOGY iSCSI Storage    4.0  PQ: 0 ANSI: 5
sd 4:0:0:0: Attached scsi generic sg2 type 0
sd 4:0:0:0: [sdb] 209715200 512-byte logical blocks: (107 GB/100 GiB)
sd 4:0:0:0: [sdb] Write Protect is off
sd 4:0:0:0: [sdb] Mode Sense: 43 00 10 08
sd 4:0:0:0: [sdb] Write cache: enabled, read cache: enabled, supports DPO and FUA
sd 4:0:0:0: [sdb] Attached SCSI disk
# lsscsi | grep SYN
[4:0:0:0]    disk    SYNOLOGY iSCSI Storage    4.0   /dev/sdb 

File system

I prefer disk labels as device file may change over time. Make sure you select correct device:

# mkfs.btrfs -L lukas-backup /dev/sdb
btrfs-progs v4.0
See http://btrfs.wiki.kernel.org for more information.

Performing full device TRIM (100.00GiB) ...
Turning ON incompat feature 'extref': increased hardlink limit per file to 65536
Turning ON incompat feature 'skinny-metadata': reduced-size metadata extent refs
fs created label lukas-backup on /dev/sdb
	nodesize 16384 leafsize 16384 sectorsize 4096 size 100.00GiB

Note: TRIM on iSCSI LUN is feature of DSM 6.0 running on selected models of NAS from Synology. It may be available also on NAS devices from different vendors.

FS first time mounted

File system will be mounted by script therefore it is not necessary for system itself to mount it during boot up. Entry in /etc/fstab should looks like:

# backup
LABEL=lukas-backup	/mnt/backup	btrfs	noauto				0 0

Btrfs can be managed only while it is mounted so it is necessary to mount it first.

mkdir -p /mnt/backup
chmod  0 /mnt/backup
mount    /mnt/backup

Subvolume & quota

Subvolume and snapshot size are internally handled as quota. In order to see which snapshot or subvolume take so much space it is necessary to enable quota on file system level:

btrfs quota enable /mnt/backup

Note: enable quota before placing data on fs otherwise it will take some time to collect (scan) it.

I prefer to use separate subvolume for backup. With this configuration it is possible to use one filesystem as target for different backups:

# btrfs sub create /mnt/backup/lukas
Create subvolume '/mnt/backup/lukas'

Umount & logoff

My script is handling iSCSI and mounting of file system. It is necessary to unmount file system and disconnect from NAS in order to have "clean" start.

# umount -v /mnt/backup/
umount: /mnt/backup/ unmounted
# iscsiadm -m node -T iqn.2000-01.com.synology:narnia-nas.lukas --logout
Logging out of session [sid: 2, target: iqn.2000-01.com.synology:narnia-nas.lukas, portal: 10.x.x.x,3260]
Logout of [sid: 2, target: iqn.2000-01.com.synology:narnia-nas.lukas, portal: 10.x.x.x,3260] successful.

Backup script

This script don't try to be smart. It simply execute commands and end immediately if failure occur. If failure occur while executing rsync then snapshot is marked as "incomplete".

Note: don't use this script directly. It is created to fulfill my needs and it may be necessary to modify it before you can use it in your environment.

#!/bin/bash

echo
echo "To verify using \"--checksum\" execute:"
echo "${0} verify"
echo
sleep 5

if [ "${1}" == "verify" ]
then
        echo "... verify mode selected"
        opt="--checksum"
else
        echo "... normal mode selected"
        opt=""
fi

sleep 5
echo
echo

echo "Discovering narnia-nas ..."
iscsiadm -m discovery -t st -p narnia-nas || exit 1
echo

echo "Connecting to narnia-nas ..."
iscsiadm -m node -T iqn.2000-01.com.synology:narnia-nas.lukas --login || exit 2
echo

echo "Sleeping ... kernel need some time to detect new devices"
sleep 10
echo

echo "Mounting backup fs ..."
mount -v /mnt/backup || exit 3
echo

echo "Copying data ..."
# output of following commands is saved along with backup
(  echo; echo "lsusb:" ; lsusb;
   echo; echo "lsscsi:"; lsscsi;
   echo; echo "lshw:"  ; lshw -short;
   echo; echo "date:"  ; date;
   echo; echo "dpkg -l"; dpkg -l;
   echo; echo "# EOF"  ;
) > /_lastbackup_iscsi
echo

# copy data to backup location
rsync ${opt} --archive --delete --delete-excluded --human-readable --stats --progress \
 --exclude=/cdrom --exclude=/dev --exclude=/media --exclude=/mnt --exclude=/proc --exclude=/run \
 --exclude=/sys --exclude=/tmp \
 --exclude=/btrfs \
 --exclude=/root/hekate-certificates \
 --exclude=/home/lukas/.cache/google-chrome \
 --exclude=/home/lukas/.cache/mozilla/firefox \
 --exclude=/home/lukas/.cache/thumbnails \
 --exclude=/data/VMs/no-backup \
 --exclude=/data/swap \
 / /mnt/backup/lukas/

RC=$?

echo
echo "Done with rc: ${RC}"
echo

echo "Flushing file system buffers ..."
time sync
btrfs filesystem sync /mnt/backup
time sync
echo

echo "Creating snapshot of backup ..."
if [ "${RC}" -eq 0 ]
then
	btrfs sub snap -r /mnt/backup/lukas "/mnt/backup/lukas_$(LANG=C date +%Y-%m-%d_%s)"                  || exit 4
else
	btrfs sub snap -r /mnt/backup/lukas "/mnt/backup/lukas_$(LANG=C date +%Y-%m-%d_%s)_incomplete_${RC}" || exit 5
fi
echo

echo "Hit enter to continue ... "
read

echo "Umounting backup filesystem ..."
umount -v /mnt/backup || exit 6
echo

echo "Disconecting from narnia-nas ..."
iscsiadm -m node -T iqn.2000-01.com.synology:narnia-nas.lukas --logout || exit 7
echo

echo "Done :o)"
echo

# EOF

md5sum: e075be22b429a2be4b3dbf2fbb467ab9

Useful btrfs commands

"filesystem df"

BTRFS use different data layout compared to file systems like ext{2,3,4}. Data and metadata are organized to pools and pools are allocated from raw device. There are several different pools and each one have it's own utilization. Therefore it is not easy to provide "numbers" for df command. If you ran out of space or you are unsure what is causing disk utilization then review output of following command:

# btrfs filesystem df /mnt/backup/

Data, single: total=79.01GiB, used=78.66GiB

System, DUP: total=8.00MiB, used=16.00KiB
System, single: total=4.00MiB, used=0.00B

Metadata, DUP: total=1.00GiB, used=440.55MiB
Metadata, single: total=8.00MiB, used=0.00B

GlobalReserve, single: total=160.00MiB, used=0.00B

Note1: I put empty lines to output in order to visually separate pools

Note2: Data -> user data, System -> stuff related to "super block", Metadata -> Metadata :o) , GlobalReserve -> FS reserve to prevent deadlock

how to identify space consumers

Files and blocks of files can be shared between volumes (and snapshots). Standard Linux tools don't understand underlying data layout so it is not easy to find space consumers using this tools. It is necessary to use btrfs native commands in order to get accurate numbers. Example of usage:

  • First step is to get ID of subvolumes:
# btrfs sub list /mnt/backup/
ID 257 gen 44 top level 5 path lukas
ID 337 gen 30 top level 5 path lukas_2016-09-11_1473624103
ID 345 gen 35 top level 5 path lukas_2016-09-11_1473624272
ID 349 gen 39 top level 5 path lukas_2016-09-11_1473624385
ID 350 gen 42 top level 5 path lukas_2016-09-11_1473624546
  • Second step is list of quota groups:
# btrfs qgroup show /mnt/backup/
qgroupid         rfer         excl 
--------         ----         ---- 
0/5          16.00KiB     16.00KiB 
0/257        78.41GiB     42.92MiB 
0/337        78.84GiB      7.37GiB 
0/345        78.42GiB     48.53MiB 
0/349        78.42GiB     46.27MiB 
0/350        78.43GiB     37.96MiB 

First number represent subvolume id (snapshot is also subvolume). Second one is size of it (in mean of all data accessible via subvolume). Third one show data exclusively stored in this group. This size can be recovered by removing subvolume / snapshot.

As a example -> By removing "0/337 " I can get back 7.37GiB of space.

Subvolume (snapshot) remove

Snapshots and subvolumes are removed in same way:

# btrfs sub delete /mnt/backup/lukas_2016-09-11_1473624103/
Delete subvolume (no-commit): '/mnt/backup/lukas_2016-09-11_1473624103'

It may take some time till BTRFS release all data used by snapshot or subvolume.

File system extend

I am using iSCSI LUN so I can extend it. Here is way how to extend also BTRFS on it:

# btrfs filesystem resize max /mnt/backup/
Resize '/mnt/backup/' of 'max'

This command will extend all attached devices in btrfs to reflect maximum HW size (for example after LUN resize).