Refactor archive buffering

This PR refactors archive to add buffering to help fix #7291. This PR is the first one of the two PRs required to fix #7291.

The first commit (move some io related utils to pkg/ioutils) moves some Readers and Writers to pkg/ioutils. I've moved these first so that I would avoid adding WriteCloseWrapper to utils/utils.go. I've moved only the io utils which had the least dependencies on other things (e.g. no HTTP related utils were moved and so on).

This PR adds archive/pool to help reuse buffers for reading and for writing. This allows us to use larger buffers by reusing them.

The PR also adds buffering to archive writing, thus helping speed up archive writing and a few other operations.

Please focus on stress testing this with pulls, pushes, builds and anything you can think of. Please check if this helps speed up `docker pull` and `docker push` with the Docker Hub and with private registries.

Open questions:
- [x] Should we make the pool global and share it across components of Docker? We could reuse it in other places as well. Conclusion: YES
- [x] Should we increase the 512K buffers to 1024K to help make downloads even smoother? Conclusion: NO
- [ ] Should we decrease the big buffers to 256K?
@LK4D4 This is pretty much what it's doing, but it has to keep sharing the pools and it's also resetting the reader to the target Reader:
https://github.com/unclejack/docker/blob/refactor_archive_buffering/archive/archive.go#L91
https://github.com/unclejack/docker/blob/refactor_archive_buffering/archive/archive.go#L113

The BufferedReadCloserWrapper is needed so we can read from one thing, return the bufio.Reader to the pool and maybe close another thing. This is needed when you need to read from a gzip Reader, to return the buffer to the pool and to close the same gzip Reader. Sometimes you need to close something else, not what you're reading from.