yuck

I've been working on documenting the userspace NBD code a bit; document what global variables are used for, what each function does, and so on. Doxygen has been a great help in making this a bit easier. I've been marking places in the source that need fixing, and documented what every global variable does, and how I could get rid of it; before I did this, I had a general idea of what each of them did, but perhaps not in detail as I didn't write most of the code, I'm simply its maintainer.

Nbd-server is a piece of code that was written in a mostly hackish way, which has had its bugs removed and some extra features added (most of which were, again, done in a hackish way with bugs removed later on), but it doesn't appear as if it was given a lot of thought before it was coded. As a result, it's got global variables that have no business being global, functions that span 80 lines and more which could easily be split up, and simply braindead things, too.

One example of the latter is the implementation of the copy on write option. As it is currently implemented, it uses an in-memory array which maps blocks in the exported file to blocks in the "diffile". I had thought previously that it did this by doing an lseek() to the right position in the file -taking advantage of the kernel's support for sparse files- and that the global variable which keeps track of which blocks are to be found in the difffile would know whether that block had been written to or not.

That is not the case.

Instead, when you write to such an export, nbd-server appends the block to that file, and stores the offset to the block you're looking for in the array. That means that if you first write block 12, then 10, then 9, then 11, and then try to read them in order (so, 9-10-11-12), that nbd-server has to do four seeks to read it out again; and since keeping track of what-block-goes-where is done using an array, the copy on write file is useless once the server stops serving (at which point it, obviously, unlinks the file).

No wonder that copy on write thing is dog slow. Yuck.