3448: check block timestamp before DELETE

volume.Delete locks the target file and checks the timestamp before
proceeding. If the file is newer than permission_ttl specifies, return a
PermissionError. This way, a block that has been marked for recycling by
Data Manager but subsequently was re-added by a user will not be
prematurely deleted.

PutBlock now updates the timestamp on the target block if it already
exists on disk, to prevent DELETE from recycling old blocks that have
just been refreshed.

To update block timestamps, the blob server uses the new volume.Touch
method.  MockVolume and UnixVolume have been updated appropriately.

Refs #3448.
3448: minor bugfixes

Refs #3448.
3448: code review comments.

Extend GetBlock() to optionally update the file modification time, so
PUT operations can update the timestamp of an existing block.

UnixVolume.Delete() returns nil if the file is too new to delete (the
reasoning here is that this is the correct thing for the server to do,
even if the result technically does not fulfill the user's request, so
the server should return success).

Refs #3448.
3448: unit tests for deleting new blocks

Added cases to TestDeleteHandler to test that blocks newer than
-permission_ttl will not be removed from the volume even if
volume.Delete() returned true.

Refs #3448.
3448: add error checking

Code review comments in https://arvados.org/issues/3448#note-9

* volume.Touch() must fail if the file cannot be locked
* if volume.Touch() fails, continue looking for other volumes that can
  fulfill the request.

Refs #3448.
3448: add error checking in volume.Touch()

Add error checking that was erroneously left out of previous commit.

Refs #3448.
3448: unit tests, bug fixes

UnixVolume.Delete tests the return status of lockfile (oops, left out of
previous commit)

New unit/integration tests:

* TestPutTouch (volume_unix_test.go): issues a volume.Put for a block
  that already exists, and confirms that the mtime of the existing block
  is updated.

* TestPutBlockTouchFails (keepstore_test.go): issues PutBlock for a
  block that already exists but cannot be modified, confirms that the
  mtime on the old block is unchanged and that a new copy has been
  stored.

Added a volume.Mtime() method to return the block mtime, to assist in
testing.
3448: update tests with "untouchable" volumes

Added a "Touchable" flag to MockVolume, so that we can test that
PutBlock does the right thing when Touch fails.  Previous code was using
volume.Bad as an attempt to test this, but that short-circuited the Put
request before it ever attempted to call Touch.

Added TODOs with more testing improvements we can make as time permits.
Merge branch '3448-keep-put-timestamps'

Closes #3448.