mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-20 15:04:37 +00:00
fix(ec): reject an unstamped shard when the caller has an encode identity
The read guard required both identities nonzero, so a current (stamped) caller accepted a holder with identity 0 and could be served a stale pre-upgrade shard. Reject when the caller is stamped and the holder differs (including unstamped); stay lenient only when the caller itself has no identity (pre-upgrade reader). A skipped shard recovers from parity.
This commit is contained in:
@@ -657,9 +657,11 @@ func (vs *VolumeServer) VolumeEcShardRead(req *volume_server_pb.VolumeEcShardRea
|
||||
if !found {
|
||||
return fmt.Errorf("not found ec shard %d.%d", req.VolumeId, req.ShardId)
|
||||
}
|
||||
// Reject a shard from a different encode run than the caller's index; the
|
||||
// caller then recovers from parity. 0 on either side = pre-upgrade volume.
|
||||
if req.EncodeTsNs != 0 && ecVolume.EncodeTsNs != 0 && req.EncodeTsNs != ecVolume.EncodeTsNs {
|
||||
// Reject a shard whose identity doesn't match the caller's index; the caller
|
||||
// then recovers from parity. Lenient only when the caller has no identity
|
||||
// (pre-upgrade reader): a known caller must not accept an unstamped holder,
|
||||
// which would serve a stale pre-upgrade shard.
|
||||
if req.EncodeTsNs != 0 && req.EncodeTsNs != ecVolume.EncodeTsNs {
|
||||
return fmt.Errorf("ec shard %d.%d belongs to a different encode run", req.VolumeId, req.ShardId)
|
||||
}
|
||||
|
||||
|
||||
@@ -527,9 +527,11 @@ func (s *Store) readLocalEcShardInterval(ecVolume *erasure_coding.EcVolume, shar
|
||||
if !found {
|
||||
return fmt.Errorf("shard %d for volume %d: %w", shardId, ecVolume.VolumeId, errShardNotLocal)
|
||||
}
|
||||
// Skip a local shard from a different encode run than the caller's index;
|
||||
// treat it as not-local so the read recovers from the correct generation.
|
||||
if ecVolume.EncodeTsNs != 0 && ownerVolume.EncodeTsNs != 0 && ecVolume.EncodeTsNs != ownerVolume.EncodeTsNs {
|
||||
// Skip a local shard whose identity doesn't match the caller's index, so the
|
||||
// read recovers from the correct generation. Lenient only when the caller has
|
||||
// no identity (pre-upgrade): a known caller must not accept an unstamped local
|
||||
// shard, which would serve a stale pre-upgrade generation.
|
||||
if ecVolume.EncodeTsNs != 0 && ecVolume.EncodeTsNs != ownerVolume.EncodeTsNs {
|
||||
glog.V(1).Infof("skip local ec shard %d.%d from a different encode run: caller EncodeTsNs %d, local %d", ecVolume.VolumeId, shardId, ecVolume.EncodeTsNs, ownerVolume.EncodeTsNs)
|
||||
return fmt.Errorf("shard %d for volume %d: %w", shardId, ecVolume.VolumeId, errShardNotLocal)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user