mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-20 22:27:04 +00:00
fix(ec): full-teardown delete so cluster cleanup wipes a whole generation
The pre-encode cluster sweep deleted only the listed canonical shards on remote nodes, leaving index/sidecar (and, on builds with versioned generations, those too) behind. Add a full_teardown flag to VolumeEcShardsDelete that evicts the volume and wipes every EC artifact for it on every disk via removeStaleEcArtifacts; the shell and worker pre-encode cleanup paths set it. Other delete callers (balance/decode/repair) are unchanged.
This commit is contained in:
@@ -452,6 +452,7 @@ message VolumeEcShardsDeleteRequest {
|
||||
uint32 volume_id = 1;
|
||||
string collection = 2;
|
||||
repeated uint32 shard_ids = 3;
|
||||
bool full_teardown = 4; // pre-encode cleanup: wipe every EC artifact + generation for this volume, not just shard_ids
|
||||
}
|
||||
message VolumeEcShardsDeleteResponse {
|
||||
}
|
||||
|
||||
@@ -3605,6 +3605,7 @@ type VolumeEcShardsDeleteRequest struct {
|
||||
VolumeId uint32 `protobuf:"varint,1,opt,name=volume_id,json=volumeId,proto3" json:"volume_id,omitempty"`
|
||||
Collection string `protobuf:"bytes,2,opt,name=collection,proto3" json:"collection,omitempty"`
|
||||
ShardIds []uint32 `protobuf:"varint,3,rep,packed,name=shard_ids,json=shardIds,proto3" json:"shard_ids,omitempty"`
|
||||
FullTeardown bool `protobuf:"varint,4,opt,name=full_teardown,json=fullTeardown,proto3" json:"full_teardown,omitempty"` // pre-encode cleanup: wipe every EC artifact + generation for this volume, not just shard_ids
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@@ -3660,6 +3661,13 @@ func (x *VolumeEcShardsDeleteRequest) GetShardIds() []uint32 {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *VolumeEcShardsDeleteRequest) GetFullTeardown() bool {
|
||||
if x != nil {
|
||||
return x.FullTeardown
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type VolumeEcShardsDeleteResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
@@ -7244,13 +7252,14 @@ const file_volume_server_proto_rawDesc = "" +
|
||||
"\rcopy_vif_file\x18\a \x01(\bR\vcopyVifFile\x12\x17\n" +
|
||||
"\adisk_id\x18\b \x01(\rR\x06diskId\x12&\n" +
|
||||
"\x0fcopy_ecsum_file\x18\t \x01(\bR\rcopyEcsumFile\"\x1c\n" +
|
||||
"\x1aVolumeEcShardsCopyResponse\"w\n" +
|
||||
"\x1aVolumeEcShardsCopyResponse\"\x9c\x01\n" +
|
||||
"\x1bVolumeEcShardsDeleteRequest\x12\x1b\n" +
|
||||
"\tvolume_id\x18\x01 \x01(\rR\bvolumeId\x12\x1e\n" +
|
||||
"\n" +
|
||||
"collection\x18\x02 \x01(\tR\n" +
|
||||
"collection\x12\x1b\n" +
|
||||
"\tshard_ids\x18\x03 \x03(\rR\bshardIds\"\x1e\n" +
|
||||
"\tshard_ids\x18\x03 \x03(\rR\bshardIds\x12#\n" +
|
||||
"\rfull_teardown\x18\x04 \x01(\bR\ffullTeardown\"\x1e\n" +
|
||||
"\x1cVolumeEcShardsDeleteResponse\"\xa0\x01\n" +
|
||||
"\x1aVolumeEcShardsMountRequest\x12\x1b\n" +
|
||||
"\tvolume_id\x18\x01 \x01(\rR\bvolumeId\x12\x1e\n" +
|
||||
|
||||
@@ -417,6 +417,23 @@ func (vs *VolumeServer) VolumeEcShardsDelete(ctx context.Context, req *volume_se
|
||||
|
||||
bName := erasure_coding.EcShardBaseFileName(req.Collection, int(req.VolumeId))
|
||||
|
||||
if req.FullTeardown {
|
||||
// Pre-encode cleanup: evict the volume and wipe every EC artifact for it on
|
||||
// every disk (the same teardown the generator does locally), not just the
|
||||
// listed shards, so a remote node retains no stale generation that a fresh
|
||||
// gen-0 copy would later collide with.
|
||||
glog.V(0).Infof("ec volume %s full teardown", bName)
|
||||
vs.store.UnloadEcVolume(needle.VolumeId(req.VolumeId))
|
||||
for _, location := range vs.store.Locations {
|
||||
dataBase := storage.VolumeFileName(location.Directory, req.Collection, int(req.VolumeId))
|
||||
idxBase := storage.VolumeFileName(location.IdxDirectory, req.Collection, int(req.VolumeId))
|
||||
if err := removeStaleEcArtifacts(dataBase, idxBase, erasure_coding.MaxShardCount); err != nil {
|
||||
return nil, fmt.Errorf("full teardown of ec volume %d on %s: %w", req.VolumeId, location.Directory, err)
|
||||
}
|
||||
}
|
||||
return &volume_server_pb.VolumeEcShardsDeleteResponse{}, nil
|
||||
}
|
||||
|
||||
glog.V(0).Infof("ec volume %s shard delete %v", bName, req.ShardIds)
|
||||
|
||||
for diskId, location := range vs.store.Locations {
|
||||
|
||||
@@ -550,9 +550,10 @@ func unmountAndDeleteEcShardsQuiet(grpcDialOption grpc.DialOption, collection st
|
||||
return fmt.Errorf("unmount: %w", err)
|
||||
}
|
||||
if _, err := volumeServerClient.VolumeEcShardsDelete(context.Background(), &volume_server_pb.VolumeEcShardsDeleteRequest{
|
||||
VolumeId: uint32(volumeId),
|
||||
Collection: collection,
|
||||
ShardIds: ids,
|
||||
VolumeId: uint32(volumeId),
|
||||
Collection: collection,
|
||||
ShardIds: ids,
|
||||
FullTeardown: true,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("delete: %w", err)
|
||||
}
|
||||
|
||||
@@ -978,9 +978,10 @@ func unmountAndDeleteEcShards(
|
||||
return fmt.Errorf("unmount: %w", err)
|
||||
}
|
||||
if _, err := client.VolumeEcShardsDelete(ctx, &volume_server_pb.VolumeEcShardsDeleteRequest{
|
||||
VolumeId: volumeID,
|
||||
Collection: collection,
|
||||
ShardIds: shardIds,
|
||||
VolumeId: volumeID,
|
||||
Collection: collection,
|
||||
ShardIds: shardIds,
|
||||
FullTeardown: true,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("delete: %w", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user