mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-25 06:20:42 +01:00
master: repair the lookup index after a vacuum that raced a disconnect (#10226)
* master: re-create a vacuum-committed volume the index has lost SetVolumeAvailable dereferenced vid2location[vid] with no nil check. A disconnect during a long vacuum can drop a single-replica volume from the lookup index while it stays on the node; the commit then panics the master instead of re-registering it. Re-create the entry, and seed its size tracking so assigns are counted right away rather than after the next heartbeat. * master: re-register a vacuumed volume the index lost on mark-writable The maintenance worker re-enables a volume by marking it writable after the vacuum commit, but VolumeMarkReadonly only updated nodes the lookup index already knew. If a disconnect race dropped the volume from the index during the vacuum, that path was a no-op and the volume stayed "not found" until the next full heartbeat healed it. Re-register it from the node that still holds it.
This commit is contained in:
1 parent
60e7b30009
commit
a6effe3cfb
3 files changed
+100
-16
No files matched your search
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/seaweedfs/raft"
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/glog"
|
||||
"github.com/seaweedfs/seaweedfs/weed/pb"
|
||||
"github.com/seaweedfs/seaweedfs/weed/pb/master_pb"
|
||||
"github.com/seaweedfs/seaweedfs/weed/security"
|
||||
"github.com/seaweedfs/seaweedfs/weed/storage/needle"
|
||||
@@ -323,18 +324,33 @@ func (ms *MasterServer) VolumeMarkReadonly(ctx context.Context, req *master_pb.V
|
||||
|
||||
replicaPlacement, _ := super_block.NewReplicaPlacementFromByte(byte(req.ReplicaPlacement))
|
||||
vl := ms.Topo.GetVolumeLayout(req.Collection, replicaPlacement, needle.LoadTTLFromUint32(req.Ttl), types.ToDiskType(req.DiskType))
|
||||
dataNodes := ms.Topo.Lookup(req.Collection, needle.VolumeId(req.VolumeId))
|
||||
vid := needle.VolumeId(req.VolumeId)
|
||||
dataNodes := ms.Topo.Lookup(req.Collection, vid)
|
||||
|
||||
found := false
|
||||
for _, dn := range dataNodes {
|
||||
if dn.Ip == req.Ip && dn.Port == int(req.Port) {
|
||||
found = true
|
||||
if req.IsReadonly {
|
||||
vid := needle.VolumeId(req.VolumeId)
|
||||
vl.SetVolumeReadOnly(dn, vid)
|
||||
if pending := vl.GetPendingSize(vid); pending > 0 {
|
||||
glog.V(0).Infof("volume %d marked readonly with %d pending bytes", vid, pending)
|
||||
}
|
||||
} else {
|
||||
vl.SetVolumeWritable(dn, needle.VolumeId(req.VolumeId))
|
||||
vl.SetVolumeWritable(dn, vid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A vacuum worker marks the volume writable after a successful commit. If the
|
||||
// index lost it meanwhile (e.g. a disconnect race during the vacuum), the loop
|
||||
// found nothing to update; re-register it from the node that still holds it so
|
||||
// LookupVolume stops returning "not found".
|
||||
if !found && !req.IsReadonly {
|
||||
if dn := ms.Topo.LookupDataNodeByAddress(pb.NewServerAddress(req.Ip, int(req.Port), 0)); dn != nil {
|
||||
if vi, err := dn.GetVolumesById(vid); err == nil {
|
||||
ms.Topo.RegisterVolumeLayout(vi, dn)
|
||||
glog.V(0).Infof("volume %d re-registered from %s:%d, was missing from the lookup index at mark-writable", vid, req.Ip, req.Port)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user