MAYBE BUG in dar 2.7.2 with hardlinks handling
Alexey Loukianov via Dar-support <[email protected]>
| Newsgroups | gmane.comp.sysutils.backup.dar.support |
|---|---|
| Message-ID | <[email protected]> |
Hi Denis,
Thanks a lot for such a wonderful piece of software you created, dar is
simply brilliant.
I've been using it for a long time to handle my incremental backups
needs and it was working flawlessly.
Backup strategy I use is:
1. rsync with --dest-link option from a remote box to a backup handling
box once per day, dir names are in YYYY-MM-DD format, link-dest for
today's backup is always last available previous backup, typically - one
that was done yesterday.
2. Middle-term storage for last 4 years: create full dar backups with
"-R YYYY-MM-DD -c YYYY-MM-DD" for any "first backup of the month",
create incremental dar backups with "-R YYYY-MM-DD -A YYYY-MM-(DD-1) -c
YYYY-MM-DD" for all other dirs of the same month.
3. Long-term storage: retention policy is to keep one full backup per
month done at the beginning of the month for anything that is older than
4 years, write these to a cold storage and store somewhere in the attic
for future generations :-).
As mentioned previously it was working flawlessly for years and I was
more than happy with it.
One thing that kind-a annoyed me was that in case I wanted to restore
backups from dars back to the way directories were laid out and files
hardlinked after initial rsync I had to use shell-scripting similar to
this one:
mkdir work
DARs_DIR="/opt/storage/DARs/2016/"
P=2016-12
ls -1 "$DAR_DIR/$P*.1.dar" | sort -n | while read f; do
d=${f%.1.dar}
dar -wa -x "${d}" -R $PWD/work/ || break;
mkdir -p $d
rsync -a --link-dest=$PWD/$P ./work/ ./$d/ || break
P="$d"
done
Code above does what I want but it is too complex for such a simple
task, rsync usage slows things down and the need to use "work" dir to
store WIP "checkpoints" inflates disk space requirement.
Thus I thought about an optimization of the backup methodology that was
possible in theory knowing that dar is expected to be able to properly
handle hardlinks. Idea was to run dar with "-R" set to the parent
directory where all YYYY-MM-DD directories are stored and limit what is
getting backed up by using "-g" options like this:
dar -c 2016-12-01 -R /opt/storage/backups/2016 -g 2016-12-01/ # Create
full backup of the month start
dar -c 2016-12-02 -A 2016-12-01 -R /opt/storage/backups/2016 -g
2016-12-01/ -g 2016-12-02/ # Create first incremental backup of the
month for day 02
dar -c 2016-12-03 -A 2016-12-02 -R /opt/storage/backups/2016 -g
2016-12-02/ -g 2016-12-03/ # Create first incremental backup of the
month for day 03
... and so on. Expectations are that archive for day 02 of the month
would not include any files for day 01 - as they all were backed up and
available in reference full archive for day 01 - and for day 02 it would
only save new or changed files compared to day 01 as all other files in
dir for day 02 are hardlinks to files in dir for day 01 - which again
are already saved in previous backup. Same stands for day 03 incremental
backup and so on.
Observed behaviour does not match expectations - for day 02 hardlinks
get always saved into dar ignoring the fact that same files are already
saved in reference archive for day 01. For days 03 and greater things
seem to go wildly random - sometimes hardlinks are saved into backup,
sometimes not.
Here is a small test script reproducing the problem:
================8<===================
#!/bin/bash -x
WDIR=$(mktemp -q -d -p "$PWD" dar-test-XXX)
[ -d "$WDIR" ] || { echo "Failed to create working dir!" >&2; exit 1; }
LAST_DIR=z
pushd "$WDIR"
mkdir a
truncate -s 16192 a/abc.txt
for i in `eval echo \{b..$LAST_DIR\}` ; do
mkdir $i
ln a/abc.txt $i/abc.txt
done
ls -li `eval echo \{a..$LAST_DIR\}`
dar -ah --sparse-file-min-size 1E -c dif-when-hardlink-a -R . -g a
--fsa-scope none
dar -l dif-when-hardlink-a -alist-ea
PREV=a
for i in `eval echo \{b..$LAST_DIR\}` ; do
dar -ah --sparse-file-min-size 1E -c dif-when-hardlink-$i -R . -g
$PREV/ -g $i/ -A dif-when-hardlink-$PREV --fsa-scope none
dar -l dif-when-hardlink-$i -alist-ea
PREV=$i
done
popd
================8<===================
Here is listing of produced dars on the test VM I use as a playground:
# ll *.dar
-rw-r--r-- 1 root root 17025 Dec 3 02:03 dif-when-hardlink-a.1.dar
-rw-r--r-- 1 root root 17220 Dec 3 02:03 dif-when-hardlink-b.1.dar
-rw-r--r-- 1 root root 894 Dec 3 02:03 dif-when-hardlink-c.1.dar
-rw-r--r-- 1 root root 17220 Dec 3 02:03 dif-when-hardlink-d.1.dar
-rw-r--r-- 1 root root 17220 Dec 3 02:03 dif-when-hardlink-e.1.dar
-rw-r--r-- 1 root root 17220 Dec 3 02:03 dif-when-hardlink-f.1.dar
-rw-r--r-- 1 root root 894 Dec 3 02:03 dif-when-hardlink-g.1.dar
-rw-r--r-- 1 root root 894 Dec 3 02:03 dif-when-hardlink-h.1.dar
-rw-r--r-- 1 root root 17220 Dec 3 02:03 dif-when-hardlink-i.1.dar
-rw-r--r-- 1 root root 894 Dec 3 02:03 dif-when-hardlink-j.1.dar
-rw-r--r-- 1 root root 17220 Dec 3 02:03 dif-when-hardlink-k.1.dar
-rw-r--r-- 1 root root 894 Dec 3 02:03 dif-when-hardlink-l.1.dar
-rw-r--r-- 1 root root 17220 Dec 3 02:03 dif-when-hardlink-m.1.dar
-rw-r--r-- 1 root root 894 Dec 3 02:03 dif-when-hardlink-n.1.dar
-rw-r--r-- 1 root root 894 Dec 3 02:03 dif-when-hardlink-o.1.dar
-rw-r--r-- 1 root root 17220 Dec 3 02:03 dif-when-hardlink-p.1.dar
-rw-r--r-- 1 root root 894 Dec 3 02:03 dif-when-hardlink-q.1.dar
-rw-r--r-- 1 root root 17220 Dec 3 02:03 dif-when-hardlink-r.1.dar
-rw-r--r-- 1 root root 894 Dec 3 02:03 dif-when-hardlink-s.1.dar
-rw-r--r-- 1 root root 17220 Dec 3 02:03 dif-when-hardlink-t.1.dar
-rw-r--r-- 1 root root 894 Dec 3 02:03 dif-when-hardlink-u.1.dar
-rw-r--r-- 1 root root 894 Dec 3 02:03 dif-when-hardlink-v.1.dar
-rw-r--r-- 1 root root 17220 Dec 3 02:03 dif-when-hardlink-w.1.dar
-rw-r--r-- 1 root root 17220 Dec 3 02:03 dif-when-hardlink-x.1.dar
-rw-r--r-- 1 root root 894 Dec 3 02:03 dif-when-hardlink-y.1.dar
-rw-r--r-- 1 root root 17220 Dec 3 02:03 dif-when-hardlink-z.1.dar
Notice the file size column, it shows all the story.
I'm not sure if this one is really the bug or it's me doing something
weird and having wrong assumptions/expectations.
Please advice on what's going on here and why do I get this behaviour
for this incremental backup approach?
Thanks in advance and sorry for a fuzz (and a wall of text this message is).
--
Regards,
Alexey Loukianov