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?
Why is it hard to use? This is how this is done in other packages in the stdlib. This is merely a package which puts all of these 8K, 32K and 512K bufio.Readers/Writers in one place so they can be shared across packages.

I've already commented below to explain and show how this is used. If you take a look at the changes made to archive/diff.go and archive/changes.go, it should be obvious how easy to use these can be.

That being said, we can add convenience functions and functions which return wrapped bufio.Readers to return them to the pools automatically.