File Backup Storage with Btrfs Snapshots

The Linux kernel 3.6 finally added a feature to btrfs which I needed to easily implement a snapshot file backup storage. This feature will be automatically enabled if the backup storage path points to a btrfs file system and btrfs supports cross-sub-volume reflinks.

A backup with snapshots works like this:

  • Every file backup is put into a separate sub-volume, i.e., a file backup with a name like “121102-1010” is not a normal folder any more. It is a sub-volume in the btrfs file system.
  • Btrfs can make snapshots of sub-volumes. On an incremental backup UrBackup creates a snapshot with the usual name like “121102-2210”. The snapshot has the contents of the last file backup. This snapshot operation is very fast, because no files have to be copied or file entries created. Btrfs does not internally create another copy of the file tree. It only creates copies of parts that we change in the future.
  • UrBackup deletes all the files in the snapshot that have changed or have been deleted since the last backup.
  • Then UrBackup loads the files that have changed or are new. If a file was changed UrBackup only writes changed parts of the file causing btrfs to only save the blocks in the file that are actually different.
  • Once the backup has to be removed UrBackup simply deletes the whole sub-volume.

This has several advantages:

  • Snapshot creation is very fast, causing faster incremental backups.
  • Deleting the file backups is way faster because not every file has to be deleted.
  • Only data that has changed in files between incremental backups is stored in the file system. This drastically reduces the storage requirements, e.g, for large database files.

The cross-device reflinks enable UrBackup to store same files which occur on different sub-volumes only once. On other filesystems this is done using hard links, but those only work on the same file system. Because the Linux kernel sees the sub-volume as a different file system the cross-device reflinks have to be used. There is no disadvantage in using them instead of hard links.

Starting a process for all currently logged in users

For silently updating the client I needed to

  1. Kill all the client GUIs (tray icons) of all users
  2. Stop the background service; Update the files and executables; Start the new background service
  3. Start the client GUI for all currently logged in users

The silent update is done by simply calling the normal NSIS installer with a parameter that makes it non-interactive. Information about how step one is handled is in the previous post. Step two was already in the Installer. Step three remained to be solved.

For that I created a NSIS plugin which checks if the current user is the SYSTEM user. If yes, it starts the executable for all currently logged in users. If not it returns zero. It is used like this:

StrCpy $0 "$INSTDIRUrBackupClient.exe"
startplugin::start
Pop $0
${If} $0 == '0'
Exec "$INSTDIRUrBackupClient.exe"
${EndIf}

Source code is here: http://download.urbackup.org/startplugin.zip
Binary is here (for NSIS Unicode): http://download.urbackup.org/startplugin_bin.zip

Killing 64bit processes from a 32bit NSIS installer

There is no 64bit version of the NSIS (Nullsoft Scriptable Install System). 64Bit processes can only be terminated from 64bit processes, so all the available NSIS plugins, such as the KillProc plugin, do not work. Additionally they do not kill the processes of all users – only those of the currently logged in users – which I wanted as well.

The problem is easily solved by packing an executable into the Installer which is then extracted and called. It is used like this in the UrBackup installer:

${If} ${RunningX64}
File "data_x64KillProc.exe"
nsExec::Exec '"$INSTDIRKillProc.exe" UrBackupClient.exe'
${Else}
File "dataKillProc.exe"
nsExec::Exec '"$INSTDIRKillProc.exe" UrBackupClient.exe'
${EndIf}

The source code of that executable is available here: http://download.urbackup.org/KillProc_src.zip
The binary files here: http://download.urbackup.org/KillProc_bin.zip
It expects only one parameter: The name of the running process to kill.

Btrfs: Experimental or approaching stable?

Thinking that btrfs should approach a stable status by now, I used it as file system for the backups on my primary test server. Well, it works well and is really fast. Compression seems to work, too.
But there was a unexpected warning during one backup. It could not create a hard link. In this case UrBackup logs a warning and copies the file.
I checked the inode number of the file that failed to link and it was hard linked nonetheless – weird: Btrfs claimed it could not hard link even though it already did it. There were also only about 500 links to that inode. I checked the file system limit for the number of hard links and discovered that btrfs supports as few as 31 hard links to the same inode in one directory.
There is a relatively new patch to raise this limitation http://lwn.net/Articles/498226/, but it has not landed in the kernel yet. This issue does not affect UrBackup that much, but nonetheless, it shows us something about the stability of btrfs.
Thus my advise: Don’t use it yet.

Status of next major version

I’m releasing UrBackup Server 0.26.1 and Client 0.40.1 soon. They do have only minor bug fixes and additionally a Russian translation.

The next major version, which will probably be 1.0, will have following new features:

First of all you will be able to start and stop backups from the server web interface.

 

Then I reorganized the settings, both on the server web interface and on the client. You can also see the new bandwidth throttling feature which can limit the bandwidth usage of the backup server, both globally and for each client.

 

I added a few features to the new internet mode, described in the last post. Per default UrBackup does not do full file backups or image backups with an internet connection, but it can be enabled. Total global backup speed and backup speeds for each client can be set separately from the local backup speed. You can e.g. use this on the client to prevent UrBackup from using all your bandwidth. Additionally to being able to encrypt the transfer over internet UrBackup can now also compress it.

 

 

 

There is a new feature which lets you archive certain backups in certain intervals. Archived backups are not deleted during cleanups, until they are not archived anymore. Additionally to the automated archival you can also manually archive and un-archive certain file backups simply by clicking on them. For now only file backups can be archived.

 

This should be the major improvements. The are some minor ones as well.

Everything except the internet mode is ready for testing, so if anyone wants to help send me a mail at martin@urbackup.org or drop by in the forums and I will upload the appropriate builds.

Internet Mode

Currently I’m working on a new internet mode for UrBackup. This means that you will be able to backup clients to a server on the internet with the upcoming new version.
This communication is of course encrypted and authenticated. It uses a shared key encryption with AES256 in CFB mode. It should be easy to configure: You just need to supply the server with its internet name/IP and the ports the clients should connect to. These settings, as well as random keys, are then pushed to the clients via the local (trusted) network. They can be manually entered on the client side as well. Then the key is pushed from the client to the server.

If you are not in the local network the client tries to connect to the internet server, if you entered something (e.g. a dns name or IP address) there. Then both check if they have the same key and if they do have the same shared key a normal connection, like if the client were in the local network, is established and backups can be performed.

I’ll now implement special options for disabling image and full file backups for clients connected via internet. Then I will implement a special, block based file (rsync like) transfer mode which will be used for those clients and which transfers less data in some scenarios.

Then you can look forward to backup archival and more detailed backup retention capabilities, which I’ll be working on next.

I’m better than you, Explorer

A long time ago I fixed a bug, where UrBackup Server on Windows could not backup files with a path name longer than 255 characters. It’s here:
https://sourceforge.net/apps/mantisbt/urbackup/view.php?id=2
Yesterday I reinstalled a test server and today I wanted to delete the old UrBackup backup folder. It threw error messages like you see in the screenshot.
Apparently the Windows Explorer (even in Windows Server 2008R2) cannot delete files with path names longer than 255 characters. And contrary to the error message you can also not move or rename them. You have to install some alternative file manager, to get rid of these files or shorten directory names such that the path length is smaller than 256 characters. Or let UrBackup delete them. In my case: I just left the folder there. I do not care. It’s a test server anyway.

Well done, Explorer.

Desktop GNU/Linux: You Have to Love It

You know those parents that love their child so much, they do not see how bad their child in reality really is. I think you have to have a similar relationship to GNU/Linux if you really want to use it as your desktop operating system. That does not mean, that it is generally bad. Just like the child it has its strong points. E.g. the kernel. I am an avid fan of Linus Torvals autocratic management of kernel development. And have no doubt, it is autocratic. He decides in which direction the kernel moves and the success the kernel has had, is in my opinion, largely caused by his pragmatic style.
One could say that the success of the kernel part of GNU/Linux was caused by his strong leadership. And in areas where the operating system does less well, there is a lack of leadership.
For example the window managers. Mainly there is KDE and Gnome. They have different UI frameworks and it is already kind of sacrilegious to use a KDE application in Gnome, because it uses more memory. But additionally to that, this application won’t have the same style.
Of course they have different systems for start menu entries, tray icons, settings and pretty much everything you can think of. Thankfully there is kind of a standardization body named FreeDesktop.org. The problem – as with every standardization process – is that it moves slowly and the resulting standard does not define all useful scenarios. Thus the new features are sometimes still not accessible in a common way.
We speak here of a fragmentation within the operating system: In order to make a GNU/Linux application which uses UI and has a native look&fell you need to do everything twice now. Once with GTK and once with Qt (used by KDE).
But this does not end there: You have to think of the zillion other window managers out there. XFCE, Unity, Fluxbox you name them. Thankfully most are based on either GTK or Qt. Nevertheless: In each one of those, your application may not display its tray icon correctly.
And as you perhaps know: The UrBackup Client displays a tray icon.

Anticipating all these complications I am using a cross platform toolkit for the UrBackup Client: wxWidgets. Theoretically it is available for both Qt and GTK. As every level of abstraction this gives you slightly less power, but the application is simple right?
Well, try to show such a balloon popup on windows and we can talk. But otherwise it really worked mostly well.
So I compiled the client in Debian and checked if everything was working. And it did. Then – to test it in a more popular desktop distribution – I downloaded Ubuntu.
The tray icon did not show up. Turns out Unity has a whitelist of apps that can show tray icons. This annoys many users as e.g. Skype won’t show up any more. You can of course allow tray icons by editing some arcane setting somewhere. But this is not something the end-user should do right?
But it gets worse: After I edited that setting to allow all applications, it still did not work.
Turns out they did not like the FreeDesktop.org standard any more and made their own. In order for it to work I would have to use a separate library (libappindicator) to display the tray icon. Libappindicator only works with Unity on Ubuntu, so I would have to make and release a different version of my application for Ubuntu. Not acceptable.
I’ll repeat: I’m using libwxgtk2.8 which is officially part of Ubuntu to display a tray icon. This does not work because wxWidgets uses the FreeDesktop.org protocol to display the tray icon which Ubuntu decided to abandon. The wxWidget guys (understandably) seem to not want to fix that issue in wxWidgets 2.9, probability because they do not want to implement something only for Ubuntu, as well.
Simultaneously the Ubuntu fork Mint which does not use Unity is becoming more popular. So perhaps this specific problem will resolve itself this way. This issue certainly seems to have caused some waves: http://blogs.gnome.org/bolsh/2011/03/11/lessons-learned/
Bottom line of that article is that the FreeDesktop.org standardization process is broken. And this is just one example of the kind of fragmentation we developers have to think about.
Compare that to Windows where the program that displayed tray icons in Windows 95 probably still can display it in Windows 7. After 11 years! Too easy.

I said at the beginning that a strong leadership is needed just like for the Linux kernel. This strong leadership would have to coordinate efforts in different window managers and in different distributions. This is difficult because the distribution is the thing the users sees and holds responsible for something that is not working. This is also the reason why you install packets from your distribution. Because doing it any other way probably causes something to not work or even break. Because only distributors are accountable it is very difficult to establish something like FreeDesktop.org – an inter distribution standardization body. There is simply no incentive to play along nicely, especially since standardization processes tend to be lengthy and difficult and you want your distribution to be progressive and modern.
The only way I see this dilemma could be solved, is by having one distribution which the majority of GNU/Linux (desktop) users use. I hoped this could be Ubuntu lead by Mark Shuttleworth. But Ubuntu is sadly moving into the wrong direction at the moment.
Additionally to that. It is moving too fast. Given some time and persuasion Gnome probability would have adapted the libappindicator interface and I would not have this problem now.
Unity is – in my opinion – really crappy. I did not even find out how to switch applications without alt+tabbing and had to use the windows key to start one (start menu where are you?). If this is someone’s idea of usability and end user friendliness then I give up all remaining hope for Ubuntu.

Given all that, I have decided to not start building any packages for Ubuntu/Debian. The support matrix would just be too great and I already named one issue. If you really love Linux that much that you use it as a desktop operating system, I leave you to grab the source code and build it yourself – no guarantees that it works on your specific distribution in your window manager. Thankfully the back-end part – the part that does the backups – is not dependant on any flaky UI/Window manager stuff and so should be there to stay. If the frontend does not work for you (aka it does not display the tray icon) you can always set the directories it backs up on the server.
I hope that some time in the future someone from a distribution picks up that code and builds working packages for that distribution. But that someone won’t be me. This far, and no further! Sorry, Linux. I will still love you. But only as my server child. Not a desktop one.

No BerkeleyDB backend

My previous announcement that there will be a Berkeley DB backend was too hasty. I ran into some (for now) unsolvable problems. I posted them into the official Oracle forums but seem to get no reply there:
https://forums.oracle.com/forums/thread.jspa?threadID=2307258&tstart=15

The final nail in the coffin was, that the advertised increased concurrency was not present. In my tests it performed even worse then SQLite in WAL journal mode. That and the perceived instability (I had a database corruption once) shine a pretty bad light on Berkeley DB. Maybe the SQL layer for Berkeley DB which I used is not stable yet?

On the plus side the tables I had to denormalize cause a significant speed increase for SQLite as well, so all this work was not for nothing.
Maybe I will revisit Berkeley DB in a few months/years.

MSI installers with next version

I finally bit the bullet and worked on MSI installers for Windows. As anticipated it was not easy. I used WiX.

They do have some advantages over an installer distributed as “exe”:

  • One can add the Microsoft Visual Studio runtime as a “merge module” thus avoiding starting it in the installer manually
  • Apparently installing centralized on domain computers is easier

On the negative side:

  • No shared 32/64 bit MSIs are possible. That means the user has to select the right one before downloading
  • You cannot add custom commands as easily as in NSIS

I think I will only publish 64bit MSIs for now. Most Windows Servers should be 64bit now anyway and I will still publish the “old” installers for users of older and 32bit systems.