* fix(volume): harden volume copy validation
* fix(volume): use stream context for ReadVolumeFileStatus in VolumeCopy
ReadVolumeFileStatus ran on context.Background() while the adjacent
VolumeStatus call used stream.Context(), an inconsistency left over
from the context revert in #11252. Use stream.Context() consistently
so the source status check is cancelled with the VolumeCopy stream.
* fix(volume): reserve destination before deleting existing replica
FindFreeLocation now runs before DeleteVolume so a full target fails
without destroying the existing replica. Previously, when the initial
VolumeStatus check failed (advisory) but ReadVolumeFileStatus
succeeded, the existing replica was deleted before a destination was
reserved, risking data loss if no location had enough free space.
Add a regression test verifying the existing replica survives when
the destination is full and the initial status check fails.
* fix(volume): count replaced replica slot in FindFreeLocation
FindFreeLocation now accepts the volume being replaced so its slot is
treated as available. Without this, a location at its MaxVolumeCount
limit could not replace its sole replica even though deleting it would
free the slot. VolumeCopy passes the volume ID so destination selection
succeeds before the existing replica is deleted.
Add TestVolumeCopyReplacesReplicaAtSlotLimit covering a single-slot
location that must replace its only replica.
---------
Co-authored-by: Chris Lu <chris.lu@gmail.com>