--- Begin Message ---
Subject: |
Bug#556114: tar: --listed-incremental ignores changed files when using filesystem snapshots |
Date: |
Fri, 13 Nov 2009 17:05:53 +0100 |
Package: tar
Version: 1.20-1
Severity: normal
When creating incremental backups using snapshot filesystems, tar fails
to include files in a level 1 backup (presumably any level > 0) if they
were modified in the original filesystem between the time the snapshot
was created and the time the level 0 backup was created of the
snapshot.
(actually, they are not included if their modification times are less
than the creation time of of the higher-level incremental backup -
whatever may have been the cause: the use of a snapshot, a bad system
clock, etc.)
The net result is that it may not be possible to restore the filesystem
to the state at the time of last backup: files that were changed may
not have their latest version in any archive. Only level 0 archives
will be complete.
I.e.:
- Level 0 backup
(e.g. sunday full backup)
- create snapshot of filesystem
- (system is busy: some files modified on original filesystem)
- create level 0 archive of snapshot
- Level 1 backup
(e.g. monday level 1 incremental backup)
- create snapshot of filesystem
- create level 1 archive of snapshot
- Restore backup
(e.g. tuesday afternoon after crash tuesday morning)
- restore level 0 backup
- restore level 1 backup
(files modified on sunday, between shapshot and archive creation
are now again at their pre-sunday versions. Changes made on sunday
are lost)
I have had a look at the source, and the cause seems to be that the option
newer_mtime_option is set from the creation time of the previous incremental
archive (in incremen.c:read_incr_db_01 and incremen.c:read_incr_db_2)
While I can't think of any good reason to set this option at all, except as a
(failed) attempt to avoid unnecessary work, I cannot assess the full impact of
simply removing the code in question.
The code seems to be present since the file's creation (1997-04-24) and in
that version, it has a 'FIXME' comment about the dubious nature of it. The
comment is no longer in the next version of the file, but the code stayed.
(version dated 2003-08-31, which has extensive restructuring and modification)
The following script demonstrates the behavior:
Basically, it implements the testcase outlined above
Make sure to run this in an empty directory - the script does some
indiscriminate
cleaning up.
-------------------------------------------------------------------------------
# Clean up stuff from previous tests (indiscriminate)
umount ./mnt* 2> /dev/null
rm -rf filesys* mnt* backup*
set -v
# Create & mount test filesystem
dd if=/dev/zero of=filesys bs=1k count=200 2> /dev/null
mke2fs -F -q ./filesys
mkdir mnt
mount -o loop ./filesys ./mnt
# Create files, & let them age
echo "somefile, first version" > mnt/somefile
echo "otherfile, first version" > mnt/otherfile
echo "yetanotherfile, first version" > mnt/yetanotherfile
echo "fourthfile, first version" > mnt/fourthfile
echo "fifthfile, first version" > mnt/fifthfile
sleep 1
# Start making backup: create and mount snapshot
mount -o remount -r ./mnt
cp filesys filesys-snap
mount -o remount -w ./mnt
mkdir -p mnt-snap
mount -r -o loop ./filesys-snap ./mnt-snap
# Processing backup scripts takes some time; in the mean
# time, original filesystem is in use
sleep 1
echo "somefile, second version" > mnt/somefile
rm mnt/fourthfile
sleep 1
# Backup script gets around to running tar on snapshot filesystem
tar -cvf backup.0.tar -g backup.0.list --no-check-device -C mnt-snap .
umount ./mnt-snap
# (snapshot could be removed now.)
# Usage of original filesystem continues
sleep 1
echo "otherfile, second version" > mnt/otherfile
rm mnt/fifthfile
echo "newfile, first version" > mnt/newfile
sleep 1
# Time for an incremental backup.
# Normally, this would be done using a snapshot, but for the
# sake of this test, that is not necessary
# Note that mnt/somefile was modified, but is not archived.
# The problem: it was modified in the original filesystem, *before* the
# timestamp recorded in the level 0 backup's list file
cp backup.0.list backup.1.list
tar -cvf backup.1.tar -g backup.1.list --no-check-device -C mnt .
# Additional verification that the level 1 backup is indeed incomplete:
# Restoring everything from backup
mkdir mnt2
tar -xGf backup.0.tar -C mnt2
tar -xGf backup.1.tar -C mnt2
diff mnt mnt2
-------------------------------------------------------------------------------
Output is the following:
-------------------------------------------------------------------------------
# Create & mount test filesystem
dd if=/dev/zero of=filesys bs=1k count=200 2> /dev/null
mke2fs -F -q ./filesys
mkdir mnt
mount -o loop ./filesys ./mnt
# Create files, & let them age
echo "somefile, first version" > mnt/somefile
echo "otherfile, first version" > mnt/otherfile
echo "yetanotherfile, first version" > mnt/yetanotherfile
echo "fourthfile, first version" > mnt/fourthfile
echo "fifthfile, first version" > mnt/fifthfile
sleep 1
# Start making backup: create and mount snapshot
mount -o remount -r ./mnt
cp filesys filesys-snap
mount -o remount -w ./mnt
mkdir -p mnt-snap
mount -r -o loop ./filesys-snap ./mnt-snap
# Processing backup scripts takes some time;
# in the mean time, original filesystem is in use
sleep 1
echo "somefile, second version" > mnt/somefile
rm mnt/fourthfile
sleep 1
# Backup script gets around to running tar on snapshot filesystem
tar -cvf backup.0.tar -g backup.0.list --no-check-device -C mnt-snap .
tar: ./lost+found: Directory is new
./
./lost+found/
./fifthfile
./fourthfile
./otherfile
./somefile
./yetanotherfile
umount ./mnt-snap
# (snapshot could be removed now.)
# Usage of original filesystem continues
sleep 1
echo "otherfile, second version" > mnt/otherfile
rm mnt/fifthfile
echo "newfile, first version" > mnt/newfile
sleep 1
# Time for an incremental backup.
# Normally, this would be done using a snapshot, but for the
# sake of this test, that is not necessary
# Note that mnt/somefile was modified, but is not archived.
# The problem: it was modified in the original filesystem, *before* the
# level 0 backup started
cp backup.0.list backup.1.list
tar -cvf backup.1.tar -g backup.1.list --no-check-device -C mnt .
./
./lost+found/
./newfile
./otherfile
# Additional verification that the level 1 backup is indeed incomplete:
# Restoring everything from backup
mkdir mnt2
tar -xGf backup.0.tar -C mnt2
tar -xGf backup.1.tar -C mnt2
diff mnt mnt2
Common subdirectories: mnt/lost+found and mnt2/lost+found
diff mnt/somefile mnt2/somefile
1c1
< somefile, second version
---
> somefile, first version
-------------------------------------------------------------------------------
Note: The same kind of behavior is seen when a file is modified shortly
*after* an archive was created:
Test script:
-------------------------------------------------------------------------------
# remove leftovers from previous run
rm -rf dir*
set -v
# setup directory tree & let age
mkdir dir
touch dir/{a,b,c}
sleep 1
# Create archive; Immediately thereafter, modify a file
tar -cvf dir.0.tar -g dir.0.list dir
touch dir/a
# Wait & modify more files
sleep 1
touch dir/b
# Create incremental archive.
# In general, dir/a will not be included, even though
# it was modified after the level 0 archive was created
# (i.e. I haven't seen it included, even though I assume
# that there is a chance it will be, depending on the
# timing)
cp dir.0.list dir.1.list
tar -cvf dir.1.tar -g dir.1.list dir
-------------------------------------------------------------------------------
Output of the script:
-------------------------------------------------------------------------------
# setup directory tree & let age
mkdir dir
touch dir/{a,b,c}
sleep 1
# Create archive; Immediately thereafter, modify a file
tar -cvf dir.0.tar -g dir.0.list dir
dir/
dir/a
dir/b
dir/c
touch dir/a
# Wait & modify more files
sleep 1
touch dir/b
# Create incremental archive.
# In general, dir/a will not be included, even though
# it was modified after the level 0 archive was created
# (i.e. I haven't seen it included, even though I assume
# that there is a chance it will be, depending on the
# timing)
cp dir.0.list dir.1.list
tar -cvf dir.1.tar -g dir.1.list dir
dir/
dir/b
-------------------------------------------------------------------------------
-- System Information:
Debian Release: 5.0.3
APT prefers stable
APT policy: (500, 'stable')
Architecture: i386 (i686)
Kernel: Linux 2.6.26-2-486
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash
Versions of packages tar depends on:
ii libc6 2.7-18 GNU C Library: Shared libraries
tar recommends no packages.
Versions of packages tar suggests:
ii bzip2 1.0.5-1 high-quality block-sorting file co
pn ncompress <none> (no description available)
-- no debconf information
--- End Message ---