Recent changes to this wiki:

point to new locations
diff --git a/genbackupdata.mdwn b/genbackupdata.mdwn
index 8c04c4d..eee4d30 100644
--- a/genbackupdata.mdwn
+++ b/genbackupdata.mdwn
@@ -1,14 +1 @@
-genbackupdata is a program to generate test data for backup software testing.
-
-* [[README]]
-* [[NEWS]]
-* [[manpage|genbackupdata.1.txt]]
-* [Using stuff on code.liw.fi](http://liw.fi/code/)
-* Version control: `bzr get http://code.liw.fi/genbackupdata/bzr/trunk/`
-* Tarball and Debian packages: 
-  <http://code.liw.fi/debian/pool/main/g/genbackupdata/>
-* [Bugs](http://liw.fi/genbackupdata/bugs/)
-
-See also:
-
-* [seivot](http://liw.fi/seivot/)
+Moved to [liw.fi](http://liw.fi/genbackupdata/).
diff --git a/obnam.mdwn b/obnam.mdwn
index 28c4247..4ef83bc 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -1,44 +1 @@
-Obnam is an **easy, secure backup program.**
-Backups can be stored on local hard disks, 
-or online via the 
-[SSH SFTP](http://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol) protocol.
-The backup server, if used, does not require any special software,
-on top of SSH.
-
-Some **features** that may interest you:
-
-* **Snapshot** backups. Every generation looks like a complete snapshot,
-  so you don't need to care about full versus incremental backups, or
-  rotate real or virtual tapes.
-* Data **de-duplication**, across files, and backup generations. If the
-  backup repository already contains a particular chunk of data, it will
-  be re-used, even if it was in another file in an older backup
-  generation. This way, you don't need to worry about moving around large
-  files, or modifying them.
-* **Encrypted** backups, using GnuPG.
-* **Push** or **pull** operation, depending on what you need. You can run
-  Obnam on the client, and push backups to the server, or on the server,
-  and pull from the client over SFTP.
-
-See the [[tutorial]] for examples of how to use Obnam.
-  
-* [[Status and support|status]]
-* [[Download]]
-* [[Contact]]
-* [[Bugs]]
-
-Documentation
--------------
-
-* [[README]] (updated at release time)
-* [[NEWS]] (updated at release time)
-* [[obnam manual page|obnam.1.txt]]
-* [[obnam-benchmark manual page|obnam-benchmark.1.txt]]
-* [[Roadmap for 1.0|roadmap-for-1.0]]
-* [[FAQ]]
-
-Links
------
-
-* [Cache Directory Caching Standard](http://www.bford.info/cachedir/)
-
+Moved to [liw.fi](http://liw.fi/obnam/).

replace with link to liw.fi
diff --git a/index.mdwn b/index.mdwn
index 42324d1..70aaa5e 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -1,4 +1 @@
-This will be the new braawi.org.
-
-* [[obnam]]
-* [[genbackupdata]]
+Moved to [liw.fi](http://liw.fi/).

move stuff to liw.fi
diff --git a/genbackupdata/NEWS.mdwn b/genbackupdata/NEWS.mdwn
deleted file mode 100644
index 4bede84..0000000
--- a/genbackupdata/NEWS.mdwn
+++ /dev/null
@@ -1,21 +0,0 @@
-NEWS for genbackupdata
-======================
-
-Version 1.5, released 2011-06-12
---------------------------------
-
-* Fix genbackupdatalib to work better with pydoc.
-* Change to use newer cliapp API for adding new settings. This avoids
-  the deprecated old API.
-
-Version 1.3.1, released 2011-02-02
-----------------------------------
-
-* Fix setup.py so that the genbackupdatalib Python library is
-  included in the package.
-
-Version 1.3, released 2011-02-01
---------------------------------
-
-* Rewrite from scratch, becaue the old code was hard to test.
-  It was also full of features nobody uses. New code is small.
diff --git a/genbackupdata/README.mdwn b/genbackupdata/README.mdwn
deleted file mode 100644
index 2d84a88..0000000
--- a/genbackupdata/README.mdwn
+++ /dev/null
@@ -1,43 +0,0 @@
-genbackupdata
-=============
-
-genbackupdata creates or modifies directory trees in ways that simulate
-real filesystems sufficiently well for performance testing of backup
-software. For example, it can create files that are a mix of small text
-files and big binary files, with the binary files containing random
-binary junk which compresses badly. This can then be backed up, and
-later the directory tree can be changed by creating new files, modifying
-files, or deleting or renaming files. The backup can then be run again.
-
-The output is deterministic, such that for a given set of parameters the
-same output always happens. Thus it is more efficient to distribute
-genbackupdata and a set of parameters between people who wish to
-benchmark backup software than distributing very large test sets.
-
-Also included are a couple of benchmark programs I've written to measure
-aspects of the work genbackupdata does:
-
-* binaryjunk.py compares various ways of generating random binary data
-
-* createfiles.py compares various directory structures when creating
-  lots of new files
-
-The home page is: http://braawi.org/genbackupdata/
-
-Legalese:
-
-  Copyright (C) 2007-2011  Lars Wirzenius <liw@iki.fi>
- 
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
- 
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
- 
-  You should have received a copy of the GNU General Public License along
-  with this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
diff --git a/genbackupdata/genbackupdata.1.txt b/genbackupdata/genbackupdata.1.txt
deleted file mode 100644
index 2d707ca..0000000
--- a/genbackupdata/genbackupdata.1.txt
+++ /dev/null
@@ -1,125 +0,0 @@
-GENBACKUPDATA(1)					      GENBACKUPDATA(1)
-
-
-
-NAME
-       genbackupdata - generate backup test data
-
-SYNOPSIS
-       genbackupdata [options] directory
-
-DESCRIPTION
-       genbackupdata  generates  test  data  sets  for	performance testing of
-       backup software.  It creates a directory tree filled with files of dif‐
-       ferent  sizes.	The  total  size and the distribution of sizes between
-       small and big are configurable.	The program can also modify an	exist‐
-       ing  directory  tree  by creating new files, and deleting, renaming, or
-       modifying existing files.  This can be used to generate test  data  for
-       successive generations of backups.
-
-       The  program  is  deterministic:  with a given set of parameters (and a
-       given pre-existing directory tree), it always creates the same  output.
-       This  way,  it  is  possible to reproduce backup tests exactly, without
-       having to distribute the potentially very large test sets.
-
-       The data set consists of plain files and directories.  Files are either
-       small  text  files  or big binary files.  Text files contain the "lorem
-       ipsum" stanza, binary files contain randomly  generated	byte  streams.
-       The  percentage of file data that is small text or big binary files can
-       be set, as can the sizes of the respective file types.
-
-       Files and directories are named "fileXXXX" or "dirXXXX",  where	"XXXX"
-       is  a  successive  integer, separate successions for files and directo‐
-       ries.  There is an upper limit to how many files a directory  may  con‐
-       tain.  After the file limit is reached, a new sub-directory is created.
-       The first set of files go into the root directory of the test set.
-
-       You have to give one of the options --create,  --delete,  --rename,  or
-       --modify  for  the program to do anything.  You can, however, give more
-       than one of them, if DIR already exists.  (Giving the same option  more
-       than once means that only the last instance is counted.)  (DIR) is cre‐
-       ated if it doesn't exist already.
-
-OPTIONS
-       When giving file sizes (SIZE below), the default unit is a  byte.   The
-       suffixes  "K",  "M", "G", and "T" (upper or lower) can be used to refer
-       to kibi-, mebi-, gibi-, and tebibytes, respectively (2 to the power  of
-       10, 20, 30, or 40).
-
-       When  giving  file counts (COUNT below), the same suffixes may be used,
-       but then they will refer to kilo-, mega-, giga-, and tera- (10  to  the
-       power of 3, 6, 9, or 12).
-
-       When  referring	to a size or file count, when it makes sense to give a
-       relative size, the suffix "%" may be used to indicate percentage.
-
-       Numbers may be integer or floating point (using the  locale's  floating
-       point syntax).
-
-       --seed=SEED
-	      Set  the	(integer)  seed to the psuedo-random number generator.
-	      Default: 0.
-
-       --max-count=COUNT
-	      Set the maximum number of files in a directory.  Default: 256.
-
-       -p, --percentage-text-data=PERCENTAGE
-	      Set the percentage of file data (not file count) in  newly  cre‐
-	      ated  files  (not modified files) allocated to small text files.
-	      Default: 10%.
-
-       -t, --text-file-size=SIZE
-	      Set the  size  of  text  files.	Cannot	be  a  relative  size.
-	      Default: 10 KiB.
-
-       -b, --binary-file-size=SIZE
-	      Set  the	size  of  binary  files.   Cannot  be a relative size.
-	      Default: 10 MiB.
-
-       -c, --create=SIZE
-	      Create SIZE amount of new files.	A relative  amount  refers  to
-	      the  size  of  the  pre-existing	files.	 DIR  is created if it
-	      doesn't exist already.  Default: 0.
-
-       -d, --delete=COUNT
-	      Remove COUNT pre-existing files.	A relative  amount  refers  to
-	      the  number  of  pre-existing  files.   DIR  must exist already.
-	      Default: 0.
-
-       -r, --rename=COUNT
-	      Rename COUNT pre-existing files to new names,  without  changing
-	      the  contents.   A  relative amount refers to the number of pre-
-	      existing files.  DIR must exist already.	Default: 0.
-
-       -l, --link=COUNT
-	      Create COUNT links to pre-existing files.
-
-       -m, --modify=SIZE
-	      Modify pre-existing files by appending to them.  The new data is
-	      divided into text and binary data as for --create, but no regard
-	      is given as to whether the file that receives the new data is  a
-	      text  or binary file.  Files are picked by random among the pre-
-	      existing ones, and the size is increased according to  the  per‐
-	      centage  set  by --modify-percentage.  A relative SIZE refers to
-	      the total size of pre-existing files.  DIR must  exist  already.
-	      Default: 0.
-
-       --modify-percentage=PERCENT
-	      Set  the	number of percent each file is grown when using --mod‐
-	      ify.  Note that zero size files are not grown (X% of 0 is always
-	      0).  Default: 10%.
-
-EXAMPLES
-       Create data for the first generation of a backup:
-
-	      genbackupdata --create=10G testdir
-
-       Modify an existing set of backup data to create a new generation:
-

(Diff truncated)
remove more old benchmark stuff
diff --git a/obnam/benchmarks.mdwn b/obnam/benchmarks.mdwn
deleted file mode 100644
index 9be74c6..0000000
--- a/obnam/benchmarks.mdwn
+++ /dev/null
@@ -1,26 +0,0 @@
-Benchmark results for obnam
-===========================
-
-Live data size 1 GB
--------------------
-
-Backup:
-
-[[!table file="obnam/benchmarks/backup-1000000000.csv"]]
-
-Restore:
-
-[[!table file="obnam/benchmarks/restore-1000000000.csv"]]
-
-List:
-
-[[!table file="obnam/benchmarks/list_files-1000000000.csv"]]
-
-Forget:
-
-[[!table file="obnam/benchmarks/forget-1000000000.csv"]]
-
-Individual benchmark results
-----------------------------
-
-[[!inline pages='obnam-*.mdwn']]

remove ancient benchmarks
diff --git a/obnam/benchmarks-alpha/891-176.mdwn b/obnam/benchmarks-alpha/891-176.mdwn
deleted file mode 100644
index f4cb9cb..0000000
--- a/obnam/benchmarks-alpha/891-176.mdwn
+++ /dev/null
@@ -1,89 +0,0 @@
-[[!meta title="Obnam r891 with btree r176"]]
-
-Benchmark result: Obnam r891 with btree r176
--------------------------------------------------------
-
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-0-cumulative.txt">obnam-100000m-0-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-0.log">obnam-100000m-0.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-0.prof">obnam-100000m-0.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-0-time.txt">obnam-100000m-0-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-1-cumulative.txt">obnam-100000m-1-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-1.log">obnam-100000m-1.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-1.prof">obnam-100000m-1.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-1-time.txt">obnam-100000m-1-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-2-cumulative.txt">obnam-100000m-2-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-2.log">obnam-100000m-2.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-2.prof">obnam-100000m-2.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-2-time.txt">obnam-100000m-2-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-3-cumulative.txt">obnam-100000m-3-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-3.log">obnam-100000m-3.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-3.prof">obnam-100000m-3.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-3-time.txt">obnam-100000m-3-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-4-cumulative.txt">obnam-100000m-4-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-4.log">obnam-100000m-4.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-4.prof">obnam-100000m-4.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m-4-time.txt">obnam-100000m-4-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100000m.seivot">obnam-100000m.seivot</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-0-cumulative.txt">obnam-10000m-0-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-0.log">obnam-10000m-0.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-0.prof">obnam-10000m-0.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-0-time.txt">obnam-10000m-0-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-1-cumulative.txt">obnam-10000m-1-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-1.log">obnam-10000m-1.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-1.prof">obnam-10000m-1.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-1-time.txt">obnam-10000m-1-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-2-cumulative.txt">obnam-10000m-2-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-2.log">obnam-10000m-2.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-2.prof">obnam-10000m-2.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-2-time.txt">obnam-10000m-2-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-3-cumulative.txt">obnam-10000m-3-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-3.log">obnam-10000m-3.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-3.prof">obnam-10000m-3.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-3-time.txt">obnam-10000m-3-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-4-cumulative.txt">obnam-10000m-4-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-4.log">obnam-10000m-4.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-4.prof">obnam-10000m-4.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m-4-time.txt">obnam-10000m-4-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-10000m.seivot">obnam-10000m.seivot</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-0-cumulative.txt">obnam-1000m-0-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-0.log">obnam-1000m-0.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-0.prof">obnam-1000m-0.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-0-time.txt">obnam-1000m-0-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-1-cumulative.txt">obnam-1000m-1-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-1.log">obnam-1000m-1.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-1.prof">obnam-1000m-1.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-1-time.txt">obnam-1000m-1-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-2-cumulative.txt">obnam-1000m-2-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-2.log">obnam-1000m-2.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-2.prof">obnam-1000m-2.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-2-time.txt">obnam-1000m-2-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-3-cumulative.txt">obnam-1000m-3-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-3.log">obnam-1000m-3.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-3.prof">obnam-1000m-3.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-3-time.txt">obnam-1000m-3-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-4-cumulative.txt">obnam-1000m-4-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-4.log">obnam-1000m-4.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-4.prof">obnam-1000m-4.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m-4-time.txt">obnam-1000m-4-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-1000m.seivot">obnam-1000m.seivot</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-0-cumulative.txt">obnam-100m-0-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-0.log">obnam-100m-0.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-0.prof">obnam-100m-0.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-0-time.txt">obnam-100m-0-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-1-cumulative.txt">obnam-100m-1-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-1.log">obnam-100m-1.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-1.prof">obnam-100m-1.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-1-time.txt">obnam-100m-1-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-2-cumulative.txt">obnam-100m-2-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-2.log">obnam-100m-2.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-2.prof">obnam-100m-2.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-2-time.txt">obnam-100m-2-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-3-cumulative.txt">obnam-100m-3-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-3.log">obnam-100m-3.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-3.prof">obnam-100m-3.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-3-time.txt">obnam-100m-3-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-4-cumulative.txt">obnam-100m-4-cumulative.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-4.log">obnam-100m-4.log</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-4.prof">obnam-100m-4.prof</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m-4-time.txt">obnam-100m-4-time.txt</a>
-* <a href="/obnam/benchmarks/891-176/obnam-100m.seivot">obnam-100m.seivot</a>
diff --git a/obnam/benchmarks-alpha/891-176/obnam-100000m-0-cumulative.txt b/obnam/benchmarks-alpha/891-176/obnam-100000m-0-cumulative.txt
deleted file mode 100644
index f9bc6ba..0000000
--- a/obnam/benchmarks-alpha/891-176/obnam-100000m-0-cumulative.txt
+++ /dev/null
@@ -1,2707 +0,0 @@
-Mon Nov 15 23:13:22 2010    obnam.prof
-
-         1963342555 function calls (1936913878 primitive calls) in 12188.355 CPU seconds
-
-   Ordered by: cumulative time
-
-   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
-        1    0.000    0.000 12188.387 12188.387 <string>:1(<module>)
-        1    0.000    0.000 12188.387 12188.387 obnam:26(main)
-        1    0.000    0.000 12188.385 12188.385 app.py:108(run)
-        1    0.000    0.000 12187.599 12187.599 interp.py:28(execute)
-        1   16.473   16.473 12187.599 12187.599 backup_plugin.py:45(backup)
-  1033000   45.550    0.000 6165.356    0.006 backup_plugin.py:194(backup_file_contents)
-  2160176    6.357    0.000 6132.387    0.003 store.py:73(helper)
-  4405222   18.992    0.000 4974.286    0.001 tree.py:215(insert)
-6833415/4405217   98.924    0.000 4933.100    0.001 tree.py:247(_insert_into_index)
-  1037036    4.263    0.000 4835.927    0.005 backup_plugin.py:188(backup_metadata)
-  1037174    7.780    0.000 4820.337    0.005 store.py:909(create)
-  1037174   25.078    0.000 4753.863    0.005 store.py:436(create)
-  4405217   29.094    0.000 4145.134    0.001 tree.py:287(_insert_into_leaf)
-  1037043    6.286    0.000 3936.151    0.004 store.py:462(set_metadata)
-  3678214 3685.813    0.001 3723.389    0.001 vfs_local.py:28(read)
- 11253884   14.743    0.000 3272.800    0.000 tree.py:119(put_node)
- 11253911   28.327    0.000 3258.057    0.000 nodestore_disk.py:269(put_node)
-   560850    2.502    0.000 3206.492    0.006 nodestore_disk.py:132(_push_oldest)
-   560850    8.022    0.000 3202.307    0.006 nodestore_disk.py:276(_really_put_node)
- 11253911   44.935    0.000 3133.411    0.000 nodestore_disk.py:120(put)
-   651412 3062.101    0.005 3062.101    0.005 {zip}
-   560850    4.807    0.000 2768.952    0.005 codec.py:120(encode)
-   560747   46.192    0.000 2762.099    0.005 codec.py:57(encode_leaf)
-  1024000    2.556    0.000 1157.456    0.001 store.py:1030(set_file_chunks)
-  1024000   11.732    0.000 1154.900    0.001 store.py:488(set_file_chunks)
-  1037037   14.418    0.000  974.044    0.001 backup_plugin.py:119(find_files)
-  4405217   13.361    0.000  802.554    0.000 tree.py:123(_leaf_size)
-  4405217  622.343    0.000  786.867    0.000 codec.py:52(leaf_size)
- 23282235   32.186    0.000  785.967    0.000 tree.py:115(get_node)
- 23282257   33.136    0.000  753.780    0.000 nodestore_disk.py:286(get_node)
- 58339199  494.106    0.000  703.286    0.000 bsearch.py:27(bsearch)
-  1033000    4.218    0.000  659.785    0.001 tree.py:432(remove_range)
-1964017/1033000   57.045    0.000  651.203    0.001 tree.py:442(_remove_range_from_index)
-  3501037   12.573    0.000  587.086    0.000 store.py:62(helper)
-  3197453    9.488    0.000  583.807    0.000 tree.py:128(lookup)
-8175613/3197453   38.802    0.000  568.597    0.000 tree.py:140(_lookup)
-  3497003   10.233    0.000  566.323    0.000 hooks.py:83(call)
-  3497003    9.482    0.000  556.089    0.000 hooks.py:47(call_callbacks)
-  2464000   12.164    0.000  518.076    0.000 backup_plugin.py:227(backup_file_chunk)
-  4530001   75.750    0.000  507.739    0.000 status.py:63(__setitem__)
-  4928004  501.312    0.000  501.312    0.000 {method 'update' of '_hashlib.HASH' objects}
-    90561    1.556    0.000  498.396    0.006 codec.py:126(decode)
-    90228   38.370    0.000  491.511    0.005 codec.py:66(decode_leaf)
- 12306883  239.505    0.000  462.096    0.000 {method 'join' of 'str' objects}
-  1033001    4.741    0.000  359.835    0.000 backup_plugin.py:160(needs_backup)
-  1033001   17.927    0.000  349.725    0.000 store.py:899(get_metadata)
-  1033001    4.938    0.000  331.798    0.000 store.py:458(get_metadata)
-  2464000   11.323    0.000  323.124    0.000 terminal_status_plugin.py:70(data_uploaded_cb)
-   560996    2.391    0.000  285.595    0.001 store.py:143(write_file)
- 14579486   51.070    0.000  283.222    0.000 nodes.py:77(add)
-   560996   13.315    0.000  283.204    0.001 vfs_local.py:159(overwrite_file)
-  2464004    8.574    0.000  276.024    0.000 store.py:692(checksum)
-  1037175   39.403    0.000  275.852    0.000 metadata.py:83(read_metadata)
- 52294000   63.366    0.000  242.979    0.000 widget.py:46(__str__)
- 13336738   48.754    0.000  238.308    0.000 nodes.py:93(remove)
-   561022    9.774    0.000  226.705    0.000 vfs_local.py:181(_write_to_tempfile)
-  1033000   12.108    0.000  223.483    0.000 terminal_status_plugin.py:60(found_file_cb)
-  2464000    4.858    0.000  222.695    0.000 store.py:974(find_chunks)
-  2464000   21.025    0.000  217.837    0.000 store.py:545(find)
- 45300001   64.565    0.000  217.658    0.000 status.py:75(<genexpr>)
- 11811611   28.785    0.000  198.057    0.000 nodes.py:145(find_key_for_child_containing)
-    69/46    0.000    0.000  163.310    3.550 store.py:47(helper)
-  2468035    5.499    0.000  159.375    0.000 tree.py:151(lookup_range)
-4938436/2468035   26.561    0.000  153.875    0.000 tree.py:162(_lookup_range)
-       93    0.001    0.000  150.617    1.620 forest.py:75(commit)
-       23    0.001    0.000  150.616    6.549 store.py:815(commit_host)
-       93    0.000    0.000  148.310    1.595 nodestore_disk.py:273(push_upload_queue)
-       93    0.047    0.001  148.309    1.595 nodestore_disk.py:140(push)
- 23282257   79.652    0.000  138.520    0.000 lru.py:88(get)
-       23    0.000    0.000  137.270    5.968 store.py:354(commit)
-  1037175  114.180    0.000  114.180    0.000 {grp.getgrgid}
-    90000    1.068    0.000  106.830    0.001 store.py:994(put_chunk_group)
- 15605878   17.583    0.000  105.990    0.000 tree.py:207(_shadow)
-  1667613  105.149    0.000  105.149    0.000 {posix.remove}
-175573628/159961086   84.430    0.000  100.994    0.000 {len}
-   545571    1.148    0.000   98.937    0.000 store.py:152(remove_file)
-   545595    1.527    0.000   97.790    0.000 vfs_local.py:88(remove)
- 11344472   53.640    0.000   97.352    0.000 lru.py:72(add)
-  8369645   17.901    0.000   92.837    0.000 store.py:320(key)
-  2403229   11.290    0.000   91.323    0.000 tree.py:506(_remove_range_from_leaf)
-12110/4038    2.933    0.000   88.348    0.022 vfs.py:172(depth_first)
-   560998   47.584    0.000   85.591    0.000 vfs_local.py:36(write)
- 35957188   40.537    0.000   84.415    0.000 nodestore_disk.py:327(get_refcount)
-   561022    1.238    0.000   81.910    0.000 tempfile.py:259(mkstemp)
-   561022    7.352    0.000   80.672    0.000 tempfile.py:219(_mkstemp_inner)
-    90607    0.402    0.000   78.442    0.001 store.py:140(read_file)
- 10174271   22.836    0.000   78.099    0.000 tree.py:519(increment)
-    90607    1.323    0.000   78.040    0.001 vfs_local.py:135(cat)
- 10167662   21.326    0.000   65.194    0.000 tree.py:524(decrement)
-  6994000   48.649    0.000   61.781    0.000 bytespeed.py:37(format)
-  3115605   60.953    0.000   60.953    0.000 {_obnam.fadvise_dontneed}
- 20350603   23.736    0.000   59.195    0.000 nodestore_disk.py:330(set_refcount)

(Diff truncated)
mark bug fixed
diff --git a/obnam/bugs/avoid-hash-collisions.mdwn b/obnam/bugs/avoid-hash-collisions.mdwn
index 5fbfc81..eacb9d7 100644
--- a/obnam/bugs/avoid-hash-collisions.mdwn
+++ b/obnam/bugs/avoid-hash-collisions.mdwn
@@ -13,3 +13,5 @@ Three modes are needed:
 
 --liw
 
+
+[[done]]

remove ancient and now-pointless benchmark results
diff --git a/obnam/benchmarkreport.mdwn b/obnam/benchmarkreport.mdwn
deleted file mode 100644
index a2437ad..0000000
--- a/obnam/benchmarkreport.mdwn
+++ /dev/null
@@ -1,294 +0,0 @@
-
-[[!meta title="Obnam benchmark archive"]]
-
-Obnam+btree benchmark archive
-====
-
-This page lists results of benchmark runs of [[Obnam]],
-done by <a href="http://liw.fi/">Lars Wirzenius</a>.
-See [[the obnam benchmark page|benchmarkspec]]
-for information on how the benchmark is set up. 
-This page has summarizes results of each benchmark run,
-so they can be compared.
-
-Note that this page reports old benchmarks, from the ALPHA
-era, and is no longer representative of what is really going on.
-
-Size 100.0 MiB, increment 10.0 MiB
-----
-
-<table>
-<tr>
-    <th>obnam</th>
-    <th>btree</th>
-    <th>gen0</th>
-    <th>slowest inc</th>
-</tr>
-<tr>
-<td>891</td>
-<td>176</td>
-<td>183.5 Mbit/s</td>
-<td>45.4 Mbit/s</td>
-</tr>
-<tr>
-<td>893</td>
-<td>177</td>
-<td>159.4 Mbit/s</td>
-<td>36.1 Mbit/s</td>
-</tr>
-<tr>
-<td>894</td>
-<td>177</td>
-<td>138.8 Mbit/s</td>
-<td>41.3 Mbit/s</td>
-</tr>
-<tr>
-<td>900</td>
-<td>178</td>
-<td>159.7 Mbit/s</td>
-<td>41.4 Mbit/s</td>
-</tr>
-<tr>
-<td>908</td>
-<td>199</td>
-<td>111.0 Mbit/s</td>
-<td>24.8 Mbit/s</td>
-</tr>
-<tr>
-<td>916</td>
-<td>205</td>
-<td>116.6 Mbit/s</td>
-<td>29.7 Mbit/s</td>
-</tr>
-<tr>
-<td>919</td>
-<td>209</td>
-<td>125.7 Mbit/s</td>
-<td>34.1 Mbit/s</td>
-</tr>
-<tr>
-<td>921</td>
-<td>213</td>
-<td>137.3 Mbit/s</td>
-<td>39.9 Mbit/s</td>
-</tr>
-<tr>
-<td>924</td>
-<td>219</td>
-<td>105.2 Mbit/s</td>
-<td>40.1 Mbit/s</td>
-</tr>
-<tr>
-<td>925</td>
-<td>220</td>
-<td>78.8 Mbit/s</td>
-<td>33.8 Mbit/s</td>
-</tr>
-</table>
-Size 1000.0 MiB, increment 100.0 MiB
-----
-
-<table>
-<tr>
-    <th>obnam</th>
-    <th>btree</th>
-    <th>gen0</th>
-    <th>slowest inc</th>
-</tr>
-<tr>
-<td>891</td>
-<td>176</td>
-<td>172.3 Mbit/s</td>
-<td>69.2 Mbit/s</td>
-</tr>
-<tr>
-<td>893</td>
-<td>177</td>
-<td>136.3 Mbit/s</td>
-<td>60.1 Mbit/s</td>
-</tr>
-<tr>
-<td>894</td>
-<td>177</td>
-<td>126.8 Mbit/s</td>
-<td>55.1 Mbit/s</td>
-</tr>
-<tr>
-<td>900</td>
-<td>178</td>
-<td>121.7 Mbit/s</td>
-<td>54.0 Mbit/s</td>
-</tr>
-<tr>
-<td>908</td>
-<td>199</td>
-<td>92.0 Mbit/s</td>
-<td>41.0 Mbit/s</td>
-</tr>
-<tr>
-<td>916</td>
-<td>205</td>
-<td>96.2 Mbit/s</td>
-<td>42.2 Mbit/s</td>
-</tr>
-<tr>
-<td>919</td>
-<td>209</td>
-<td>126.6 Mbit/s</td>
-<td>43.6 Mbit/s</td>
-</tr>
-<tr>
-<td>921</td>
-<td>213</td>
-<td>156.3 Mbit/s</td>
-<td>56.6 Mbit/s</td>
-</tr>
-<tr>
-<td>924</td>
-<td>219</td>
-<td>126.0 Mbit/s</td>
-<td>48.7 Mbit/s</td>
-</tr>
-<tr>
-<td>925</td>
-<td>220</td>
-<td>74.2 Mbit/s</td>
-<td>39.9 Mbit/s</td>
-</tr>
-</table>
-Size 10000.0 MiB, increment 1000.0 MiB
-----
-
-<table>
-<tr>
-    <th>obnam</th>
-    <th>btree</th>
-    <th>gen0</th>
-    <th>slowest inc</th>
-</tr>
-<tr>
-<td>891</td>
-<td>176</td>
-<td>153.3 Mbit/s</td>
-<td>64.3 Mbit/s</td>
-</tr>
-<tr>
-<td>893</td>
-<td>177</td>
-<td>115.6 Mbit/s</td>
-<td>56.0 Mbit/s</td>
-</tr>
-<tr>
-<td>894</td>
-<td>177</td>
-<td>114.3 Mbit/s</td>
-<td>51.7 Mbit/s</td>
-</tr>
-<tr>
-<td>900</td>
-<td>178</td>
-<td>112.0 Mbit/s</td>
-<td>51.2 Mbit/s</td>
-</tr>
-<tr>
-<td>908</td>

(Diff truncated)
comment on bug
diff --git a/obnam/bugs/missing-progress-reporting.mdwn b/obnam/bugs/missing-progress-reporting.mdwn
index dfef722..30fa6d0 100644
--- a/obnam/bugs/missing-progress-reporting.mdwn
+++ b/obnam/bugs/missing-progress-reporting.mdwn
@@ -7,3 +7,6 @@ The following operations should have progress reporting added:
 
 --liw
 
+restore and fsck already have progress reporting.
+forget and verify need it.
+--liw

diff --git a/obnam/bugs/too_much_test_coverage_exclusion.mdwn b/obnam/bugs/too_much_test_coverage_exclusion.mdwn
new file mode 100644
index 0000000..e1129ff
--- /dev/null
+++ b/obnam/bugs/too_much_test_coverage_exclusion.mdwn
@@ -0,0 +1 @@
+Too much code is excluded from test coverage. For example, as much code as possible in plugins should be unit tested (so coverage can be meaningfully tested). --liw

add bug post form
diff --git a/obnam/bugs.mdwn b/obnam/bugs.mdwn
index 539045e..9d0b1dd 100644
--- a/obnam/bugs.mdwn
+++ b/obnam/bugs.mdwn
@@ -5,5 +5,6 @@ Open bugs in Obnam
                  !obnam/bugs/*/* and
                  !obnam/bugs/done and 
                  !link(obnam/bugs/done)"
-          show=0]]
+          show=0
+          postform=yes]]
 

comment on bug
diff --git a/obnam/bugs/specify-ssh-key.mdwn b/obnam/bugs/specify-ssh-key.mdwn
index 28dfa6d..b43356d 100644
--- a/obnam/bugs/specify-ssh-key.mdwn
+++ b/obnam/bugs/specify-ssh-key.mdwn
@@ -1,2 +1,5 @@
 Obnam needs a way to specify which ssh key (key file) to use.
 Cf. `ssh -i` option. --liw
+
+At the moment, obnam only uses ssh agent for authentication. That
+should be fixed. --liw

close report for fixed bug
diff --git a/obnam/bugs/lacks-compression-plugin.mdwn b/obnam/bugs/lacks-compression-plugin.mdwn
index ee839cf..754b031 100644
--- a/obnam/bugs/lacks-compression-plugin.mdwn
+++ b/obnam/bugs/lacks-compression-plugin.mdwn
@@ -12,3 +12,4 @@ plugin, but be triggered by a different setting.
 
 --liw
 
+[[done]]

close fixed bug
diff --git a/obnam/bugs/bad-message-for-regexp-syntax-error.mdwn b/obnam/bugs/bad-message-for-regexp-syntax-error.mdwn
index e2f0757..624cd27 100644
--- a/obnam/bugs/bad-message-for-regexp-syntax-error.mdwn
+++ b/obnam/bugs/bad-message-for-regexp-syntax-error.mdwn
@@ -23,3 +23,5 @@ If an exclude regexp has a syntax error, the error message is awful:
     > error: nothing to repeat
 
 --liw
+
+[[done]]

update obnam 1.0 roadmap with current status
diff --git a/obnam/roadmap-for-1.0.mdwn b/obnam/roadmap-for-1.0.mdwn
index 4f79e8e..f5a2424 100644
--- a/obnam/roadmap-for-1.0.mdwn
+++ b/obnam/roadmap-for-1.0.mdwn
@@ -1,7 +1,8 @@
 Roadmap and work estimates for Obnam version 1.0
 ================================================
 
-Date: 2011-04-06
+Date: 2011-04-06 <br/>
+Latest update: 2011-12-03
 
 I was asked what it would take to make Obnam good enough that I would
 be willing to rely on it as my sole form of backup. I might not ever 
@@ -80,17 +81,14 @@ TODO:
     - remove key from user's own per-client toplevel, if one exists
     - optionally remove key from other per-client toplevels
     - alternatively, remove key only from specified toplevels
-  - estimate: 1 workday
 * Fix the concurrency issue:
   - design the right way to lock with multiple clients
   - implement the design, or a subset, depending on the amount of work
-  - estimate: 1-3 workdays
 * Implement client removal from repository. **(Done in 0.16.)**
   - remove per-client toplevel
   - remove all per-client data chunks
   - remove client from clientlist
   - remove client's keys from shared toplevels
-  - estimate: 1 workday
   
 Repository format
 -----------------
@@ -110,10 +108,6 @@ both the stable and development version installable in parallel.
 Given that, I don't think this risk would stop me from relying
 on Obnam as my sole backup system.
 
-TODO:
-
-* Nothing, the concurrent installability can be handled post-1.0.
-
 Bugs
 ----
 
@@ -140,11 +134,8 @@ TODO:
 
 * Design and implement a verification test.
   - should, by preference, be done in a way that is easy for anyone to do
-  - estimate: 1 workday
 * Execute the verification test, make note of problems.
-  - estimate: 1 workday
 * Fix any problems found.
-  - estimate: 1-5 workdays
 * Repeat until it goes flawlessly.
 
 Robustness
@@ -184,7 +175,6 @@ TODO:
     layer: allow N operations, then remove a file
   - deploy test framework
   - fix any bugs found
-  - estimate: 1-3 workdays
 * Fix Obnam bug about repository data being corrupt or missing. Restore 
   must be possible for the remaining data. Fsck must be able to notice 
   missing files, and report what is still recoverable. Any chunk file 
@@ -195,7 +185,6 @@ TODO:
   - develop test that removes B-tree nodes and verifies that files
     in the remaining nodes are restored correctly
   - fix any problems found
-  - estimate: 1-2 workdays
 
 Performance
 -----------
@@ -211,11 +200,8 @@ in less than an hour. Say, up to ten gigabytes of data.
 TODO:
 
 * Re-implement the Obnam benchmark setup to allow for encryption,
-  network backups, and different profiles.
-  - estimate: 2 workdays
+  network backups, and different profiles. (**done**)
 * Run, profile, and optimize, until performance goal is met.
-  - this is very hard to estimate well, but...
-  - estimate: 0-5 workdays
 
 Losing the program
 ------------------
@@ -228,30 +214,11 @@ my backups.
 TODO:
 
 * Review and fix Debian packages of Obnam and its dependencies.
-  Then upload them to Debian.
-  - estimate: 2 workdays
+  Then upload them to Debian. (**done**)
 
 Work estimate
 -------------
 
-Adding up the estimates above, I expect the work remaining for 1.0
-to be between 12 and 18 work days. However, some caveats:
-
-* I have not made detailed plans, and thus the estimates are somewhat
-  shaky. They're also measured in "optimistic/optimal engineering time",
-  i.e., assuming no interruptions and in general an ability to
-  concentrate.
-* The bug fixing estimates are highly speculative. Bugs have a tendency
-  to sometimes require quite a lot of time to debug and fix.
-* The performance optimizations, likewise, might take quite a lot
-  of time. This is basically impossible for me to know beforehand.
-
-Mapping these 12-18 workdays into calendar time, I expect that they'd
-take at least four and possibly eight weeks. Part of the problem is
-that things like performance benchmark runs take a lot of time, during
-which I can't do much else on the project. I do not count the hours
-spent waiting for a benchmark run into the "optimistic/optimal
-engineering time".
-
-I do have a terrible track record with estimates.
+EDIT: Hah, it's months later, and all my estimates are already blown.
+I'm removing them, since they're not even amusing anymore.
 

close bug
diff --git a/obnam/bugs/acl-xattr.mdwn b/obnam/bugs/acl-xattr.mdwn
index 4aade0e..0cd7130 100644
--- a/obnam/bugs/acl-xattr.mdwn
+++ b/obnam/bugs/acl-xattr.mdwn
@@ -9,3 +9,7 @@ operates on multiple pairs at once, and on Irix they're syscalls. Those
 functions have a fairly complicated API, though. Might want to keep
 things simple, at least initially.  --liw
 
+This is now implemented for local filesystems. Paramiko does not seem
+to support them for SFTP, so that will have to not work. --liw
+
+[[done]]

comment on bug
diff --git a/obnam/bugs/acl-xattr.mdwn b/obnam/bugs/acl-xattr.mdwn
index fa59705..4aade0e 100644
--- a/obnam/bugs/acl-xattr.mdwn
+++ b/obnam/bugs/acl-xattr.mdwn
@@ -1 +1,11 @@
 Obnam should provide xattr and ACL support. --liw
+
+I only need to support extended attributes, since ACLs are implemented
+in terms of those. Good, this makes things simpler. I can just read the
+list of xattrs on backup, and set it on restore, and I can treat the
+list as a string blob. It seems that in Linux, one needs to do a syscall
+for each key/value pair for a file, but there's a library function that
+operates on multiple pairs at once, and on Irix they're syscalls. Those
+functions have a fairly complicated API, though. Might want to keep
+things simple, at least initially.  --liw
+

mark myself as bug reporter
diff --git a/obnam/bugs/acl-xattr.mdwn b/obnam/bugs/acl-xattr.mdwn
index 54eb579..fa59705 100644
--- a/obnam/bugs/acl-xattr.mdwn
+++ b/obnam/bugs/acl-xattr.mdwn
@@ -1 +1 @@
-Obnam should provide xattr and ACL support.
+Obnam should provide xattr and ACL support. --liw

fix wrong closing of bug
diff --git a/obnam/bugs/benchmarks-make-restore-elapsed-be-zeroes.mdwn b/obnam/bugs/benchmarks-make-restore-elapsed-be-zeroes.mdwn
index 5dfd565..574b27a 100644
--- a/obnam/bugs/benchmarks-make-restore-elapsed-be-zeroes.mdwn
+++ b/obnam/bugs/benchmarks-make-restore-elapsed-be-zeroes.mdwn
@@ -1,2 +1,6 @@
 When running `obnam-benchmark`, the restore elapsed timers end at 
 00:00:00. Why? --liw
+
+It's not a bug: it's reporting remaining time, not elapsed time. Oops.
+--liw
+[[done]]
diff --git a/obnam/bugs/restore-timestamp-trouble.mdwn b/obnam/bugs/restore-timestamp-trouble.mdwn
index 903e074..e58de86 100644
--- a/obnam/bugs/restore-timestamp-trouble.mdwn
+++ b/obnam/bugs/restore-timestamp-trouble.mdwn
@@ -2,6 +2,3 @@ Why does restore verification fail with small timestamp differences
 when seivot runs summain with mtime enabled?
 --liw
 
-It's not a bug: it's reporting remaining time, not elapsed time. Oops.
---liw
-[[done]]

add wishlist bug
diff --git a/obnam/bugs/performance-with-many-hardlinks.mdwn b/obnam/bugs/performance-with-many-hardlinks.mdwn
new file mode 100644
index 0000000..c1a410c
--- /dev/null
+++ b/obnam/bugs/performance-with-many-hardlinks.mdwn
@@ -0,0 +1,10 @@
+How does Obnam perform if the live data has massive numbers of hardlinks?
+Such hardlink trees are not rare, but it would be good to at least know
+how Obnam handles them. Perform a benchmark comparing three cases:
+
+1. a very large number (one million?) of small files, all unique
+2. same, but all files identical
+3. same, but all files hardlinks to the same content
+
+Ideally, Obnam should perform about the same for all. --liw
+

report feature request
diff --git a/obnam/bugs/more-rsync-like.mdwn b/obnam/bugs/more-rsync-like.mdwn
new file mode 100644
index 0000000..b8b29fb
--- /dev/null
+++ b/obnam/bugs/more-rsync-like.mdwn
@@ -0,0 +1,5 @@
+Moving forward in small increments than individual chunks would allow
+more rsync-like behavior, and more chance of finding duplicate data.
+This might be worthwhile, for some users, some of the time. It should
+be configurable, though, since it's also potentially going to be a 
+big performance problem. --liw

report bug
diff --git a/obnam/bugs/needs-porting-to-rhel-sl-centos.mdwn b/obnam/bugs/needs-porting-to-rhel-sl-centos.mdwn
new file mode 100644
index 0000000..90519d6
--- /dev/null
+++ b/obnam/bugs/needs-porting-to-rhel-sl-centos.mdwn
@@ -0,0 +1,3 @@
+Obnam should work on RHEL, Scientific Linux, and CentOS, and other
+popular distros such as Fedora, Ubuntu. Help porting these would
+be welcome. --liw

comment on bug
diff --git a/obnam/bugs/too-slow.mdwn b/obnam/bugs/too-slow.mdwn
index e6b0f59..bd06cd3 100644
--- a/obnam/bugs/too-slow.mdwn
+++ b/obnam/bugs/too-slow.mdwn
@@ -2,3 +2,6 @@ Obnam should be fast enough that it can back up my laptop's home
 directory, overnight, encrypted, to an unencrypted USB hard disk.
 That's 140 gigabytes of data, much of music and videos and photographs,
 in 12 hours. --liw
+
+I can now back up 200+ gigabytes of data without encryption, to an
+encrypted USB drive, in four hours. --liw

mark bug done
diff --git a/obnam/bugs/restore-timestamp-trouble.mdwn b/obnam/bugs/restore-timestamp-trouble.mdwn
index e58de86..903e074 100644
--- a/obnam/bugs/restore-timestamp-trouble.mdwn
+++ b/obnam/bugs/restore-timestamp-trouble.mdwn
@@ -2,3 +2,6 @@ Why does restore verification fail with small timestamp differences
 when seivot runs summain with mtime enabled?
 --liw
 
+It's not a bug: it's reporting remaining time, not elapsed time. Oops.
+--liw
+[[done]]

mark bug done
diff --git a/obnam/bugs/backup-plugin-reporting.mdwn b/obnam/bugs/backup-plugin-reporting.mdwn
index cc7f585..e54df15 100644
--- a/obnam/bugs/backup-plugin-reporting.mdwn
+++ b/obnam/bugs/backup-plugin-reporting.mdwn
@@ -1,3 +1,4 @@
 Fix obnam backup plugin to report when it's doing something else than
 backing up a file.
 --liw
+[[done]]

mark bug done
diff --git a/obnam/bugs/memory-profiling-everywhere.mdwn b/obnam/bugs/memory-profiling-everywhere.mdwn
index f7f8d77..7b17e56 100644
--- a/obnam/bugs/memory-profiling-everywhere.mdwn
+++ b/obnam/bugs/memory-profiling-everywhere.mdwn
@@ -1,3 +1,4 @@
 All Obnam operations should be calling the memory profiling operations,
 so that all operations can be profiled when needed. The profiling functions
 should go into cliapp, however. --liw
+[[done]]

Report bug
diff --git a/obnam/bugs/benchmarks-make-restore-elapsed-be-zeroes.mdwn b/obnam/bugs/benchmarks-make-restore-elapsed-be-zeroes.mdwn
new file mode 100644
index 0000000..5dfd565
--- /dev/null
+++ b/obnam/bugs/benchmarks-make-restore-elapsed-be-zeroes.mdwn
@@ -0,0 +1,2 @@
+When running `obnam-benchmark`, the restore elapsed timers end at 
+00:00:00. Why? --liw

Add bug
diff --git a/obnam/bugs/specify-ssh-key.mdwn b/obnam/bugs/specify-ssh-key.mdwn
new file mode 100644
index 0000000..28dfa6d
--- /dev/null
+++ b/obnam/bugs/specify-ssh-key.mdwn
@@ -0,0 +1,2 @@
+Obnam needs a way to specify which ssh key (key file) to use.
+Cf. `ssh -i` option. --liw

Move wishlist into bugs
diff --git a/obnam.mdwn b/obnam.mdwn
index 0596d84..28c4247 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -25,7 +25,7 @@ See the [[tutorial]] for examples of how to use Obnam.
 * [[Status and support|status]]
 * [[Download]]
 * [[Contact]]
-* [[Feature requests|wishlist]]
+* [[Bugs]]
 
 Documentation
 -------------
diff --git a/obnam/bugs/fuse.mdwn b/obnam/bugs/fuse.mdwn
new file mode 100644
index 0000000..660a211
--- /dev/null
+++ b/obnam/bugs/fuse.mdwn
@@ -0,0 +1,2 @@
+It would be good to have a FUSE filesystem for restoring data. --liw
+
diff --git a/obnam/wishlist.mdwn b/obnam/wishlist.mdwn
deleted file mode 100644
index ee1058b..0000000
--- a/obnam/wishlist.mdwn
+++ /dev/null
@@ -1,5 +0,0 @@
-Feature requests
-----------------
-
-* FUSE filesystem for restoring data.
-

Obnam bug fixed in trunk
diff --git a/obnam/bugs/c-lstat.mdwn b/obnam/bugs/c-lstat.mdwn
index a2b4384..fc9399c 100644
--- a/obnam/bugs/c-lstat.mdwn
+++ b/obnam/bugs/c-lstat.mdwn
@@ -5,3 +5,5 @@ system call and returns timestamps as (pairs of) integers instead.
 This would allow full timestamp precision.
 
 --liw
+
+[[done]]

Show everything on bugs pages
diff --git a/obnam/bugs.mdwn b/obnam/bugs.mdwn
index bde60b1..539045e 100644
--- a/obnam/bugs.mdwn
+++ b/obnam/bugs.mdwn
@@ -4,5 +4,6 @@ Open bugs in Obnam
 [[!inline pages="page(obnam/bugs/*) and 
                  !obnam/bugs/*/* and
                  !obnam/bugs/done and 
-                 !link(obnam/bugs/done)"]]
+                 !link(obnam/bugs/done)"
+          show=0]]
 
diff --git a/obnam/bugs/done.mdwn b/obnam/bugs/done.mdwn
index b73aa89..28503c4 100644
--- a/obnam/bugs/done.mdwn
+++ b/obnam/bugs/done.mdwn
@@ -4,5 +4,7 @@ Closed bugs for Obnam
 [[!inline pages="page(obnam/bugs/*) and 
                  !obnam/bugs/*/* and
                  !obnam/bugs/done and
-                 link(obnam/bugs/done)"]]
+                 link(obnam/bugs/done)"
+          show=0
+          archive=yes]]
 

Add Obnam bugs from my GTD system
diff --git a/obnam/bugs/backup-plugin-reporting.mdwn b/obnam/bugs/backup-plugin-reporting.mdwn
new file mode 100644
index 0000000..cc7f585
--- /dev/null
+++ b/obnam/bugs/backup-plugin-reporting.mdwn
@@ -0,0 +1,3 @@
+Fix obnam backup plugin to report when it's doing something else than
+backing up a file.
+--liw
diff --git a/obnam/bugs/benchmark-fsck.mdwn b/obnam/bugs/benchmark-fsck.mdwn
new file mode 100644
index 0000000..dec50e8
--- /dev/null
+++ b/obnam/bugs/benchmark-fsck.mdwn
@@ -0,0 +1 @@
+`obnam-benchmark` should benchmark also the fsck operation. --liw
diff --git a/obnam/bugs/c-lstat.mdwn b/obnam/bugs/c-lstat.mdwn
new file mode 100644
index 0000000..a2b4384
--- /dev/null
+++ b/obnam/bugs/c-lstat.mdwn
@@ -0,0 +1,7 @@
+Obnam is using the Python os.lstat method to get metadata from files.
+Python returns timestamps as floats, which are awkward to store on
+disk. It would be good to switch to a C extension that does the lstat
+system call and returns timestamps as (pairs of) integers instead.
+This would allow full timestamp precision.
+
+--liw
diff --git a/obnam/bugs/estimate-backup-time.mdwn b/obnam/bugs/estimate-backup-time.mdwn
new file mode 100644
index 0000000..7d7c99b
--- /dev/null
+++ b/obnam/bugs/estimate-backup-time.mdwn
@@ -0,0 +1,3 @@
+It would be cool if Obnam could do a very quick estimate of the amount
+of new data to be backed up, without having to perform a complete new
+backup. --liw
diff --git a/obnam/bugs/estimate-to-be-freed-space.mdwn b/obnam/bugs/estimate-to-be-freed-space.mdwn
new file mode 100644
index 0000000..ffed486
--- /dev/null
+++ b/obnam/bugs/estimate-to-be-freed-space.mdwn
@@ -0,0 +1,11 @@
+It would be nice for Obnam to have a tool to answer the question 
+"how much space will be freed if I remove these generations?"
+
+  - need to find list of chunks that are used only by the specified gens
+  - perhaps also count B-tree reduction? cound nodes that are unshared by
+    the relevant trees, or only shared by the trees to be deleted
+  - however, the B-trees are going to be a fraction (a few percent) of
+    the size of the chunk data, so they're not really worth it
+
+--liw
+
diff --git a/obnam/bugs/forget-is-too-slow.mdwn b/obnam/bugs/forget-is-too-slow.mdwn
new file mode 100644
index 0000000..2240c10
--- /dev/null
+++ b/obnam/bugs/forget-is-too-slow.mdwn
@@ -0,0 +1,6 @@
+`obnam forget` is currently too slow to be usable. It might be much
+faster if it removed all data for all generations to be removed at
+once, rather than generation-by-generation. Needs experimentation and
+benchmarking.
+
+--liw
diff --git a/obnam/bugs/fsck-should-reconstruct-chunk-btrees.mdwn b/obnam/bugs/fsck-should-reconstruct-chunk-btrees.mdwn
new file mode 100644
index 0000000..90e2319
--- /dev/null
+++ b/obnam/bugs/fsck-should-reconstruct-chunk-btrees.mdwn
@@ -0,0 +1,5 @@
+fsck has all the necessary information it needs to reconstruct the
+chunksums and chunklist B-trees in a repository. It should do so,
+at least when requested.
+
+--liw
diff --git a/obnam/bugs/fsck-workitem-unification.mdwn b/obnam/bugs/fsck-workitem-unification.mdwn
new file mode 100644
index 0000000..354c210
--- /dev/null
+++ b/obnam/bugs/fsck-workitem-unification.mdwn
@@ -0,0 +1,4 @@
+Combine larch and obnam fsck workitems. Merge the two current WorkItem
+classes, put them into larch, and adapt both code bases accordingly.
+--liw
+
diff --git a/obnam/bugs/fstype-include-exclude-mdwn b/obnam/bugs/fstype-include-exclude-mdwn
new file mode 100644
index 0000000..837f36e
--- /dev/null
+++ b/obnam/bugs/fstype-include-exclude-mdwn
@@ -0,0 +1,13 @@
+Implement --exclude-fstype and --include-fstype for Obnam. 2011-08
+whenever obnam backup is crossing a filesystem boundary (mount point), 
+it looks up the type of the filesystem beyond the boundary, and if it
+matches an excluded filesystem type, but does not match an included
+one, then it won't recurse beyond the mount point (it will back up
+the actual directory, using metadata of the root of the mounted
+filesystem)
+
+- in backup_plugin.py:can_be_backed_up, add tests after the test for
+  one-file-system
+
+--liw
+
diff --git a/obnam/bugs/gpg-options.mdwn b/obnam/bugs/gpg-options.mdwn
new file mode 100644
index 0000000..1ecc6aa
--- /dev/null
+++ b/obnam/bugs/gpg-options.mdwn
@@ -0,0 +1,5 @@
+Obnam should have a `gnupg-home` setting to set the GnuPG home directory
+(`~/.gnupg`), or possibly a `gnupg-option` string list setting to pass
+any options to GnuPG.
+--liw
+
diff --git a/obnam/bugs/integer-too-big.mdwn b/obnam/bugs/integer-too-big.mdwn
new file mode 100644
index 0000000..2a337e2
--- /dev/null
+++ b/obnam/bugs/integer-too-big.mdwn
@@ -0,0 +1,30 @@
+Fix "long too large to convert to int" problem found by Jo.
+
+    Traceback (most recent call last):
+      File "/usr/lib/python2.6/dist-packages/cliapp/app.py", line 135, in _run
+        self.process_args(args)
+      File "/usr/lib/python2.6/dist-packages/obnamlib/app.py", line 116, in process_args
+        cliapp.Application.process_args(self, args)
+      File "/usr/lib/python2.6/dist-packages/cliapp/app.py", line 275, in process_args
+        method(args[1:])
+      File "/usr/lib/python2.6/dist-packages/obnamlib/plugins/backup_plugin.py", line 80, in backup
+        self.backup_roots(roots)
+      File "/usr/lib/python2.6/dist-packages/obnamlib/plugins/backup_plugin.py", line 136, in backup_roots
+        self.backup_metadata(pathname, metadata)
+      File "/usr/lib/python2.6/dist-packages/obnamlib/plugins/backup_plugin.py", line 250, in backup_metadata
+        self.repo.create(pathname, metadata)
+      File "/usr/lib/python2.6/dist-packages/obnamlib/repo.py", line 509, in create
+        encoded = obnamlib.encode_metadata(metadata)
+      File "/usr/lib/python2.6/dist-packages/obnamlib/metadata.py", line 200, in encode_metadata
+        len(metadata.md5 or ''))
+    error: long too large to convert to int
+
+- hypothesis: overflows int on the way to the struct, on 32-bit
+- wrote script to test hypothesis, but proved it wrong: the limit where
+  struct gives error is 2**64-1, as is proper, so the problem is something
+  else
+- talk to directhex to extract more information, possibly add logging to
+  pinpoint the value
+
+--liw
+
diff --git a/obnam/bugs/lacks-compression-plugin.mdwn b/obnam/bugs/lacks-compression-plugin.mdwn
new file mode 100644
index 0000000..ee839cf
--- /dev/null
+++ b/obnam/bugs/lacks-compression-plugin.mdwn
@@ -0,0 +1,14 @@
+Obnam could do with a plugin that just compresses data, without
+encrypting it. Encryption might be unwanted, or unnecessary, for
+example when backing to a USB drive that uses whole-disk encryption.
+However, saving space by compressing data with gzip or xz is still
+a reasonable thing to do.
+
+The compression plugin would be similar to the existing encryption
+plugin, but be triggered by a different setting.
+
+* `compress-with`: program to compress files with; 
+  default to gzip, but can be any program
+
+--liw
+
diff --git a/obnam/bugs/live-data-backup-restore-benchmark-failure.mdwn b/obnam/bugs/live-data-backup-restore-benchmark-failure.mdwn
new file mode 100644
index 0000000..c1fb4c4
--- /dev/null
+++ b/obnam/bugs/live-data-backup-restore-benchmark-failure.mdwn
@@ -0,0 +1,8 @@
+Tried to run obnam benchmark with real data and verification on xander. 
+
+- failed: no restored files
+- see /home/liw/tmp/benchmark-with-real-data-failed-to-restore
+- investigate why
+
+--liw
+
diff --git a/obnam/bugs/memory-profiling-everywhere.mdwn b/obnam/bugs/memory-profiling-everywhere.mdwn
new file mode 100644
index 0000000..f7f8d77
--- /dev/null
+++ b/obnam/bugs/memory-profiling-everywhere.mdwn
@@ -0,0 +1,3 @@
+All Obnam operations should be calling the memory profiling operations,
+so that all operations can be profiled when needed. The profiling functions
+should go into cliapp, however. --liw
diff --git a/obnam/bugs/multirepository.mdwn b/obnam/bugs/multirepository.mdwn
new file mode 100644
index 0000000..93cac34

(Diff truncated)
Fix bugs link for genbackupdata
diff --git a/genbackupdata.mdwn b/genbackupdata.mdwn
index 1b8a9d0..8c04c4d 100644
--- a/genbackupdata.mdwn
+++ b/genbackupdata.mdwn
@@ -7,7 +7,7 @@ genbackupdata is a program to generate test data for backup software testing.
 * Version control: `bzr get http://code.liw.fi/genbackupdata/bzr/trunk/`
 * Tarball and Debian packages: 
   <http://code.liw.fi/debian/pool/main/g/genbackupdata/>
-* [Bugs](http://code.liw.fi/genbackupdata/bugs/)
+* [Bugs](http://liw.fi/genbackupdata/bugs/)
 
 See also:
 

Replace link to SD HTML output with ikiwiki bug list
diff --git a/obnam/status.mdwn b/obnam/status.mdwn
index a8bb03d..19f500f 100644
--- a/obnam/status.mdwn
+++ b/obnam/status.mdwn
@@ -6,11 +6,14 @@ but may be slow and buggy. There are no known bugs that would corrupt
 backed up data, or prevent it from being restored.
 (See [[NEWS]] for release notes.)
 
-If you find a bug or other problem, please report it!
-The list of bugs is at <http://code.liw.fi/obnam/bugs/>.
+If you find a bug or other problem, please report it by using e-mail
+to the mailing list (see below), directly to Lars, or on IRC (see
+below). Debian users may also report bugs to the Debian bug tracking
+system.
 
 * E-mail to the <mailto:obnam@braawi.org> mailing list.
 * On IRC via the `#obnam` channel.
+* [[bugs]] page lists all open bugs.
 
 See [[contact page|contact]] for more instructions on the mailing list and
 IRC channel.

Move rest of the bugs from SD
diff --git a/obnam/bugs/avoid-stat-for-unchanged-directory.mdwn b/obnam/bugs/avoid-stat-for-unchanged-directory.mdwn
new file mode 100644
index 0000000..3b19ac4
--- /dev/null
+++ b/obnam/bugs/avoid-stat-for-unchanged-directory.mdwn
@@ -0,0 +1,13 @@
+This is an idea for optimizing Obnam.
+
+Store MD5 of string containing names + relevant metadata of all
+files in a directory, then re-compute that when backing up a 
+directory: if checksums are same, then no file in the directory
+has changed, and there's no need to check each of them separately,
+saving many tree lookups
+
+Consider only non-dirs, since subsubdir can change without it being visible
+at grandparent level. Thus, recursing is always necessary.
+
+--liw
+
diff --git a/obnam/bugs/bad-message-for-regexp-syntax-error.mdwn b/obnam/bugs/bad-message-for-regexp-syntax-error.mdwn
new file mode 100644
index 0000000..e2f0757
--- /dev/null
+++ b/obnam/bugs/bad-message-for-regexp-syntax-error.mdwn
@@ -0,0 +1,25 @@
+If an exclude regexp has a syntax error, the error message is awful:
+
+    > peter@dewsbx07:/media/GreenDrive/Backups$ obnam backup $HOME
+    > Traceback (most recent call last):
+    >   File "/usr/lib/python2.6/dist-packages/cliapp/app.py", line 141, in _run
+    >     self.process_args(args)
+    >   File "/usr/lib/python2.6/dist-packages/obnamlib/app.py", line 123, in
+    > process_args
+    >     cliapp.Application.process_args(self, args)
+    >   File "/usr/lib/python2.6/dist-packages/cliapp/app.py", line 316, in
+    > process_args
+    >     method(args[1:])
+    >   File "/usr/lib/python2.6/dist-packages/obnamlib/plugins/backup_plugin.py",
+    > line 95, in backup
+    >     self.compile_exclusion_patterns()
+    >   File "/usr/lib/python2.6/dist-packages/obnamlib/plugins/backup_plugin.py",
+    > line 136, in compile_exclusion_patterns
+    >     for x in self.app.settings['exclude']]
+    >   File "/usr/lib/python2.6/re.py", line 190, in compile
+    >     return _compile(pattern, flags)
+    >   File "/usr/lib/python2.6/re.py", line 245, in _compile
+    >     raise error, v # invalid expression
+    > error: nothing to repeat
+
+--liw
diff --git a/obnam/bugs/lock-key-in-ram.mdwn b/obnam/bugs/lock-key-in-ram.mdwn
new file mode 100644
index 0000000..bd92b6a
--- /dev/null
+++ b/obnam/bugs/lock-key-in-ram.mdwn
@@ -0,0 +1,15 @@
+Joey asked:
+
+<joeyh> have you done anything in obnam to deal with it needing to keep
+the symmetric key, decrypted, in RAM?
+
+<joeyh> yeah, it's tough. probably could be avoided by having gpg decrypt
+the passphrase and pipe it to the encrypting gpg .. but then gpg would
+constantly be using the public key
+
+It might be possible to have a C extension that holds the symmetric
+key, locks it into RAM, and feeds it to gpg whenever necessary,
+via a file descriptor.
+
+--liw
+
diff --git a/obnam/bugs/ro-ops-while-rw-runs-crash.mdwn b/obnam/bugs/ro-ops-while-rw-runs-crash.mdwn
new file mode 100644
index 0000000..b46bc98
--- /dev/null
+++ b/obnam/bugs/ro-ops-while-rw-runs-crash.mdwn
@@ -0,0 +1,5 @@
+    <weasel> runing 'generations' while a backup or forget just is being run, 
+        results in a backtrace
+    <weasel> probably should say 'repository locked', if it cannot provide the 
+        information if work is in progress
+
diff --git a/obnam/bugs/test-against-old-format-versions.mdwn b/obnam/bugs/test-against-old-format-versions.mdwn
new file mode 100644
index 0000000..4c1b9a8
--- /dev/null
+++ b/obnam/bugs/test-against-old-format-versions.mdwn
@@ -0,0 +1,3 @@
+The test suite should verify that Obnam works in the proper way when
+it encounters a repository with the old format version. Whatever that
+proper way might be. --liw
diff --git a/obnam/bugs/too-slow.mdwn b/obnam/bugs/too-slow.mdwn
new file mode 100644
index 0000000..e6b0f59
--- /dev/null
+++ b/obnam/bugs/too-slow.mdwn
@@ -0,0 +1,4 @@
+Obnam should be fast enough that it can back up my laptop's home
+directory, overnight, encrypted, to an unencrypted USB hard disk.
+That's 140 gigabytes of data, much of music and videos and photographs,
+in 12 hours. --liw
diff --git a/obnam/bugs/username-groupname-over-sftp-wrong.mdwn b/obnam/bugs/username-groupname-over-sftp-wrong.mdwn
new file mode 100644
index 0000000..4f0b423
--- /dev/null
+++ b/obnam/bugs/username-groupname-over-sftp-wrong.mdwn
@@ -0,0 +1,5 @@
+When the backup root (i.e., live data) is accessed over sftp, obnam
+queries the _local_ system for the names of the user and group. This
+is going to result in bad data. In this case, unless it can query
+the remote server, it should just not store the username and groupname
+at all. --liw

Copy some bugs from SD
diff --git a/obnam/bugs/avoid-hash-collisions.mdwn b/obnam/bugs/avoid-hash-collisions.mdwn
new file mode 100644
index 0000000..5fbfc81
--- /dev/null
+++ b/obnam/bugs/avoid-hash-collisions.mdwn
@@ -0,0 +1,15 @@
+It would be good for Obnam to optionally be able to verify that hash
+collisions do not happen. This requires downloading the data with
+the same hash, and comparing the bytes, which can be quite expensive.
+However, backup programs should be reliable, and the user should be
+able to choose reliability over speed.
+
+Three modes are needed:
+
+* assume hash collisions do not happen (deduplication, max speed, max risk)
+* verify that hash collisions do not happen 
+  (deduplication, no risk, performance hit)
+* do not deduplicate (max speed, no risk)
+
+--liw
+
diff --git a/obnam/bugs/chunk-size-based-on-data-type-and-size.mdwn b/obnam/bugs/chunk-size-based-on-data-type-and-size.mdwn
new file mode 100644
index 0000000..50d4872
--- /dev/null
+++ b/obnam/bugs/chunk-size-based-on-data-type-and-size.mdwn
@@ -0,0 +1,12 @@
+Would it be beneficial to choose the size of data chunks based on the
+type of data, or its size? Text data might benefit from small chunks,
+whereas video data might benefit from large chunks, for example.
+Possibly the size of a file would be a sufficient indicator.
+
+The goal would be to reduce the number of chunks, without reducing
+the effectiveness of de-duplication.
+
+This needs to be measurements of real data to see if there are interesting
+parameters.
+
+--liw
diff --git a/obnam/bugs/filename-hash-collisions.mdwn b/obnam/bugs/filename-hash-collisions.mdwn
new file mode 100644
index 0000000..7f8124d
--- /dev/null
+++ b/obnam/bugs/filename-hash-collisions.mdwn
@@ -0,0 +1,7 @@
+Obnam does not handle hash collisions in filenames. If two different
+filenames have the same hash, Obnam assumes they're the same filename.
+
+This should be possible to test by using a very weak filename hash
+function.
+
+--liw
diff --git a/obnam/bugs/insufficient-locking.mdwn b/obnam/bugs/insufficient-locking.mdwn
new file mode 100644
index 0000000..2d5e08b
--- /dev/null
+++ b/obnam/bugs/insufficient-locking.mdwn
@@ -0,0 +1,3 @@
+Obnam does not currently do locking properly. It locks the per-client
+directory, but not the shared directories. --liw
+
diff --git a/obnam/bugs/missing-progress-reporting.mdwn b/obnam/bugs/missing-progress-reporting.mdwn
new file mode 100644
index 0000000..dfef722
--- /dev/null
+++ b/obnam/bugs/missing-progress-reporting.mdwn
@@ -0,0 +1,9 @@
+The following operations should have progress reporting added:
+
+       obnam [options] forget
+       obnam [options] fsck
+       obnam [options] restore
+       obnam [options] verify
+
+--liw
+
diff --git a/obnam/bugs/multiple-checksums.mdwn b/obnam/bugs/multiple-checksums.mdwn
new file mode 100644
index 0000000..d3de3c0
--- /dev/null
+++ b/obnam/bugs/multiple-checksums.mdwn
@@ -0,0 +1,25 @@
+From Joey Hess:
+
+> My take on this is that, by choosing to use a tool that uses hashes, I
+> am giving up (near-)absolute certainty for speed, or space, or whatever.
+> So it's important that the hash type be good at collision resistance (for
+> example, no two likely filenames should hash the same; "/etc/passwd"
+> should only tend to collide with blobs that are very unlike a filename).
+> It's also important that the tool be upfront about using hashes, and
+> about what hash it uses. And if it's not designed to allow swapping the
+> hash out when it gets broken, I will trust it less (hello git).
+
+Ah, the replacement of hash functions is an interesting problem.
+
+For pathnames, it's not at all important, I think, except perhaps for
+performance, since pathnames will be compared byte-by-byte instead of
+by hashes.
+
+For file data, replacing is easy, if one is willing to back up everything
+from scratch. Supporting several hashes in the same backup store is a
+little bit more work, but not a whole lot: instead of having just one
+tree for mapping checksums to chunk identifiers, one would have one per
+checksum algorithm.
+
+--liw
+
diff --git a/obnam/bugs/small-chunks-in-btree.mdwn b/obnam/bugs/small-chunks-in-btree.mdwn
new file mode 100644
index 0000000..4871326
--- /dev/null
+++ b/obnam/bugs/small-chunks-in-btree.mdwn
@@ -0,0 +1,4 @@
+Would it be more efficient to store small amounts of data directly in
+the B-tree rather than as a separate chunk?
+
+--liw
diff --git a/obnam/bugs/verify-pick-randomly.mdwn b/obnam/bugs/verify-pick-randomly.mdwn
new file mode 100644
index 0000000..95ebf92
--- /dev/null
+++ b/obnam/bugs/verify-pick-randomly.mdwn
@@ -0,0 +1,7 @@
+Currently, `obnam verify` compares all files in the backup with all files
+in live data. Often it would be enough to just verify a few files, to
+sample the data rather than do a full verification. Obnam should be able
+to pick a desired number of files randomly from the backup and compare
+those.
+
+--liw

Close fake bug for testing
diff --git a/obnam/bugs/keep-bugs-in-ikiwiki.mdwn b/obnam/bugs/keep-bugs-in-ikiwiki.mdwn
index 1f43bda..5ed976f 100644
--- a/obnam/bugs/keep-bugs-in-ikiwiki.mdwn
+++ b/obnam/bugs/keep-bugs-in-ikiwiki.mdwn
@@ -1,2 +1,4 @@
 I want to move my bug tracking from SD to ikiwiki. --liw
 
+[[done]]
+

Add fake bug for testing
diff --git a/obnam/bugs/keep-bugs-in-ikiwiki.mdwn b/obnam/bugs/keep-bugs-in-ikiwiki.mdwn
new file mode 100644
index 0000000..1f43bda
--- /dev/null
+++ b/obnam/bugs/keep-bugs-in-ikiwiki.mdwn
@@ -0,0 +1,2 @@
+I want to move my bug tracking from SD to ikiwiki. --liw
+

Tweak bugs setup
diff --git a/obnam/bugs/done.mdwn b/obnam/bugs/done.mdwn
index fb699a0..b73aa89 100644
--- a/obnam/bugs/done.mdwn
+++ b/obnam/bugs/done.mdwn
@@ -3,5 +3,6 @@ Closed bugs for Obnam
 
 [[!inline pages="page(obnam/bugs/*) and 
                  !obnam/bugs/*/* and
-                 !obnam/bugs/done"]]
+                 !obnam/bugs/done and
+                 link(obnam/bugs/done)"]]
 

Tweak bugs setup
diff --git a/obnam/bugs.mdwn b/obnam/bugs.mdwn
index c9583fd..bde60b1 100644
--- a/obnam/bugs.mdwn
+++ b/obnam/bugs.mdwn
@@ -1,4 +1,8 @@
-Bugs in Obnam.
+Open bugs in Obnam
+==================
 
-[[!inline pages="page(obnam/bugs/*)"]]
+[[!inline pages="page(obnam/bugs/*) and 
+                 !obnam/bugs/*/* and
+                 !obnam/bugs/done and 
+                 !link(obnam/bugs/done)"]]
 
diff --git a/obnam/bugs/done.mdwn b/obnam/bugs/done.mdwn
new file mode 100644
index 0000000..fb699a0
--- /dev/null
+++ b/obnam/bugs/done.mdwn
@@ -0,0 +1,7 @@
+Closed bugs for Obnam
+=====================
+
+[[!inline pages="page(obnam/bugs/*) and 
+                 !obnam/bugs/*/* and
+                 !obnam/bugs/done"]]
+

Tweak inline
diff --git a/obnam/bugs.mdwn b/obnam/bugs.mdwn
index 86376ca..c9583fd 100644
--- a/obnam/bugs.mdwn
+++ b/obnam/bugs.mdwn
@@ -1,4 +1,4 @@
 Bugs in Obnam.
 
-[[!inline pages="page(bugs/*)"]]
+[[!inline pages="page(obnam/bugs/*)"]]
 

Start tracking bugs in ikiwiki
diff --git a/obnam/bugs.mdwn b/obnam/bugs.mdwn
new file mode 100644
index 0000000..86376ca
--- /dev/null
+++ b/obnam/bugs.mdwn
@@ -0,0 +1,4 @@
+Bugs in Obnam.
+
+[[!inline pages="page(bugs/*)"]]
+
diff --git a/obnam/bugs/acl-xattr.mdwn b/obnam/bugs/acl-xattr.mdwn
new file mode 100644
index 0000000..54eb579
--- /dev/null
+++ b/obnam/bugs/acl-xattr.mdwn
@@ -0,0 +1 @@
+Obnam should provide xattr and ACL support.

Fix typo which inverted the sense of an answer.
diff --git a/obnam/faq.mdwn b/obnam/faq.mdwn
index 71f30fd..a2666e7 100644
--- a/obnam/faq.mdwn
+++ b/obnam/faq.mdwn
@@ -3,7 +3,7 @@
 Can Alice and Bob share repository without sharing file data?
 -------------------------------------------------------------
 
-This does work particularly well. Obnam does not currently support it
+This doesn't work particularly well. Obnam does not currently support it
 at all. On a conceptual level, it could work, by turning all de-duplication
 off, and having Alice and Bob encrypt their own chunks only with their
 own, separate keys.

According to bzr, "The command 'bzr get' has been deprecated in bzr 2.4. Please use 'bzr branch' instead."
diff --git a/obnam/download.mdwn b/obnam/download.mdwn
index a7b638b..065b974 100644
--- a/obnam/download.mdwn
+++ b/obnam/download.mdwn
@@ -13,7 +13,7 @@ Download
 
 * from version control:
 
-    `bzr get http://code.liw.fi/obnam/bzr/trunk/`
+    `bzr branch http://code.liw.fi/obnam/bzr/trunk/`
 
 The code is licensed under GNU General Public License version 3, or later.
 

Add link to Obnam bug tracker.
diff --git a/obnam/status.mdwn b/obnam/status.mdwn
index 03b862e..a8bb03d 100644
--- a/obnam/status.mdwn
+++ b/obnam/status.mdwn
@@ -7,6 +7,7 @@ backed up data, or prevent it from being restored.
 (See [[NEWS]] for release notes.)
 
 If you find a bug or other problem, please report it!
+The list of bugs is at <http://code.liw.fi/obnam/bugs/>.
 
 * E-mail to the <mailto:obnam@braawi.org> mailing list.
 * On IRC via the `#obnam` channel.

Obnam 0.23.
diff --git a/obnam/NEWS.mdwn b/obnam/NEWS.mdwn
index 7712692..4d09e65 100644
--- a/obnam/NEWS.mdwn
+++ b/obnam/NEWS.mdwn
@@ -4,6 +4,89 @@ Obnam NEWS
 
 This file summarizes changes between releases of Obnam.
 
+Version 0.23, released 2011-10-02; a BETA release
+-------------------------------------------------
+
+USER VISIBLE CHANGES:
+
+* `restore` now shows a progress bar.
+* `fsck` now has more useful progress reporting, and does more checking,
+  including the integrity of the contents of file content.
+* `fsck` now also checks the integrity of the B-trees in the repository,
+  so that it is not necessary to run `fsck-larch` manually anymore. This
+  works remotely as well, whereas `fsck-larch` only worked on B-trees
+  on the local filesystem.
+* `force-lock` now gives a warning if the client does not exist in the
+  repository.
+* Subcommands for encryption now give a warning if encryption key is not
+  given.
+* The `--fsck-fix` option will now instruct `obnam fsck` to try to fix
+  problems found. For this release, it only means fixing B-tree missing
+  node problems, but more will follow.
+* The default sizes have been changed for B-tree nodes (256 KiB) 
+  and file contents chunks (1 MiB), based on benchmarking. 
+* SFTP protocol use has been optimized, which should result in some
+  more speed. This also highlights the need to change obnam so it can
+  do uploads in the background.
+* If a client does not exist in the repository, `force-lock` now gives
+  a warning to the user, rather than ignoring it silently.
+
+DEVELOPER CHANGES:
+
+* New `--sftp-delay=100` option can be used to simulate SFTP backups over
+  networks with long round trip times.
+* `obnam-benchmark` can now use `--sftp-delay` and other changes to make
+  it more useful.
+
+INTERNAL CHANGES:
+
+* Got rid of terminal status plugin. Now, the `Application` class provides
+  a `ttystatus.TerminalStatus` instance instead, in the `ts` attribute.
+  Other plugings are supposed to use that for progress reporting and
+  messaging to the user.
+* The `posix_fadvise` system call is used only if available. This should
+  improve Obnam's portability a bit.
+
+Version 0.22, released 2011-08-25; a BETA release
+-------------------------------------------------
+
+USER VISIBLE CHANGES:
+
+* Obnam now reports its current configuration in the log file at startup.
+  This will hopefully remove one round of "did you use the --foo option?"
+  questions between developers and bug reporters.
+
+BUG FIXES:
+
+* The repository is now unlocked on exit only if it is still locked.
+* A wrongly caught `GeneratorExit` is now dealt with properly.
+* Keyboard interrupts are logged, so they don't show up as anonymous errors.
+
+CHANGES RELEVANT TO DEVELOPERS ONLY:
+
+* `setup.py` has been enhanced to work more like the old `Makefile` did:
+  `clean` removes more artifacts. Instructions in `README` have been updated
+  to point at `setup.py`.
+* Compiler warning about `_XOPEN_SOURCE` re-definition fixed.
+* Tests are now again run during a Debian package build.
+
+Version 0.21, released 2011-08-23; a BETA release
+-------------------------------------------------
+
+USER VISIBLE CHANGES:
+
+* Obnam will now unlock the repository if there's an error during a backup.
+  For the most part, the `force-lock` operation should now be unnecessary,
+  but it's still there in case it's useful some day.
+
+BUG FIXES:
+
+* Negative timestamps for files now work. Thanks to Jamil Djadala
+  for reporting the bug.
+* The documentation for --checkpoint units fixed. Thanks, user weinzwang
+  from IRC.
+* The connections to the repository and live data filesystem are now
+  properly closed. This makes benchmark read/write statistics be correct.
 
 Version 0.20.1, released 2011-08-11; a BETA release
 -------------------------------------------------
diff --git a/obnam/README.mdwn b/obnam/README.mdwn
index 1b4e9af..5612c16 100644
--- a/obnam/README.mdwn
+++ b/obnam/README.mdwn
@@ -68,14 +68,14 @@ The canonical version control repository for obnam itself is at:
 The 'trunk' branch is the main development one. Note that the URL points
 at a bzr repository, it is not useful to browse it by hand.
 
-To build:
+To build and run automatic tests:
 
-    make
-    
-To run automatic tests:
+    ./check
+    ./check --fast # unit tests only, no blackboxtests
+    ./check --network # requires ssh access to localhost
 
-    make check 
-    make network-tests # Requires ssh access to localhost.
+`check` is a wrapper around `python setup.py`, but since using that
+takes several steps, the script makes things easier.
     
 You need my CoverageTestRunner to run tests, see above for where to get it.
 A couple of scripts exist to run benchmarks and profiles:
diff --git a/obnam/obnam-benchmark.1.txt b/obnam/obnam-benchmark.1.txt
index c148220..df926c5 100644
--- a/obnam/obnam-benchmark.1.txt
+++ b/obnam/obnam-benchmark.1.txt
@@ -7,39 +7,40 @@ NAME
 
 SYNOPSIS
        obnam-benchmark	     [--config=FILE]	   [--description=DESCRIPTION]
-       [--dump-config]	[--dump-setting-names]	 [--generate-manpage=TEMPLATE]
-       [--generations=N]	[-h]	   [--help]	  [--larch-branch=DIR]
-       [--list-config-files] [--log=FILE]  [--log-keep=N]  [--log-level=LEVEL]
-       [--log-max=SIZE]       [--no-default-configs]	  [--obnam-branch=DIR]
-       [--output=FILE]	[--results=DIR]  [--seivot-branch=DIR]	 [--size=PAIR]
-       [--use-existing=DIR]	 [--use-sftp-repository]     [--use-sftp-root]
-       [--version] [--wiki=DIR] [--with-encryption]
+       [--dump-config]	[--dump-memory-profile=METHOD]	[--dump-setting-names]
+       [--generate-manpage=TEMPLATE]	 [--generations=N]    [-h]    [--help]
+       [--larch-branch=DIR] [--list-config-files] [--log=FILE]	[--log-keep=N]
+       [--log-level=LEVEL]	 [--log-max=SIZE]	[--no-default-configs]
+       [--obnam-branch=DIR]	     [--output=FILE]	       [--results=DIR]
+       [--seivot-branch=DIR]	  [--sftp-delay=SFTP-DELAY]	 [--size=PAIR]
+       [--use-existing=DIR]	[--use-sftp-repository]      [--use-sftp-root]
+       [--verify] [--version] [--wiki=DIR] [--with-encryption] [FILE]...
 
 DESCRIPTION
-       obnam-benchmark benchmarks the obnam(1) backup application, by  measur‐
-       ing  how  much  time  it takes to do a backup, restore, etc, in various
-       scenarios.  obnam-benchmark uses the seivot(1) tool for	actually  run‐
-       ning  the  benchmarks, but makes some helpful assumptions about things,
+       obnam-benchmark	benchmarks the obnam(1) backup application, by measur‐
+       ing how much time it takes to do a backup,  restore,  etc,  in  various
+       scenarios.   obnam-benchmark  uses the seivot(1) tool for actually run‐
+       ning the benchmarks, but makes some helpful assumptions	about  things,
        to make it simpler to run than running seivot directly.
 
-       Benchmarks are run using two different usage profiles:  mailspool  (all
-       files  are  small), and mediaserver (all files are big).  For each pro‐
-       file, test data of the desired total size is generated, backed up,  and
-       then  several  incremental  generations are backed up, each adding some
-       more generated test data.  Then other operations are  run  against  the
-       backup  repository:  restoring,	listing  the contents of, and removing
+       Benchmarks  are	run using two different usage profiles: mailspool (all
+       files are small), and mediaserver (all files are big).  For  each  pro‐
+       file,  test data of the desired total size is generated, backed up, and
+       then several incremental generations are backed up,  each  adding  some
+       more  generated	test  data.  Then other operations are run against the
+       backup repository: restoring, listing the  contents  of,  and  removing
        each generation.
 
-       The result of the benchmark is a  .seivot  file	per  profile,  plus  a
-       Python  profiler  file  for  each  run  of  obnam.  These are stored in
+       The  result  of	the  benchmark	is  a .seivot file per profile, plus a
+       Python profiler file for each  run  of  obnam.	These  are  stored  in
        ../benchmarks.  A set of .seivot files can be summarized for comparison
-       with  seivots-summary(1).   The	profiling files can be viewed with the
+       with seivots-summary(1).  The profiling files can be  viewed  with  the
        usual Python tools: see the pstats module.
 
        The benchmarks are run against a version of obnam checked out from ver‐
-       sion  control.	It  is	not  (currently) possible to run the benchmark
-       against an installed version of obnam.  Also the larch Python  library,
-       which  obnam  needs, needs to be checked out from version control.  The
+       sion control.  It is not (currently)  possible  to  run	the  benchmark
+       against	an installed version of obnam.	Also the larch Python library,
+       which obnam needs, needs to be checked out from version	control.   The
        --obnam-branch and --larch-branch options set the locations, if the de‐
        faults are not correct.
 
@@ -53,6 +54,10 @@ OPTIONS
        --dump-config
 	      write out the entire current configuration
 
+       --dump-memory-profile=METHOD
+	      make memory profiling dumps using METHOD, which is one of: none,
+	      simple, meliae, or heapy (default: simple)
+
        --dump-setting-names
 	      write out all names of settings and quit
 
@@ -72,13 +77,14 @@ OPTIONS
 	      list all possible config files

(Diff truncated)
Finish split-off of Obnam front page into subpages.
diff --git a/obnam.mdwn b/obnam.mdwn
index a6bc752..0596d84 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -22,8 +22,13 @@ Some **features** that may interest you:
 
 See the [[tutorial]] for examples of how to use Obnam.
   
-More information
-----------------
+* [[Status and support|status]]
+* [[Download]]
+* [[Contact]]
+* [[Feature requests|wishlist]]
+
+Documentation
+-------------
 
 * [[README]] (updated at release time)
 * [[NEWS]] (updated at release time)
@@ -32,107 +37,8 @@ More information
 * [[Roadmap for 1.0|roadmap-for-1.0]]
 * [[FAQ]]
 
-Status and support
-------
-
-Obnam is currently in BETA. It is feature complete,
-but may be slow and buggy. There are no known bugs that would corrupt
-backed up data, or prevent it from being restored.
-(See [[NEWS]] for release notes.)
-
-If you find a bug or other problem, please report it!
-
-* E-mail to the <mailto:obnam@braawi.org> mailing list.
-* On IRC via the `#obnam` channel.
-
-See "Contact" below for more instructions on the mailing list and
-IRC channel.
-
-This is a free software project. Lars as the author will provide 
-support as well as he can (but no guarantees), and users may support 
-themselves, or each other, or may buy support from whomever they like. 
-(Lars is happy to sell some, for example.)
-
-Download
---------
-
-* [direct download](http://code.liw.fi/debian/pool/main/o/obnam/);
-  includes source code, and Debian source and binary packages for
-  i386, amd64, and armel architectures (squeeze release)
-* [using apt](http://liw.fi/code/):
-
-    `deb http://code.liw.fi/debian squeeze main`
-
-* For Ubuntu, see [Chris's 
-  PPA](https://launchpad.net/~chris-bigballofwax/+archive/obnam-ppa/).
-
-* from version control:
-
-    `bzr get http://code.liw.fi/obnam/bzr/trunk/`
-
-The code is licensed under GNU General Public License version 3, or later.
-
-Contact
--------
-
-* Mailing list: mail obnam-help@braawi.org for instructions.
-  * [Archive](http://lists.liw.fi/obnam@braawi.org/threads.html)
-  * [Gname](nntp://news.gmane.org/gmane.comp.sysutils.backup.obnam)
-* [Obnam on identi.ca](http://identi.ca/liw/tag/obnam)
-* `#obnam` on `irc.oftc.net` for IRC discussions about Obnam
-* [Lars's blog posts about Obnam](http://blog.liw.fi/tag/obnam/)
-  and [btree](http://blog.liw.fi/tag/btree/).
-* Also, [Lars's private journal entries](http://liw.fi/obnam/journal-dump/) 
-  about obnam and btree.
-
-Development
------------
-
-**Contributions are welcome.** Every level of contribution is most
-appreciated: bug reports, spelling and grammar fixes, code patches,
-questions on how to get started, offers to run a continuous integration
-server, etc. See [[README]] for information
-on how to modify the code. and ask on the mailing list or on IRC for
-anything else. If anything's unclear, ask!
-
-Things to do, if you want to help:
-
-* Review manual page. It is easy for documentation to get
-  out of date. Pointing out problems is helpful.
-* Code review, both of obnam and the larch btree library.
-* Benchmarking.
-* Add support for translations.
-* More! Add here your own ideas.
-
-Other stuff:
-
-* [[Obnam on-disk data structures|ondisk]]
-* Repository [[encryption]] and [[signing]]
-* Repository [[locking]]
-* [Bugs](http://code.liw.fi/obnam/bugs/)
-  - see [code.liw.fi](http://liw.fi/code/) for instructions
-* Benchmarks:
-  * [[specification|obnam/benchmarkspec]]
-  * [[recent benchmarks|benchmark-summary.txt]]
-  * [[slightly less ancient benchmarks|benchmarks]] (no longer updated)
-  * [[ancient benchmarks|benchmarkreport]] (no longer updated)
-* [[Obnam release procedure|obnam/release]] 
-
-Dependencies:
-
-* larch: <http://liw.fi/larch/>
-* python-lru: <http://liw.fi/lru/>
-* ttystatus: <http://liw.fi/ttystatus/>
-* CoverageTestRunner: <http://liw.fi/coverage-test-runner/>
-  (you only need this for running the test suite)
-* extrautils: <http://liw.fi/extrautils/>
-
-Feature requests
-----------------
-
-* FUSE filesystem for restoring data.
-
 Links
 -----
 
 * [Cache Directory Caching Standard](http://www.bford.info/cachedir/)
+

Obnam FAQ: Alice and Bob sharing repository but not data.
diff --git a/obnam/faq.mdwn b/obnam/faq.mdwn
index 8ff584b..71f30fd 100644
--- a/obnam/faq.mdwn
+++ b/obnam/faq.mdwn
@@ -1,5 +1,17 @@
 [[!meta title="Obnam FAQ"]]
 
+Can Alice and Bob share repository without sharing file data?
+-------------------------------------------------------------
+
+This does work particularly well. Obnam does not currently support it
+at all. On a conceptual level, it could work, by turning all de-duplication
+off, and having Alice and Bob encrypt their own chunks only with their
+own, separate keys.
+
+However, it would be simpler to just have a separate repository for
+each of them. That would also prevent either of them to remove the
+other's files.
+
 What does the name "Obnam" mean?
 --------------------------------
 

Split obnam front page into subpages.
diff --git a/obnam/contact.mdwn b/obnam/contact.mdwn
new file mode 100644
index 0000000..489ae8d
--- /dev/null
+++ b/obnam/contact.mdwn
@@ -0,0 +1,13 @@
+Contact
+-------
+
+* Mailing list: mail obnam-help@braawi.org for instructions.
+  * [Archive](http://lists.liw.fi/obnam@braawi.org/threads.html)
+  * [Gname](nntp://news.gmane.org/gmane.comp.sysutils.backup.obnam)
+* [Obnam on identi.ca](http://identi.ca/liw/tag/obnam)
+* `#obnam` on `irc.oftc.net` for IRC discussions about Obnam
+* [Lars's blog posts about Obnam](http://blog.liw.fi/tag/obnam/)
+  and [btree](http://blog.liw.fi/tag/btree/).
+* Also, [Lars's private journal entries](http://liw.fi/obnam/journal-dump/) 
+  about obnam and btree.
+
diff --git a/obnam/development.mdwn b/obnam/development.mdwn
new file mode 100644
index 0000000..bb39bd0
--- /dev/null
+++ b/obnam/development.mdwn
@@ -0,0 +1,42 @@
+Development
+-----------
+
+**Contributions are welcome.** Every level of contribution is most
+appreciated: bug reports, spelling and grammar fixes, code patches,
+questions on how to get started, offers to run a continuous integration
+server, etc. See [[README]] for information
+on how to modify the code. and ask on the mailing list or on IRC for
+anything else. If anything's unclear, ask!
+
+Things to do, if you want to help:
+
+* Review manual page. It is easy for documentation to get
+  out of date. Pointing out problems is helpful.
+* Code review, both of obnam and the larch btree library.
+* Benchmarking.
+* Add support for translations.
+* More! Add here your own ideas.
+
+Other stuff:
+
+* [[Obnam on-disk data structures|ondisk]]
+* Repository [[encryption]] and [[signing]]
+* Repository [[locking]]
+* [Bugs](http://code.liw.fi/obnam/bugs/)
+  - see [code.liw.fi](http://liw.fi/code/) for instructions
+* Benchmarks:
+  * [[specification|obnam/benchmarkspec]]
+  * [[recent benchmarks|benchmark-summary.txt]]
+  * [[slightly less ancient benchmarks|benchmarks]] (no longer updated)
+  * [[ancient benchmarks|benchmarkreport]] (no longer updated)
+* [[Obnam release procedure|obnam/release]] 
+
+Dependencies:
+
+* larch: <http://liw.fi/larch/>
+* python-lru: <http://liw.fi/lru/>
+* ttystatus: <http://liw.fi/ttystatus/>
+* CoverageTestRunner: <http://liw.fi/coverage-test-runner/>
+  (you only need this for running the test suite)
+* extrautils: <http://liw.fi/extrautils/>
+
diff --git a/obnam/download.mdwn b/obnam/download.mdwn
new file mode 100644
index 0000000..a7b638b
--- /dev/null
+++ b/obnam/download.mdwn
@@ -0,0 +1,19 @@
+Download
+--------
+
+* [direct download](http://code.liw.fi/debian/pool/main/o/obnam/);
+  includes source code, and Debian source and binary packages for
+  i386, amd64, and armel architectures (squeeze release)
+* [using apt](http://liw.fi/code/):
+
+    `deb http://code.liw.fi/debian squeeze main`
+
+* For Ubuntu, see [Chris's 
+  PPA](https://launchpad.net/~chris-bigballofwax/+archive/obnam-ppa/).
+
+* from version control:
+
+    `bzr get http://code.liw.fi/obnam/bzr/trunk/`
+
+The code is licensed under GNU General Public License version 3, or later.
+
diff --git a/obnam/status.mdwn b/obnam/status.mdwn
new file mode 100644
index 0000000..03b862e
--- /dev/null
+++ b/obnam/status.mdwn
@@ -0,0 +1,21 @@
+Status and support
+------
+
+Obnam is currently in BETA. It is feature complete,
+but may be slow and buggy. There are no known bugs that would corrupt
+backed up data, or prevent it from being restored.
+(See [[NEWS]] for release notes.)
+
+If you find a bug or other problem, please report it!
+
+* E-mail to the <mailto:obnam@braawi.org> mailing list.
+* On IRC via the `#obnam` channel.
+
+See [[contact page|contact]] for more instructions on the mailing list and
+IRC channel.
+
+This is a free software project. Lars as the author will provide 
+support as well as he can (but no guarantees), and users may support 
+themselves, or each other, or may buy support from whomever they like. 
+(Lars is happy to sell some, for example.)
+
diff --git a/obnam/wishlist.mdwn b/obnam/wishlist.mdwn
new file mode 100644
index 0000000..ee1058b
--- /dev/null
+++ b/obnam/wishlist.mdwn
@@ -0,0 +1,5 @@
+Feature requests
+----------------
+
+* FUSE filesystem for restoring data.
+

Update obnam locking spec based on feedback from mailing list.
diff --git a/obnam/locking.mdwn b/obnam/locking.mdwn
index 24fe4b8..e20bd49 100644
--- a/obnam/locking.mdwn
+++ b/obnam/locking.mdwn
@@ -6,7 +6,7 @@ Obnam supports multiple clients backing up to the same repository at
 the same time. It further allows the clients to share data, so that
 if Alice has backed up a large file, and Bob has the same file, he
 does not need to actually upload the file a second time to the backup
-repository.
+repository. (See [[ondisk]] for more details of on-disk data structures.)
 
 For Alice and Bob not to overwrite each others' changes to shared
 data, there needs to be some locking, so that only one of them can
@@ -68,7 +68,8 @@ read-only client can treat any failures due to concurrent access
 the same way it treats other failures: it can try to restore as much
 as it can, or it can give up. Locking does not help against bad sectors
 on the repository. Not having to lock for read-only access will allow
-faster access.
+faster access and avoids having a long-running read-only operation locking
+out new backups.
 
 Destructive access will need locking. Thus, each B-tree will have a
 lock file at its root (called 'lock'): existence of the file indicates
@@ -77,15 +78,13 @@ the tree is locked. Only one writer can have a lock at the same time.
 The client list B-tree only needs to be changed when a client is added
 or removed from the tree, or its encryption details are changed. The
 other shared B-trees need to be changed during every backup run of every
-client.
+client. The per-client B-trees need to be locked during backup and forget
+operations for that client. All B-trees will need to be locked while
+an fsck runs. (Per-client B-trees need to be locked to protect against
+concurrent backup, forget, and fsck operations, for example.)
 
-For simplicity, there will be only two kinds of locks: one for the shared
-B-trees, and one for each per-client B-tree. The shared B-tree lock is
-implemented at the repository level: a file called `lock` at the root
-of the repository.
-
-The per-client B-trees are locked by a file called `lock` at the root
-of the B-tree directory.
+Each B-tree is locked separately, by creating a file called `lock`
+inside its directory.
 
 Repository metadata
 -------------------
@@ -103,17 +102,36 @@ client list B-tree is locked.
 Avoiding deadlocks and reducing lock contention on shared stuff
 ---------------------------------------------------------------
 
-To avoid deadlocks, every client must create locks in the same order:
-first the per-client lock or locks, then the global lock. fsck may
-need to lock each client: if so, it locks clients in client-id order.
-
-Locking shared B-trees first would not work, because a client making
-a backup needs to lock its own B-tree first, and only lock the shared
-B-trees while it actually updates them at commit time.
-
-In other words, a client will pool its updates to the shared B-trees
+To avoid deadlocks, every client must create locks in the same order.
+
+1. The client list B-tree.
+1. Any per-client B-trees, in the order of their directory basenames.
+1. Any other shared B-trees, in the order of their directory basenames.
+
+(Directory basenames are ordered byte by byte, using unsigned bytes.)
+
+There are several scenarios in which a client may require a lock:
+
+* adding a new client
+  - lock client list, add new client to it
+  - create, then lock per-client B-tree
+  - unlock everything
+* making backups for a client
+  - lock per-client B-tree, add new metadata
+  - lock chunklist and chunksums B-trees, update with info about new chunks,
+    unlock (possibly do this several times, for checkpoints)
+  - unlock per-client B-tree
+* forgetting backups for a client
+  - lock per-client B-tree, remove generations, gather list of chunks
+    that may need to be deleted, unlock
+  - lock chunklist and chunksums, update about chunks that aren't used
+    by the client anymore, possibly remove chunks from disk, unlock
+* fsck for repository
+  - lock everything, fsck, unlock everything
+
+When making backups, a client will pool its updates to the shared B-trees
 until it is ready to do all of them in a batch, typically at the end
-of a backup, or at a checkpoing generation. This way, it can keep
+of a backup, or at a checkpoint generation. This way, it can keep
 the shared lock for only a short while. If the client crashes before
 it can update the shared B-trees, it is unfortunate, but not 
 catastrophic: it will have stored some chunks in the repository that

Update benchmark summary.
diff --git a/obnam/benchmark-summary.txt b/obnam/benchmark-summary.txt
index 619712d..0873d13 100644
--- a/obnam/benchmark-summary.txt
+++ b/obnam/benchmark-summary.txt
@@ -3,218 +3,242 @@ Profile: mailspool 48/5 MiB (unencrypted)
 
 Operation: backup
 
-obnam  larch  gen0    gen0   gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
-revno  revno     s  Mbit/s    MiB        s   Mbit/s      MiB        MiB       MiB      MiB                                    
+obnam  larch  gen0    gen0   gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc          
+revno  revno     s  Mbit/s    MiB        s   Mbit/s      MiB        MiB       MiB      MiB                                        
 
- 1019    284  58.7     6.8  170.6      9.3      4.3    206.6       47.7      52.8      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284  66.5     6.0  170.4     10.0      4.0    207.5       47.7      52.8      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285  72.8     5.5  169.6     13.6      2.9    209.4       47.7      52.8      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284  58.7     6.8  170.6      9.3      4.3    206.6       47.7      52.8      0.0  xander-mirror-1019-284  Obnam 0.18    
+ 1055    284  66.5     6.0  170.4     10.0      4.0    207.5       47.7      52.8      0.0  xander-mirror-1055-284  Obnam 0.19    
+ 1068    285  72.8     5.5  169.6     13.6      2.9    209.4       47.7      52.8      0.0  xander-mirror-1068-285  Obnam 0.20    
+ 1094    294  61.6     6.5  170.9     11.1      3.6    204.7       47.7      52.8      0.0  xander-mirror-1094-294  Obnam 0.22-ish
 
 Operation: restore
 
-obnam  larch  gen0    gen0   gen0  slowest  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno     s  Mbit/s    MiB        s   Mbit/s      MiB       MiB      MiB                                    
+obnam  larch  gen0    gen0   gen0  slowest  slowest  biggest  r-writes  r-reads  branch                  desc          
+revno  revno     s  Mbit/s    MiB        s   Mbit/s      MiB       MiB      MiB                                        
 
- 1019    284  33.1    12.1  135.5     34.4      1.2    142.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284  57.4     7.0  136.4     41.9      1.0    143.2       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285  61.6     6.5  137.1     42.0      1.0    143.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284  33.1    12.1  135.5     34.4      1.2    142.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18    
+ 1055    284  57.4     7.0  136.4     41.9      1.0    143.2       0.0      0.0  xander-mirror-1055-284  Obnam 0.19    
+ 1068    285  61.6     6.5  137.1     42.0      1.0    143.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20    
+ 1094    294  32.7    12.2  137.4     34.7      1.2    143.3       0.0     51.9  xander-mirror-1094-294  Obnam 0.22-ish
 
 Operation: list_files
 
-obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno     s    MiB        s      MiB       MiB      MiB                                    
+obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc          
+revno  revno     s    MiB        s      MiB       MiB      MiB                                        
 
- 1019    284   6.2  125.1      6.8    131.8       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284   6.2  126.0      6.9    132.8       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285   6.7  126.8      7.3    133.0       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284   6.2  125.1      6.8    131.8       0.0      0.0  xander-mirror-1019-284  Obnam 0.18    
+ 1055    284   6.2  126.0      6.9    132.8       0.0      0.0  xander-mirror-1055-284  Obnam 0.19    
+ 1068    285   6.7  126.8      7.3    133.0       0.0      0.0  xander-mirror-1068-285  Obnam 0.20    
+ 1094    294   6.6  127.3      7.2    133.2       0.0      3.7  xander-mirror-1094-294  Obnam 0.22-ish
 
 Operation: forget
 
-obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno     s    MiB        s      MiB       MiB      MiB                                    
+obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc          
+revno  revno     s    MiB        s      MiB       MiB      MiB                                        
 
- 1019    284   3.2  166.0      2.8    131.4       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284   3.2  163.5      2.8    130.9       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285   3.2  165.7      2.8    131.6       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284   3.2  166.0      2.8    131.4       0.0      0.0  xander-mirror-1019-284  Obnam 0.18    
+ 1055    284   3.2  163.5      2.8    130.9       0.0      0.0  xander-mirror-1055-284  Obnam 0.19    
+ 1068    285   3.2  165.7      2.8    131.6       0.0      0.0  xander-mirror-1068-285  Obnam 0.20    
+ 1094    294   2.6  154.3      2.2    124.6       0.1      2.1  xander-mirror-1094-294  Obnam 0.22-ish
 
 Profile: mediaserver 48/5 MiB (unencrypted)
 -------------------------------------------
 
 Operation: backup
 
-obnam  larch  gen0    gen0  gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
-revno  revno     s  Mbit/s   MiB        s   Mbit/s      MiB        MiB       MiB      MiB                                    
+obnam  larch  gen0    gen0  gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc          
+revno  revno     s  Mbit/s   MiB        s   Mbit/s      MiB        MiB       MiB      MiB                                        
 
- 1019    284   2.3   173.9  74.6      0.5     80.0    105.5       47.7      48.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284   2.1   190.5  73.8      0.5     80.0    103.5       47.7      48.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285   2.0   200.0  73.8      0.5     80.0    103.6       47.7      48.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284   2.3   173.9  74.6      0.5     80.0    105.5       47.7      48.0      0.0  xander-mirror-1019-284  Obnam 0.18    
+ 1055    284   2.1   190.5  73.8      0.5     80.0    103.5       47.7      48.0      0.0  xander-mirror-1055-284  Obnam 0.19    
+ 1068    285   2.0   200.0  73.8      0.5     80.0    103.6       47.7      48.0      0.0  xander-mirror-1068-285  Obnam 0.20    
+ 1094    294   2.8   142.9  74.8      0.5     80.0    105.6       47.7      48.0      0.0  xander-mirror-1094-294  Obnam 0.22-ish
 
 Operation: restore
 
-obnam  larch  gen0    gen0  gen0  slowest  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno     s  Mbit/s   MiB        s   Mbit/s      MiB       MiB      MiB                                    
+obnam  larch  gen0    gen0  gen0  slowest  slowest  biggest  r-writes  r-reads  branch                  desc          
+revno  revno     s  Mbit/s   MiB        s   Mbit/s      MiB       MiB      MiB                                        
 
- 1019    284   2.1   190.5  58.4      2.0     20.0     58.4       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284   2.2   181.8  58.4      2.5     16.0     58.4       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285   2.6   153.8  58.4      2.4     16.7     58.4       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284   2.1   190.5  58.4      2.0     20.0     58.4       0.0      0.0  xander-mirror-1019-284  Obnam 0.18    
+ 1055    284   2.2   181.8  58.4      2.5     16.0     58.4       0.0      0.0  xander-mirror-1055-284  Obnam 0.19    
+ 1068    285   2.6   153.8  58.4      2.4     16.7     58.4       0.0      0.0  xander-mirror-1068-285  Obnam 0.20    
+ 1094    294   2.7   148.1  58.1      2.9     13.8     58.1       0.0     47.9  xander-mirror-1094-294  Obnam 0.22-ish
 
 Operation: list_files
 
-obnam  larch  gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno     s   MiB        s      MiB       MiB      MiB                                    
+obnam  larch  gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc          
+revno  revno     s   MiB        s      MiB       MiB      MiB                                        
 
- 1019    284   0.2  57.2      0.2     57.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284   0.2  57.3      0.2     57.3       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285   0.2  57.4      0.2     57.4       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284   0.2  57.2      0.2     57.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18    
+ 1055    284   0.2  57.3      0.2     57.3       0.0      0.0  xander-mirror-1055-284  Obnam 0.19    
+ 1068    285   0.2  57.4      0.2     57.4       0.0      0.0  xander-mirror-1068-285  Obnam 0.20    
+ 1094    294   0.2  57.1      0.2     57.0       0.0      0.1  xander-mirror-1094-294  Obnam 0.22-ish
 
 Operation: forget
 
-obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno     s    MiB        s      MiB       MiB      MiB                                    
+obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc          
+revno  revno     s    MiB        s      MiB       MiB      MiB                                        
 
- 1019    284   0.4  108.2      0.3    106.1       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284   0.4  108.2      0.3    103.2       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285   0.4  102.6      0.3    102.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284   0.4  108.2      0.3    106.1       0.0      0.0  xander-mirror-1019-284  Obnam 0.18    
+ 1055    284   0.4  108.2      0.3    103.2       0.0      0.0  xander-mirror-1055-284  Obnam 0.19    
+ 1068    285   0.4  102.6      0.3    102.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20    
+ 1094    294   0.3  102.3      0.3    102.0       0.1      0.2  xander-mirror-1094-294  Obnam 0.22-ish
 
 Profile: mailspool 477/48 MiB (unencrypted)
 -------------------------------------------
 
 Operation: backup
 
-obnam  larch    gen0    gen0    gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
-revno  revno       s  Mbit/s     MiB        s   Mbit/s      MiB        MiB       MiB      MiB                                    
+obnam  larch    gen0    gen0    gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc          
+revno  revno       s  Mbit/s     MiB        s   Mbit/s      MiB        MiB       MiB      MiB                                        
 
- 1019    284   986.1     4.1  1005.7     88.2      4.5    548.7      476.8     525.4      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284  1383.8     2.9  1002.3     94.3      4.2    541.2      476.8     525.4      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285  1293.0     3.1  1003.8    126.0      3.2    543.0      476.8     525.4      0.1  xander-mirror-1068-285  Obnam 0.20
+ 1019    284   986.1     4.1  1005.7     88.2      4.5    548.7      476.8     525.4      0.0  xander-mirror-1019-284  Obnam 0.18    
+ 1055    284  1383.8     2.9  1002.3     94.3      4.2    541.2      476.8     525.4      0.0  xander-mirror-1055-284  Obnam 0.19    
+ 1068    285  1293.0     3.1  1003.8    126.0      3.2    543.0      476.8     525.4      0.1  xander-mirror-1068-285  Obnam 0.20    
+ 1094    294  1131.1     3.5  1003.3    105.9      3.8    533.8      476.8     525.4      0.0  xander-mirror-1094-294  Obnam 0.22-ish
 
 Operation: restore
 
-obnam  larch   gen0    gen0   gen0  slowest  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno      s  Mbit/s    MiB        s   Mbit/s      MiB       MiB      MiB                                    
+obnam  larch   gen0    gen0   gen0  slowest  slowest  biggest  r-writes  r-reads  branch                  desc          
+revno  revno      s  Mbit/s    MiB        s   Mbit/s      MiB       MiB      MiB                                        
 
- 1019    284  323.3    12.4  438.6    335.5      1.2    439.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284  521.5     7.7  441.3    376.8      1.1    437.6       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285  498.8     8.0  441.1    377.6      1.1    440.5       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284  323.3    12.4  438.6    335.5      1.2    439.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18    
+ 1055    284  521.5     7.7  441.3    376.8      1.1    437.6       0.0      0.0  xander-mirror-1055-284  Obnam 0.19    
+ 1068    285  498.8     8.0  441.1    377.6      1.1    440.5       0.0      0.0  xander-mirror-1068-285  Obnam 0.20    
+ 1094    294  664.0     6.0  438.1    390.1      1.0    438.6       0.0    532.2  xander-mirror-1094-294  Obnam 0.22-ish
 
 Operation: list_files
 
-obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno     s    MiB        s      MiB       MiB      MiB                                    
+obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc          
+revno  revno     s    MiB        s      MiB       MiB      MiB                                        
 
- 1019    284  60.1  351.4     66.3    352.3       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284  60.4  351.6     66.8    351.6       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285  64.8  351.2     71.7    351.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284  60.1  351.4     66.3    352.3       0.0      0.0  xander-mirror-1019-284  Obnam 0.18    
+ 1055    284  60.4  351.6     66.8    351.6       0.0      0.0  xander-mirror-1055-284  Obnam 0.19    
+ 1068    285  64.8  351.2     71.7    351.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20    
+ 1094    294  64.4  348.5     71.4    350.7       0.0     50.0  xander-mirror-1094-294  Obnam 0.22-ish
 
 Operation: forget
 
-obnam  larch   gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno      s    MiB        s      MiB       MiB      MiB                                    
+obnam  larch   gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc          
+revno  revno      s    MiB        s      MiB       MiB      MiB                                        
 
- 1019    284  173.1  400.2    153.9    327.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284  221.0  415.8    155.2    313.8       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285  174.3  399.9    156.5    322.3       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284  173.1  400.2    153.9    327.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18    
+ 1055    284  221.0  415.8    155.2    313.8       0.0      0.0  xander-mirror-1055-284  Obnam 0.19    
+ 1068    285  174.3  399.9    156.5    322.3       0.0      0.0  xander-mirror-1068-285  Obnam 0.20    
+ 1094    294  219.2  462.5    157.6    365.6       0.1     10.5  xander-mirror-1094-294  Obnam 0.22-ish
 
 Profile: mediaserver 477/48 MiB (unencrypted)
 ---------------------------------------------
 
 Operation: backup
 
-obnam  larch  gen0    gen0  gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
-revno  revno     s  Mbit/s   MiB        s   Mbit/s      MiB        MiB       MiB      MiB                                    
+obnam  larch  gen0    gen0  gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc          

(Diff truncated)
Add note about draftness.
diff --git a/obnam/locking.mdwn b/obnam/locking.mdwn
index ef35b91..24fe4b8 100644
--- a/obnam/locking.mdwn
+++ b/obnam/locking.mdwn
@@ -1,5 +1,7 @@
 [[!meta title="Locking in Obnam repositories"]]
 
+**THIS IS A DRAFT**
+
 Obnam supports multiple clients backing up to the same repository at
 the same time. It further allows the clients to share data, so that
 if Alice has backed up a large file, and Bob has the same file, he

Add design document for repository locking.
diff --git a/obnam.mdwn b/obnam.mdwn
index f7c6ffa..a6bc752 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -108,6 +108,7 @@ Other stuff:
 
 * [[Obnam on-disk data structures|ondisk]]
 * Repository [[encryption]] and [[signing]]
+* Repository [[locking]]
 * [Bugs](http://code.liw.fi/obnam/bugs/)
   - see [code.liw.fi](http://liw.fi/code/) for instructions
 * Benchmarks:
diff --git a/obnam/locking.mdwn b/obnam/locking.mdwn
new file mode 100644
index 0000000..ef35b91
--- /dev/null
+++ b/obnam/locking.mdwn
@@ -0,0 +1,137 @@
+[[!meta title="Locking in Obnam repositories"]]
+
+Obnam supports multiple clients backing up to the same repository at
+the same time. It further allows the clients to share data, so that
+if Alice has backed up a large file, and Bob has the same file, he
+does not need to actually upload the file a second time to the backup
+repository.
+
+For Alice and Bob not to overwrite each others' changes to shared
+data, there needs to be some locking, so that only one of them can
+modify the data structures at the same time.
+
+The repository has five different classes of data:
+
+* metadata about the repository (shared, needs locking)
+  - currently this is the version number of the repository format
+* a list of clients (shared, needs locking)
+* file data chunks (shared, but does not need locking)
+* shared metadata about file chunks (shared, needs locking)
+* per-client file metadata (not shared, but does need locking)
+
+Another way to consider the data is as follows:
+
+* shared chunk storage
+* shared and per-client B-trees
+* repository metadata
+
+We can discuss the locking for each of these groups separately
+
+Shared chunk storage
+--------------------
+
+The shared chunk storage consists of a directory tree, where chunks are
+stored in files named after the chunk identifier. When a client is 
+making a backup, they only ever add chunks, and they do that by picking
+a chunk identifier by random, and creating a file with that name. If
+the file creation fails, the chunk id was already in use, and the client
+picks a new one by random.
+
+This means that the filesystem takes care of atomicity, and Obnam does
+not need to care about that. Adding chunks is a lock-free operation even
+when multiple clients are backing up at the same time.
+
+Read-only access to the chunks also does not require any locking,
+obviously.
+
+The operations that can delete chunks (forget, fsck) can also do without
+locking the chunk storage. They lock the relevant B-trees, so that other
+clients do not at the same time try to change the state of the repository,
+and this protects the shared chunks as well.
+
+Shared and per-client B-trees
+-----------------------------
+
+There are several shared B-trees: the list of clients, the mapping of
+chunk identifiers to chunk sums, and the mapping of chunk sums to
+chunk ids. There is one B-tree per client. From a locking point of
+view, they can be treated identically: if nothing else, even the
+per-client tree can be considered shared, when the backup server is
+doing a repository-wide fsck, for example.
+
+Read-only access to the B-trees should not be locked. This is not entirely
+safe: Alice may do read-only access (e.g., during a restore), while
+Bob is doing a destructive operation (e.g., forget). However, the
+read-only client can treat any failures due to concurrent access
+the same way it treats other failures: it can try to restore as much
+as it can, or it can give up. Locking does not help against bad sectors
+on the repository. Not having to lock for read-only access will allow
+faster access.
+
+Destructive access will need locking. Thus, each B-tree will have a
+lock file at its root (called 'lock'): existence of the file indicates
+the tree is locked. Only one writer can have a lock at the same time.
+
+The client list B-tree only needs to be changed when a client is added
+or removed from the tree, or its encryption details are changed. The
+other shared B-trees need to be changed during every backup run of every
+client.
+
+For simplicity, there will be only two kinds of locks: one for the shared
+B-trees, and one for each per-client B-tree. The shared B-tree lock is
+implemented at the repository level: a file called `lock` at the root
+of the repository.
+
+The per-client B-trees are locked by a file called `lock` at the root
+of the B-tree directory.
+
+Repository metadata
+-------------------
+
+The repository metadata (the directory `metadata` at the root of
+the repository, not to be confused with the similar directories inside
+B-tree directories), may need to be locked against writes. For example,
+a future version of Obnam may provide a way to upgrade the repository
+format to a new version, and this requires locking against any changes
+to the repository.
+
+The repository metadata will be considered locked implicitly when the
+client list B-tree is locked.
+
+Avoiding deadlocks and reducing lock contention on shared stuff
+---------------------------------------------------------------
+
+To avoid deadlocks, every client must create locks in the same order:
+first the per-client lock or locks, then the global lock. fsck may
+need to lock each client: if so, it locks clients in client-id order.
+
+Locking shared B-trees first would not work, because a client making
+a backup needs to lock its own B-tree first, and only lock the shared
+B-trees while it actually updates them at commit time.
+
+In other words, a client will pool its updates to the shared B-trees
+until it is ready to do all of them in a batch, typically at the end
+of a backup, or at a checkpoing generation. This way, it can keep
+the shared lock for only a short while. If the client crashes before
+it can update the shared B-trees, it is unfortunate, but not 
+catastrophic: it will have stored some chunks in the repository that
+cannot be used for de-duplication, but no actual data is lost.
+
+Reliability and scalability testing of locking
+----------------------------------------------
+
+The reliability of locking will be tested by writing a script to do
+small backup generations, and running it concurrently many times 
+against the same repository. The script will verify that each client
+can restore every generation successfully after all generations have
+been backed up. Also, repository wide fsck will be run.
+
+The amount of data to back up in each generation shall vary for
+each client, so that they are less likely to get into lockstep.
+
+Another test will be to write a script that creates a lock file,
+increments a counter in a file, and then releases the lock, and
+repeates this some number of times, and then running many concurrent
+copies of this script. The counter must have the correct value at
+the end.
+

Add Obnam FUSE filesystem feature request.
diff --git a/obnam.mdwn b/obnam.mdwn
index 52bd339..f7c6ffa 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -126,6 +126,11 @@ Dependencies:
   (you only need this for running the test suite)
 * extrautils: <http://liw.fi/extrautils/>
 
+Feature requests
+----------------
+
+* FUSE filesystem for restoring data.
+
 Links
 -----
 

Use ASCII, not UTF-8 for manpage text.
Thanks to Peter Palfrader for pointing that out.
diff --git a/obnam/obnam.1.txt b/obnam/obnam.1.txt
index e9ed74d..6e57fda 100644
--- a/obnam/obnam.1.txt
+++ b/obnam/obnam.1.txt
@@ -24,12 +24,12 @@ SYNOPSIS
 DESCRIPTION
        obnam makes, restores, manipulates, and otherwise deals	with  backups.
        It  can	store  backups on a local disk or to a server via sftp.  Every
-       backup generation looks like a fresh snapshot, but is really  incremen‐
+       backup generation looks like a fresh snapshot, but is really  incremen-
        tal: the user does not need to worry whether it's a full backup or not.
        Only changed data is backed up, and if  a  chunk  of  data  is  already
        backed up in another file, that data is re-used.
 
-       The place where backed up data is placed is called the backup reposito‐
+       The place where backed up data is placed is called the backup reposito-
        ry.  A repository may be, for example, a directory on an  sftp  server,
        or  a  directory  on  a USB hard disk.  A single repository may contain
        backups from several clients.  Their data will intermingle as  if  they
@@ -39,59 +39,59 @@ DESCRIPTION
        obnam command line syntax consists of a command	possibly  followed  by
        arguments.  The commands are list below.
 
-       ·      backup makes a new backup.  The first time it is run, it makes a
+       o      backup makes a new backup.  The first time it is run, it makes a
 	      full backup, after that an incremental one.
 
-       ·      restore is the opposite of a backup.  It copies backed  up  data
+       o      restore is the opposite of a backup.  It copies backed  up  data
 	      from the backup repository to a target directory.
 
-       ·      clients lists the clients that are backed up to the repository.
+       o      clients lists the clients that are backed up to the repository.
 
-       ·      generations  lists  every  backup generation for a given client,
+       o      generations  lists  every  backup generation for a given client,
 	      plus some metadata about the generation.
 
-       ·      genids lists the identifier for every backup  generation	for  a
-	      given  client.  No other information is shown.  This can be use‐
+       o      genids lists the identifier for every backup  generation	for  a
+	      given  client.  No other information is shown.  This can be use-
 	      ful for scripting.
 
-       ·      ls lists the contents of a given generation, similar to ls-lAR.
+       o      ls lists the contents of a given generation, similar to ls-lAR.
 
-       ·      verify compares data in the backup with actual  user  data,  and
-	      makes  sures they are identical.	It is most useful to run imme‐
+       o      verify compares data in the backup with actual  user  data,  and
+	      makes  sures they are identical.	It is most useful to run imme-
 	      diately after a backup, to check that it	actually  worked.   It
-	      can  be run at any time, but if the user data has changed, veri‐
+	      can  be run at any time, but if the user data has changed, veri-
 	      fication fails even though the backup is OK.
 
-       ·      forget removes backup generations that are no longer wanted,  so
-	      that they don't use disk space.  Note that after a backup gener‐
+       o      forget removes backup generations that are no longer wanted,  so
+	      that they don't use disk space.  Note that after a backup gener-
 	      ation is removed the data can't be restored  anymore.   You  can
 	      either  specify the generations to remove by listing them on the
 	      command line, or use the --keep option to specify a  policy  for
 	      what to keep (everything else will be removed).
 
-       ·      fsck  checks  the internal consistency of the backup repository.
+       o      fsck  checks  the internal consistency of the backup repository.
 	      It verifies that all clients, generations,  directories,	files,
 	      and all file contents still exists in the backup repository.  It
 	      may take quite a long time to run.
 
-       ·      force-lock removes a lock file for a client in  the  repository.
+       o      force-lock removes a lock file for a client in  the  repository.
 	      You should only force a lock if you are sure no-one is accessing
 	      that client's data in the repository.   A  dangling  lock  might
 	      happen,  for  example,  if obnam loses its network connection to
 	      the backup repository.
 
-       ·      client-keys  lists  the  encryption  key	associated  with  each
+       o      client-keys  lists  the  encryption  key	associated  with  each
 	      client.
 
-       ·      list-keys  lists	the  keys  that can access the repository, and
+       o      list-keys  lists	the  keys  that can access the repository, and
 	      which toplevel directories each key can  access.	 Some  of  the
-	      toplevel directories are shared between clients, others are spe‐
+	      toplevel directories are shared between clients, others are spe-
 	      cific to a client.
 
-       ·      list-toplevels is like list-keys, but lists toplevels and  which
+       o      list-toplevels is like list-keys, but lists toplevels and  which
 	      keys can access them.
 
-       ·      add-key  adds  an encryption key to the repository.  By default,
+       o      add-key  adds  an encryption key to the repository.  By default,
 	      they key is added only to the shared toplevel  directories,  but
 	      it  can also be added to specific clients: list the names of the
 	      clients on the command line.  They key is given with the --keyid
@@ -99,7 +99,7 @@ DESCRIPTION
 	      the  key	id  can  access  the  backup  repository  (the	shared
 	      toplevels plus specified clients).
 
-       ·      remove-key  removes  a key from the shared toplevel directories,
+       o      remove-key  removes  a key from the shared toplevel directories,
 	      plus any clients specified on the command line.
 
    Making backups
@@ -109,10 +109,10 @@ DESCRIPTION
        with  files that have been changed or renamed since the previous backup
        run.  It also allows several backup clients to avoid uploading the same
        data.   If,  for example, everyone in the office has a copy of the same
-       sales brochures, only one copy needs to be stored in the backup reposi‐
+       sales brochures, only one copy needs to be stored in the backup reposi-
        tory.
 
-       Every  backup run is a generation.  In addition, obnam will make check‐
+       Every  backup run is a generation.  In addition, obnam will make check-
        point generations every now and then.  These are  exactly  like	normal
        generations,  but  are  not guaranteed to be a complete snapshot of the
        live data.  If the backup run needs to be aborted in  the  middle,  the
@@ -136,13 +136,13 @@ DESCRIPTION
 
        By default verification happens on all files.  You can also specify the
        files  to  be verified by listing them on the command line.  You should
-       specify the full paths to the files, not relative to the current direc‐
+       specify the full paths to the files, not relative to the current direc-
        tory.
 
        The  output lists files that fail verification for some reason.	If you
-       verify everything, it is likely that some files (e.g., parent  directo‐
+       verify everything, it is likely that some files (e.g., parent  directo-
        ries of backup root) may have changed without it being a problem.  Note
-       that you will need to specify the whole path to the files  or  directo‐
+       that you will need to specify the whole path to the files  or  directo-
        ries  to  be verified, not relative to the backup root.	You still need
        to specify at least one of the backup roots via the  --root  option  so
        that obnam will find the filesystem, in case it is a remote one.
@@ -156,7 +156,7 @@ DESCRIPTION
        where domain is a normal Internetl domain name,	port  is  an  optional
        port  number,  and path is a pathname on the server side.  Like bzr(1),
        but unlike the sftp URL standard, the pathname is absolute,  unless  it
-       starts  with /~/ in which case it is relative to the user's home direc‐
+       starts  with /~/ in which case it is relative to the user's home direc-
        tory on the server.
 
        See the EXAMPLES section for examples of URLs.
@@ -171,8 +171,8 @@ DESCRIPTION
        When not using the latest generation, you will need  to	specify  which
        one  you  need.	 This will be done with the --generation option, which
        takes a generation specification as its argument.  The specification is
-       either  the  word  latest,  meaning the latest generation (also the de‐
-       fault), or a number.  See the generations command to see  what  genera‐
+       either  the  word  latest,  meaning the latest generation (also the de-
+       fault), or a number.  See the generations command to see  what  genera-
        tions are available, and what their numbers are.
 
    Policy for keeping and removing backup generations
@@ -184,19 +184,19 @@ DESCRIPTION
        and a time period.  The time periods are h, d, w, m, and y,  for  hour,
        day, week, month, and year.
 
-       A policy of 30d means to keep the latest backup for each day, for thir‐
+       A policy of 30d means to keep the latest backup for each day, for thir-
        ty days.  Any backups in between will be removed, as will  any  backups
        older than thirty days.
 
        As  an  example,  assume  backups are taken every hour, on the hour: at
        00:00, 01:00, 02:00, and so on, until 23:00.  If the forget command  is
        run  at	23:15, with the above policy, it will keep the backup taken at
-       23:00 on each day, and remove every other backup that day.  It will al‐
+       23:00 on each day, and remove every other backup that day.  It will al-
        so remove backups older than 30 days.
 
        Note  that obnam will only inspect timestamps in the backup repository,
        and does not care what the actual current time is.  This means that  if
-       you  stop  making new backups, the existing ones won't be removed auto‐
+       you  stop  making new backups, the existing ones won't be removed auto-
        matically.  In essence, obnam pretends the current time is  just  after
        the latest backup when forget is run.
 
@@ -206,7 +206,7 @@ DESCRIPTION
        rule.
 
        For example, assume the same backup frequence as above, but a policy of
-       30d,52w.  This will keep the newest daily backup for each day for thir‐
+       30d,52w.  This will keep the newest daily backup for each day for thir-
        ty days, and the newest weekly backup for 52 weeks.  Because the hourly
        backups	will  be removed daily, before they have a chance to get saved
        by a weekly rule, the effect is that the 23:00 o'clock backup for  each
@@ -234,7 +234,7 @@ DESCRIPTION
        other sections are ignored).
 
        The long names of options are used as keys for configuration variables.
-       Any  setting that can be set from the command line can be set in a con‐
+       Any  setting that can be set from the command line can be set in a con-
        figuration file, in the [config] section.
 
        For example, the options in the following command line:
@@ -251,8 +251,7 @@ DESCRIPTION
 

(Diff truncated)
Fix release date in NEWS.
diff --git a/obnam/NEWS.mdwn b/obnam/NEWS.mdwn
index b2d578a..7712692 100644
--- a/obnam/NEWS.mdwn
+++ b/obnam/NEWS.mdwn
@@ -5,7 +5,7 @@ Obnam NEWS
 This file summarizes changes between releases of Obnam.
 
 
-Version 0.20.1, released UNRELEASED; a BETA release
+Version 0.20.1, released 2011-08-11; a BETA release
 -------------------------------------------------
 
 BUG FIXES:

Obnam 0.20.1.
diff --git a/obnam/NEWS.mdwn b/obnam/NEWS.mdwn
index 6349ad6..b2d578a 100644
--- a/obnam/NEWS.mdwn
+++ b/obnam/NEWS.mdwn
@@ -5,6 +5,14 @@ Obnam NEWS
 This file summarizes changes between releases of Obnam.
 
 
+Version 0.20.1, released UNRELEASED; a BETA release
+-------------------------------------------------
+
+BUG FIXES:
+
+* More cases of Unicode strings versus plain strings in filenames
+  over SFTP fixed. Thanks to Tapani Tarvainen.
+
 Version 0.20, released 2011-08-09; a BETA release
 -------------------------------------------------
 

Update benchmark summary report.
diff --git a/obnam/benchmark-summary.txt b/obnam/benchmark-summary.txt
index cee5db1..619712d 100644
--- a/obnam/benchmark-summary.txt
+++ b/obnam/benchmark-summary.txt
@@ -3,21 +3,21 @@ Profile: mailspool 48/5 MiB (unencrypted)
 
 Operation: backup
 
-obnam  larch    gen0   gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
-revno  revno  Mbit/s    MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
+obnam  larch  gen0    gen0   gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
+revno  revno     s  Mbit/s    MiB        s   Mbit/s      MiB        MiB       MiB      MiB                                    
 
- 1019    284     6.8  170.6      4.3    206.6       47.7      52.8      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284     6.0  170.4      4.0    207.5       47.7      52.8      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285     5.5  169.6      2.9    209.4       47.7      52.8      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284  58.7     6.8  170.6      9.3      4.3    206.6       47.7      52.8      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284  66.5     6.0  170.4     10.0      4.0    207.5       47.7      52.8      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285  72.8     5.5  169.6     13.6      2.9    209.4       47.7      52.8      0.0  xander-mirror-1068-285  Obnam 0.20
 
 Operation: restore
 
-obnam  larch    gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno  Mbit/s    MiB   Mbit/s      MiB       MiB      MiB                                    
+obnam  larch  gen0    gen0   gen0  slowest  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno     s  Mbit/s    MiB        s   Mbit/s      MiB       MiB      MiB                                    
 
- 1019    284    12.1  135.5      1.2    142.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284     7.0  136.4      1.0    143.2       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285     6.5  137.1      1.0    143.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284  33.1    12.1  135.5     34.4      1.2    142.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284  57.4     7.0  136.4     41.9      1.0    143.2       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285  61.6     6.5  137.1     42.0      1.0    143.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 Operation: list_files
 
@@ -42,21 +42,21 @@ Profile: mediaserver 48/5 MiB (unencrypted)
 
 Operation: backup
 
-obnam  larch    gen0  gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
-revno  revno  Mbit/s   MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
+obnam  larch  gen0    gen0  gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
+revno  revno     s  Mbit/s   MiB        s   Mbit/s      MiB        MiB       MiB      MiB                                    
 
- 1019    284   173.9  74.6     80.0    105.5       47.7      48.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284   190.5  73.8     80.0    103.5       47.7      48.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285   200.0  73.8     80.0    103.6       47.7      48.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284   2.3   173.9  74.6      0.5     80.0    105.5       47.7      48.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284   2.1   190.5  73.8      0.5     80.0    103.5       47.7      48.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285   2.0   200.0  73.8      0.5     80.0    103.6       47.7      48.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 Operation: restore
 
-obnam  larch    gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno  Mbit/s   MiB   Mbit/s      MiB       MiB      MiB                                    
+obnam  larch  gen0    gen0  gen0  slowest  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno     s  Mbit/s   MiB        s   Mbit/s      MiB       MiB      MiB                                    
 
- 1019    284   190.5  58.4     20.0     58.4       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284   181.8  58.4     16.0     58.4       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285   153.8  58.4     16.7     58.4       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284   2.1   190.5  58.4      2.0     20.0     58.4       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284   2.2   181.8  58.4      2.5     16.0     58.4       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285   2.6   153.8  58.4      2.4     16.7     58.4       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 Operation: list_files
 
@@ -81,21 +81,21 @@ Profile: mailspool 477/48 MiB (unencrypted)
 
 Operation: backup
 
-obnam  larch    gen0    gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
-revno  revno  Mbit/s     MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
+obnam  larch    gen0    gen0    gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
+revno  revno       s  Mbit/s     MiB        s   Mbit/s      MiB        MiB       MiB      MiB                                    
 
- 1019    284     4.1  1005.7      4.5    548.7      476.8     525.4      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284     2.9  1002.3      4.2    541.2      476.8     525.4      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285     3.1  1003.8      3.2    543.0      476.8     525.4      0.1  xander-mirror-1068-285  Obnam 0.20
+ 1019    284   986.1     4.1  1005.7     88.2      4.5    548.7      476.8     525.4      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284  1383.8     2.9  1002.3     94.3      4.2    541.2      476.8     525.4      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285  1293.0     3.1  1003.8    126.0      3.2    543.0      476.8     525.4      0.1  xander-mirror-1068-285  Obnam 0.20
 
 Operation: restore
 
-obnam  larch    gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno  Mbit/s    MiB   Mbit/s      MiB       MiB      MiB                                    
+obnam  larch   gen0    gen0   gen0  slowest  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno      s  Mbit/s    MiB        s   Mbit/s      MiB       MiB      MiB                                    
 
- 1019    284    12.4  438.6      1.2    439.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284     7.7  441.3      1.1    437.6       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285     8.0  441.1      1.1    440.5       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284  323.3    12.4  438.6    335.5      1.2    439.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284  521.5     7.7  441.3    376.8      1.1    437.6       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285  498.8     8.0  441.1    377.6      1.1    440.5       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 Operation: list_files
 
@@ -120,21 +120,21 @@ Profile: mediaserver 477/48 MiB (unencrypted)
 
 Operation: backup
 
-obnam  larch    gen0  gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
-revno  revno  Mbit/s   MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
+obnam  larch  gen0    gen0  gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
+revno  revno     s  Mbit/s   MiB        s   Mbit/s      MiB        MiB       MiB      MiB                                    
 
- 1019    284   203.0  95.9    333.3    113.5      476.8     478.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284   137.9  95.1    307.7    112.0      476.8     478.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285   125.4  95.1    307.7    112.3      476.8     478.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284  19.7   203.0  95.9      1.2    333.3    113.5      476.8     478.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284  29.0   137.9  95.1      1.3    307.7    112.0      476.8     478.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285  31.9   125.4  95.1      1.3    307.7    112.3      476.8     478.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 Operation: restore
 
-obnam  larch    gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno  Mbit/s   MiB   Mbit/s      MiB       MiB      MiB                                    
+obnam  larch  gen0    gen0  gen0  slowest  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno     s  Mbit/s   MiB        s   Mbit/s      MiB       MiB      MiB                                    
 
- 1019    284   154.4  70.2     12.5     70.3       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
- 1055    284   150.4  68.6     14.7     68.7       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
- 1068    285   174.7  68.7     15.2     68.8       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1019    284  25.9   154.4  70.2     32.1     12.5     70.3       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284  26.6   150.4  68.6     27.2     14.7     68.7       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285  22.9   174.7  68.7     26.3     15.2     68.8       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 Operation: list_files
 
@@ -159,17 +159,17 @@ Profile: mailspool 954/95 MiB (unencrypted)
 
 Operation: backup
 
-obnam  larch    gen0    gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
-revno  revno  Mbit/s     MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
+obnam  larch    gen0    gen0    gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
+revno  revno       s  Mbit/s     MiB        s   Mbit/s      MiB        MiB       MiB      MiB                                    
 
- 1068    285     3.2  1266.3      3.1    658.4      953.7    1060.1      9.5  xander-mirror-1068-285  Obnam 0.20
+ 1068    285  2526.8     3.2  1266.3    254.3      3.1    658.4      953.7    1060.1      9.5  xander-mirror-1068-285  Obnam 0.20
 
 Operation: restore
 
-obnam  larch    gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno  Mbit/s    MiB   Mbit/s      MiB       MiB      MiB                                    
+obnam  larch    gen0    gen0   gen0  slowest  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno       s  Mbit/s    MiB        s   Mbit/s      MiB       MiB      MiB                                    
 
- 1068    285     7.2  539.5      0.9    539.0       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1068    285  1115.0     7.2  539.5    858.0      0.9    539.0       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 Operation: list_files
 
@@ -190,17 +190,17 @@ Profile: mediaserver 954/95 MiB (unencrypted)
 
 Operation: backup
 
-obnam  larch    gen0   gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
-revno  revno  Mbit/s    MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
+obnam  larch  gen0    gen0   gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
+revno  revno     s  Mbit/s    MiB        s   Mbit/s      MiB        MiB       MiB      MiB                                    
 
- 1068    285   144.9  118.0    285.7    120.4      953.7     955.8      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1068    285  55.2   144.9  118.0      2.8    285.7    120.4      953.7     955.8      0.0  xander-mirror-1068-285  Obnam 0.20
 
 Operation: restore
 
-obnam  larch    gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
-revno  revno  Mbit/s   MiB   Mbit/s      MiB       MiB      MiB                                    
+obnam  larch  gen0    gen0  gen0  slowest  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno     s  Mbit/s   MiB        s   Mbit/s      MiB       MiB      MiB                                    
 
- 1068    285   167.7  75.6     14.8     75.7       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+ 1068    285  47.7   167.7  75.6     53.9     14.8     75.7       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 Operation: list_files
 
@@ -221,17 +221,17 @@ Profile: existing+mailspool 142835/95 MiB (unencrypted)
 
 Operation: backup
 
-obnam  larch    gen0    gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc           
-revno  revno  Mbit/s     MiB   Mbit/s      MiB        MiB       MiB      MiB                                         
+obnam  larch     gen0    gen0    gen0  slowest  slowest  biggest  repo size  r-writes  r-reads  branch                  desc           
+revno  revno        s  Mbit/s     MiB        s   Mbit/s      MiB        MiB       MiB      MiB                                         
 
- 1062    285    56.6  1499.3      2.8   1124.2   142834.5  171328.3  39492.6  xander-mirror-1062-285  Using real data
+ 1062    285  21169.2    56.6  1499.3    286.3      2.8   1124.2   142834.5  171328.3  39492.6  xander-mirror-1062-285  Using real data
 
 Operation: restore
 
-obnam  larch      gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc           
-revno  revno    Mbit/s    MiB   Mbit/s      MiB       MiB      MiB                                         
+obnam  larch  gen0      gen0   gen0  slowest  slowest  biggest  r-writes  r-reads  branch                  desc           
+revno  revno     s    Mbit/s    MiB        s   Mbit/s      MiB       MiB      MiB                                         
 
- 1062    285  704813.4  509.4    470.6    509.1       0.0      0.0  xander-mirror-1062-285  Using real data

(Diff truncated)
Format benchmark summary more readably.
diff --git a/obnam/benchmark-summary.txt b/obnam/benchmark-summary.txt
index 401df29..cee5db1 100644
--- a/obnam/benchmark-summary.txt
+++ b/obnam/benchmark-summary.txt
@@ -1,5 +1,7 @@
-backup: mailspool 48/5 MiB (unencrypted)
-----------------------------------------
+Profile: mailspool 48/5 MiB (unencrypted)
+-----------------------------------------
+
+Operation: backup
 
 obnam  larch    gen0   gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
 revno  revno  Mbit/s    MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
@@ -8,8 +10,7 @@ revno  revno  Mbit/s    MiB   Mbit/s      MiB        MiB       MiB      MiB
  1055    284     6.0  170.4      4.0    207.5       47.7      52.8      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285     5.5  169.6      2.9    209.4       47.7      52.8      0.0  xander-mirror-1068-285  Obnam 0.20
 
-restore: mailspool 48/5 MiB (unencrypted)
------------------------------------------
+Operation: restore
 
 obnam  larch    gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
 revno  revno  Mbit/s    MiB   Mbit/s      MiB       MiB      MiB                                    
@@ -18,8 +19,7 @@ revno  revno  Mbit/s    MiB   Mbit/s      MiB       MiB      MiB
  1055    284     7.0  136.4      1.0    143.2       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285     6.5  137.1      1.0    143.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-list_files: mailspool 48/5 MiB (unencrypted)
---------------------------------------------
+Operation: list_files
 
 obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
 revno  revno     s    MiB        s      MiB       MiB      MiB                                    
@@ -28,8 +28,7 @@ revno  revno     s    MiB        s      MiB       MiB      MiB
  1055    284   6.2  126.0      6.9    132.8       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285   6.7  126.8      7.3    133.0       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-forget: mailspool 48/5 MiB (unencrypted)
-----------------------------------------
+Operation: forget
 
 obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
 revno  revno     s    MiB        s      MiB       MiB      MiB                                    
@@ -38,8 +37,10 @@ revno  revno     s    MiB        s      MiB       MiB      MiB
  1055    284   3.2  163.5      2.8    130.9       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285   3.2  165.7      2.8    131.6       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-backup: mediaserver 48/5 MiB (unencrypted)
-------------------------------------------
+Profile: mediaserver 48/5 MiB (unencrypted)
+-------------------------------------------
+
+Operation: backup
 
 obnam  larch    gen0  gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
 revno  revno  Mbit/s   MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
@@ -48,8 +49,7 @@ revno  revno  Mbit/s   MiB   Mbit/s      MiB        MiB       MiB      MiB
  1055    284   190.5  73.8     80.0    103.5       47.7      48.0      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285   200.0  73.8     80.0    103.6       47.7      48.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-restore: mediaserver 48/5 MiB (unencrypted)
--------------------------------------------
+Operation: restore
 
 obnam  larch    gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
 revno  revno  Mbit/s   MiB   Mbit/s      MiB       MiB      MiB                                    
@@ -58,8 +58,7 @@ revno  revno  Mbit/s   MiB   Mbit/s      MiB       MiB      MiB
  1055    284   181.8  58.4     16.0     58.4       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285   153.8  58.4     16.7     58.4       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-list_files: mediaserver 48/5 MiB (unencrypted)
-----------------------------------------------
+Operation: list_files
 
 obnam  larch  gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
 revno  revno     s   MiB        s      MiB       MiB      MiB                                    
@@ -68,8 +67,7 @@ revno  revno     s   MiB        s      MiB       MiB      MiB
  1055    284   0.2  57.3      0.2     57.3       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285   0.2  57.4      0.2     57.4       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-forget: mediaserver 48/5 MiB (unencrypted)
-------------------------------------------
+Operation: forget
 
 obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
 revno  revno     s    MiB        s      MiB       MiB      MiB                                    
@@ -78,8 +76,10 @@ revno  revno     s    MiB        s      MiB       MiB      MiB
  1055    284   0.4  108.2      0.3    103.2       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285   0.4  102.6      0.3    102.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-backup: mailspool 477/48 MiB (unencrypted)
-------------------------------------------
+Profile: mailspool 477/48 MiB (unencrypted)
+-------------------------------------------
+
+Operation: backup
 
 obnam  larch    gen0    gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
 revno  revno  Mbit/s     MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
@@ -88,8 +88,7 @@ revno  revno  Mbit/s     MiB   Mbit/s      MiB        MiB       MiB      MiB
  1055    284     2.9  1002.3      4.2    541.2      476.8     525.4      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285     3.1  1003.8      3.2    543.0      476.8     525.4      0.1  xander-mirror-1068-285  Obnam 0.20
 
-restore: mailspool 477/48 MiB (unencrypted)
--------------------------------------------
+Operation: restore
 
 obnam  larch    gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
 revno  revno  Mbit/s    MiB   Mbit/s      MiB       MiB      MiB                                    
@@ -98,8 +97,7 @@ revno  revno  Mbit/s    MiB   Mbit/s      MiB       MiB      MiB
  1055    284     7.7  441.3      1.1    437.6       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285     8.0  441.1      1.1    440.5       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-list_files: mailspool 477/48 MiB (unencrypted)
-----------------------------------------------
+Operation: list_files
 
 obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
 revno  revno     s    MiB        s      MiB       MiB      MiB                                    
@@ -108,8 +106,7 @@ revno  revno     s    MiB        s      MiB       MiB      MiB
  1055    284  60.4  351.6     66.8    351.6       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285  64.8  351.2     71.7    351.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-forget: mailspool 477/48 MiB (unencrypted)
-------------------------------------------
+Operation: forget
 
 obnam  larch   gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
 revno  revno      s    MiB        s      MiB       MiB      MiB                                    
@@ -118,8 +115,10 @@ revno  revno      s    MiB        s      MiB       MiB      MiB
  1055    284  221.0  415.8    155.2    313.8       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285  174.3  399.9    156.5    322.3       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-backup: mediaserver 477/48 MiB (unencrypted)
---------------------------------------------
+Profile: mediaserver 477/48 MiB (unencrypted)
+---------------------------------------------
+
+Operation: backup
 
 obnam  larch    gen0  gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
 revno  revno  Mbit/s   MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
@@ -128,8 +127,7 @@ revno  revno  Mbit/s   MiB   Mbit/s      MiB        MiB       MiB      MiB
  1055    284   137.9  95.1    307.7    112.0      476.8     478.0      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285   125.4  95.1    307.7    112.3      476.8     478.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-restore: mediaserver 477/48 MiB (unencrypted)
----------------------------------------------
+Operation: restore
 
 obnam  larch    gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
 revno  revno  Mbit/s   MiB   Mbit/s      MiB       MiB      MiB                                    
@@ -138,8 +136,7 @@ revno  revno  Mbit/s   MiB   Mbit/s      MiB       MiB      MiB
  1055    284   150.4  68.6     14.7     68.7       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285   174.7  68.7     15.2     68.8       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-list_files: mediaserver 477/48 MiB (unencrypted)
-------------------------------------------------
+Operation: list_files
 
 obnam  larch  gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
 revno  revno     s   MiB        s      MiB       MiB      MiB                                    
@@ -148,8 +145,7 @@ revno  revno     s   MiB        s      MiB       MiB      MiB
  1055    284   0.3  61.6      0.3     61.7       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285   0.3  61.7      0.3     61.7       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-forget: mediaserver 477/48 MiB (unencrypted)
---------------------------------------------
+Operation: forget
 
 obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
 revno  revno     s    MiB        s      MiB       MiB      MiB                                    
@@ -158,128 +154,124 @@ revno  revno     s    MiB        s      MiB       MiB      MiB
  1055    284   1.6  126.3      1.3    116.9       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
  1068    285   1.6  124.3      1.3    114.9       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-backup: mailspool 954/95 MiB (unencrypted)
-------------------------------------------
+Profile: mailspool 954/95 MiB (unencrypted)
+-------------------------------------------
+
+Operation: backup
 
 obnam  larch    gen0    gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
 revno  revno  Mbit/s     MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
 
  1068    285     3.2  1266.3      3.1    658.4      953.7    1060.1      9.5  xander-mirror-1068-285  Obnam 0.20
 
-restore: mailspool 954/95 MiB (unencrypted)
--------------------------------------------
+Operation: restore
 
 obnam  larch    gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
 revno  revno  Mbit/s    MiB   Mbit/s      MiB       MiB      MiB                                    
 
  1068    285     7.2  539.5      0.9    539.0       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
-list_files: mailspool 954/95 MiB (unencrypted)
-----------------------------------------------

(Diff truncated)
Update benchmark summary with Obnam 0.20 results.
diff --git a/obnam/benchmark-summary.txt b/obnam/benchmark-summary.txt
index aa5058a..401df29 100644
--- a/obnam/benchmark-summary.txt
+++ b/obnam/benchmark-summary.txt
@@ -6,6 +6,7 @@ revno  revno  Mbit/s    MiB   Mbit/s      MiB        MiB       MiB      MiB
 
  1019    284     6.8  170.6      4.3    206.6       47.7      52.8      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284     6.0  170.4      4.0    207.5       47.7      52.8      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285     5.5  169.6      2.9    209.4       47.7      52.8      0.0  xander-mirror-1068-285  Obnam 0.20
 
 restore: mailspool 48/5 MiB (unencrypted)
 -----------------------------------------
@@ -15,6 +16,7 @@ revno  revno  Mbit/s    MiB   Mbit/s      MiB       MiB      MiB
 
  1019    284    12.1  135.5      1.2    142.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284     7.0  136.4      1.0    143.2       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285     6.5  137.1      1.0    143.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 list_files: mailspool 48/5 MiB (unencrypted)
 --------------------------------------------
@@ -24,6 +26,7 @@ revno  revno     s    MiB        s      MiB       MiB      MiB
 
  1019    284   6.2  125.1      6.8    131.8       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284   6.2  126.0      6.9    132.8       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285   6.7  126.8      7.3    133.0       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 forget: mailspool 48/5 MiB (unencrypted)
 ----------------------------------------
@@ -33,6 +36,7 @@ revno  revno     s    MiB        s      MiB       MiB      MiB
 
  1019    284   3.2  166.0      2.8    131.4       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284   3.2  163.5      2.8    130.9       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285   3.2  165.7      2.8    131.6       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 backup: mediaserver 48/5 MiB (unencrypted)
 ------------------------------------------
@@ -42,6 +46,7 @@ revno  revno  Mbit/s   MiB   Mbit/s      MiB        MiB       MiB      MiB
 
  1019    284   173.9  74.6     80.0    105.5       47.7      48.0      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284   190.5  73.8     80.0    103.5       47.7      48.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285   200.0  73.8     80.0    103.6       47.7      48.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 restore: mediaserver 48/5 MiB (unencrypted)
 -------------------------------------------
@@ -51,6 +56,7 @@ revno  revno  Mbit/s   MiB   Mbit/s      MiB       MiB      MiB
 
  1019    284   190.5  58.4     20.0     58.4       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284   181.8  58.4     16.0     58.4       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285   153.8  58.4     16.7     58.4       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 list_files: mediaserver 48/5 MiB (unencrypted)
 ----------------------------------------------
@@ -60,6 +66,7 @@ revno  revno     s   MiB        s      MiB       MiB      MiB
 
  1019    284   0.2  57.2      0.2     57.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284   0.2  57.3      0.2     57.3       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285   0.2  57.4      0.2     57.4       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 forget: mediaserver 48/5 MiB (unencrypted)
 ------------------------------------------
@@ -69,6 +76,7 @@ revno  revno     s    MiB        s      MiB       MiB      MiB
 
  1019    284   0.4  108.2      0.3    106.1       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284   0.4  108.2      0.3    103.2       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285   0.4  102.6      0.3    102.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 backup: mailspool 477/48 MiB (unencrypted)
 ------------------------------------------
@@ -78,6 +86,7 @@ revno  revno  Mbit/s     MiB   Mbit/s      MiB        MiB       MiB      MiB
 
  1019    284     4.1  1005.7      4.5    548.7      476.8     525.4      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284     2.9  1002.3      4.2    541.2      476.8     525.4      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285     3.1  1003.8      3.2    543.0      476.8     525.4      0.1  xander-mirror-1068-285  Obnam 0.20
 
 restore: mailspool 477/48 MiB (unencrypted)
 -------------------------------------------
@@ -87,6 +96,7 @@ revno  revno  Mbit/s    MiB   Mbit/s      MiB       MiB      MiB
 
  1019    284    12.4  438.6      1.2    439.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284     7.7  441.3      1.1    437.6       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285     8.0  441.1      1.1    440.5       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 list_files: mailspool 477/48 MiB (unencrypted)
 ----------------------------------------------
@@ -96,6 +106,7 @@ revno  revno     s    MiB        s      MiB       MiB      MiB
 
  1019    284  60.1  351.4     66.3    352.3       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284  60.4  351.6     66.8    351.6       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285  64.8  351.2     71.7    351.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 forget: mailspool 477/48 MiB (unencrypted)
 ------------------------------------------
@@ -105,6 +116,7 @@ revno  revno      s    MiB        s      MiB       MiB      MiB
 
  1019    284  173.1  400.2    153.9    327.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284  221.0  415.8    155.2    313.8       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285  174.3  399.9    156.5    322.3       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 backup: mediaserver 477/48 MiB (unencrypted)
 --------------------------------------------
@@ -114,6 +126,7 @@ revno  revno  Mbit/s   MiB   Mbit/s      MiB        MiB       MiB      MiB
 
  1019    284   203.0  95.9    333.3    113.5      476.8     478.0      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284   137.9  95.1    307.7    112.0      476.8     478.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285   125.4  95.1    307.7    112.3      476.8     478.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 restore: mediaserver 477/48 MiB (unencrypted)
 ---------------------------------------------
@@ -123,6 +136,7 @@ revno  revno  Mbit/s   MiB   Mbit/s      MiB       MiB      MiB
 
  1019    284   154.4  70.2     12.5     70.3       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284   150.4  68.6     14.7     68.7       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285   174.7  68.7     15.2     68.8       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 list_files: mediaserver 477/48 MiB (unencrypted)
 ------------------------------------------------
@@ -132,6 +146,7 @@ revno  revno     s   MiB        s      MiB       MiB      MiB
 
  1019    284   0.5  63.3      0.3     63.3       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284   0.3  61.6      0.3     61.7       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285   0.3  61.7      0.3     61.7       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
 
 forget: mediaserver 477/48 MiB (unencrypted)
 --------------------------------------------
@@ -141,4 +156,133 @@ revno  revno     s    MiB        s      MiB       MiB      MiB
 
  1019    284   1.4  123.9      1.1    111.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
  1055    284   1.6  126.3      1.3    116.9       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+ 1068    285   1.6  124.3      1.3    114.9       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+
+backup: mailspool 954/95 MiB (unencrypted)
+------------------------------------------
+
+obnam  larch    gen0    gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
+revno  revno  Mbit/s     MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
+
+ 1068    285     3.2  1266.3      3.1    658.4      953.7    1060.1      9.5  xander-mirror-1068-285  Obnam 0.20
+
+restore: mailspool 954/95 MiB (unencrypted)
+-------------------------------------------
+
+obnam  larch    gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno  Mbit/s    MiB   Mbit/s      MiB       MiB      MiB                                    
+
+ 1068    285     7.2  539.5      0.9    539.0       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+
+list_files: mailspool 954/95 MiB (unencrypted)
+----------------------------------------------
+
+obnam  larch   gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno      s    MiB        s      MiB       MiB      MiB                                    
+
+ 1068    285  130.6  351.2    143.3    351.2       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+
+forget: mailspool 954/95 MiB (unencrypted)
+------------------------------------------
+
+obnam  larch   gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno      s    MiB        s      MiB       MiB      MiB                                    
+
+ 1068    285  757.0  695.9    320.6    519.4       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+
+backup: mediaserver 954/95 MiB (unencrypted)
+--------------------------------------------
+
+obnam  larch    gen0   gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
+revno  revno  Mbit/s    MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
+
+ 1068    285   144.9  118.0    285.7    120.4      953.7     955.8      0.0  xander-mirror-1068-285  Obnam 0.20
+
+restore: mediaserver 954/95 MiB (unencrypted)
+---------------------------------------------
+
+obnam  larch    gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno  Mbit/s   MiB   Mbit/s      MiB       MiB      MiB                                    
+
+ 1068    285   167.7  75.6     14.8     75.7       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+
+list_files: mediaserver 954/95 MiB (unencrypted)
+------------------------------------------------
+
+obnam  larch  gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno     s   MiB        s      MiB       MiB      MiB                                    
+
+ 1068    285   0.5  62.5      0.3     62.5       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+
+forget: mediaserver 954/95 MiB (unencrypted)
+--------------------------------------------
+
+obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno     s    MiB        s      MiB       MiB      MiB                                    
+
+ 1068    285   4.5  139.3      4.0    127.5       0.0      0.0  xander-mirror-1068-285  Obnam 0.20
+
+backup: existing+mailspool 142835/95 MiB (unencrypted)
+------------------------------------------------------
+
+obnam  larch    gen0    gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc           
+revno  revno  Mbit/s     MiB   Mbit/s      MiB        MiB       MiB      MiB                                         
+

(Diff truncated)
Add links to obnam manpages.
diff --git a/obnam.mdwn b/obnam.mdwn
index a1e405e..52bd339 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -27,6 +27,8 @@ More information
 
 * [[README]] (updated at release time)
 * [[NEWS]] (updated at release time)
+* [[obnam manual page|obnam.1.txt]]
+* [[obnam-benchmark manual page|obnam-benchmark.1.txt]]
 * [[Roadmap for 1.0|roadmap-for-1.0]]
 * [[FAQ]]
 

Obnam 0.20.
diff --git a/obnam/NEWS.mdwn b/obnam/NEWS.mdwn
index 055c781..6349ad6 100644
--- a/obnam/NEWS.mdwn
+++ b/obnam/NEWS.mdwn
@@ -5,6 +5,25 @@ Obnam NEWS
 This file summarizes changes between releases of Obnam.
 
 
+Version 0.20, released 2011-08-09; a BETA release
+-------------------------------------------------
+
+BUG FIXES:
+
+* Non-ASCII filenames over SFTP root now work. (Thanks, Tapani Tarvainen,
+  for the reproducible bug report.)
+* The count of files while making a backup now counts all files found,
+  not just those backed up. The old behavior was confusing people.
+
+USER VISIBLE CHANGES:
+
+* The output of `obnam ls` now formats the columns a little prettier,
+  so that wide values do not cause misalignment.
+* The error message when trying to use an encrypted repository without
+  encryption is now better (and suggests missing encryption being the
+  reason). Thanks, chrysn.
+* Obnam now supports backing up of Unix sockets.
+
 Version 0.19, released 2011-08-03; a BETA release
 -------------------------------------------------
 
diff --git a/obnam/README.mdwn b/obnam/README.mdwn
index cafe21e..1b4e9af 100644
--- a/obnam/README.mdwn
+++ b/obnam/README.mdwn
@@ -29,15 +29,18 @@ On other systems, using the `setup.py` file should work: run
 "python setup.py --help" for advice. If not, please report a bug.
 (I've only tested `setup.py` enough for to build the Debian package.)
 
-You need to install my Python B-tree library, and some other libraries 
+You need to install my Python B-tree library, and some of my other libraries 
 and tools, which you can get from:
 
 * <http://liw.fi/larch/>
 * <http://liw.fi/ttystatus/>
-* <http://liw.fi/lru/>
-* <http://liw.fi/coverage-test-runner/>
-* <http://liw.fi/extrautils/>
+* <http://liw.fi/coverage-test-runner/> (for automatic tests)
+* <http://liw.fi/tracing/>
+* <http://liw.fi/seivot/> (for benchmarks)
 
+You also need third party libraries:
+
+* paramiko: <http://www.lag.net/paramiko/>
 
 Use
 ---
@@ -71,17 +74,34 @@ To build:
     
 To run automatic tests:
 
-    make check
-    python test-sftpfs # Read it first, though. Requires ssh setup.
+    make check 
+    make network-tests # Requires ssh access to localhost.
     
 You need my CoverageTestRunner to run tests, see above for where to get it.
 A couple of scripts exist to run benchmarks and profiles:
 
-    ./run-benchmark
-    viewprof obnam.prof cumulative | less -S
+    ./metadata-speed 10000
+    ./obnam-benchmark --size=1m/100k --results /tmp/benchmark-results
+    viewprof /tmp/benchmark-results/*/*backup-0.prof
+    seivots-summary /tmp/benchmark-results/*/*.seivot | less -S
     
-viewprof is a little helper script I wrote, around the Python pstats module.
-You can use your own, or get mine from extrautils (see above).
+There are two kinds of results: Python profiling output, and `.seivot`
+files.
+
+For the former, `viewprof` is a little helper script I wrote, 
+around the Python pstats module.
+You can use your own, or get mine from extrautils 
+(<http://liw.fi/extrautils/>). Running the benchmarks under profiling
+makes them a little slower (typically around 10% for me, when I've
+compared), but that's OK: the absolute numbers of the benchmarks are
+less important than the relative ones. It's nice to be able to look at
+the profiler output, if a benchmark is surprisingly slow, without
+having to re-run it.
+
+`seivots-summary` is a tool to display summaries of the measurements
+made during a benchmark run. `seivot` is the tool that makes the
+measurements. I typically save a number of benchmark results, so that
+I can see how my changes affect performance over time.
 
 If you make any changes, I welcome patches, either as plain diffs, bzr
 bundles, or public repositories I can merge from.
diff --git a/obnam/obnam-benchmark.1.txt b/obnam/obnam-benchmark.1.txt
new file mode 100644
index 0000000..c148220
--- /dev/null
+++ b/obnam/obnam-benchmark.1.txt
@@ -0,0 +1,159 @@
+OBNAM-BENCHMARK(1)					    OBNAM-BENCHMARK(1)
+
+
+
+NAME
+       obnam-benchmark - benchmark obnam
+
+SYNOPSIS
+       obnam-benchmark	     [--config=FILE]	   [--description=DESCRIPTION]
+       [--dump-config]	[--dump-setting-names]	 [--generate-manpage=TEMPLATE]
+       [--generations=N]	[-h]	   [--help]	  [--larch-branch=DIR]
+       [--list-config-files] [--log=FILE]  [--log-keep=N]  [--log-level=LEVEL]
+       [--log-max=SIZE]       [--no-default-configs]	  [--obnam-branch=DIR]
+       [--output=FILE]	[--results=DIR]  [--seivot-branch=DIR]	 [--size=PAIR]
+       [--use-existing=DIR]	 [--use-sftp-repository]     [--use-sftp-root]
+       [--version] [--wiki=DIR] [--with-encryption]
+
+DESCRIPTION
+       obnam-benchmark benchmarks the obnam(1) backup application, by  measur‐
+       ing  how  much  time  it takes to do a backup, restore, etc, in various
+       scenarios.  obnam-benchmark uses the seivot(1) tool for	actually  run‐
+       ning  the  benchmarks, but makes some helpful assumptions about things,
+       to make it simpler to run than running seivot directly.
+
+       Benchmarks are run using two different usage profiles:  mailspool  (all
+       files  are  small), and mediaserver (all files are big).  For each pro‐
+       file, test data of the desired total size is generated, backed up,  and
+       then  several  incremental  generations are backed up, each adding some
+       more generated test data.  Then other operations are  run  against  the
+       backup  repository:  restoring,	listing  the contents of, and removing
+       each generation.
+
+       The result of the benchmark is a  .seivot  file	per  profile,  plus  a
+       Python  profiler  file  for  each  run  of  obnam.  These are stored in
+       ../benchmarks.  A set of .seivot files can be summarized for comparison
+       with  seivots-summary(1).   The	profiling files can be viewed with the
+       usual Python tools: see the pstats module.
+
+       The benchmarks are run against a version of obnam checked out from ver‐
+       sion  control.	It  is	not  (currently) possible to run the benchmark
+       against an installed version of obnam.  Also the larch Python  library,
+       which  obnam  needs, needs to be checked out from version control.  The
+       --obnam-branch and --larch-branch options set the locations, if the de‐
+       faults are not correct.
+
+OPTIONS
+       --config=FILE
+	      add FILE to config files
+
+       --description=DESCRIPTION
+	      describe benchmark
+
+       --dump-config
+	      write out the entire current configuration
+
+       --dump-setting-names
+	      write out all names of settings and quit
+
+       --generate-manpage=TEMPLATE
+	      fill in manual page TEMPLATE
+
+       --generations=N
+	      benchmark N generations (default: 5)
+
+       -h, --help
+	      show this help message and exit
+
+       --larch-branch=DIR
+	      use DIR as the larch branch (default: /home/liw/larch/trunk)
+
+       --list-config-files
+	      list all possible config files
+
+       --log=FILE
+	      write log entries to FILE
+
+       --log-keep=N
+	      keep last N logs (10)
+
+       --log-level=LEVEL
+	      log  at LEVEL, one of debug, info, warning, error, critical, fa‐
+	      tal (default: debug)
+
+       --log-max=SIZE
+	      rotate logs larger than SIZE, zero for never (default: 0)
+
+       --no-default-configs
+	      clear list of configuration files to read
+
+       --obnam-branch=DIR
+	      use DIR as the obnam branch to benchmark (default: .)
+
+       --output=FILE
+	      write output to FILE, instead of standard output
+
+       --results=DIR

(Diff truncated)
Add Obnam FAQ.
diff --git a/obnam.mdwn b/obnam.mdwn
index 912faa7..a1e405e 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -28,6 +28,7 @@ More information
 * [[README]] (updated at release time)
 * [[NEWS]] (updated at release time)
 * [[Roadmap for 1.0|roadmap-for-1.0]]
+* [[FAQ]]
 
 Status and support
 ------
diff --git a/obnam/faq.mdwn b/obnam/faq.mdwn
new file mode 100644
index 0000000..8ff584b
--- /dev/null
+++ b/obnam/faq.mdwn
@@ -0,0 +1,11 @@
+[[!meta title="Obnam FAQ"]]
+
+What does the name "Obnam" mean?
+--------------------------------
+
+Back in 2006, when Obnam started, we wanted to have a name that was
+short, reasonably pronounceable by major cultures, and did not have
+too many Google hits. After much trying, we failed to come up with
+anything good. However, without a name, you can't even start the
+project, because what will you call its source directory? So we
+chose the OBligatory NAMe.

diff --git a/index.mdwn b/index.mdwn
index 3f4ae15..42324d1 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -2,5 +2,3 @@ This will be the new braawi.org.
 
 * [[obnam]]
 * [[genbackupdata]]
-* [Mari Berkomunitas Di Faceblog](http://athamz.info/mari-berkomunitas-di-faceblog/)
-* [Tablet Android Honeycomb Terbaik Murah](http://athamz.info/tablet-android-honeycomb-terbaik-murah/)

diff --git a/index.mdwn b/index.mdwn
index 42324d1..3f4ae15 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -2,3 +2,5 @@ This will be the new braawi.org.
 
 * [[obnam]]
 * [[genbackupdata]]
+* [Mari Berkomunitas Di Faceblog](http://athamz.info/mari-berkomunitas-di-faceblog/)
+* [Tablet Android Honeycomb Terbaik Murah](http://athamz.info/tablet-android-honeycomb-terbaik-murah/)

diff --git a/index.mdwn b/index.mdwn
index 3f4ae15..42324d1 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -2,5 +2,3 @@ This will be the new braawi.org.
 
 * [[obnam]]
 * [[genbackupdata]]
-* [Mari Berkomunitas Di Faceblog](http://athamz.info/mari-berkomunitas-di-faceblog/)
-* [Tablet Android Honeycomb Terbaik Murah](http://athamz.info/tablet-android-honeycomb-terbaik-murah/)

diff --git a/index.mdwn b/index.mdwn
index 42324d1..3f4ae15 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -2,3 +2,5 @@ This will be the new braawi.org.
 
 * [[obnam]]
 * [[genbackupdata]]
+* [Mari Berkomunitas Di Faceblog](http://athamz.info/mari-berkomunitas-di-faceblog/)
+* [Tablet Android Honeycomb Terbaik Murah](http://athamz.info/tablet-android-honeycomb-terbaik-murah/)

Add note about obnam bug reporting.
diff --git a/obnam.mdwn b/obnam.mdwn
index d452815..912faa7 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -37,9 +37,18 @@ but may be slow and buggy. There are no known bugs that would corrupt
 backed up data, or prevent it from being restored.
 (See [[NEWS]] for release notes.)
 
-This is a free software project. Users may support themselves, or each
-other, or may buy support from whomever they like. (Lars is happy to
-sell some, for example.)
+If you find a bug or other problem, please report it!
+
+* E-mail to the <mailto:obnam@braawi.org> mailing list.
+* On IRC via the `#obnam` channel.
+
+See "Contact" below for more instructions on the mailing list and
+IRC channel.
+
+This is a free software project. Lars as the author will provide 
+support as well as he can (but no guarantees), and users may support 
+themselves, or each other, or may buy support from whomever they like. 
+(Lars is happy to sell some, for example.)
 
 Download
 --------

Benchmarks.
diff --git a/obnam.mdwn b/obnam.mdwn
index f82e38d..d452815 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -100,7 +100,8 @@ Other stuff:
   - see [code.liw.fi](http://liw.fi/code/) for instructions
 * Benchmarks:
   * [[specification|obnam/benchmarkspec]]
-  * [[results|benchmarks]]
+  * [[recent benchmarks|benchmark-summary.txt]]
+  * [[slightly less ancient benchmarks|benchmarks]] (no longer updated)
   * [[ancient benchmarks|benchmarkreport]] (no longer updated)
 * [[Obnam release procedure|obnam/release]] 
 
diff --git a/obnam/benchmark-summary.txt b/obnam/benchmark-summary.txt
new file mode 100644
index 0000000..aa5058a
--- /dev/null
+++ b/obnam/benchmark-summary.txt
@@ -0,0 +1,144 @@
+backup: mailspool 48/5 MiB (unencrypted)
+----------------------------------------
+
+obnam  larch    gen0   gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
+revno  revno  Mbit/s    MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
+
+ 1019    284     6.8  170.6      4.3    206.6       47.7      52.8      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284     6.0  170.4      4.0    207.5       47.7      52.8      0.0  xander-mirror-1055-284  Obnam 0.19
+
+restore: mailspool 48/5 MiB (unencrypted)
+-----------------------------------------
+
+obnam  larch    gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno  Mbit/s    MiB   Mbit/s      MiB       MiB      MiB                                    
+
+ 1019    284    12.1  135.5      1.2    142.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284     7.0  136.4      1.0    143.2       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+
+list_files: mailspool 48/5 MiB (unencrypted)
+--------------------------------------------
+
+obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno     s    MiB        s      MiB       MiB      MiB                                    
+
+ 1019    284   6.2  125.1      6.8    131.8       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284   6.2  126.0      6.9    132.8       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+
+forget: mailspool 48/5 MiB (unencrypted)
+----------------------------------------
+
+obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno     s    MiB        s      MiB       MiB      MiB                                    
+
+ 1019    284   3.2  166.0      2.8    131.4       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284   3.2  163.5      2.8    130.9       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+
+backup: mediaserver 48/5 MiB (unencrypted)
+------------------------------------------
+
+obnam  larch    gen0  gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
+revno  revno  Mbit/s   MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
+
+ 1019    284   173.9  74.6     80.0    105.5       47.7      48.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284   190.5  73.8     80.0    103.5       47.7      48.0      0.0  xander-mirror-1055-284  Obnam 0.19
+
+restore: mediaserver 48/5 MiB (unencrypted)
+-------------------------------------------
+
+obnam  larch    gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno  Mbit/s   MiB   Mbit/s      MiB       MiB      MiB                                    
+
+ 1019    284   190.5  58.4     20.0     58.4       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284   181.8  58.4     16.0     58.4       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+
+list_files: mediaserver 48/5 MiB (unencrypted)
+----------------------------------------------
+
+obnam  larch  gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno     s   MiB        s      MiB       MiB      MiB                                    
+
+ 1019    284   0.2  57.2      0.2     57.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284   0.2  57.3      0.2     57.3       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+
+forget: mediaserver 48/5 MiB (unencrypted)
+------------------------------------------
+
+obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno     s    MiB        s      MiB       MiB      MiB                                    
+
+ 1019    284   0.4  108.2      0.3    106.1       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284   0.4  108.2      0.3    103.2       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+
+backup: mailspool 477/48 MiB (unencrypted)
+------------------------------------------
+
+obnam  larch    gen0    gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
+revno  revno  Mbit/s     MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
+
+ 1019    284     4.1  1005.7      4.5    548.7      476.8     525.4      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284     2.9  1002.3      4.2    541.2      476.8     525.4      0.0  xander-mirror-1055-284  Obnam 0.19
+
+restore: mailspool 477/48 MiB (unencrypted)
+-------------------------------------------
+
+obnam  larch    gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno  Mbit/s    MiB   Mbit/s      MiB       MiB      MiB                                    
+
+ 1019    284    12.4  438.6      1.2    439.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284     7.7  441.3      1.1    437.6       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+
+list_files: mailspool 477/48 MiB (unencrypted)
+----------------------------------------------
+
+obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno     s    MiB        s      MiB       MiB      MiB                                    
+
+ 1019    284  60.1  351.4     66.3    352.3       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284  60.4  351.6     66.8    351.6       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+
+forget: mailspool 477/48 MiB (unencrypted)
+------------------------------------------
+
+obnam  larch   gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno      s    MiB        s      MiB       MiB      MiB                                    
+
+ 1019    284  173.1  400.2    153.9    327.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284  221.0  415.8    155.2    313.8       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+
+backup: mediaserver 477/48 MiB (unencrypted)
+--------------------------------------------
+
+obnam  larch    gen0  gen0  slowest  biggest  repo size  r-writes  r-reads  branch                  desc      
+revno  revno  Mbit/s   MiB   Mbit/s      MiB        MiB       MiB      MiB                                    
+
+ 1019    284   203.0  95.9    333.3    113.5      476.8     478.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284   137.9  95.1    307.7    112.0      476.8     478.0      0.0  xander-mirror-1055-284  Obnam 0.19
+
+restore: mediaserver 477/48 MiB (unencrypted)
+---------------------------------------------
+
+obnam  larch    gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno  Mbit/s   MiB   Mbit/s      MiB       MiB      MiB                                    
+
+ 1019    284   154.4  70.2     12.5     70.3       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284   150.4  68.6     14.7     68.7       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+
+list_files: mediaserver 477/48 MiB (unencrypted)
+------------------------------------------------
+
+obnam  larch  gen0  gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno     s   MiB        s      MiB       MiB      MiB                                    
+
+ 1019    284   0.5  63.3      0.3     63.3       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284   0.3  61.6      0.3     61.7       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+
+forget: mediaserver 477/48 MiB (unencrypted)
+--------------------------------------------
+
+obnam  larch  gen0   gen0  slowest  biggest  r-writes  r-reads  branch                  desc      
+revno  revno     s    MiB        s      MiB       MiB      MiB                                    
+
+ 1019    284   1.4  123.9      1.1    111.2       0.0      0.0  xander-mirror-1019-284  Obnam 0.18
+ 1055    284   1.6  126.3      1.3    116.9       0.0      0.0  xander-mirror-1055-284  Obnam 0.19
+

Fix path to obnam config file in /home/liw (thanks, Robin Sheat).
diff --git a/obnam/tutorial.mdwn b/obnam/tutorial.mdwn
index 4ba8691..d93fedd 100644
--- a/obnam/tutorial.mdwn
+++ b/obnam/tutorial.mdwn
@@ -26,7 +26,7 @@ Configuration
 
 Obnam does not require a configuration file, and you can configure
 everything using command line options. You can, however, use a
-configuration file: save it as `~/.local/share/obnam/obnam.conf` and
+configuration file: save it as `~/.obnam.conf` and
 make it have content like this:
 
     [config]

added reference to nntp access to mailing list via gname.org --ferdy
diff --git a/obnam.mdwn b/obnam.mdwn
index 5fb83fc..f82e38d 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -65,6 +65,7 @@ Contact
 
 * Mailing list: mail obnam-help@braawi.org for instructions.
   * [Archive](http://lists.liw.fi/obnam@braawi.org/threads.html)
+  * [Gname](nntp://news.gmane.org/gmane.comp.sysutils.backup.obnam)
 * [Obnam on identi.ca](http://identi.ca/liw/tag/obnam)
 * `#obnam` on `irc.oftc.net` for IRC discussions about Obnam
 * [Lars's blog posts about Obnam](http://blog.liw.fi/tag/obnam/)

Obnam 0.19.
diff --git a/obnam/NEWS.mdwn b/obnam/NEWS.mdwn
index 27d7c63..055c781 100644
--- a/obnam/NEWS.mdwn
+++ b/obnam/NEWS.mdwn
@@ -5,6 +5,54 @@ Obnam NEWS
 This file summarizes changes between releases of Obnam.
 
 
+Version 0.19, released 2011-08-03; a BETA release
+-------------------------------------------------
+
+INCOMPATIBILITY CHANGES:
+
+* We now require version 0.21 of the `larch` library, and this requires
+  bumping the repository format. This means old backup repositories can't
+  be used with this version, and you need to back up everything again.
+  (Please tell me when this becomes a problem.)
+
+BUG FIXES:
+
+* Found one more place where a file going missing during a backup may
+  cause a crash.
+* Typo in error message about on-disk formats fixed.
+  (Thanks, Tapani Tarvainen.)
+* The `--trace` option works again.
+* `fcntl.F_SETFL` does not seem to work on file descriptors for files
+  owned by root that are read-only to the user running obnam. Worked
+  around by ignoring any problems with setting the flags.
+* The funnest bug in this release: if no log file was specified with `--log`,
+  the current working directory was excluded from the backup.
+
+USER VISIBLE CHANGES:
+
+* `obnam(1)` manual page now discusses how configuration files are used.
+* The manual page describes problems using sftp to access live data.
+* The documentation for `--no-act` was clarified to say it only works
+  for `forget. (Thanks, Daniel Silverstone.)
+* `obnam-benchmark` now has a manual page.
+* The backup plugin logs files it excludes, so the user can find out what's
+  going on. A confused user is an unhappy user.
+
+INTERNAL STUFF:
+
+* Tracing statements added to various parts of the code, to help debug
+  mysterious problems.
+* All exceptions are derived from `obnamlib.AppException` or
+  `obnamlib.Error`, and those are derived from `cliapp.AppException`,
+  so that the user gets nicer error messages than Python stack traces.
+* `blackboxtests` is no longer run under fakeroot, because Debian packages
+  are built under fakeroot, and fakeroot within fakeroot causes trouble.
+  However, the point of running tests under fakeroot was to make sure
+  certain kinds of bugs are caught, and since Debian package building runs
+  the tests anyway, the test coverage is not actually diminished.
+* The `Makefile` has new targets `fast-check` and `network-tests`. The
+  latter runs tests over sftp to localhost.
+
 Version 0.18, released 2011-07-20; a BETA release
 -------------------------------------------------
 

Obnam Ubuntu PPA.
diff --git a/obnam.mdwn b/obnam.mdwn
index 4709c3a..5fb83fc 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -51,6 +51,9 @@ Download
 
     `deb http://code.liw.fi/debian squeeze main`
 
+* For Ubuntu, see [Chris's 
+  PPA](https://launchpad.net/~chris-bigballofwax/+archive/obnam-ppa/).
+
 * from version control:
 
     `bzr get http://code.liw.fi/obnam/bzr/trunk/`

Obnam 0.18 release.
diff --git a/obnam/NEWS.mdwn b/obnam/NEWS.mdwn
index 9050a4f..27d7c63 100644
--- a/obnam/NEWS.mdwn
+++ b/obnam/NEWS.mdwn
@@ -5,6 +5,50 @@ Obnam NEWS
 This file summarizes changes between releases of Obnam.
 
 
+Version 0.18, released 2011-07-20; a BETA release
+-------------------------------------------------
+
+* The repository format has again changed in an incompatible manner,
+  so you will need to re-backup everything again. (If this is a problem,
+  tell me, and I'll consider adding backwards compatibility before 1.0
+  is released.)
+* New option `--exclude-caches` allows automatic exclusion of cache
+  directories that are marked as such.
+* Obnam now makes files in the repository be read-only, so that they're
+  that much harder to delete by mistake.
+* Error message about files that can't be backed up now mentions the
+  correct file.
+* Bugfix: unreadable files and directories no longer cause the backup
+  to fail. The problems are reported, but the backup continues.
+  Thanks to Jeff Epler for reporting the bug.
+* Speed improvement from Jeff Epler for excluding files from backups.
+* Various other speed improvements.
+* Bugfix: restoring symlinks now works even if the symlink is restored
+  before its target. Also, the permissions of the symlink (rather than its
+  target) are now restored correctly. Thanks to Jeff Epler for an 
+  exemplary bug report.
+* New option `--one-file-system`, from Jeff Epler.
+* New benchmarking tool `obnam-benchmark`, which is more flexible than
+  the old `run-benchmark`.
+* When encrypting/decrypting data with GnuPG, temporary files are no
+  longer used.
+* When verifying, `.../foo` and `.../foo/` now work the same way.
+* New option `--symmetric-key-bits`.
+* The chunk directory uses more hierarchy levels, and the way chunks
+  are stored there is now user-configurable (but you'll get into trouble
+  if you don't always use the same configuration). This should speed
+  things up a bit once the number of chunks grows very large.
+* New `--chunkids-per-group` option, for yet more knobs to tweak when
+  searching for optimal performance.
+* Local files are now opened using `O_NOATIME` so they can be backed
+  up without affecting timestamps.
+* Now uses the `cliapp` framework for writing command line applications.
+  The primary user-visible effect is that the manpage now has an
+  accurate list of options.
+* Bugfix: Obnam now again reports VFS I/O statistics.
+* Bugfix: Obnam can again back up live data that is accessed using sftp.
+  Thanks to Tapani Tarvainen for reporting the problem.
+
 Version 0.17, released 2011-05-21; a BETA release
 -------------------------------------------------
 
@@ -29,7 +73,7 @@ Version 0.17, released 2011-05-21; a BETA release
 * Obnam now does not crash if files go missing during a backup, or can't
   be read, or there are other problems with them. It will report the
   problem, but then continue as if it had never heard of the file.
-* Obnam now supports FIFO files (Unix sockets).
+* Obnam now supports FIFO files.
 * Obnam now verifies checksums when it restores files.
 * Obnam now stores the checksum for the whole file, not just the checksum
   for each chunk of its contents.
diff --git a/obnam/obnam.1.txt b/obnam/obnam.1.txt
index 48bad83..1087848 100644
--- a/obnam/obnam.1.txt
+++ b/obnam/obnam.1.txt
@@ -6,7 +6,19 @@ NAME
        obnam - make, restore, and manipulate backups
 
 SYNOPSIS
-       obnam [options] command [args]...
+       obnam		  [--checkpoint=SIZE]		   [--chunk-size=SIZE]
+       [--chunkids-per-group=NUM] [--client-name=CLIENT-NAME]  [--dump-config]
+       [--dump-memory-profile=DUMP-MEMORY-PROFILE]	[--dump-setting-names]
+       [--encrypt-with=ENCRYPT-WITH]  [--exclude=EXCLUDE]   [--exclude-caches]
+       [--generate-manpage=TEMPLATE]  [--generation=GENERATION]  [-h] [--help]
+       [--idpath-bits=IDPATH-BITS]		 [--idpath-depth=IDPATH-DEPTH]
+       [--idpath-skip=IDPATH-SKIP]  [--keep=KEEP] [--keyid=KEYID] [--log=FILE]
+       [--log-keep=N] [--log-level=LEVEL]  [--log-max=SIZE]  [--lru-size=SIZE]
+       [--node-size=SIZE]   [--one-file-system]   [--output=FILE]  [--pretend]
+       [--dry-run]	  [--no-act]	     [--quiet]	       [-r=REPOSITORY]
+       [--repository=REPOSITORY]				 [--root=ROOT]
+       [--symmetric-key-bits=SYMMETRIC-KEY-BITS]   [--to=TO]   [--trace=TRACE]
+       [--upload-queue-size=SIZE] [--version] [--weak-random]
 
 DESCRIPTION
        obnam  makes,  restores, manipulates, and otherwise deals with backups.
@@ -16,8 +28,8 @@ DESCRIPTION
        Only  changed  data  is	backed	up,  and if a chunk of data is already
        backed up in another file, that data is re-used.
 
-       The place where backed up data is placed is called the  backup  reposi‐
-       tory.  A repository may be, for example, a directory on an sftp server,
+       The place where backed up data is placed is called the backup reposito‐
+       ry.   A	repository may be, for example, a directory on an sftp server,
        or a directory on a USB hard disk.  A  single  repository  may  contain
        backups	from  several clients.	Their data will intermingle as if they
        were using separate repositories, but if one client backs  up  a  file,
@@ -152,8 +164,8 @@ DESCRIPTION
        When  not  using  the latest generation, you will need to specify which
        one you need.  This will be done with the  --generation	option,  which
        takes a generation specification as its argument.  The specification is
-       either the  word  latest,  meaning  the	latest	generation  (also  the
-       default), or a number.  See the generations command to see what genera‐
+       either the word latest, meaning the latest  generation  (also  the  de‐
+       fault),	or  a number.  See the generations command to see what genera‐
        tions are available, and what their numbers are.
 
    Policy for keeping and removing backup generations
@@ -165,15 +177,15 @@ DESCRIPTION
        and  a  time period.  The time periods are h, d, w, m, and y, for hour,
        day, week, month, and year.
 
-       A policy of 30d means to keep the  latest  backup  for  each  day,  for
-       thirty days.  Any backups in between will be removed, as will any back‐
-       ups older than thirty days.
+       A policy of 30d means to keep the latest backup for each day, for thir‐
+       ty  days.   Any backups in between will be removed, as will any backups
+       older than thirty days.
 
        As an example, assume backups are taken every hour,  on	the  hour:  at
        00:00,  01:00, 02:00, and so on, until 23:00.  If the forget command is
        run at 23:15, with the above policy, it will keep the backup  taken  at
-       23:00  on  each	day,  and remove every other backup that day.  It will
-       also remove backups older than 30 days.
+       23:00 on each day, and remove every other backup that day.  It will al‐
+       so remove backups older than 30 days.
 
        Note that obnam will only inspect timestamps in the backup  repository,
        and  does not care what the actual current time is.  This means that if
@@ -187,12 +199,12 @@ DESCRIPTION
        rule.
 
        For example, assume the same backup frequence as above, but a policy of
-       30d,52w.  This will keep the newest  daily  backup  for	each  day  for
-       thirty  days,  and  the newest weekly backup for 52 weeks.  Because the
-       hourly backups will be removed daily, before they have a chance to  get
-       saved by a weekly rule, the effect is that the 23:00 o'clock backup for
-       each day is saved for a month, and the 23:00 backup on Sundays is saved
-       for a year.
+       30d,52w.  This will keep the newest daily backup for each day for thir‐
+       ty days, and the newest weekly backup for 52 weeks.  Because the hourly
+       backups will be removed daily, before they have a chance to  get  saved
+       by  a weekly rule, the effect is that the 23:00 o'clock backup for each
+       day is saved for a month, and the 23:00 backup on Sundays is saved  for
+       a year.
 
        If no policy is given, forget will keep everything.
 
@@ -207,113 +219,134 @@ DESCRIPTION
        using the --encrypt-with option.
 
 OPTIONS
-       -h, --help
-	      Show a summary of options.
+       --checkpoint=SIZE
+	      make a checkpoint after  a  given  size,	default  unit  is  MiB
+	      (1073741824)
 
-       --log=FILE
-	      Write log messages to FILE.
+       --chunk-size=SIZE
+	      size of chunks of file data backed up (default: 65536)
 
-       --log-level=LEVEL
-	      Log messages at LEVEL and above.	Level is one of  debug,  info,
-	      warning, error, or critical.  Default is info.
+       --chunkids-per-group=NUM
+	      encode NUM chunk ids per group (1024)
 
-       --log-keep=N
-	      Keep  the N last log files.  This only applies when running as a
-	      normal user, not when running as root.  Log  files  are  rotated
-	      when  obnam  starts,  if they are larger than the limit set with
-	      --log-max.  The current log file is renamed to have a .0 suffix,
-	      and if such a file already existed, it gets renamed to have a .1
-	      suffix, etc.
+       --client-name=CLIENT-NAME
+	      name of client (havelock)
 
-       --log-max=SIZE
-	      If run as a normal user, rotate log file if it  is  larger  than
-	      SIZE bytes.
+       --dump-config
+	      write out the entire current configuration
 
-       -r, --repository=URL
-	      Store  backups in URL, which may be either a pathname or an sftp
-	      URL.  See above for a description of URL syntax.
+       --dump-memory-profile=DUMP-MEMORY-PROFILE
+	      make  memory  profiling  dumps after each checkpoint and at end?
+	      set to none, simple, meliae, or heapy (default: simple)
 
-       --client-name=CLIENT_NAME
-	      Set name of client to use.   Default  is	the  hostname  of  the
-	      machine  where obnam runs.  This is used to determine which part
-	      of the backup repository to put backups in.
+       --dump-setting-names

(Diff truncated)
Add a tutorial.
diff --git a/obnam.mdwn b/obnam.mdwn
index 108f6a5..4709c3a 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -19,6 +19,8 @@ Some **features** that may interest you:
 * **Push** or **pull** operation, depending on what you need. You can run
   Obnam on the client, and push backups to the server, or on the server,
   and pull from the client over SFTP.
+
+See the [[tutorial]] for examples of how to use Obnam.
   
 More information
 ----------------
diff --git a/obnam/tutorial.mdwn b/obnam/tutorial.mdwn
new file mode 100644
index 0000000..4ba8691
--- /dev/null
+++ b/obnam/tutorial.mdwn
@@ -0,0 +1,115 @@
+[[!meta title="Obnam tutorial"]]
+
+Installation
+------------
+
+It is easiest to install Obnam on a Debian system. Add the following
+line to your `/etc/apt/sources.list` file:
+
+    deb http://code.liw.fi/debian squeeze main
+
+Then run the following commands as root:
+
+* `apt-get update`
+* `apt-get install obnam`
+
+The commands will complain that the PGP key used to sign the archive
+is not known to apt. You can either ignore this, or add the key from
+<http://code.liw.fi/apt.asc> to your key. This will become unnecessary
+once Obnam has been uploaded to Debian.
+
+For other systems, you need to install from sources. See the `README`
+file for instructions.
+
+Configuration
+-------------
+
+Obnam does not require a configuration file, and you can configure
+everything using command line options. You can, however, use a
+configuration file: save it as `~/.local/share/obnam/obnam.conf` and
+make it have content like this:
+
+    [config]
+    repository = sftp://your.server/home/youruser/backups/
+
+The examples below assume you have created a configuration file,
+so that options do not need to be repeated every time.
+
+Initial backup
+--------------
+
+Your first backup will be pretty big, and will take a long time.
+A long backup may crash, but that is not a problem: Obnam makes
+a **checkpoint** every gigabyte or so.
+
+    obnam backup $HOME
+
+Still, it may be nicer to back up only a part of your data initially,
+and then add more to be backed up later on:
+
+    obnam backup $HOME/Mail
+    obnam backup $HOME/Archive
+    obnam backup $HOME
+
+The first command backs up your e-mail only. The second your archive
+directory only, but the mails are not removed from the backup repository.
+The third command backs up your entire home directory, but does not back
+up the mails and archived files that were already backed up, since it
+can find them in older generation in the backup repository.
+
+Incremental backups
+-------------------
+
+When you've made your initial, full backup (possibly in stages), you can
+back up any changes simply by running Obnam again:
+
+    obnam backup $HOME
+
+This will back up all new files, and any changed files. It will also
+record which files have been deleted since the previous backup.
+
+You can run Obnam as often as you like. Only the changes from the
+previous run are backed up.
+
+Removing old generations
+------------------------
+
+Eventually your backup repository will grow so big you'll want to
+remove some old generations. The Obnam operation is called forget:
+
+    obnam forget --keep=30d
+    
+This would keep one backup from each of the last thirty calendar
+days, counting from the newest backup (not current time). 
+If you've backed up several times during a day, only the latest
+generation from that day is kept.
+
+Any data that is part of a generation that is to be kept will
+remain in the repository. Any data that exists only in those
+generations that is to be forgotten gets removed.
+
+Restoring data
+--------------
+
+You will hopefully never need this, but the whole point of having
+backups is to restore data in case of a disaster.
+
+    obnam restore --to=/var/tmp/my-recovery $HOME
+    
+The above command will restore your entire home directory to
+`/var/tmp/my-recovery`, from the latest backup generation.
+If you only need some particular directory or file, you can
+specify that instead:
+
+    obnam restore --to=/var/tmp/my-recover $HOME/Archive/receipts
+    
+If you can't remember the name of the file you need, use `obnam ls`:
+
+    obnam ls > /var/tmp/my-recovery.list
+
+This will output the contents of the backup generation, in a format
+similar to `ls -lAR`. Save it into a file and browse that.
+(It's a fairly slow command, so it's comfortable to save to a file.)
+
+Best of luck.
+

Update NEWS for genbackupdata 1.5.
diff --git a/genbackupdata/NEWS.mdwn b/genbackupdata/NEWS.mdwn
index 1aaedcf..4bede84 100644
--- a/genbackupdata/NEWS.mdwn
+++ b/genbackupdata/NEWS.mdwn
@@ -1,6 +1,13 @@
 NEWS for genbackupdata
 ======================
 
+Version 1.5, released 2011-06-12
+--------------------------------
+
+* Fix genbackupdatalib to work better with pydoc.
+* Change to use newer cliapp API for adding new settings. This avoids
+  the deprecated old API.
+
 Version 1.3.1, released 2011-02-02
 ----------------------------------
 

die spammer die
This reverts commit 648c999773ee834a7065d96f6dd1022df25823c8
diff --git a/index.mdwn b/index.mdwn
index 9e11e74..42324d1 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -1,5 +1,4 @@
-This will be the [new](http://stridecoupons.webs.com) braawi.org.
+This will be the new braawi.org.
 
 * [[obnam]]
 * [[genbackupdata]]
-

diff --git a/index.mdwn b/index.mdwn
index 42324d1..9e11e74 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -1,4 +1,5 @@
-This will be the new braawi.org.
+This will be the [new](http://stridecoupons.webs.com) braawi.org.
 
 * [[obnam]]
 * [[genbackupdata]]
+

Show list of individual benchmark results.
diff --git a/obnam/benchmarks.mdwn b/obnam/benchmarks.mdwn
index 44a540b..9be74c6 100644
--- a/obnam/benchmarks.mdwn
+++ b/obnam/benchmarks.mdwn
@@ -20,3 +20,7 @@ Forget:
 
 [[!table file="obnam/benchmarks/forget-1000000000.csv"]]
 
+Individual benchmark results
+----------------------------
+
+[[!inline pages='obnam-*.mdwn']]

Remove version number from front page (since I foret to update it).
diff --git a/obnam.mdwn b/obnam.mdwn
index c91a124..108f6a5 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -30,9 +30,10 @@ More information
 Status and support
 ------
 
-The current BETA version is 0.16, released 2011-04-17. It is feature complete,
+Obnam is currently in BETA. It is feature complete,
 but may be slow and buggy. There are no known bugs that would corrupt
 backed up data, or prevent it from being restored.
+(See [[NEWS]] for release notes.)
 
 This is a free software project. Users may support themselves, or each
 other, or may buy support from whomever they like. (Lars is happy to

Start link section with Cache Directory Tagging standard.
diff --git a/obnam.mdwn b/obnam.mdwn
index 22e8460..c91a124 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -106,3 +106,7 @@ Dependencies:
   (you only need this for running the test suite)
 * extrautils: <http://liw.fi/extrautils/>
 
+Links
+-----
+
+* [Cache Directory Caching Standard](http://www.bford.info/cachedir/)

Update for Obnam release 0.17.
diff --git a/obnam/NEWS.mdwn b/obnam/NEWS.mdwn
index eb1be7a..9050a4f 100644
--- a/obnam/NEWS.mdwn
+++ b/obnam/NEWS.mdwn
@@ -5,7 +5,43 @@ Obnam NEWS
 This file summarizes changes between releases of Obnam.
 
 
-Version 0.16, released 2011-03-21; a BETA release
+Version 0.17, released 2011-05-21; a BETA release
+-------------------------------------------------
+
+* This is the second BETA release.
+* The `run-benchmark` script now works with the new version of `seivot`.
+  The only benchmark size is one gibibyte, for now, because Obnam's too
+  slow to do big ones in reasonable time. As an aside, the benchmark
+  script got rewritten in Python, so it can be made more flexible.
+* Benchmarks are run using encrypted backups.
+* The kernel buffer cache is dropped before each obnam run, so the
+  benchmark result is more realistic (read: slower).
+* Obnam now rotates its logs. See `--log-max` and `--log-keep` options
+  in the manual page. The default location for the log file is now
+  `~/.cache/obnam/obnam.log` for people, and
+  `/var/log/obnam.log` for root.
+* Obnam now restores sparse files correctly.
+* There have been some speed improvements to Obnam.
+* The `--repository` option now has the shorter alias `-r`, since it
+  gets used so often.
+* `obnam force-lock` now merely gives an error message, instead of a
+  Python stack trace, if the repository does not exist.
+* Obnam now does not crash if files go missing during a backup, or can't
+  be read, or there are other problems with them. It will report the
+  problem, but then continue as if it had never heard of the file.
+* Obnam now supports FIFO files (Unix sockets).
+* Obnam now verifies checksums when it restores files.
+* Obnam now stores the checksum for the whole file, not just the checksum
+  for each chunk of its contents.
+* Obnam's own log file is automatically excluded from backups.
+* Obnam now stores and restores file timestamps to full accuracy,
+  instead of truncating them to whole seconds.
+* The format of the backup repository has changed in an incompatible way,
+  and Obnam will now refuse to use an old repository. This means you
+  will need to use an old version to restore from them, and need to
+  re-backup everything. Sorry.
+
+Version 0.16, released 2011-07-17; a BETA release
 -------------------------------------------------
 
 * This is the first BETA release. Obnam should now be feature complete
@@ -14,7 +50,6 @@ Version 0.16, released 2011-03-21; a BETA release
   its recovery.
 * Add encryption support. See the manual page for how to use it.
 
-
 Version 0.15.1, released 2011-03-21; an ALPHA release
 ----------------------------------------------------
 
diff --git a/obnam/README.mdwn b/obnam/README.mdwn
index 22b36df..cafe21e 100644
--- a/obnam/README.mdwn
+++ b/obnam/README.mdwn
@@ -9,7 +9,7 @@ make you abandon all hope for civilisation, move into the rain forest,
 and talk to birds for the rest of your life.
 
 It would be inadvisable to rely on Obnam as your only backup solution,
-but it should be ready for evaluation use.
+but it should be ready for feature evaluation use.
 
 
 Home page
diff --git a/obnam/obnam.1.txt b/obnam/obnam.1.txt
index 52b35ea..48bad83 100644
--- a/obnam/obnam.1.txt
+++ b/obnam/obnam.1.txt
@@ -217,7 +217,19 @@ OPTIONS
 	      Log messages at LEVEL and above.	Level is one of  debug,  info,
 	      warning, error, or critical.  Default is info.
 
-       --repository=URL
+       --log-keep=N
+	      Keep  the N last log files.  This only applies when running as a
+	      normal user, not when running as root.  Log  files  are  rotated
+	      when  obnam  starts,  if they are larger than the limit set with
+	      --log-max.  The current log file is renamed to have a .0 suffix,
+	      and if such a file already existed, it gets renamed to have a .1
+	      suffix, etc.
+
+       --log-max=SIZE
+	      If run as a normal user, rotate log file if it  is  larger  than
+	      SIZE bytes.
+
+       -r, --repository=URL
 	      Store  backups in URL, which may be either a pathname or an sftp
 	      URL.  See above for a description of URL syntax.
 

Add link to Obnam mailing list archive.
diff --git a/obnam.mdwn b/obnam.mdwn
index f3f0406..22e8460 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -58,6 +58,7 @@ Contact
 -------
 
 * Mailing list: mail obnam-help@braawi.org for instructions.
+  * [Archive](http://lists.liw.fi/obnam@braawi.org/threads.html)
 * [Obnam on identi.ca](http://identi.ca/liw/tag/obnam)
 * `#obnam` on `irc.oftc.net` for IRC discussions about Obnam
 * [Lars's blog posts about Obnam](http://blog.liw.fi/tag/obnam/)
diff --git a/obnam/benchmarks/backup-1000000.csv b/obnam/benchmarks/backup-1000000.csv
index 06aebd5..cae0a21 100644
--- a/obnam/benchmarks/backup-1000000.csv
+++ b/obnam/benchmarks/backup-1000000.csv
@@ -1,2 +1,2 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r962,r237,1.1,61.9,0.9,86.2
+obnam,larch,gen0 time (s),gen0 speed (Mbit/s),gen0 RAM (MiB),slowest inc (s),slowest inc (Mbit/s),largest RAM inc (MiB)
+r967,r237,63.8,0.1,62.2,1.4,5.7,87.3
diff --git a/obnam/benchmarks/forget-1000000.csv b/obnam/benchmarks/forget-1000000.csv
index 82ea791..a44438d 100644
--- a/obnam/benchmarks/forget-1000000.csv
+++ b/obnam/benchmarks/forget-1000000.csv
@@ -1,2 +1,2 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r962,r237,0.4,90.3,0.4,87.2
+obnam,larch,gen0 time (s),gen0 speed (Mbit/s),gen0 RAM (MiB),slowest inc (s),slowest inc (Mbit/s),largest RAM inc (MiB)
+r967,r237,0.7,0.0,91.1,0.6,0.0,88.1
diff --git a/obnam/benchmarks/list_files-1000000.csv b/obnam/benchmarks/list_files-1000000.csv
index 9222696..5957758 100644
--- a/obnam/benchmarks/list_files-1000000.csv
+++ b/obnam/benchmarks/list_files-1000000.csv
@@ -1,2 +1,2 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r962,r237,0.3,55.1,0.3,55.1
+obnam,larch,gen0 time (s),gen0 speed (Mbit/s),gen0 RAM (MiB),slowest inc (s),slowest inc (Mbit/s),largest RAM inc (MiB)
+r967,r237,0.8,0.0,55.5,0.6,0.0,55.5
diff --git a/obnam/benchmarks/restore-1000000.csv b/obnam/benchmarks/restore-1000000.csv
index 6c1727b..c955036 100644
--- a/obnam/benchmarks/restore-1000000.csv
+++ b/obnam/benchmarks/restore-1000000.csv
@@ -1,2 +1,2 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r962,r237,0.3,55.3,0.6,55.3
+obnam,larch,gen0 time (s),gen0 speed (Mbit/s),gen0 RAM (MiB),slowest inc (s),slowest inc (Mbit/s),largest RAM inc (MiB)
+r967,r237,1.9,0.0,55.7,3.2,0.0,55.7

New benchmark result.
diff --git a/obnam/benchmarks/979-239/obnam-1g-backup-0-cumulative.txt b/obnam/benchmarks/979-239/obnam-1g-backup-0-cumulative.txt
new file mode 100644
index 0000000..d293fca
--- /dev/null
+++ b/obnam/benchmarks/979-239/obnam-1g-backup-0-cumulative.txt
@@ -0,0 +1,3088 @@
+Fri May  6 00:07:49 2011    /home/liw/tmp/tmpR3nNkf
+
+         164397705 function calls (162926069 primitive calls) in 3493.910 CPU seconds
+
+   Ordered by: cumulative time
+
+   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
+        1    0.000    0.000 3493.915 3493.915 <string>:1(<module>)
+        1    0.000    0.000 3493.914 3493.914 obnam:26(main)
+        1    0.000    0.000 3493.913 3493.913 app.py:170(run)
+        1    0.000    0.000 3493.771 3493.771 interp.py:28(execute)
+        1    5.129    5.129 3493.771 3493.771 backup_plugin.py:47(backup)
+   305669    6.244    0.000 3089.409    0.010 repo.py:78(helper)
+    61036   15.144    0.000 2711.920    0.044 backup_plugin.py:262(backup_file_contents)
+    61036    2.169    0.000 1973.009    0.032 backup_plugin.py:288(backup_file_chunk)
+    61036   13.234    0.000 1940.649    0.032 repo.py:565(put_chunk)
+    61037    7.862    0.000 1664.191    0.027 repo.py:157(write_file)
+   183769    9.969    0.000 1649.974    0.009 hooks.py:107(call)
+    61687    5.788    0.000 1567.773    0.025 hooks.py:71(call_callbacks)
+    61685    4.838    0.000 1561.956    0.025 encryption_plugin.py:103(toplevel_write_data)
+    61691    7.277    0.000 1553.530    0.025 encryption.py:103(encrypt_symmetric)
+    61693   12.014    0.000 1544.963    0.025 encryption.py:55(_gpg_pipe)
+   611829   15.884    0.000 1302.691    0.002 tree.py:211(insert)
+   611825   22.592    0.000 1245.178    0.002 tree.py:256(_insert_into_index)
+   611825   16.305    0.000 1079.293    0.002 tree.py:303(_insert_into_leaf)
+    61718   24.101    0.000 1035.503    0.017 subprocess.py:563(__init__)
+    61718   48.861    0.001  999.456    0.016 subprocess.py:1017(_execute_child)
+  1225547  894.708    0.001  958.313    0.001 codec.py:52(leaf_size)
+   616873    3.605    0.000  880.578    0.001 tree.py:120(_leaf_size)
+    61519    0.296    0.000  585.359    0.010 backup_plugin.py:256(backup_metadata)
+    61525    0.685    0.000  584.817    0.010 repo.py:549(create)
+    61525    2.647    0.000  575.779    0.009 clientmetadatatree.py:223(create)
+   439079  555.375    0.001  555.375    0.001 {posix.read}
+   123436    1.378    0.000  549.445    0.004 subprocess.py:452(_eintr_retry_call)
+    61718    5.873    0.000  479.629    0.008 subprocess.py:664(communicate)
+    61718   21.078    0.000  473.378    0.008 subprocess.py:1187(_communicate)
+   316078  431.197    0.001  431.197    0.001 {select.select}
+    61718  396.246    0.006  396.246    0.006 {posix.fork}
+    61036    2.571    0.000  367.460    0.006 repo.py:692(set_file_checksum)
+    61036    1.517    0.000  364.889    0.006 clientmetadatatree.py:385(set_file_checksum)
+    61524    0.482    0.000  322.734    0.005 clientmetadatatree.py:253(set_metadata)
+   122072    1.802    0.000  178.582    0.001 clientmetadatatree.py:340(append_file_chunks)
+    61036    5.739    0.000  177.496    0.003 chunklist.py:45(add)
+    61520    0.118    0.000  160.386    0.003 backup_plugin.py:156(find_files)
+    61520    0.848    0.000  160.268    0.003 backup_plugin.py:174(_real_find_files)
+    61519    2.906    0.000  156.381    0.003 backup_plugin.py:193(_real_find_basenames)
+    61036    0.208    0.000  142.112    0.002 repo.py:672(append_file_chunks)
+  1836118    7.843    0.000  133.609    0.000 tree.py:114(put_node)
+    61050    3.411    0.000  103.766    0.002 vfs_local.py:153(write_file)
+    61525    8.396    0.000  102.409    0.002 metadata.py:83(read_metadata)
+    61698   11.457    0.000   97.211    0.002 vfs_local.py:185(_write_to_tempfile)
+  1836118    6.931    0.000   94.664    0.000 codec.py:136(size)
+  1902792   70.359    0.000   88.999    0.000 {method 'join' of 'str' objects}
+   122088   86.603    0.001   88.245    0.001 vfs_local.py:28(read)
+  3966678   79.070    0.000   79.070    0.000 {_bisect.bisect_left}
+    61525   78.317    0.001   78.317    0.001 {grp.getgrgid}
+  1224285   19.122    0.000   74.559    0.000 nodes.py:121(add)
+   122082    4.687    0.000   72.232    0.001 hooks.py:47(call_callbacks)
+   122076    0.324    0.000   65.799    0.001 clientmetadatatree.py:154(_insert_int)
+    61036    1.444    0.000   64.417    0.001 checksumtree.py:45(add)
+   244145   15.794    0.000   58.064    0.000 status.py:63(__setitem__)
+  5018263    9.253    0.000   53.898    0.000 lru.py:101(remove)
+  1223654    4.730    0.000   53.446    0.000 tree.py:198(_shadow)
+    61036    0.155    0.000   48.127    0.001 repo.py:662(set_file_chunks)
+    61036    0.652    0.000   47.971    0.001 clientmetadatatree.py:326(set_file_chunks)
+  5018263   44.645    0.000   44.645    0.000 lru.py:75(_remove)
+   123391    1.081    0.000   43.330    0.000 tempfile.py:259(mkstemp)
+   122556    1.510    0.000   42.782    0.000 repo.py:67(helper)
+   123391    5.650    0.000   42.155    0.000 tempfile.py:219(_mkstemp_inner)
+    61036    3.777    0.000   40.241    0.001 terminal_status_plugin.py:72(data_uploaded_cb)
+  1223654    7.777    0.000   39.142    0.000 nodestore_disk.py:173(start_modification)
+  1346666    1.952    0.000   38.740    0.000 tree.py:110(get_node)
+  1346666    2.438    0.000   36.788    0.000 nodestore_disk.py:154(get_node)
+    61036    0.271    0.000   35.090    0.001 clientmetadatatree.py:321(_insert_chunks)
+  1346666    7.448    0.000   34.350    0.000 lru.py:86(get)
+  1836118    4.831    0.000   30.278    0.000 nodestore_disk.py:134(put_node)
+   307295   29.474    0.000   29.474    0.000 {method 'close' of 'file' objects}
+  5018902   17.634    0.000   29.323    0.000 lru.py:54(add)
+        4    0.000    0.000   29.115    7.279 repo_tree.py:76(commit)
+        4    0.001    0.000   29.114    7.279 forest.py:93(commit)
+      3/2    0.000    0.000   28.982   14.491 repo.py:52(helper)
+        1    0.000    0.000   28.981   28.981 repo.py:428(commit_client)
+        4    0.000    0.000   28.711    7.178 nodestore_disk.py:139(push_upload_queue)
+        4    0.092    0.023   28.711    7.178 uploadqueue.py:52(push)
+      639    0.113    0.000   28.489    0.045 nodestore_disk.py:142(_really_put_node)
+  1223654    4.556    0.000   27.832    0.000 uploadqueue.py:57(remove)
+    61036    2.376    0.000   26.877    0.000 terminal_status_plugin.py:61(found_file_cb)
+   979510    3.468    0.000   26.776    0.000 nodes.py:199(find_key_for_child_containing)
+   245114    1.110    0.000   26.492    0.000 tree.py:148(lookup_range)
+   367685    3.519    0.000   26.132    0.000 tree.py:126(lookup)
+      648    0.112    0.000   25.045    0.039 repo.py:163(overwrite_file)
+490213/245114    2.843    0.000   24.742    0.000 tree.py:161(_lookup_range)
+   611833    3.525    0.000   23.171    0.000 tree.py:99(set_root)
+    61037    4.835    0.000   22.966    0.000 backup_plugin.py:134(dump_memory_profile)
+        1    0.000    0.000   22.693   22.693 clientmetadatatree.py:157(commit)
+  2807656    5.280    0.000   22.394    0.000 widget.py:46(__str__)
+    61042    0.635    0.000   22.046    0.000 backup_plugin.py:224(needs_backup)
+    61036    5.142    0.000   20.662    0.000 repo.py:539(get_metadata)
+    61036    0.429    0.000   20.170    0.000 repo.py:618(find_chunks)
+    61036    0.906    0.000   19.741    0.000 checksumtree.py:50(find)
+   123410   12.075    0.000   19.217    0.000 tempfile.py:127(next)
+  2441441    5.179    0.000   18.284    0.000 status.py:75(<genexpr>)
+   122561    0.865    0.000   18.267    0.000 clientmetadatatree.py:246(get_metadata)
+  1028537    9.759    0.000   15.763    0.000 nodes.py:137(remove)
+   368856    1.595    0.000   15.227    0.000 genericpath.py:15(exists)
+21131582/19907230   12.659    0.000   15.141    0.000 {len}
+   122074    1.988    0.000   14.498    0.000 repo.py:241(checksum)
+  2326501   14.021    0.000   14.021    0.000 {method 'insert' of 'list' objects}
+   368861   13.632    0.000   13.632    0.000 {posix.stat}
+   307117    1.346    0.000   13.303    0.000 vfs_local.py:121(exists)
+  2447308    4.343    0.000   13.106    0.000 nodestore.py:148(can_be_modified)
+   677308    6.679    0.000   12.927    0.000 vfs_local.py:86(join)
+  3671593    7.535    0.000   11.337    0.000 nodestore_disk.py:198(get_refcount)
+   612460    3.978    0.000   11.305    0.000 tree.py:522(increment)
+   122075    3.846    0.000   10.926    0.000 repo_tree.py:63(start_changes)
+   551762    1.132    0.000   10.208    0.000 clientmetadatatree.py:138(get_file_id)
+  1836118    2.260    0.000    9.982    0.000 uploadqueue.py:46(put)
+    61037    5.476    0.000    9.943    0.000 backup_plugin.py:125(vmrss)
+  1836118    2.247    0.000    9.805    0.000 nodestore_disk.py:201(set_refcount)
+   123462    9.544    0.000    9.544    0.000 {posix.fdopen}
+   183579    1.100    0.000    9.160    0.000 nodes.py:176(find_keys_in_range)
+   551764    1.877    0.000    9.077    0.000 clientmetadatatree.py:80(hash_name)
+    61525    5.967    0.000    8.353    0.000 repo.py:94(encode_metadata)
+  1047721    6.507    0.000    8.028    0.000 posixpath.py:59(join)
+  1836118    6.523    0.000    7.558    0.000 refcountstore.py:62(set_refcount)
+   183110    7.351    0.000    7.351    0.000 {method 'update' of '_hashlib.HASH' objects}
+  1223658    7.192    0.000    7.192    0.000 {repr}
+    61525    6.974    0.000    6.974    0.000 {pwd.getpwuid}
+   183599    0.872    0.000    6.828    0.000 clientmetadatatree.py:145(_lookup_int)
+   123394    6.767    0.000    6.767    0.000 {posix.open}
+   611825    3.196    0.000    6.581    0.000 tree.py:529(decrement)
+   734875    6.530    0.000    6.530    0.000 {_hashlib.openssl_md5}
+   493676    6.398    0.000    6.398    0.000 {posix.close}
+   122742    5.556    0.000    6.365    0.000 vfs_local.py:118(open)
+   123399    0.505    0.000    6.349    0.000 posixpath.py:340(abspath)
+  9975708    5.872    0.000    5.872    0.000 tracing.py:64(trace)
+   740460    4.988    0.000    5.854    0.000 random.py:259(choice)
+   122074    4.267    0.000    5.686    0.000 __init__.py:1483(debug)
+  1427468    5.672    0.000    5.672    0.000 {method 'append' of 'list' objects}
+   183110    2.305    0.000    5.659    0.000 repo.py:256(new_checksummer)
+    61697    4.835    0.000    5.606    0.000 vfs_local.py:36(write)
+   305180    2.723    0.000    5.603    0.000 bytespeed.py:37(format)
+   183594    1.214    0.000    5.576    0.000 nodes.py:215(find_children_in_range)
+   674317    1.012    0.000    5.484    0.000 clientmetadatatree.py:116(fskey)
+   123399    3.081    0.000    5.476    0.000 posixpath.py:311(normpath)
+   796885    3.476    0.000    5.474    0.000 clientmetadatatree.py:84(hashkey)
+   305180    5.338    0.000    5.338    0.000 bytesize.py:29(format)
+   245942    4.088    0.000    4.887    0.000 posixpath.py:117(dirname)
+   183594    0.531    0.000    4.362    0.000 nodes.py:79(find_potential_range)
+  1408698    4.204    0.000    4.204    0.000 nodes.py:51(__getitem__)
+  4411762    4.122    0.000    4.122    0.000 {isinstance}
+   183792    4.069    0.000    4.069    0.000 cfg.py:110(__getitem__)
+   551777    4.023    0.000    4.023    0.000 {method 'digest' of '_hashlib.HASH' objects}
+   367188    0.916    0.000    3.831    0.000 nodes.py:95(helper)
+  3671593    3.714    0.000    3.803    0.000 refcountstore.py:51(get_refcount)
+  1285838    3.728    0.000    3.728    0.000 {_struct.pack}
+    61036    0.228    0.000    3.643    0.000 tree.py:478(remove_range)
+    61718    1.240    0.000    3.576    0.000 subprocess.py:1178(wait)
+      639    0.043    0.000    3.511    0.005 codec.py:121(encode)
+    61526    0.209    0.000    3.500    0.000 clientmetadatatree.py:209(get_generation_id)
+      635    0.236    0.000    3.465    0.005 codec.py:57(encode_leaf)
+   488288    3.453    0.000    3.453    0.000 elapsed.py:35(format)
+  1468774    2.802    0.000    3.410    0.000 tree.py:73(check_key_size)
+   123391    1.975    0.000    3.404    0.000 tempfile.py:47(_set_cloexec)
+   183110    3.268    0.000    3.268    0.000 {method 'hexdigest' of '_hashlib.HASH' objects}
+    61525    1.473    0.000    3.193    0.000 metadata.py:67(__init__)
+   244145    1.144    0.000    3.173    0.000 messager.py:106(write)
+   123043    0.842    0.000    3.079    0.000 vfs_local.py:95(lstat)
+   123410    3.066    0.000    3.066    0.000 {posix.write}
+  1223654    2.472    0.000    2.947    0.000 nodes.py:64(__len__)
+   305178    2.625    0.000    2.880    0.000 bytespeed.py:32(now)
+      635    2.879    0.005    2.879    0.005 {map}
+   183108    1.665    0.000    2.775    0.000 checksumtree.py:39(key)
+   366216    2.455    0.000    2.749    0.000 status.py:55(__getitem__)
+  4539083    2.715    0.000    2.715    0.000 {method 'startswith' of 'str' objects}
+    61687    1.870    0.000    2.647    0.000 encryption_plugin.py:109(get_symmetric_key)
+    61698    2.528    0.000    2.528    0.000 {posix.link}
+  2768413    2.491    0.000    2.491    0.000 {getattr}
+   246230    2.335    0.000    2.335    0.000 {method 'split' of 'str' objects}
+    61038    2.086    0.000    2.311    0.000 chunklist.py:42(key)
+  1223658    1.896    0.000    2.311    0.000 codec.py:91(index_size)
+    61072    2.309    0.000    2.309    0.000 {open}
+    61718    1.752    0.000    2.227    0.000 subprocess.py:957(_get_handles)
+ 2406/484    0.327    0.000    2.224    0.005 vfs.py:179(depth_first)
+    61036    1.635    0.000    2.201    0.000 repo.py:560(_chunk_filename)
+  1415390    2.032    0.000    2.032    0.000 {setattr}
+   244144    1.411    0.000    2.015    0.000 elapsed.py:43(update)
+   370218    1.889    0.000    1.889    0.000 {fcntl.fcntl}
+    61718    1.826    0.000    1.826    0.000 {gc.enable}
+    61036    1.599    0.000    1.736    0.000 bytesize.py:44(update)
+   122072    1.317    0.000    1.687    0.000 counter.py:33(update)
+   123121    1.675    0.000    1.675    0.000 {posix.lstat}
+   123453    1.658    0.000    1.658    0.000 {posix.remove}
+   183115    1.557    0.000    1.561    0.000 repo_tree.py:50(init_forest)

(Diff truncated)
Add new benchmark result.
diff --git a/obnam/benchmarks/973-239/obnam-1g-backup-0-cumulative.txt b/obnam/benchmarks/973-239/obnam-1g-backup-0-cumulative.txt
new file mode 100644
index 0000000..b79164f
--- /dev/null
+++ b/obnam/benchmarks/973-239/obnam-1g-backup-0-cumulative.txt
@@ -0,0 +1,3067 @@
+Thu May  5 12:59:33 2011    /home/liw/tmp/tmpxTF0FV
+
+         161955041 function calls (160605531 primitive calls) in 5062.141 CPU seconds
+
+   Ordered by: cumulative time
+
+   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
+        1    0.000    0.000 5062.163 5062.163 <string>:1(<module>)
+        1    0.000    0.000 5062.163 5062.163 obnam:26(main)
+        1    0.000    0.000 5062.161 5062.161 app.py:169(run)
+        1    0.000    0.000 5061.936 5061.936 interp.py:28(execute)
+        1    5.042    5.042 5061.936 5061.936 backup_plugin.py:47(backup)
+   244633    4.336    0.000 4684.092    0.019 repo.py:78(helper)
+    61036   11.343    0.000 4334.504    0.071 backup_plugin.py:238(backup_file_contents)
+    61036    2.248    0.000 3688.163    0.060 backup_plugin.py:261(backup_file_chunk)
+    61036   15.131    0.000 3657.801    0.060 repo.py:565(put_chunk)
+    61037    9.216    0.000 3384.944    0.055 repo.py:157(write_file)
+   183713   11.010    0.000 3383.137    0.018 hooks.py:107(call)
+    61631    4.568    0.000 3303.638    0.054 hooks.py:71(call_callbacks)
+    61629   25.650    0.000 3299.003    0.054 encryption_plugin.py:105(toplevel_write_data)
+   123287   52.965    0.000 2037.759    0.017 subprocess.py:563(__init__)
+   123287  103.256    0.001 1953.460    0.016 subprocess.py:1017(_execute_child)
+    61631   12.043    0.000 1716.635    0.028 encryption_plugin.py:121(get_symmetric_key)
+    61631   14.599    0.000 1632.994    0.026 encryption.py:226(decrypt_with_secret_keys)
+    61650   15.289    0.000 1617.156    0.026 encryption.py:92(_gpg)
+    61635    9.864    0.000 1555.608    0.025 encryption.py:82(encrypt_symmetric)
+    61637   18.222    0.000 1544.203    0.025 encryption.py:34(_gpg_pipe)
+   550793   17.526    0.000 1165.806    0.002 tree.py:211(insert)
+   745126 1123.095    0.002 1123.095    0.002 {posix.read}
+   246574    6.557    0.000 1119.620    0.005 subprocess.py:452(_eintr_retry_call)
+   550789   20.536    0.000 1109.876    0.002 tree.py:256(_insert_into_index)
+   123287    9.518    0.000 1027.070    0.008 subprocess.py:664(communicate)
+   123287   41.253    0.000 1016.749    0.008 subprocess.py:1187(_communicate)
+   550789   13.899    0.000  962.356    0.002 tree.py:303(_insert_into_leaf)
+   560882  936.618    0.002  936.618    0.002 {select.select}
+  1103307  791.841    0.001  850.734    0.001 codec.py:52(leaf_size)
+   555389    3.373    0.000  781.660    0.001 tree.py:120(_leaf_size)
+   123287  718.588    0.006  718.588    0.006 {posix.fork}
+    61519    0.987    0.000  525.252    0.009 backup_plugin.py:232(backup_metadata)
+    61525    0.591    0.000  524.023    0.009 repo.py:549(create)
+    61525    2.487    0.000  514.997    0.008 clientmetadatatree.py:222(create)
+   122072    2.025    0.000  484.747    0.004 clientmetadatatree.py:339(append_file_chunks)
+    61036    1.815    0.000  450.525    0.007 repo.py:672(append_file_chunks)
+    61036    0.326    0.000  325.422    0.005 clientmetadatatree.py:320(_insert_chunks)
+    61524    0.445    0.000  291.229    0.005 clientmetadatatree.py:252(set_metadata)
+    61036    5.543    0.000  169.924    0.003 chunklist.py:45(add)
+    61520    3.891    0.000  149.408    0.002 backup_plugin.py:156(find_files)
+   245338  124.554    0.001  126.936    0.001 vfs_local.py:28(read)
+  1652954    7.101    0.000  120.082    0.000 tree.py:114(put_node)
+    61050    3.256    0.000  104.468    0.002 vfs_local.py:150(write_file)
+    61642   11.701    0.000   97.617    0.002 vfs_local.py:182(_write_to_tempfile)
+    61525    7.242    0.000   91.675    0.001 metadata.py:83(read_metadata)
+  1652954    6.926    0.000   85.309    0.000 codec.py:136(size)
+  1964978   68.388    0.000   84.061    0.000 {method 'join' of 'str' objects}
+   123279    1.737    0.000   77.293    0.001 tempfile.py:259(mkstemp)
+  3687882   77.239    0.000   77.239    0.000 {_bisect.bisect_left}
+   123279   10.782    0.000   74.821    0.001 tempfile.py:219(_mkstemp_inner)
+  1102157   18.812    0.000   72.700    0.000 nodes.py:121(add)
+    61633    1.588    0.000   70.239    0.001 vfs_local.py:136(cat)
+    61525   69.825    0.001   69.825    0.001 {grp.getgrgid}
+   122082    4.686    0.000   68.489    0.001 hooks.py:47(call_callbacks)
+    61036    1.824    0.000   66.327    0.001 checksumtree.py:45(add)
+   122076    0.345    0.000   66.082    0.001 clientmetadatatree.py:153(_insert_int)
+   244145   14.455    0.000   53.840    0.000 status.py:63(__setitem__)
+  4590945    9.031    0.000   50.727    0.000 lru.py:101(remove)
+  1101582    4.551    0.000   49.358    0.000 tree.py:198(_shadow)
+    61036    0.183    0.000   47.408    0.001 repo.py:662(set_file_chunks)
+    61036    0.606    0.000   47.226    0.001 clientmetadatatree.py:325(set_file_chunks)
+        4    0.000    0.000   45.825   11.456 repo_tree.py:76(commit)
+        4    0.001    0.000   45.825   11.456 forest.py:93(commit)
+      3/2    0.000    0.000   45.646   22.823 repo.py:52(helper)
+        1    0.001    0.001   45.644   45.644 repo.py:428(commit_client)
+        4    0.000    0.000   45.181   11.295 nodestore_disk.py:139(push_upload_queue)
+        4    0.082    0.021   45.180   11.295 uploadqueue.py:52(push)
+      583    0.094    0.000   44.972    0.077 nodestore_disk.py:142(_really_put_node)
+      592    0.108    0.000   42.651    0.072 repo.py:163(overwrite_file)
+   122556    1.454    0.000   42.565    0.000 repo.py:67(helper)
+   123298   27.916    0.000   42.407    0.000 tempfile.py:127(next)
+  4590945   41.696    0.000   41.696    0.000 lru.py:75(_remove)
+   367685    3.635    0.000   37.496    0.000 tree.py:126(lookup)
+  1285620    1.869    0.000   37.380    0.000 tree.py:110(get_node)
+    61036    4.760    0.000   37.151    0.001 terminal_status_plugin.py:72(data_uploaded_cb)
+  1101582    6.746    0.000   36.259    0.000 nodestore_disk.py:173(start_modification)
+  1285620    2.766    0.000   35.510    0.000 nodestore_disk.py:154(get_node)
+        1    0.000    0.000   34.288   34.288 clientmetadatatree.py:156(commit)
+  1285620    7.500    0.000   32.744    0.000 lru.py:86(get)
+   553627   31.001    0.000   31.001    0.000 {method 'close' of 'file' objects}
+  1652954    4.481    0.000   26.934    0.000 nodestore_disk.py:134(put_node)
+   918474    3.920    0.000   26.622    0.000 nodes.py:199(find_key_for_child_containing)
+    61037    7.930    0.000   26.551    0.000 backup_plugin.py:134(dump_memory_profile)
+  1101582    4.309    0.000   26.292    0.000 uploadqueue.py:57(remove)
+    61036    2.507    0.000   26.152    0.000 terminal_status_plugin.py:61(found_file_cb)
+  4591528   15.169    0.000   26.000    0.000 lru.py:54(add)
+   245114    0.904    0.000   25.913    0.000 tree.py:148(lookup_range)
+   308225   24.936    0.000   24.936    0.000 {posix.fdopen}
+490215/245114    2.623    0.000   24.306    0.000 tree.py:161(_lookup_range)
+    61042    1.247    0.000   23.337    0.000 backup_plugin.py:200(needs_backup)
+   550797    3.508    0.000   21.505    0.000 tree.py:99(set_root)
+    61036    5.540    0.000   21.291    0.000 repo.py:539(get_metadata)
+   183599    1.480    0.000   19.935    0.000 clientmetadatatree.py:144(_lookup_int)
+  2807656    4.190    0.000   19.694    0.000 widget.py:46(__str__)
+    61036    0.346    0.000   19.380    0.000 repo.py:618(find_chunks)
+    61036    0.821    0.000   19.034    0.000 checksumtree.py:50(find)
+   122561    0.830    0.000   18.493    0.000 clientmetadatatree.py:245(get_metadata)
+  2441441    5.180    0.000   15.324    0.000 status.py:75(<genexpr>)
+   932901    9.228    0.000   14.988    0.000 nodes.py:137(remove)
+   122074    2.254    0.000   14.947    0.000 repo.py:241(checksum)
+   368633    1.541    0.000   14.664    0.000 genericpath.py:15(exists)
+19758883/18656659   12.184    0.000   14.343    0.000 {len}
+  2082245   13.479    0.000   13.479    0.000 {method 'insert' of 'list' objects}
+   368638   13.124    0.000   13.124    0.000 {posix.stat}
+   739788    9.338    0.000   12.330    0.000 random.py:259(choice)
+   306949    1.321    0.000   12.263    0.000 vfs_local.py:121(exists)
+  1917605   11.917    0.000   11.917    0.000 {method 'append' of 'list' objects}
+    61662    7.056    0.000   11.837    0.000 {method 'update' of 'dict' objects}
+  2203164    3.631    0.000   11.770    0.000 nodestore.py:148(can_be_modified)
+   800223    6.140    0.000   11.509    0.000 vfs_local.py:86(join)
+   122075    4.582    0.000   11.446    0.000 repo_tree.py:63(start_changes)
+   551368    3.562    0.000   10.563    0.000 tree.py:522(increment)
+  3305321    7.017    0.000   10.463    0.000 nodestore_disk.py:198(get_refcount)
+    61037    5.749    0.000   10.332    0.000 backup_plugin.py:125(vmrss)
+   490726    0.812    0.000    9.506    0.000 clientmetadatatree.py:137(get_file_id)
+   801353    9.313    0.000    9.313    0.000 {posix.close}
+  1652954    1.999    0.000    9.278    0.000 nodestore_disk.py:201(set_refcount)
+   183581    1.295    0.000    9.225    0.000 nodes.py:176(find_keys_in_range)
+   123287    0.676    0.000    9.052    0.000 posixpath.py:340(abspath)
+  1652954    2.077    0.000    8.771    0.000 uploadqueue.py:46(put)
+   490728    1.885    0.000    8.693    0.000 clientmetadatatree.py:79(hash_name)
+  1232048    6.824    0.000    8.651    0.000 posixpath.py:59(join)
+    61525    6.005    0.000    8.434    0.000 repo.py:94(encode_metadata)
+   184311    7.293    0.000    8.251    0.000 vfs_local.py:118(open)
+   123287    5.357    0.000    7.898    0.000 posixpath.py:311(normpath)
+  1652954    6.322    0.000    7.280    0.000 refcountstore.py:62(set_refcount)
+   123282    7.048    0.000    7.048    0.000 {posix.open}
+   123287    1.210    0.000    6.336    0.000 subprocess.py:1178(wait)
+   550789    3.164    0.000    6.211    0.000 tree.py:529(decrement)
+   612803    6.111    0.000    6.111    0.000 {_hashlib.openssl_md5}
+   123287    4.551    0.000    5.926    0.000 subprocess.py:957(_get_handles)
+  1101586    5.830    0.000    5.830    0.000 {repr}
+    61641    5.042    0.000    5.786    0.000 vfs_local.py:36(write)
+   122074    4.313    0.000    5.736    0.000 __init__.py:1483(debug)
+   493132    5.633    0.000    5.633    0.000 {fcntl.fcntl}
+   735849    3.725    0.000    5.608    0.000 clientmetadatatree.py:83(hashkey)
+   613281    0.950    0.000    5.486    0.000 clientmetadatatree.py:115(fskey)
+  8998964    5.391    0.000    5.391    0.000 tracing.py:64(trace)
+   183594    1.106    0.000    5.389    0.000 nodes.py:215(find_children_in_range)
+  1347650    5.386    0.000    5.386    0.000 nodes.py:51(__getitem__)
+    61525    5.290    0.000    5.290    0.000 {pwd.getpwuid}
+   305180    2.761    0.000    5.267    0.000 bytespeed.py:37(format)
+   122074    2.269    0.000    5.137    0.000 repo.py:256(new_checksummer)
+   122074    4.998    0.000    4.998    0.000 {method 'update' of '_hashlib.HASH' objects}
+   305180    4.972    0.000    4.972    0.000 bytesize.py:29(format)
+   123287    0.708    0.000    4.807    0.000 subprocess.py:1002(_set_cloexec_flag)
+   183736    4.318    0.000    4.318    0.000 cfg.py:110(__getitem__)
+   183594    0.509    0.000    4.284    0.000 nodes.py:79(find_potential_range)
+   184923    4.200    0.000    4.200    0.000 {posix.write}
+  4290452    4.164    0.000    4.164    0.000 {isinstance}
+  1407738    3.235    0.000    3.824    0.000 tree.py:73(check_key_size)
+   367188    0.930    0.000    3.774    0.000 nodes.py:95(helper)
+   123279    2.186    0.000    3.720    0.000 tempfile.py:47(_set_cloexec)
+   245830    2.920    0.000    3.709    0.000 posixpath.py:117(dirname)
+   123341    3.671    0.000    3.671    0.000 {posix.remove}
+    61036    0.223    0.000    3.663    0.000 tree.py:478(remove_range)
+  1224746    3.603    0.000    3.603    0.000 {_struct.pack}
+   490741    3.565    0.000    3.565    0.000 {method 'digest' of '_hashlib.HASH' objects}
+   123287    3.525    0.000    3.525    0.000 {gc.enable}
+   244145    1.098    0.000    3.521    0.000 messager.py:106(write)
+   488288    3.486    0.000    3.486    0.000 elapsed.py:35(format)
+    61526    0.208    0.000    3.485    0.000 clientmetadatatree.py:208(get_generation_id)
+  3305321    3.374    0.000    3.446    0.000 refcountstore.py:51(get_refcount)
+  2768244    3.175    0.000    3.175    0.000 {getattr}
+  2096105    3.175    0.000    3.175    0.000 UserDict.py:17(__getitem__)
+   123287    2.894    0.000    3.137    0.000 subprocess.py:653(__del__)
+    61525    1.341    0.000    3.119    0.000 metadata.py:67(__init__)
+  4722906    2.995    0.000    2.995    0.000 {method 'startswith' of 'str' objects}
+   123043    0.811    0.000    2.942    0.000 vfs_local.py:95(lstat)
+    61642    2.903    0.000    2.903    0.000 {posix.link}
+   183108    1.626    0.000    2.680    0.000 checksumtree.py:39(key)
+      583    0.022    0.000    2.669    0.005 codec.py:121(encode)
+      579    0.214    0.000    2.645    0.005 codec.py:57(encode_leaf)
+   739788    2.632    0.000    2.632    0.000 {method 'random' of '_random.Random' objects}
+  1101582    2.149    0.000    2.568    0.000 nodes.py:64(__len__)
+   122074    2.558    0.000    2.558    0.000 {method 'hexdigest' of '_hashlib.HASH' objects}
+    61038    2.315    0.000    2.530    0.000 chunklist.py:42(key)
+   305178    2.258    0.000    2.506    0.000 bytespeed.py:32(now)
+   246061    2.464    0.000    2.464    0.000 {method 'split' of 'str' objects}
+   123287    2.390    0.000    2.390    0.000 {posix.waitpid}
+    61072    2.343    0.000    2.343    0.000 {open}
+   493148    2.268    0.000    2.268    0.000 {posix.pipe}
+  1101586    1.839    0.000    2.224    0.000 codec.py:91(index_size)
+   244144    1.603    0.000    2.202    0.000 elapsed.py:43(update)
+      579    2.136    0.004    2.136    0.004 {map}
+  1415390    2.097    0.000    2.097    0.000 {setattr}
+    61036    1.542    0.000    2.090    0.000 repo.py:560(_chunk_filename)

(Diff truncated)
Tweak obnam benchmark a little.
diff --git a/obnam/benchmarkspec.mdwn b/obnam/benchmarkspec.mdwn
index e5affea..0f51a14 100644
--- a/obnam/benchmarkspec.mdwn
+++ b/obnam/benchmarkspec.mdwn
@@ -22,7 +22,8 @@ The main indication of performance for a backup program is how fast it
 transfers data to or from the backup store. Specifically, the amount
 of actual file data; all data on top of data is to be considered
 overhead. Thus, for a given amount of live data to back up, the
-performance will be expressed as a transfer speed: bytes per second.
+performance will be expressed as a transfer speed: bits of live
+data per second.
 
 For a full backup, the amount of file data is easy: the sum of the
 lengths of all files in the live data.
@@ -75,7 +76,7 @@ a wrapper and/or modifications to be perfect, but that's easy to arrange.
 The `run-benchmark` script in the Obnam source tree uses seivot to run a
 benchmark as outlined above.
 
-* Command line: `TMPDIR=/media/store ./run-benchmark . ~/btree/trunk`
+* Command line: `TMPDIR=/media/store ./run-benchmark`
 * Virtual machine: 2 GiB RAM, 3 vCPUs, 5 TB hard disk space,
 * Physical machine with Intel Core2 Quad CPU Q6600 at 2.40GHz,
   8 GiB RAM, 4 * 2 TB hard disks at 7200 RPM. While benchmark runs,

Obnam benchmark result.
diff --git a/obnam/benchmarks/968-237/obnam-1g-backup-0-cumulative.txt b/obnam/benchmarks/968-237/obnam-1g-backup-0-cumulative.txt
new file mode 100644
index 0000000..35ccda5
--- /dev/null
+++ b/obnam/benchmarks/968-237/obnam-1g-backup-0-cumulative.txt
@@ -0,0 +1,3044 @@
+Sat Apr 23 18:33:53 2011    /home/liw/tmp/tmpILyIqg
+
+         162658088 function calls (161308585 primitive calls) in 6323.769 CPU seconds
+
+   Ordered by: cumulative time
+
+   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
+        1    0.000    0.000 6323.772 6323.772 <string>:1(<module>)
+        1    0.000    0.000 6323.772 6323.772 obnam:26(main)
+        1    0.000    0.000 6323.770 6323.770 app.py:130(run)
+        1    0.000    0.000 6323.476 6323.476 interp.py:28(execute)
+        1    3.764    3.764 6323.476 6323.476 backup_plugin.py:47(backup)
+    61036   12.956    0.000 5570.533    0.091 backup_plugin.py:235(backup_file_contents)
+   244633    5.614    0.000 4735.830    0.019 repo.py:78(helper)
+    61036    2.245    0.000 3695.111    0.061 backup_plugin.py:258(backup_file_chunk)
+    61036   15.195    0.000 3662.852    0.060 repo.py:565(put_chunk)
+   183706    9.160    0.000 3387.742    0.018 hooks.py:107(call)
+    61037   10.137    0.000 3380.925    0.055 repo.py:157(write_file)
+    61624    4.938    0.000 3301.242    0.054 hooks.py:71(call_callbacks)
+    61622   25.181    0.000 3296.233    0.053 encryption_plugin.py:98(toplevel_write_data)
+   123273   53.355    0.000 2052.466    0.017 subprocess.py:563(__init__)
+   123273  109.822    0.001 1966.983    0.016 subprocess.py:1017(_execute_child)
+    61624    5.789    0.000 1694.781    0.028 encryption_plugin.py:104(get_symmetric_key)
+    61624   13.922    0.000 1638.137    0.027 encryption.py:226(decrypt_with_secret_keys)
+    61643   14.227    0.000 1622.753    0.026 encryption.py:92(_gpg)
+    61628   10.135    0.000 1577.150    0.026 encryption.py:82(encrypt_symmetric)
+    61630   20.241    0.000 1565.251    0.025 encryption.py:34(_gpg_pipe)
+   550793   16.534    0.000 1223.329    0.002 tree.py:211(insert)
+    61037   28.721    0.000 1212.568    0.020 backup_plugin.py:134(dump_memory_profile)
+   550789   18.950    0.000 1170.079    0.002 tree.py:256(_insert_into_index)
+    61037 1162.306    0.019 1162.306    0.019 {gc.get_objects}
+   745068 1145.672    0.002 1145.672    0.002 {posix.read}
+   246546    6.315    0.000 1141.164    0.005 subprocess.py:452(_eintr_retry_call)
+   123273   10.150    0.000 1038.989    0.008 subprocess.py:664(communicate)
+   123273   43.963    0.000 1027.995    0.008 subprocess.py:1187(_communicate)
+   550789   14.293    0.000 1017.383    0.002 tree.py:303(_insert_into_leaf)
+   560885  944.268    0.002  944.268    0.002 {select.select}
+  1103286  839.690    0.001  899.520    0.001 codec.py:52(leaf_size)
+   555333    4.223    0.000  833.165    0.002 tree.py:120(_leaf_size)
+   123273  705.729    0.006  705.729    0.006 {posix.fork}
+    61519    1.063    0.000  552.514    0.009 backup_plugin.py:229(backup_metadata)
+    61525    0.651    0.000  551.195    0.009 repo.py:549(create)
+    61525    2.714    0.000  543.924    0.009 clientmetadatatree.py:222(create)
+   122072    2.094    0.000  503.512    0.004 clientmetadatatree.py:339(append_file_chunks)
+    61036    1.606    0.000  470.548    0.008 repo.py:672(append_file_chunks)
+    61036    0.380    0.000  339.198    0.006 clientmetadatatree.py:320(_insert_chunks)
+    61524    0.518    0.000  309.026    0.005 clientmetadatatree.py:252(set_metadata)
+    61036    6.308    0.000  176.698    0.003 chunklist.py:45(add)
+    61520    3.074    0.000  142.856    0.002 backup_plugin.py:153(find_files)
+   245324  122.232    0.000  124.903    0.001 vfs_local.py:28(read)
+  1652947    7.488    0.000  120.951    0.000 tree.py:114(put_node)
+    61050    3.531    0.000  107.367    0.002 vfs_local.py:150(write_file)
+    61635   12.454    0.000  100.145    0.002 vfs_local.py:182(_write_to_tempfile)
+    61525    3.520    0.000   90.691    0.001 metadata.py:83(read_metadata)
+  1964876   68.203    0.000   85.078    0.000 {method 'join' of 'str' objects}
+  3684687   84.335    0.000   84.335    0.000 {_bisect.bisect_left}
+  1652947    7.189    0.000   84.017    0.000 codec.py:136(size)
+   123265    1.883    0.000   83.619    0.001 tempfile.py:259(mkstemp)
+   123265   11.521    0.000   80.939    0.001 tempfile.py:219(_mkstemp_inner)
+   122082    2.898    0.000   77.340    0.001 hooks.py:47(call_callbacks)
+    61525   75.048    0.001   75.048    0.001 {grp.getgrgid}
+  1102150   17.374    0.000   74.807    0.000 nodes.py:121(add)
+    61036    1.393    0.000   69.501    0.001 checksumtree.py:45(add)
+   122076    0.322    0.000   65.530    0.001 clientmetadatatree.py:153(_insert_int)
+   244145   17.557    0.000   62.416    0.000 status.py:63(__setitem__)
+  1101582    5.276    0.000   52.746    0.000 tree.py:198(_shadow)
+  4590934    9.302    0.000   51.841    0.000 lru.py:101(remove)
+    61626    1.364    0.000   50.613    0.001 vfs_local.py:136(cat)
+        4    0.000    0.000   49.402   12.350 repo_tree.py:76(commit)
+        4    0.001    0.000   49.402   12.350 forest.py:93(commit)
+        4    0.000    0.000   47.966   11.992 nodestore_disk.py:139(push_upload_queue)
+        4    0.081    0.020   47.966   11.992 uploadqueue.py:52(push)
+      576    0.104    0.000   47.735    0.083 nodestore_disk.py:142(_really_put_node)
+      3/2    0.000    0.000   46.939   23.469 repo.py:52(helper)
+        1    0.000    0.000   46.937   46.937 repo.py:428(commit_client)
+      585    0.116    0.000   46.911    0.080 repo.py:163(overwrite_file)
+    61036    5.098    0.000   45.811    0.001 terminal_status_plugin.py:72(data_uploaded_cb)
+    61036    0.200    0.000   45.621    0.001 repo.py:662(set_file_chunks)
+    61036    0.622    0.000   45.421    0.001 clientmetadatatree.py:325(set_file_chunks)
+   123284   30.419    0.000   44.021    0.000 tempfile.py:127(next)
+  4590934   42.539    0.000   42.539    0.000 lru.py:75(_remove)
+   122556    1.317    0.000   39.024    0.000 repo.py:67(helper)
+  1101582    7.082    0.000   38.415    0.000 nodestore_disk.py:173(start_modification)
+  1285616    1.939    0.000   37.153    0.000 tree.py:110(get_node)
+   367685    4.583    0.000   36.911    0.000 tree.py:126(lookup)
+        1    0.000    0.000   35.233   35.233 clientmetadatatree.py:156(commit)
+  1285616    3.429    0.000   35.214    0.000 nodestore_disk.py:154(get_node)
+  1285616    6.409    0.000   31.784    0.000 lru.py:86(get)
+   553578   29.949    0.000   29.949    0.000 {method 'close' of 'file' objects}
+  1652947    4.771    0.000   28.713    0.000 nodestore_disk.py:134(put_node)
+  1101582    5.081    0.000   28.058    0.000 uploadqueue.py:57(remove)
+  4591510   16.545    0.000   28.008    0.000 lru.py:54(add)
+   308190   27.010    0.000   27.010    0.000 {posix.fdopen}
+   245114    0.993    0.000   26.821    0.000 tree.py:148(lookup_range)
+    61036    2.722    0.000   26.794    0.000 terminal_status_plugin.py:61(found_file_cb)
+   918474    2.822    0.000   26.653    0.000 nodes.py:199(find_key_for_child_containing)
+490215/245114    2.364    0.000   25.050    0.000 tree.py:161(_lookup_range)
+  2807656    6.092    0.000   23.570    0.000 widget.py:46(__str__)
+   183599    1.352    0.000   21.437    0.000 clientmetadatatree.py:144(_lookup_int)
+   550797    3.580    0.000   21.401    0.000 tree.py:99(set_root)
+    61036    0.310    0.000   20.366    0.000 repo.py:618(find_chunks)
+    61036    0.925    0.000   20.056    0.000 checksumtree.py:50(find)
+    61042    1.373    0.000   19.050    0.000 backup_plugin.py:197(needs_backup)
+    61036    3.698    0.000   16.908    0.000 repo.py:539(get_metadata)
+  2441441    5.303    0.000   16.559    0.000 status.py:75(<genexpr>)
+   122561    0.936    0.000   15.954    0.000 clientmetadatatree.py:245(get_metadata)
+   929713    9.682    0.000   15.602    0.000 nodes.py:137(remove)
+   122074    2.510    0.000   14.683    0.000 repo.py:241(checksum)
+  2082231   14.361    0.000   14.361    0.000 {method 'insert' of 'list' objects}
+20003906/18901689   11.960    0.000   14.348    0.000 {len}
+   368602    1.625    0.000   13.295    0.000 genericpath.py:15(exists)
+   800166    6.709    0.000   12.389    0.000 vfs_local.py:86(join)
+  2203164    4.229    0.000   12.330    0.000 nodestore.py:148(can_be_modified)
+  1917424   12.310    0.000   12.310    0.000 {method 'append' of 'list' objects}
+   368606   11.670    0.000   11.670    0.000 {posix.stat}
+   306928    1.367    0.000   11.540    0.000 vfs_local.py:121(exists)
+   551361    3.778    0.000   11.430    0.000 tree.py:522(increment)
+   122075    3.219    0.000   11.409    0.000 repo_tree.py:63(start_changes)
+   739704    9.502    0.000   11.335    0.000 random.py:259(choice)
+    61037    6.108    0.000   11.028    0.000 backup_plugin.py:125(vmrss)
+   123273    0.725    0.000   10.977    0.000 posixpath.py:340(abspath)
+  3305314    7.044    0.000   10.521    0.000 nodestore_disk.py:198(get_refcount)
+   183581    0.793    0.000   10.418    0.000 nodes.py:176(find_keys_in_range)
+   123273    7.040    0.000    9.762    0.000 posixpath.py:311(normpath)
+  1652947    2.071    0.000    9.579    0.000 nodestore_disk.py:201(set_refcount)
+  1231955    7.241    0.000    9.252    0.000 posixpath.py:59(join)
+  1652947    2.188    0.000    8.999    0.000 uploadqueue.py:46(put)
+   801262    8.664    0.000    8.664    0.000 {posix.close}
+   244148    5.617    0.000    8.355    0.000 __init__.py:1483(debug)
+   184297    6.917    0.000    7.915    0.000 vfs_local.py:118(open)
+  1652947    6.526    0.000    7.508    0.000 refcountstore.py:62(set_refcount)
+   490726    0.815    0.000    7.379    0.000 clientmetadatatree.py:137(get_file_id)
+    61655    4.526    0.000    7.260    0.000 {method 'update' of 'dict' objects}
+   183594    0.885    0.000    6.698    0.000 nodes.py:215(find_children_in_range)
+    61525    4.586    0.000    6.620    0.000 repo.py:94(encode_metadata)
+   123268    6.607    0.000    6.607    0.000 {posix.open}
+   490728    1.617    0.000    6.564    0.000 clientmetadatatree.py:79(hash_name)
+    61634    5.580    0.000    6.410    0.000 vfs_local.py:36(write)
+   550789    3.248    0.000    6.355    0.000 tree.py:529(decrement)
+   305180    6.206    0.000    6.206    0.000 bytesize.py:29(format)
+   305180    3.391    0.000    6.018    0.000 bytespeed.py:37(format)
+   613281    0.971    0.000    5.845    0.000 clientmetadatatree.py:115(fskey)
+   183594    0.534    0.000    5.813    0.000 nodes.py:79(find_potential_range)
+   123273    1.212    0.000    5.716    0.000 subprocess.py:1178(wait)
+  1101586    5.701    0.000    5.701    0.000 {repr}
+   735849    3.639    0.000    5.631    0.000 clientmetadatatree.py:83(hashkey)
+   367188    0.939    0.000    5.279    0.000 nodes.py:95(helper)
+   122074    5.039    0.000    5.039    0.000 {method 'update' of '_hashlib.HASH' objects}
+  8998943    4.920    0.000    4.920    0.000 tracing.py:64(trace)
+   123265    2.258    0.000    4.791    0.000 tempfile.py:47(_set_cloexec)
+   493076    4.684    0.000    4.684    0.000 {fcntl.fcntl}
+   612803    4.677    0.000    4.677    0.000 {_hashlib.openssl_md5}
+   123273    3.286    0.000    4.655    0.000 subprocess.py:957(_get_handles)
+   244145    1.225    0.000    4.647    0.000 messager.py:106(write)
+   122074    2.357    0.000    4.538    0.000 repo.py:256(new_checksummer)
+   184902    4.398    0.000    4.398    0.000 {posix.write}
+  4290379    4.317    0.000    4.317    0.000 {isinstance}
+  1347646    4.265    0.000    4.265    0.000 nodes.py:51(__getitem__)
+  1407738    3.475    0.000    4.060    0.000 tree.py:73(check_key_size)
+   245815    3.123    0.000    3.964    0.000 posixpath.py:117(dirname)
+   123273    3.933    0.000    3.933    0.000 {gc.enable}
+  1224739    3.778    0.000    3.778    0.000 {_struct.pack}
+   123043    0.862    0.000    3.693    0.000 vfs_local.py:95(lstat)
+    61036    0.220    0.000    3.685    0.000 tree.py:478(remove_range)
+   123273    3.337    0.000    3.583    0.000 subprocess.py:653(__del__)
+    61525    3.527    0.000    3.527    0.000 {pwd.getpwuid}
+   488288    3.499    0.000    3.499    0.000 elapsed.py:35(format)
+    61525    1.320    0.000    3.479    0.000 metadata.py:67(__init__)
+  3305314    3.405    0.000    3.477    0.000 refcountstore.py:51(get_refcount)
+      3/2    0.000    0.000    3.415    1.707 repo.py:41(helper)
+        1    0.000    0.000    3.356    3.356 repo.py:305(commit_root)
+    61526    0.216    0.000    3.325    0.000 clientmetadatatree.py:208(get_generation_id)
+  4722748    3.241    0.000    3.241    0.000 {method 'startswith' of 'str' objects}
+    61038    3.008    0.000    3.218    0.000 chunklist.py:42(key)
+      576    0.030    0.000    2.978    0.005 codec.py:121(encode)
+    61635    2.977    0.000    2.977    0.000 {posix.link}
+      572    0.219    0.000    2.945    0.005 codec.py:57(encode_leaf)
+   123327    2.922    0.000    2.922    0.000 {posix.remove}
+   183108    1.743    0.000    2.836    0.000 checksumtree.py:39(key)
+  1101582    2.369    0.000    2.796    0.000 nodes.py:64(__len__)
+   123273    0.622    0.000    2.773    0.000 subprocess.py:1002(_set_cloexec_flag)
+   305178    2.383    0.000    2.627    0.000 bytespeed.py:32(now)
+   246036    2.620    0.000    2.620    0.000 {method 'split' of 'str' objects}
+   244148    0.541    0.000    2.613    0.000 __init__.py:1034(debug)
+   122074    2.596    0.000    2.596    0.000 {method 'hexdigest' of '_hashlib.HASH' objects}
+    61072    2.551    0.000    2.551    0.000 {open}
+   183726    2.457    0.000    2.457    0.000 cfg.py:110(__getitem__)
+   490741    2.451    0.000    2.451    0.000 {method 'digest' of '_hashlib.HASH' objects}
+  1415364    2.426    0.000    2.426    0.000 {setattr}
+   183115    2.410    0.000    2.415    0.000 repo_tree.py:50(init_forest)
+      572    2.408    0.004    2.408    0.004 {map}
+   123121    2.383    0.000    2.383    0.000 {posix.lstat}
+  1101586    1.993    0.000    2.375    0.000 codec.py:91(index_size)
+    61036    1.747    0.000    2.344    0.000 repo.py:560(_chunk_filename)

(Diff truncated)
Get rid of link, add note about outdatedness.
diff --git a/obnam/benchmarkreport.mdwn b/obnam/benchmarkreport.mdwn
index 51afee1..a2437ad 100644
--- a/obnam/benchmarkreport.mdwn
+++ b/obnam/benchmarkreport.mdwn
@@ -7,11 +7,13 @@ Obnam+btree benchmark archive
 This page lists results of benchmark runs of [[Obnam]],
 done by <a href="http://liw.fi/">Lars Wirzenius</a>.
 See [[the obnam benchmark page|benchmarkspec]]
-for information on how the benchmark is set up,
-and [[the result listing|benchmarks-alpha]] for individual
-result. This page has summarizes results of each benchmark run,
+for information on how the benchmark is set up. 
+This page has summarizes results of each benchmark run,
 so they can be compared.
 
+Note that this page reports old benchmarks, from the ALPHA
+era, and is no longer representative of what is really going on.
+
 Size 100.0 MiB, increment 10.0 MiB
 ----
 

Fix link for real
diff --git a/obnam/benchmarkreport.mdwn b/obnam/benchmarkreport.mdwn
index 22ce164..51afee1 100644
--- a/obnam/benchmarkreport.mdwn
+++ b/obnam/benchmarkreport.mdwn
@@ -8,7 +8,7 @@ This page lists results of benchmark runs of [[Obnam]],
 done by <a href="http://liw.fi/">Lars Wirzenius</a>.
 See [[the obnam benchmark page|benchmarkspec]]
 for information on how the benchmark is set up,
-and [[the result listing|benchmarks-old]] for individual
+and [[the result listing|benchmarks-alpha]] for individual
 result. This page has summarizes results of each benchmark run,
 so they can be compared.
 

Fix link
diff --git a/obnam/benchmarkreport.mdwn b/obnam/benchmarkreport.mdwn
index 02bfb8e..22ce164 100644
--- a/obnam/benchmarkreport.mdwn
+++ b/obnam/benchmarkreport.mdwn
@@ -8,7 +8,7 @@ This page lists results of benchmark runs of [[Obnam]],
 done by <a href="http://liw.fi/">Lars Wirzenius</a>.
 See [[the obnam benchmark page|benchmarkspec]]
 for information on how the benchmark is set up,
-and [[the result listing|benchmarks]] for individual
+and [[the result listing|benchmarks-old]] for individual
 result. This page has summarizes results of each benchmark run,
 so they can be compared.
 

Fix benchmark links
diff --git a/obnam.mdwn b/obnam.mdwn
index e821826..f3f0406 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -90,9 +90,10 @@ Other stuff:
 * Repository [[encryption]] and [[signing]]
 * [Bugs](http://code.liw.fi/obnam/bugs/)
   - see [code.liw.fi](http://liw.fi/code/) for instructions
-* [[Benchmark specification|obnam/benchmarkspec]]
-* [[Obnam benchmark report|benchmarkreport]] (not currently updated)
-* [[Individual Obnam benchmark results|benchmarks]] (not currently updated)
+* Benchmarks:
+  * [[specification|obnam/benchmarkspec]]
+  * [[results|benchmarks]]
+  * [[ancient benchmarks|benchmarkreport]] (no longer updated)
 * [[Obnam release procedure|obnam/release]] 
 
 Dependencies:

Add links to bug trackers.
diff --git a/genbackupdata.mdwn b/genbackupdata.mdwn
index 475fff2..1b8a9d0 100644
--- a/genbackupdata.mdwn
+++ b/genbackupdata.mdwn
@@ -7,6 +7,7 @@ genbackupdata is a program to generate test data for backup software testing.
 * Version control: `bzr get http://code.liw.fi/genbackupdata/bzr/trunk/`
 * Tarball and Debian packages: 
   <http://code.liw.fi/debian/pool/main/g/genbackupdata/>
+* [Bugs](http://code.liw.fi/genbackupdata/bugs/)
 
 See also:
 
diff --git a/obnam.mdwn b/obnam.mdwn
index ddd6bf4..e821826 100644
--- a/obnam.mdwn
+++ b/obnam.mdwn
@@ -88,8 +88,8 @@ Other stuff:
 
 * [[Obnam on-disk data structures|ondisk]]
 * Repository [[encryption]] and [[signing]]
-* <http://code.liw.fi/obnam/bugs/> &mdash; [SD](http://syncwith.us/sd/)
-  bug repository for Obnam.
+* [Bugs](http://code.liw.fi/obnam/bugs/)
+  - see [code.liw.fi](http://liw.fi/code/) for instructions
 * [[Benchmark specification|obnam/benchmarkspec]]
 * [[Obnam benchmark report|benchmarkreport]] (not currently updated)
 * [[Individual Obnam benchmark results|benchmarks]] (not currently updated)

New result summary with newer seivots-to-csv.
diff --git a/obnam/benchmarks/backup-1000000000.csv b/obnam/benchmarks/backup-1000000000.csv
index e565001..d6c5047 100644
--- a/obnam/benchmarks/backup-1000000000.csv
+++ b/obnam/benchmarks/backup-1000000000.csv
@@ -1,2 +1,2 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r965,r237,627.0,568.0,81.4,493.8
+obnam,larch,gen0 time (s),gen0 speed (Mbit/s),gen0 RAM (MiB),slowest inc (s),slowest inc (Mbit/s),largest RAM inc (MiB)
+r965,r237,627.0,12.8,568.0,81.4,9.8,493.8
diff --git a/obnam/benchmarks/forget-1000000000.csv b/obnam/benchmarks/forget-1000000000.csv
index 90cf77a..624b20a 100644
--- a/obnam/benchmarks/forget-1000000000.csv
+++ b/obnam/benchmarks/forget-1000000000.csv
@@ -1,2 +1,2 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r965,r237,45.0,276.5,44.1,201.5
+obnam,larch,gen0 time (s),gen0 speed (Mbit/s),gen0 RAM (MiB),slowest inc (s),slowest inc (Mbit/s),largest RAM inc (MiB)
+r965,r237,45.0,0.0,276.5,44.1,0.0,201.5
diff --git a/obnam/benchmarks/list_files-1000000000.csv b/obnam/benchmarks/list_files-1000000000.csv
index bd9f052..19c899f 100644
--- a/obnam/benchmarks/list_files-1000000000.csv
+++ b/obnam/benchmarks/list_files-1000000000.csv
@@ -1,2 +1,2 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r965,r237,19.3,340.0,22.0,366.4
+obnam,larch,gen0 time (s),gen0 speed (Mbit/s),gen0 RAM (MiB),slowest inc (s),slowest inc (Mbit/s),largest RAM inc (MiB)
+r965,r237,19.3,0.0,340.0,22.0,0.0,366.4
diff --git a/obnam/benchmarks/restore-1000000000.csv b/obnam/benchmarks/restore-1000000000.csv
index ba4a888..8d0370d 100644
--- a/obnam/benchmarks/restore-1000000000.csv
+++ b/obnam/benchmarks/restore-1000000000.csv
@@ -1,2 +1,2 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r965,r237,197.0,340.3,135.1,366.2
+obnam,larch,gen0 time (s),gen0 speed (Mbit/s),gen0 RAM (MiB),slowest inc (s),slowest inc (Mbit/s),largest RAM inc (MiB)
+r965,r237,197.0,0.0,340.3,135.1,0.0,366.2

New benchmark result.
diff --git a/obnam/benchmarks.mdwn b/obnam/benchmarks.mdwn
index f84220a..44a540b 100644
--- a/obnam/benchmarks.mdwn
+++ b/obnam/benchmarks.mdwn
@@ -1,22 +1,22 @@
 Benchmark results for obnam
 ===========================
 
-Live data size 1 MB
+Live data size 1 GB
 -------------------
 
 Backup:
 
-[[!table file="obnam/benchmarks/backup-1000000.csv"]]
+[[!table file="obnam/benchmarks/backup-1000000000.csv"]]
 
 Restore:
 
-[[!table file="obnam/benchmarks/restore-1000000.csv"]]
+[[!table file="obnam/benchmarks/restore-1000000000.csv"]]
 
 List:
 
-[[!table file="obnam/benchmarks/list_files-1000000.csv"]]
+[[!table file="obnam/benchmarks/list_files-1000000000.csv"]]
 
 Forget:
 
-[[!table file="obnam/benchmarks/forget-1000000.csv"]]
+[[!table file="obnam/benchmarks/forget-1000000000.csv"]]
 
diff --git a/obnam/benchmarks/962-237/obnam-1m-backup-0-cumulative.txt b/obnam/benchmarks/962-237/obnam-1m-backup-0-cumulative.txt
deleted file mode 100644
index 9eff080..0000000
--- a/obnam/benchmarks/962-237/obnam-1m-backup-0-cumulative.txt
+++ /dev/null
@@ -1,2627 +0,0 @@
-Thu Apr 21 12:00:02 2011    /var/tmp/tmpI54FoD
-
-         293781 function calls (292329 primitive calls) in 1.054 CPU seconds
-
-   Ordered by: cumulative time
-
-   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
-        1    0.000    0.000    1.056    1.056 <string>:1(<module>)
-        1    0.000    0.000    1.056    1.056 obnam:26(main)
-        1    0.000    0.000    1.053    1.053 app.py:130(run)
-        1    0.000    0.000    0.936    0.936 interp.py:28(execute)
-        1    0.001    0.001    0.936    0.936 backup_plugin.py:47(backup)
-      257    0.001    0.000    0.423    0.002 repo.py:78(helper)
-       62    0.002    0.000    0.389    0.006 backup_plugin.py:235(backup_file_contents)
-        4    0.000    0.000    0.321    0.080 repo_tree.py:76(commit)
-        4    0.000    0.000    0.321    0.080 forest.py:93(commit)
-        4    0.000    0.000    0.312    0.078 nodestore_disk.py:204(save_refcounts)
-        4    0.001    0.000    0.312    0.078 refcountstore.py:70(save_refcounts)
-        4    0.168    0.042    0.303    0.076 refcountstore.py:98(encode_refcounts)
-      587    0.014    0.000    0.297    0.001 tree.py:211(insert)
-      3/2    0.000    0.000    0.240    0.120 repo.py:52(helper)
-        1    0.000    0.000    0.239    0.239 repo.py:428(commit_client)
-      583    0.017    0.000    0.223    0.000 tree.py:256(_insert_into_index)
-      124    0.002    0.000    0.141    0.001 clientmetadatatree.py:339(append_file_chunks)
-       71    0.001    0.000    0.140    0.002 repo.py:549(create)
-       62    0.001    0.000    0.136    0.002 backup_plugin.py:258(backup_file_chunk)
-       66    0.000    0.000    0.132    0.002 backup_plugin.py:229(backup_metadata)
-       71    0.002    0.000    0.131    0.002 clientmetadatatree.py:222(create)
-   131935    0.127    0.000    0.127    0.000 {method 'get' of 'dict' objects}
-       62    0.002    0.000    0.124    0.002 repo.py:565(put_chunk)
-        2    0.000    0.000    0.112    0.056 pluginmgr.py:185(load_plugins)
-       22    0.001    0.000    0.112    0.005 pluginmgr.py:205(load_plugin_file)
-       22    0.002    0.000    0.107    0.005 {imp.load_module}
-       62    0.000    0.000    0.104    0.002 repo.py:672(append_file_chunks)
-        1    0.025    0.025    0.100    0.100 __init__.py:54(<module>)
-     1761    0.012    0.000    0.100    0.000 tree.py:114(put_node)
-      583    0.008    0.000    0.098    0.000 tree.py:303(_insert_into_leaf)
-      3/2    0.000    0.000    0.085    0.043 repo.py:41(helper)
-        1    0.000    0.000    0.085    0.085 repo.py:305(commit_root)
-        1    0.000    0.000    0.082    0.082 clientmetadatatree.py:156(commit)
-       70    0.001    0.000    0.076    0.001 clientmetadatatree.py:252(set_metadata)
-        1    0.032    0.032    0.068    0.068 transport.py:21(<module>)
-      128    0.001    0.000    0.066    0.001 clientmetadatatree.py:153(_insert_int)
-       67    0.001    0.000    0.064    0.001 backup_plugin.py:153(find_files)
-       63    0.007    0.000    0.055    0.001 backup_plugin.py:134(dump_memory_profile)
-       62    0.000    0.000    0.054    0.001 repo.py:662(set_file_chunks)
-       62    0.001    0.000    0.054    0.001 clientmetadatatree.py:325(set_file_chunks)
-      216    0.001    0.000    0.053    0.000 hooks.py:107(call)
-      134    0.001    0.000    0.051    0.000 hooks.py:47(call_callbacks)
-       81    0.002    0.000    0.049    0.001 vfs_local.py:182(_write_to_tempfile)
-      249    0.006    0.000    0.047    0.000 status.py:63(__setitem__)
-     1761    0.008    0.000    0.047    0.000 nodestore_disk.py:134(put_node)
-       63    0.001    0.000    0.043    0.001 repo.py:157(write_file)
-      591    0.006    0.000    0.042    0.000 tree.py:99(set_root)
-       64    0.001    0.000    0.041    0.001 vfs_local.py:150(write_file)
-      143    0.041    0.000    0.041    0.000 {_obnam.fadvise_dontneed}
-     4880    0.022    0.000    0.040    0.000 lru.py:54(add)
-     1761    0.013    0.000    0.039    0.000 codec.py:136(size)
-     1717    0.014    0.000    0.037    0.000 {method 'join' of 'str' objects}
-     1170    0.005    0.000    0.036    0.000 tree.py:198(_shadow)
-       62    0.001    0.000    0.035    0.001 terminal_status_plugin.py:61(found_file_cb)
-       62    0.000    0.000    0.034    0.001 chunklist.py:45(add)
-       63    0.033    0.001    0.033    0.001 {gc.get_objects}
-       62    0.000    0.000    0.033    0.001 clientmetadatatree.py:320(_insert_chunks)
-       62    0.000    0.000    0.033    0.001 checksumtree.py:45(add)
-     1170    0.020    0.000    0.031    0.000 codec.py:52(leaf_size)
-     1358    0.004    0.000    0.028    0.000 tree.py:110(get_node)
-     4872    0.015    0.000    0.027    0.000 lru.py:101(remove)
-      128    0.008    0.000    0.027    0.000 vfs_local.py:28(read)
-20946/19764    0.024    0.000    0.027    0.000 {len}
-       79    0.003    0.000    0.026    0.000 vfs_local.py:36(write)
-     1358    0.004    0.000    0.024    0.000 nodestore_disk.py:154(get_node)
-     1170    0.005    0.000    0.023    0.000 nodestore_disk.py:173(start_modification)
-     2481    0.007    0.000    0.022    0.000 status.py:75(<genexpr>)
-      401    0.006    0.000    0.022    0.000 tree.py:126(lookup)
-      583    0.004    0.000    0.021    0.000 tree.py:120(_leaf_size)
-      260    0.001    0.000    0.021    0.000 tree.py:148(lookup_range)
-     1358    0.006    0.000    0.021    0.000 lru.py:86(get)
-     2852    0.007    0.000    0.020    0.000 widget.py:46(__str__)
-  515/260    0.003    0.000    0.018    0.000 tree.py:161(_lookup_range)
-     1170    0.011    0.000    0.018    0.000 nodes.py:121(add)
-       71    0.004    0.000    0.017    0.000 metadata.py:83(read_metadata)
-     1761    0.005    0.000    0.017    0.000 uploadqueue.py:46(put)
-      129    0.001    0.000    0.017    0.000 repo.py:67(helper)
-     2340    0.006    0.000    0.016    0.000 nodestore.py:148(can_be_modified)
-       81    0.000    0.000    0.015    0.000 tempfile.py:259(mkstemp)
-     3510    0.009    0.000    0.015    0.000 nodestore_disk.py:198(get_refcount)
-       81    0.001    0.000    0.015    0.000 tempfile.py:219(_mkstemp_inner)
-       62    0.000    0.000    0.014    0.000 terminal_status_plugin.py:72(data_uploaded_cb)
-       17    0.000    0.000    0.013    0.001 repo.py:163(overwrite_file)
-      583    0.005    0.000    0.012    0.000 tree.py:529(decrement)
-     4872    0.012    0.000    0.012    0.000 lru.py:75(_remove)
-      197    0.001    0.000    0.012    0.000 clientmetadatatree.py:144(_lookup_int)
-       17    0.000    0.000    0.012    0.001 vfs_local.py:160(overwrite_file)
-      587    0.004    0.000    0.012    0.000 tree.py:522(increment)
-     1761    0.005    0.000    0.012    0.000 nodestore_disk.py:201(set_refcount)
-      133    0.001    0.000    0.011    0.000 clientmetadatatree.py:245(get_metadata)
-     9584    0.011    0.000    0.011    0.000 tracing.py:64(trace)
-      354    0.002    0.000    0.010    0.000 vfs_local.py:121(exists)
-     1333    0.010    0.000    0.010    0.000 {_struct.pack}
-       63    0.005    0.000    0.010    0.000 backup_plugin.py:125(vmrss)
-     1170    0.003    0.000    0.010    0.000 uploadqueue.py:57(remove)
-        1    0.002    0.002    0.009    0.009 util.py:21(<module>)
-     1233    0.006    0.000    0.009    0.000 posixpath.py:59(join)
-        1    0.000    0.000    0.009    0.009 backup_plugin.py:217(backup_parents)
-      836    0.003    0.000    0.008    0.000 vfs_local.py:86(join)
-       62    0.000    0.000    0.008    0.000 repo.py:618(find_chunks)
-       62    0.001    0.000    0.008    0.000 checksumtree.py:50(find)
-       71    0.004    0.000    0.008    0.000 repo.py:94(encode_metadata)
-       65    0.001    0.000    0.008    0.000 backup_plugin.py:197(needs_backup)
-        1    0.000    0.000    0.008    0.008 common.py:21(<module>)
-        1    0.005    0.005    0.008    0.008 channel.py:21(<module>)
-       62    0.000    0.000    0.007    0.000 tree.py:478(remove_range)
-      126    0.001    0.000    0.007    0.000 repo.py:241(checksum)
-      984    0.004    0.000    0.007    0.000 nodes.py:199(find_key_for_child_containing)
-        1    0.007    0.007    0.007    0.007 sftp_client.py:21(<module>)
-     1761    0.005    0.000    0.007    0.000 refcountstore.py:62(set_refcount)
-     4532    0.007    0.000    0.007    0.000 {isinstance}
-        1    0.000    0.000    0.007    0.007 repo.py:378(lock_client)
-      535    0.001    0.000    0.007    0.000 clientmetadatatree.py:137(get_file_id)
-      127    0.001    0.000    0.007    0.000 repo_tree.py:63(start_changes)
-       62    0.001    0.000    0.006    0.000 repo.py:539(get_metadata)
-      583    0.004    0.000    0.006    0.000 nodes.py:137(remove)
-     4916    0.006    0.000    0.006    0.000 {method 'startswith' of 'str' objects}
-     3499    0.006    0.000    0.006    0.000 {_bisect.bisect_left}
-        4    0.000    0.000    0.006    0.002 nodestore_disk.py:139(push_upload_queue)
-        4    0.000    0.000    0.006    0.002 uploadqueue.py:52(push)
-        1    0.000    0.000    0.006    0.006 pluginmgr.py:243(enable_plugins)
-        4    0.000    0.000    0.006    0.001 repo.py:344(check_format_version)
-        4    0.000    0.000    0.006    0.001 repo.py:322(get_format_version)
-        8    0.000    0.000    0.006    0.001 nodestore_disk.py:142(_really_put_node)
-        2    0.000    0.000    0.006    0.003 repo.py:151(cat)
-      663    0.002    0.000    0.006    0.000 clientmetadatatree.py:115(fskey)
-        1    0.004    0.004    0.006    0.006 dsskey.py:21(<module>)
-     1498    0.004    0.000    0.006    0.000 tree.py:73(check_key_size)
-      467    0.002    0.000    0.006    0.000 genericpath.py:15(exists)
-     3510    0.005    0.000    0.006    0.000 refcountstore.py:51(get_refcount)
-        2    0.000    0.000    0.006    0.003 vfs_local.py:136(cat)
-      126    0.005    0.000    0.005    0.000 {method 'update' of '_hashlib.HASH' objects}
-       81    0.002    0.000    0.005    0.000 tempfile.py:127(next)
-       72    0.000    0.000    0.005    0.000 clientmetadatatree.py:208(get_generation_id)
-      537    0.003    0.000    0.005    0.000 clientmetadatatree.py:79(hash_name)
-     1174    0.005    0.000    0.005    0.000 {repr}
-        1    0.004    0.004    0.005    0.005 client.py:21(<module>)
-      803    0.003    0.000    0.005    0.000 clientmetadatatree.py:83(hashkey)
-     1174    0.003    0.000    0.005    0.000 codec.py:91(index_size)
-      252    0.001    0.000    0.004    0.000 __init__.py:1483(debug)
-     3480    0.004    0.000    0.004    0.000 {getattr}
-        1    0.004    0.004    0.004    0.004 auth_handler.py:21(<module>)
-      193    0.001    0.000    0.004    0.000 nodes.py:215(find_children_in_range)
-      310    0.003    0.000    0.004    0.000 bytespeed.py:37(format)
-        1    0.000    0.000    0.004    0.004 pluginmgr.py:151(plugins)
-     1170    0.003    0.000    0.004    0.000 nodes.py:64(__len__)
-       88    0.000    0.000    0.004    0.000 posixpath.py:340(abspath)
-        1    0.000    0.000    0.004    0.004 __init__.py:31(new)
-        1    0.000    0.000    0.004    0.004 _UserFriendlyRNG.py:203(new)
-        1    0.000    0.000    0.004    0.004 _UserFriendlyRNG.py:193(_get_singleton)
-        1    0.000    0.000    0.004    0.004 _UserFriendlyRNG.py:140(__init__)
-        1    0.000    0.000    0.004    0.004 _UserFriendlyRNG.py:81(__init__)
-        2    0.000    0.000    0.004    0.002 __init__.py:25(<module>)
-      471    0.004    0.000    0.004    0.000 {posix.stat}
-      193    0.001    0.000    0.003    0.000 nodes.py:79(find_potential_range)

(Diff truncated)
Fiddling around to get table to work.
diff --git a/obnam/benchmarks/962-237/obnam-1m-backup-0-cumulative.txt b/obnam/benchmarks/962-237/obnam-1m-backup-0-cumulative.txt
index f1790cf..9eff080 100644
--- a/obnam/benchmarks/962-237/obnam-1m-backup-0-cumulative.txt
+++ b/obnam/benchmarks/962-237/obnam-1m-backup-0-cumulative.txt
@@ -1,157 +1,162 @@
-Thu Apr 21 11:51:45 2011    /var/tmp/tmp6K8rh3
+Thu Apr 21 12:00:02 2011    /var/tmp/tmpI54FoD
 
-         293801 function calls (292349 primitive calls) in 1.038 CPU seconds
+         293781 function calls (292329 primitive calls) in 1.054 CPU seconds
 
    Ordered by: cumulative time
 
    ncalls  tottime  percall  cumtime  percall filename:lineno(function)
-        1    0.000    0.000    1.040    1.040 <string>:1(<module>)
-        1    0.000    0.000    1.040    1.040 obnam:26(main)
-        1    0.000    0.000    1.037    1.037 app.py:130(run)
-        1    0.000    0.000    0.921    0.921 interp.py:28(execute)
-        1    0.001    0.001    0.921    0.921 backup_plugin.py:47(backup)
-      257    0.001    0.000    0.420    0.002 repo.py:78(helper)
-       62    0.002    0.000    0.380    0.006 backup_plugin.py:235(backup_file_contents)
+        1    0.000    0.000    1.056    1.056 <string>:1(<module>)
+        1    0.000    0.000    1.056    1.056 obnam:26(main)
+        1    0.000    0.000    1.053    1.053 app.py:130(run)
+        1    0.000    0.000    0.936    0.936 interp.py:28(execute)
+        1    0.001    0.001    0.936    0.936 backup_plugin.py:47(backup)
+      257    0.001    0.000    0.423    0.002 repo.py:78(helper)
+       62    0.002    0.000    0.389    0.006 backup_plugin.py:235(backup_file_contents)
         4    0.000    0.000    0.321    0.080 repo_tree.py:76(commit)
         4    0.000    0.000    0.321    0.080 forest.py:93(commit)
         4    0.000    0.000    0.312    0.078 nodestore_disk.py:204(save_refcounts)
         4    0.001    0.000    0.312    0.078 refcountstore.py:70(save_refcounts)
-        4    0.167    0.042    0.304    0.076 refcountstore.py:98(encode_refcounts)
-      587    0.014    0.000    0.296    0.001 tree.py:211(insert)
-      3/2    0.000    0.000    0.241    0.121 repo.py:52(helper)
-        1    0.000    0.000    0.240    0.240 repo.py:428(commit_client)
-      583    0.017    0.000    0.222    0.000 tree.py:256(_insert_into_index)
+        4    0.168    0.042    0.303    0.076 refcountstore.py:98(encode_refcounts)
+      587    0.014    0.000    0.297    0.001 tree.py:211(insert)
+      3/2    0.000    0.000    0.240    0.120 repo.py:52(helper)
+        1    0.000    0.000    0.239    0.239 repo.py:428(commit_client)
+      583    0.017    0.000    0.223    0.000 tree.py:256(_insert_into_index)
       124    0.002    0.000    0.141    0.001 clientmetadatatree.py:339(append_file_chunks)
-       71    0.001    0.000    0.139    0.002 repo.py:549(create)
-       62    0.001    0.000    0.135    0.002 backup_plugin.py:258(backup_file_chunk)
+       71    0.001    0.000    0.140    0.002 repo.py:549(create)
+       62    0.001    0.000    0.136    0.002 backup_plugin.py:258(backup_file_chunk)
        66    0.000    0.000    0.132    0.002 backup_plugin.py:229(backup_metadata)
        71    0.002    0.000    0.131    0.002 clientmetadatatree.py:222(create)
    131935    0.127    0.000    0.127    0.000 {method 'get' of 'dict' objects}
-       62    0.002    0.000    0.122    0.002 repo.py:565(put_chunk)
+       62    0.002    0.000    0.124    0.002 repo.py:565(put_chunk)
         2    0.000    0.000    0.112    0.056 pluginmgr.py:185(load_plugins)
        22    0.001    0.000    0.112    0.005 pluginmgr.py:205(load_plugin_file)
        22    0.002    0.000    0.107    0.005 {imp.load_module}
        62    0.000    0.000    0.104    0.002 repo.py:672(append_file_chunks)
         1    0.025    0.025    0.100    0.100 __init__.py:54(<module>)
-     1761    0.012    0.000    0.099    0.000 tree.py:114(put_node)
-      583    0.008    0.000    0.097    0.000 tree.py:303(_insert_into_leaf)
-      3/2    0.000    0.000    0.085    0.042 repo.py:41(helper)
-        1    0.000    0.000    0.084    0.084 repo.py:305(commit_root)
-        1    0.000    0.000    0.080    0.080 clientmetadatatree.py:156(commit)
+     1761    0.012    0.000    0.100    0.000 tree.py:114(put_node)
+      583    0.008    0.000    0.098    0.000 tree.py:303(_insert_into_leaf)
+      3/2    0.000    0.000    0.085    0.043 repo.py:41(helper)
+        1    0.000    0.000    0.085    0.085 repo.py:305(commit_root)
+        1    0.000    0.000    0.082    0.082 clientmetadatatree.py:156(commit)
        70    0.001    0.000    0.076    0.001 clientmetadatatree.py:252(set_metadata)
-        1    0.033    0.033    0.068    0.068 transport.py:21(<module>)
-      128    0.001    0.000    0.065    0.001 clientmetadatatree.py:153(_insert_int)
-       67    0.001    0.000    0.063    0.001 backup_plugin.py:153(find_files)
+        1    0.032    0.032    0.068    0.068 transport.py:21(<module>)
+      128    0.001    0.000    0.066    0.001 clientmetadatatree.py:153(_insert_int)
+       67    0.001    0.000    0.064    0.001 backup_plugin.py:153(find_files)
+       63    0.007    0.000    0.055    0.001 backup_plugin.py:134(dump_memory_profile)
        62    0.000    0.000    0.054    0.001 repo.py:662(set_file_chunks)
        62    0.001    0.000    0.054    0.001 clientmetadatatree.py:325(set_file_chunks)
-      216    0.001    0.000    0.052    0.000 hooks.py:107(call)
-      134    0.001    0.000    0.050    0.000 hooks.py:47(call_callbacks)
-       63    0.007    0.000    0.049    0.001 backup_plugin.py:134(dump_memory_profile)
-       81    0.002    0.000    0.048    0.001 vfs_local.py:182(_write_to_tempfile)
-     1761    0.008    0.000    0.046    0.000 nodestore_disk.py:134(put_node)
-      249    0.006    0.000    0.046    0.000 status.py:63(__setitem__)
-      591    0.006    0.000    0.043    0.000 tree.py:99(set_root)
-       63    0.001    0.000    0.042    0.001 repo.py:157(write_file)
-     4882    0.022    0.000    0.040    0.000 lru.py:54(add)
-       64    0.001    0.000    0.040    0.001 vfs_local.py:150(write_file)
-      143    0.040    0.000    0.040    0.000 {_obnam.fadvise_dontneed}
+      216    0.001    0.000    0.053    0.000 hooks.py:107(call)
+      134    0.001    0.000    0.051    0.000 hooks.py:47(call_callbacks)
+       81    0.002    0.000    0.049    0.001 vfs_local.py:182(_write_to_tempfile)
+      249    0.006    0.000    0.047    0.000 status.py:63(__setitem__)
+     1761    0.008    0.000    0.047    0.000 nodestore_disk.py:134(put_node)
+       63    0.001    0.000    0.043    0.001 repo.py:157(write_file)
+      591    0.006    0.000    0.042    0.000 tree.py:99(set_root)
+       64    0.001    0.000    0.041    0.001 vfs_local.py:150(write_file)
+      143    0.041    0.000    0.041    0.000 {_obnam.fadvise_dontneed}
+     4880    0.022    0.000    0.040    0.000 lru.py:54(add)
      1761    0.013    0.000    0.039    0.000 codec.py:136(size)
      1717    0.014    0.000    0.037    0.000 {method 'join' of 'str' objects}
      1170    0.005    0.000    0.036    0.000 tree.py:198(_shadow)
        62    0.001    0.000    0.035    0.001 terminal_status_plugin.py:61(found_file_cb)
        62    0.000    0.000    0.034    0.001 chunklist.py:45(add)
+       63    0.033    0.001    0.033    0.001 {gc.get_objects}
        62    0.000    0.000    0.033    0.001 clientmetadatatree.py:320(_insert_chunks)
        62    0.000    0.000    0.033    0.001 checksumtree.py:45(add)
      1170    0.020    0.000    0.031    0.000 codec.py:52(leaf_size)
-     1360    0.004    0.000    0.028    0.000 tree.py:110(get_node)
-       63    0.027    0.000    0.027    0.000 {gc.get_objects}
-     4874    0.015    0.000    0.027    0.000 lru.py:101(remove)
-20948/19766    0.024    0.000    0.027    0.000 {len}
+     1358    0.004    0.000    0.028    0.000 tree.py:110(get_node)
+     4872    0.015    0.000    0.027    0.000 lru.py:101(remove)
+      128    0.008    0.000    0.027    0.000 vfs_local.py:28(read)
+20946/19764    0.024    0.000    0.027    0.000 {len}
        79    0.003    0.000    0.026    0.000 vfs_local.py:36(write)
-     1360    0.004    0.000    0.024    0.000 nodestore_disk.py:154(get_node)
+     1358    0.004    0.000    0.024    0.000 nodestore_disk.py:154(get_node)
      1170    0.005    0.000    0.023    0.000 nodestore_disk.py:173(start_modification)
      2481    0.007    0.000    0.022    0.000 status.py:75(<genexpr>)
       401    0.006    0.000    0.022    0.000 tree.py:126(lookup)
-      128    0.003    0.000    0.021    0.000 vfs_local.py:28(read)
-      260    0.001    0.000    0.021    0.000 tree.py:148(lookup_range)
       583    0.004    0.000    0.021    0.000 tree.py:120(_leaf_size)
-     1360    0.006    0.000    0.020    0.000 lru.py:86(get)
+      260    0.001    0.000    0.021    0.000 tree.py:148(lookup_range)
+     1358    0.006    0.000    0.021    0.000 lru.py:86(get)
      2852    0.007    0.000    0.020    0.000 widget.py:46(__str__)
   515/260    0.003    0.000    0.018    0.000 tree.py:161(_lookup_range)
-     1170    0.010    0.000    0.018    0.000 nodes.py:121(add)
-     1761    0.005    0.000    0.017    0.000 uploadqueue.py:46(put)
+     1170    0.011    0.000    0.018    0.000 nodes.py:121(add)
        71    0.004    0.000    0.017    0.000 metadata.py:83(read_metadata)
+     1761    0.005    0.000    0.017    0.000 uploadqueue.py:46(put)
       129    0.001    0.000    0.017    0.000 repo.py:67(helper)
      2340    0.006    0.000    0.016    0.000 nodestore.py:148(can_be_modified)
+       81    0.000    0.000    0.015    0.000 tempfile.py:259(mkstemp)
      3510    0.009    0.000    0.015    0.000 nodestore_disk.py:198(get_refcount)
-       81    0.000    0.000    0.014    0.000 tempfile.py:259(mkstemp)
-       81    0.001    0.000    0.014    0.000 tempfile.py:219(_mkstemp_inner)
+       81    0.001    0.000    0.015    0.000 tempfile.py:219(_mkstemp_inner)
        62    0.000    0.000    0.014    0.000 terminal_status_plugin.py:72(data_uploaded_cb)
        17    0.000    0.000    0.013    0.001 repo.py:163(overwrite_file)
       583    0.005    0.000    0.012    0.000 tree.py:529(decrement)
-     4874    0.012    0.000    0.012    0.000 lru.py:75(_remove)
+     4872    0.012    0.000    0.012    0.000 lru.py:75(_remove)
       197    0.001    0.000    0.012    0.000 clientmetadatatree.py:144(_lookup_int)
        17    0.000    0.000    0.012    0.001 vfs_local.py:160(overwrite_file)
       587    0.004    0.000    0.012    0.000 tree.py:522(increment)
      1761    0.005    0.000    0.012    0.000 nodestore_disk.py:201(set_refcount)
       133    0.001    0.000    0.011    0.000 clientmetadatatree.py:245(get_metadata)
      9584    0.011    0.000    0.011    0.000 tracing.py:64(trace)
-     1333    0.010    0.000    0.010    0.000 {_struct.pack}
       354    0.002    0.000    0.010    0.000 vfs_local.py:121(exists)
-     1170    0.003    0.000    0.010    0.000 uploadqueue.py:57(remove)
+     1333    0.010    0.000    0.010    0.000 {_struct.pack}
        63    0.005    0.000    0.010    0.000 backup_plugin.py:125(vmrss)
+     1170    0.003    0.000    0.010    0.000 uploadqueue.py:57(remove)
         1    0.002    0.002    0.009    0.009 util.py:21(<module>)
-        1    0.000    0.000    0.009    0.009 backup_plugin.py:217(backup_parents)
      1233    0.006    0.000    0.009    0.000 posixpath.py:59(join)
-       62    0.000    0.000    0.008    0.000 repo.py:618(find_chunks)
+        1    0.000    0.000    0.009    0.009 backup_plugin.py:217(backup_parents)
       836    0.003    0.000    0.008    0.000 vfs_local.py:86(join)
+       62    0.000    0.000    0.008    0.000 repo.py:618(find_chunks)
        62    0.001    0.000    0.008    0.000 checksumtree.py:50(find)
        71    0.004    0.000    0.008    0.000 repo.py:94(encode_metadata)
+       65    0.001    0.000    0.008    0.000 backup_plugin.py:197(needs_backup)
         1    0.000    0.000    0.008    0.008 common.py:21(<module>)
-       65    0.000    0.000    0.007    0.000 backup_plugin.py:197(needs_backup)
-        1    0.005    0.005    0.007    0.007 channel.py:21(<module>)
-        1    0.007    0.007    0.007    0.007 sftp_client.py:21(<module>)
+        1    0.005    0.005    0.008    0.008 channel.py:21(<module>)
        62    0.000    0.000    0.007    0.000 tree.py:478(remove_range)
       126    0.001    0.000    0.007    0.000 repo.py:241(checksum)
       984    0.004    0.000    0.007    0.000 nodes.py:199(find_key_for_child_containing)
+        1    0.007    0.007    0.007    0.007 sftp_client.py:21(<module>)
      1761    0.005    0.000    0.007    0.000 refcountstore.py:62(set_refcount)
-     4536    0.007    0.000    0.007    0.000 {isinstance}
+     4532    0.007    0.000    0.007    0.000 {isinstance}
+        1    0.000    0.000    0.007    0.007 repo.py:378(lock_client)
       535    0.001    0.000    0.007    0.000 clientmetadatatree.py:137(get_file_id)
       127    0.001    0.000    0.007    0.000 repo_tree.py:63(start_changes)
+       62    0.001    0.000    0.006    0.000 repo.py:539(get_metadata)
       583    0.004    0.000    0.006    0.000 nodes.py:137(remove)
      4916    0.006    0.000    0.006    0.000 {method 'startswith' of 'str' objects}
      3499    0.006    0.000    0.006    0.000 {_bisect.bisect_left}
-       62    0.001    0.000    0.006    0.000 repo.py:539(get_metadata)
-        4    0.000    0.000    0.006    0.001 nodestore_disk.py:139(push_upload_queue)
-        4    0.000    0.000    0.006    0.001 uploadqueue.py:52(push)
+        4    0.000    0.000    0.006    0.002 nodestore_disk.py:139(push_upload_queue)
+        4    0.000    0.000    0.006    0.002 uploadqueue.py:52(push)
         1    0.000    0.000    0.006    0.006 pluginmgr.py:243(enable_plugins)
-     1498    0.004    0.000    0.006    0.000 tree.py:73(check_key_size)
+        4    0.000    0.000    0.006    0.001 repo.py:344(check_format_version)
+        4    0.000    0.000    0.006    0.001 repo.py:322(get_format_version)
         8    0.000    0.000    0.006    0.001 nodestore_disk.py:142(_really_put_node)
+        2    0.000    0.000    0.006    0.003 repo.py:151(cat)
       663    0.002    0.000    0.006    0.000 clientmetadatatree.py:115(fskey)
         1    0.004    0.004    0.006    0.006 dsskey.py:21(<module>)

(Diff truncated)
Fiddling around to get table to work.
diff --git a/obnam/benchmarks/backup-1000000.csv b/obnam/benchmarks/backup-1000000.csv
index 349533d..71d729e 100644
--- a/obnam/benchmarks/backup-1000000.csv
+++ b/obnam/benchmarks/backup-1000000.csv
@@ -1,2 +1,2 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r962,r237,1.2,61.8,0.9,86.2
+obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
+r962,r237,1.1,61.8,0.9,86.2
diff --git a/obnam/benchmarks/forget-1000000.csv b/obnam/benchmarks/forget-1000000.csv
index f60f456..2e6e5a0 100644
--- a/obnam/benchmarks/forget-1000000.csv
+++ b/obnam/benchmarks/forget-1000000.csv
@@ -1,2 +1,2 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r962,r237,0.4,90.4,0.4,88.1
+obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
+r962,r237,0.4,90.4,0.4,88.0
diff --git a/obnam/benchmarks/list_files-1000000.csv b/obnam/benchmarks/list_files-1000000.csv
index 7608853..8e84c55 100644
--- a/obnam/benchmarks/list_files-1000000.csv
+++ b/obnam/benchmarks/list_files-1000000.csv
@@ -1,2 +1,2 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r962,r237,0.3,55.2,0.3,55.3
+obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
+r962,r237,0.3,55.2,0.3,55.2
diff --git a/obnam/benchmarks/restore-1000000.csv b/obnam/benchmarks/restore-1000000.csv
index 20515f2..9fbddc9 100644
--- a/obnam/benchmarks/restore-1000000.csv
+++ b/obnam/benchmarks/restore-1000000.csv
@@ -1,2 +1,2 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r962,r237,0.4,55.4,0.6,55.4
+obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
+r962,r237,0.3,55.4,0.6,55.4

Remove unnecessary files.
diff --git a/obnam/benchmarks/backup b/obnam/benchmarks/backup
deleted file mode 100644
index 349533d..0000000
--- a/obnam/benchmarks/backup
+++ /dev/null
@@ -1,2 +0,0 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r962,r237,1.2,61.8,0.9,86.2
diff --git a/obnam/benchmarks/backup.csv b/obnam/benchmarks/backup.csv
deleted file mode 100644
index c7c3fb1..0000000
--- a/obnam/benchmarks/backup.csv
+++ /dev/null
@@ -1,11 +0,0 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
diff --git a/obnam/benchmarks/backup.txt b/obnam/benchmarks/backup.txt
deleted file mode 100644
index 349533d..0000000
--- a/obnam/benchmarks/backup.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r962,r237,1.2,61.8,0.9,86.2

Fiddling around to get table to work.
diff --git a/obnam/benchmarks.mdwn b/obnam/benchmarks.mdwn
index d210e7c..f84220a 100644
--- a/obnam/benchmarks.mdwn
+++ b/obnam/benchmarks.mdwn
@@ -6,22 +6,17 @@ Live data size 1 MB
 
 Backup:
 
-[[!table format=csv file="obnam/benchmarks/backup.csv"]]
-
-[[!table format=csv data="""
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r962,r237,1.2,61.8,0.9,86.2
-"""]]
+[[!table file="obnam/benchmarks/backup-1000000.csv"]]
 
 Restore:
 
-[[!table file=restore-1000000.csv]]
+[[!table file="obnam/benchmarks/restore-1000000.csv"]]
 
 List:
 
-[[!table file=list_files-1000000.csv]]
+[[!table file="obnam/benchmarks/list_files-1000000.csv"]]
 
 Forget:
 
-[[!table file=forget-1000000.csv]]
+[[!table file="obnam/benchmarks/forget-1000000.csv"]]
 
diff --git a/obnam/benchmarks/962-237/obnam-1m-backup-0-cumulative.txt b/obnam/benchmarks/962-237/obnam-1m-backup-0-cumulative.txt
index 8ae7aac..f1790cf 100644
--- a/obnam/benchmarks/962-237/obnam-1m-backup-0-cumulative.txt
+++ b/obnam/benchmarks/962-237/obnam-1m-backup-0-cumulative.txt
@@ -1,155 +1,154 @@
-Thu Apr 21 11:21:17 2011    /var/tmp/tmpdXbCJV
+Thu Apr 21 11:51:45 2011    /var/tmp/tmp6K8rh3
 
-         293761 function calls (292309 primitive calls) in 1.098 CPU seconds
+         293801 function calls (292349 primitive calls) in 1.038 CPU seconds
 
    Ordered by: cumulative time
 
    ncalls  tottime  percall  cumtime  percall filename:lineno(function)
-        1    0.000    0.000    1.100    1.100 <string>:1(<module>)
-        1    0.000    0.000    1.100    1.100 obnam:26(main)
-        1    0.000    0.000    1.097    1.097 app.py:130(run)
-        1    0.000    0.000    0.979    0.979 interp.py:28(execute)
-        1    0.001    0.001    0.979    0.979 backup_plugin.py:47(backup)
-      257    0.001    0.000    0.483    0.002 repo.py:78(helper)
-       62    0.002    0.000    0.441    0.007 backup_plugin.py:235(backup_file_contents)
-        4    0.000    0.000    0.318    0.080 repo_tree.py:76(commit)
-        4    0.000    0.000    0.318    0.080 forest.py:93(commit)
-        4    0.000    0.000    0.309    0.077 nodestore_disk.py:204(save_refcounts)
-        4    0.001    0.000    0.309    0.077 refcountstore.py:70(save_refcounts)
-        4    0.164    0.041    0.301    0.075 refcountstore.py:98(encode_refcounts)
-      587    0.015    0.000    0.297    0.001 tree.py:211(insert)
-      3/2    0.000    0.000    0.239    0.119 repo.py:52(helper)
-        1    0.000    0.000    0.238    0.238 repo.py:428(commit_client)
+        1    0.000    0.000    1.040    1.040 <string>:1(<module>)
+        1    0.000    0.000    1.040    1.040 obnam:26(main)
+        1    0.000    0.000    1.037    1.037 app.py:130(run)
+        1    0.000    0.000    0.921    0.921 interp.py:28(execute)
+        1    0.001    0.001    0.921    0.921 backup_plugin.py:47(backup)
+      257    0.001    0.000    0.420    0.002 repo.py:78(helper)
+       62    0.002    0.000    0.380    0.006 backup_plugin.py:235(backup_file_contents)
+        4    0.000    0.000    0.321    0.080 repo_tree.py:76(commit)
+        4    0.000    0.000    0.321    0.080 forest.py:93(commit)
+        4    0.000    0.000    0.312    0.078 nodestore_disk.py:204(save_refcounts)
+        4    0.001    0.000    0.312    0.078 refcountstore.py:70(save_refcounts)
+        4    0.167    0.042    0.304    0.076 refcountstore.py:98(encode_refcounts)
+      587    0.014    0.000    0.296    0.001 tree.py:211(insert)
+      3/2    0.000    0.000    0.241    0.121 repo.py:52(helper)
+        1    0.000    0.000    0.240    0.240 repo.py:428(commit_client)
       583    0.017    0.000    0.222    0.000 tree.py:256(_insert_into_index)
-       62    0.001    0.000    0.197    0.003 backup_plugin.py:258(backup_file_chunk)
-       62    0.002    0.000    0.185    0.003 repo.py:565(put_chunk)
-      124    0.002    0.000    0.142    0.001 clientmetadatatree.py:339(append_file_chunks)
+      124    0.002    0.000    0.141    0.001 clientmetadatatree.py:339(append_file_chunks)
        71    0.001    0.000    0.139    0.002 repo.py:549(create)
+       62    0.001    0.000    0.135    0.002 backup_plugin.py:258(backup_file_chunk)
        66    0.000    0.000    0.132    0.002 backup_plugin.py:229(backup_metadata)
        71    0.002    0.000    0.131    0.002 clientmetadatatree.py:222(create)
-   131935    0.129    0.000    0.129    0.000 {method 'get' of 'dict' objects}
-        2    0.000    0.000    0.114    0.057 pluginmgr.py:185(load_plugins)
-       22    0.001    0.000    0.113    0.005 pluginmgr.py:205(load_plugin_file)
-       81    0.002    0.000    0.110    0.001 vfs_local.py:182(_write_to_tempfile)
-       22    0.002    0.000    0.108    0.005 {imp.load_module}
-       63    0.001    0.000    0.105    0.002 repo.py:157(write_file)
+   131935    0.127    0.000    0.127    0.000 {method 'get' of 'dict' objects}
+       62    0.002    0.000    0.122    0.002 repo.py:565(put_chunk)
+        2    0.000    0.000    0.112    0.056 pluginmgr.py:185(load_plugins)
+       22    0.001    0.000    0.112    0.005 pluginmgr.py:205(load_plugin_file)
+       22    0.002    0.000    0.107    0.005 {imp.load_module}
        62    0.000    0.000    0.104    0.002 repo.py:672(append_file_chunks)
-       64    0.001    0.000    0.103    0.002 vfs_local.py:150(write_file)
-        1    0.026    0.026    0.101    0.101 __init__.py:54(<module>)
+        1    0.025    0.025    0.100    0.100 __init__.py:54(<module>)
      1761    0.012    0.000    0.099    0.000 tree.py:114(put_node)
-      583    0.008    0.000    0.098    0.000 tree.py:303(_insert_into_leaf)
-      3/2    0.000    0.000    0.084    0.042 repo.py:41(helper)
+      583    0.008    0.000    0.097    0.000 tree.py:303(_insert_into_leaf)
+      3/2    0.000    0.000    0.085    0.042 repo.py:41(helper)
         1    0.000    0.000    0.084    0.084 repo.py:305(commit_root)
-        1    0.000    0.000    0.079    0.079 clientmetadatatree.py:156(commit)
-       81    0.000    0.000    0.077    0.001 tempfile.py:259(mkstemp)
-       81    0.001    0.000    0.077    0.001 tempfile.py:219(_mkstemp_inner)
+        1    0.000    0.000    0.080    0.080 clientmetadatatree.py:156(commit)
        70    0.001    0.000    0.076    0.001 clientmetadatatree.py:252(set_metadata)
         1    0.033    0.033    0.068    0.068 transport.py:21(<module>)
-      128    0.001    0.000    0.066    0.001 clientmetadatatree.py:153(_insert_int)
-       82    0.065    0.001    0.065    0.001 {posix.open}
-       67    0.001    0.000    0.062    0.001 backup_plugin.py:153(find_files)
+      128    0.001    0.000    0.065    0.001 clientmetadatatree.py:153(_insert_int)
+       67    0.001    0.000    0.063    0.001 backup_plugin.py:153(find_files)
        62    0.000    0.000    0.054    0.001 repo.py:662(set_file_chunks)
        62    0.001    0.000    0.054    0.001 clientmetadatatree.py:325(set_file_chunks)
       216    0.001    0.000    0.052    0.000 hooks.py:107(call)
       134    0.001    0.000    0.050    0.000 hooks.py:47(call_callbacks)
-       63    0.007    0.000    0.047    0.001 backup_plugin.py:134(dump_memory_profile)
+       63    0.007    0.000    0.049    0.001 backup_plugin.py:134(dump_memory_profile)
+       81    0.002    0.000    0.048    0.001 vfs_local.py:182(_write_to_tempfile)
      1761    0.008    0.000    0.046    0.000 nodestore_disk.py:134(put_node)
       249    0.006    0.000    0.046    0.000 status.py:63(__setitem__)
-      591    0.006    0.000    0.042    0.000 tree.py:99(set_root)
-     4878    0.022    0.000    0.040    0.000 lru.py:54(add)
+      591    0.006    0.000    0.043    0.000 tree.py:99(set_root)
+       63    0.001    0.000    0.042    0.001 repo.py:157(write_file)
+     4882    0.022    0.000    0.040    0.000 lru.py:54(add)
+       64    0.001    0.000    0.040    0.001 vfs_local.py:150(write_file)
       143    0.040    0.000    0.040    0.000 {_obnam.fadvise_dontneed}
      1761    0.013    0.000    0.039    0.000 codec.py:136(size)
      1717    0.014    0.000    0.037    0.000 {method 'join' of 'str' objects}
-     1170    0.005    0.000    0.035    0.000 tree.py:198(_shadow)
+     1170    0.005    0.000    0.036    0.000 tree.py:198(_shadow)
        62    0.001    0.000    0.035    0.001 terminal_status_plugin.py:61(found_file_cb)
-       62    0.000    0.000    0.034    0.001 clientmetadatatree.py:320(_insert_chunks)
-       62    0.000    0.000    0.033    0.001 chunklist.py:45(add)
+       62    0.000    0.000    0.034    0.001 chunklist.py:45(add)
+       62    0.000    0.000    0.033    0.001 clientmetadatatree.py:320(_insert_chunks)
        62    0.000    0.000    0.033    0.001 checksumtree.py:45(add)
      1170    0.020    0.000    0.031    0.000 codec.py:52(leaf_size)
-     1356    0.004    0.000    0.028    0.000 tree.py:110(get_node)
-     4870    0.015    0.000    0.027    0.000 lru.py:101(remove)
-20944/19762    0.024    0.000    0.026    0.000 {len}
-       63    0.026    0.000    0.026    0.000 {gc.get_objects}
-       79    0.003    0.000    0.025    0.000 vfs_local.py:36(write)
-     1356    0.004    0.000    0.024    0.000 nodestore_disk.py:154(get_node)
-     1170    0.005    0.000    0.022    0.000 nodestore_disk.py:173(start_modification)
-      128    0.004    0.000    0.022    0.000 vfs_local.py:28(read)
+     1360    0.004    0.000    0.028    0.000 tree.py:110(get_node)
+       63    0.027    0.000    0.027    0.000 {gc.get_objects}
+     4874    0.015    0.000    0.027    0.000 lru.py:101(remove)
+20948/19766    0.024    0.000    0.027    0.000 {len}
+       79    0.003    0.000    0.026    0.000 vfs_local.py:36(write)
+     1360    0.004    0.000    0.024    0.000 nodestore_disk.py:154(get_node)
+     1170    0.005    0.000    0.023    0.000 nodestore_disk.py:173(start_modification)
      2481    0.007    0.000    0.022    0.000 status.py:75(<genexpr>)
-      401    0.006    0.000    0.021    0.000 tree.py:126(lookup)
-      583    0.004    0.000    0.021    0.000 tree.py:120(_leaf_size)
+      401    0.006    0.000    0.022    0.000 tree.py:126(lookup)
+      128    0.003    0.000    0.021    0.000 vfs_local.py:28(read)
       260    0.001    0.000    0.021    0.000 tree.py:148(lookup_range)
-     1356    0.006    0.000    0.020    0.000 lru.py:86(get)
+      583    0.004    0.000    0.021    0.000 tree.py:120(_leaf_size)
+     1360    0.006    0.000    0.020    0.000 lru.py:86(get)
      2852    0.007    0.000    0.020    0.000 widget.py:46(__str__)
-     1170    0.011    0.000    0.018    0.000 nodes.py:121(add)
   515/260    0.003    0.000    0.018    0.000 tree.py:161(_lookup_range)
+     1170    0.010    0.000    0.018    0.000 nodes.py:121(add)
      1761    0.005    0.000    0.017    0.000 uploadqueue.py:46(put)
-       71    0.004    0.000    0.016    0.000 metadata.py:83(read_metadata)
-      129    0.001    0.000    0.016    0.000 repo.py:67(helper)
+       71    0.004    0.000    0.017    0.000 metadata.py:83(read_metadata)
+      129    0.001    0.000    0.017    0.000 repo.py:67(helper)
      2340    0.006    0.000    0.016    0.000 nodestore.py:148(can_be_modified)
-     3510    0.009    0.000    0.014    0.000 nodestore_disk.py:198(get_refcount)
+     3510    0.009    0.000    0.015    0.000 nodestore_disk.py:198(get_refcount)
+       81    0.000    0.000    0.014    0.000 tempfile.py:259(mkstemp)
+       81    0.001    0.000    0.014    0.000 tempfile.py:219(_mkstemp_inner)
        62    0.000    0.000    0.014    0.000 terminal_status_plugin.py:72(data_uploaded_cb)
+       17    0.000    0.000    0.013    0.001 repo.py:163(overwrite_file)
       583    0.005    0.000    0.012    0.000 tree.py:529(decrement)
-       17    0.000    0.000    0.012    0.001 repo.py:163(overwrite_file)
-     4870    0.012    0.000    0.012    0.000 lru.py:75(_remove)
+     4874    0.012    0.000    0.012    0.000 lru.py:75(_remove)
       197    0.001    0.000    0.012    0.000 clientmetadatatree.py:144(_lookup_int)
+       17    0.000    0.000    0.012    0.001 vfs_local.py:160(overwrite_file)
       587    0.004    0.000    0.012    0.000 tree.py:522(increment)
      1761    0.005    0.000    0.012    0.000 nodestore_disk.py:201(set_refcount)
-       17    0.000    0.000    0.011    0.001 vfs_local.py:160(overwrite_file)
-     9584    0.011    0.000    0.011    0.000 tracing.py:64(trace)
       133    0.001    0.000    0.011    0.000 clientmetadatatree.py:245(get_metadata)
-      354    0.002    0.000    0.010    0.000 vfs_local.py:121(exists)
+     9584    0.011    0.000    0.011    0.000 tracing.py:64(trace)
      1333    0.010    0.000    0.010    0.000 {_struct.pack}
-        1    0.002    0.002    0.010    0.010 util.py:21(<module>)
+      354    0.002    0.000    0.010    0.000 vfs_local.py:121(exists)
      1170    0.003    0.000    0.010    0.000 uploadqueue.py:57(remove)

(Diff truncated)
Fiddling around to get table to work.
diff --git a/obnam/benchmarks/backup.csv b/obnam/benchmarks/backup.csv
index 5fc9f0c..c7c3fb1 100644
--- a/obnam/benchmarks/backup.csv
+++ b/obnam/benchmarks/backup.csv
@@ -1,11 +1,11 @@
-obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
-r962,r237,1.2,61.8,0.9,86.2
+obnam,larch,gen0 time (s),gen0 RAM (MiB),slowest inc (s),largest RAM inc (MiB)
+r962,r237,1.2,61.8,0.9,86.2
+r962,r237,1.2,61.8,0.9,86.2
+r962,r237,1.2,61.8,0.9,86.2
+r962,r237,1.2,61.8,0.9,86.2
+r962,r237,1.2,61.8,0.9,86.2
+r962,r237,1.2,61.8,0.9,86.2
+r962,r237,1.2,61.8,0.9,86.2
+r962,r237,1.2,61.8,0.9,86.2
+r962,r237,1.2,61.8,0.9,86.2
+r962,r237,1.2,61.8,0.9,86.2