About lessfs-2.0.0-prealpha2
Lessfs-2.0.0 pre-alpha2 is a development release only. It’s only purpose is to show what is coming and to receive some early feedback. Do not use this code for valuable data.
Lessfs-2.0.0 pre-alpha2 implements some basic snapshot code. A number of functions are either completely removed, like hardlinks, others or not or only partially implemented like truncation.
How to use this code.
Untar the code and chdir to it.
cd lessfs-2.0.0-palpha2 ./configure; make
You can use the same lessfs configuration file that you use for the lessfs-1.x series.
Format and mount the filesystem
./mklessfs -f -c /etc/lessfs.cfg ./lessfs /fuse -o configfile=/etc/lessfs.cfg Copy a file to the filesystem root@saturn:/tmp/lessfs-2.0.0-palpha2# cp Makefile /fuse/ root@saturn:/tmp/lessfs-2.0.0-palpha2# ls -al /fuse/ total 87 drwxr--r-- 4 root root 4096 2011-01-29 21:50 . drwxr-xr-x 32 root root 4096 2011-01-27 23:07 .. drwxr--r-- 5 root root 4096 2011-01-29 21:50 .lessfs -rw-r--r-- 1 root root 83503 2011-01-29 21:50 Makefile
Now let’s create a snapshot:
root@saturn:/tmp/lessfs-2.0.0-palpha2# telnet localhost 100 Trying ::1... Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. >snapshot create TEST create snapshot 2 with label TEST +OK >exit +OK bye
Now we are going to remove the copied data from the root of the filesystem and retrieve it from the snapshot:
root@saturn:/tmp/lessfs-2.0.0-palpha2# rm /fuse/Makefile root@saturn:/tmp/lessfs-2.0.0-palpha2# cat /fuse/.snapshot-TEST/Makefile | tail -1 .NOEXPORT: root@saturn:/tmp/lessfs-2.0.0-palpha2# ls -al /fuse/.snapshot-TEST/ total 84 drwxr--r-- 4 root root 4096 2011-01-29 21:50 . drwxr--r-- 4 root root 4096 2011-01-29 21:52 .. drwxr--r-- 5 root root 4096 2011-01-29 21:50 .lessfs -rw-r--r-- 1 root root 83503 2011-01-29 21:50 Makefile
Implementation details
Lessfs-1.x used to store the internal structure of a file as:
(key) inode-blocknr : (value) hash
With lessfs-2.x this has changed to:
(key) inode-blocknr : (value) btree
The btree contains: (key) snapshotnr : (value) hash
Now all this is pretty straight forward. The difficult part is how to expose the snapshot data to the filesystem without the need to remount lessfs. As you can see lessfs now shows the snapshots in the root of the filesystem as : .snap-NAME
As soon as you enter .snap-NAME the context of the filesystem will have to change to the snapshot in that .snap-NAME resembles. Fuse does have a notion about contexts but this mechanism is not usable to maintain snapshot context.
After some experimenting I came up with the following solution to the problem.
An inode has a length of 64 bits of which we reserve 20 bits for snapshots, which leaves 44 bits for the inodes themselves. Reserving 20 bits for snapshots will mean that Lessfs can hold 1048576 snapshots.
Now for the clever stuff. When you enter a snapshot directory this directory should refer to the ‘real’ directory. Let me illustrate this with an example:
We create : /mydir/myfile after which we create a snapshot with name TEST and delete myfile. Let’s assume that snapshot TEST has snapshot number 5. When we want to restore the file we chdir to /.snapshot-TEST then /.snapshot-TEST should refer to / which has inode 1 and snapshot context 5.
To be able to retrieve the snapshot number as well as the inode number lessfs changes the inode number 1 to
70368744177668 What has happened is that the 20 bits reserved for the snapshot number have now been added to the inode. The inode now appears to be completely different while in fact it is just a combination of the snapshot and inode number. This makes it possible to retrieve the snapshot number for any given inode at any moment.
Lessfs-2 has two routines that take care of the inode-snapshot conversions:
unsigned long inode_to_snapinode(unsigned int snapshot, fuse_ino_t inode);
INOSNAP snapinode_to_inode(fuse_ino_t snap_inode);
You can find these routines in lib_common.c
Problems to solve
The problem with the approach that I just explained will be garbage collection when we remove a snapshot. As long as we remove or change data that is created and removed within the same context everything works identical to lessfs-1.x
However when we need to purge a snapshot with higher snapshots in existence the fun begins. Now every inode that has references to the snapshot needs to be checked. And the blocks that are no longer in use can be put on the freelist.
Without a doubt this will be a slow process that can be very time consuming. I am afraid that the jury is still out on this one…..