Whoops
I had a bunch of old packages in my ~/debian/nbd/ directory, that didn't serve much purpose anymore, so I wanted to clean them out.
wouter@grep.be:~/debian/nbd$ rm -Rf *
After that finished, I realized that this directory also contained my CVS checkouts of the NBD upstream CVS. And one of those checkouts contained quite a lot of uncommitted code. Whoops.
So, what do you do then? Stop writing to disk immediately. Pull the plug. Except this is a laptop, so, push the power button until you don't see anything anymore; and next, try to read the lost file from a different installation.
That "different installation" was an easy one. I've always had a second, minor, 'play' partition on my laptop, that I use to try out all sorts of operating systems. I've used it to run Debian stable, Ubuntu, MacOS X. It currently contains Gentoo; I intend to try out FreeBSD for PowerPC some time.
But the fact that it already had Gentoo meant I could use that one to run debugfs on the (not mounted) file system, and try to find my files back. Except that I'd never done that before, and I didn't know where to start. And since my gentoo installation isn't set up entirely right, I couldn't get networking to work okay, thus, no help through IRC.
My first guess was to check the ext3 journal. There's a command to dump any random inode to disk in hex format (dump <inode number>, with the square brackets), so that should help. I thought.
Hah
I spent two hours looking at kernel code, trying to find out what the on-disk format of the ext3 journal is (which, as it turns out, isn't part of the ext3 driver; it is a totally different driver, called jbd), only to find out that it wouldn't help me; a journal obviously only contains information on the new data it's going to write, not on the old data it's overwriting. And seen how removing a file means you overwrite a directory inode block with newer information that does not contain the reference to the removed file anymore, that wasn't helpful.
At least I learned what the ext3 journal's on-disk format is. Might be useful in the future.
My next move was looking at debugfs again. Found that it has some command called dump_unused, which will dump the raw data of any blocks that are not allocated, provided that raw data isn't just zeroes. That's a lot of blocks; bzip2'ed, I had already 1.5G before I killed it.
Fortunately, an easy 'bzgrep' told me that the file was, indeed, in there somewhere.
I did a commit now. Just to be sure
Yeah, I noticed. Lars already told me on IRC, too. It's been fixed now anyway. Thanks!