Zero-copy object-server PUT requests with splice()

For non-chunked PUT requests, we can now use splice() to move the data
directly from the socket to disk without passing through user space.

Rather than write another nearly-identical splice loop with the fds
swapped and the threadpool moved, I introduce a pair of classes
SpliceFd and SplicePipe; they wrap up the fds and pipes involved in
splicing data. This lets us have just one class responsible for
calling splice() and handling timeouts, trampolines, and so on.

Handling PUT is a little more complicated than GET due to buffers in
libraries. In the process of reading the headers, the first part of
the request body (i.e. the object data) might get buffered. The object
server uses some low-level socket hackery to drain those buffers
without causing any more of the request body to get copied into user
space.

TODO: benchmark results go here (they'll be awesome!)

Change-Id: Ibf5ad68cdd4700df8b15d108e1bbf63c50c2478e