Skip to content

Commit 4510fa4

Browse files
committed
review: whole-repo round — fuse post-stop quiesce, reuse the network seam
Drop QuiesceIfPending's namespace re-read on the stop and hibernate paths: under the held ops lock the committed generation is derivable from the loaded record plus whether UpdateStates landed, so quiesceAfterStop quiesces and clears directly — one meta transaction per stop instead of two. vm net resize now goes through the process-wide NetworkSeam instead of building a throwaway provider cache; NewNetProviders is unexported. Also: convergeExit's log tag mirrors its function, and EntryGuardLoad's godoc no longer references the removed EntryGuard.
1 parent 66e4232 commit 4510fa4

7 files changed

Lines changed: 29 additions & 14 deletions

File tree

cmd/core/network.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ type NetProviders struct {
3232

3333
// NetworkSeam returns the process-wide seam, so both backends share one provider cache.
3434
func NetworkSeam(conf *config.Config) *NetProviders {
35-
netOnce.Do(func() { netSeam = NewNetProviders(conf) })
35+
netOnce.Do(func() { netSeam = newNetProviders(conf) })
3636
return netSeam
3737
}
3838

39-
func NewNetProviders(conf *config.Config) *NetProviders {
39+
func newNetProviders(conf *config.Config) *NetProviders {
4040
return &NetProviders{conf: conf, bridge: map[string]network.Network{}}
4141
}
4242

cmd/vm/netresize.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,5 @@ func plumbingForVM(conf *config.Config, vm *types.VM) (network.Network, error) {
5353
if backend == types.BackendCNI && vm.ResolvedNetnsPath() == "" {
5454
return nil, fmt.Errorf("cni backend but no netns; resize would target host netns")
5555
}
56-
return cmdcore.NewNetProviders(conf).ForVM(vm)
56+
return cmdcore.NetworkSeam(conf).ForVM(vm)
5757
}

daemon/reconcile.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ func (d *Daemon) convergeExit(ctx context.Context, ev exitEvent) bool {
209209
if dead, _ := d.confirmDead(ctx, b, rec); rec.TransitionGeneration != ev.gen || !dead {
210210
return false
211211
}
212-
logger := log.WithFunc("daemon.handleExit")
212+
logger := log.WithFunc("daemon.convergeExit")
213213
if err := b.ConvergeDead(ctx, ev.key.vmID, ev.gen, ev.at); err != nil {
214214
logger.Errorf(ctx, err, "converge %s", ev.key.vmID)
215215
return false

hypervisor/network.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,22 @@ func (b *Backend) RecoverNetwork(ctx context.Context, rec *VMRecord) error {
2626
return b.Net.Recover(ctx, &rec.VM)
2727
}
2828

29-
// quiesceAfterStop runs the quiesce a just-committed stop scheduled, gated on the pre-stop record so an unplumbed VM pays no extra read; a failure keeps the pending flag for a later pass.
30-
func (b *Backend) quiesceAfterStop(ctx context.Context, id string, rec *VMRecord) {
31-
if !needsQuiesce(rec) {
29+
// quiesceAfterStop runs the quiesce a just-committed stop scheduled without re-reading the record: under the caller's ops lock the committed generation is rec's, plus one exactly when the stop just landed its transition. A quiesce failure keeps the pending flag for a later pass.
30+
func (b *Backend) quiesceAfterStop(ctx context.Context, id string, rec *VMRecord, transitioned bool) {
31+
gen, pending := rec.TransitionGeneration, rec.QuiescePending
32+
if transitioned {
33+
gen, pending = gen+1, needsQuiesce(rec)
34+
}
35+
if !pending {
36+
return
37+
}
38+
logger := log.WithFunc(b.Typ + ".quiesceAfterStop")
39+
if err := b.quiesceNetwork(ctx, &rec.VM); err != nil {
40+
logger.Warnf(ctx, "quiesce network for VM %s (pending kept): %v", id, err)
3241
return
3342
}
34-
if err := b.QuiesceIfPending(ctx, id); err != nil {
35-
log.WithFunc(b.Typ+".quiesceAfterStop").Warnf(ctx, "%v", err)
43+
if err := b.clearQuiescePending(ctx, id, gen); err != nil {
44+
logger.Warnf(ctx, "clear pending quiesce for VM %s: %v", id, err)
3645
}
3746
}
3847

hypervisor/snapshot.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,11 @@ func (b *Backend) HibernateSequence(ctx context.Context, ref string, spec Hibern
147147

148148
CleanupRuntimeFiles(ctx, rec.RunDir, spec.RuntimeFiles)
149149
// Warn-and-continue like StopAll: the VMM is dead and the flip self-heals; the snapshot is already durable.
150-
if uErr := b.UpdateStates(ctx, []string{vmID}, types.VMStateStopped); uErr != nil {
150+
uErr := b.UpdateStates(ctx, []string{vmID}, types.VMStateStopped)
151+
if uErr != nil {
151152
logger.Warnf(ctx, "mark stopped %s: %v", vmID, uErr)
152153
}
153-
b.quiesceAfterStop(ctx, vmID, &rec)
154+
b.quiesceAfterStop(ctx, vmID, &rec, uErr == nil)
154155
return nil
155156
}
156157

hypervisor/stop.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,18 @@ func (b *Backend) StopOneLocked(ctx context.Context, id string, spec StopSpec) e
5656
if err := b.HandleStopResult(ctx, id, rec.RunDir, spec.RuntimeFiles, shutdownErr); err != nil {
5757
return err
5858
}
59+
transitioned := false
5960
if !settled {
6061
// Warn-and-continue: the VMM is dead and the flip self-heals on the next reconcile.
6162
logger := log.WithFunc(b.Typ + ".StopOneLocked")
6263
if err := b.UpdateStates(ctx, []string{id}, types.VMStateStopped); err != nil {
6364
logger.Warnf(ctx, "mark stopped %s: %v", id, err)
65+
} else {
66+
transitioned = true
6467
}
6568
}
6669
// Still under the caller's ops lock: an idle TAP's TC redirect storms softirqs until its host NICs go down (#130).
67-
b.quiesceAfterStop(ctx, id, &rec)
70+
b.quiesceAfterStop(ctx, id, &rec, transitioned)
6871
return nil
6972
}
7073

hypervisor/teardown.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,10 @@ func (b *Backend) recoverVMTombstone(ctx context.Context, id string) (done bool,
122122
return true, nil
123123
}
124124

125-
// EntryGuardLoad is EntryGuard returning the VM's record from the guard's own
126-
// transaction, sparing lock-held entry paths a second whole-namespace read.
125+
// EntryGuardLoad runs the tombstone entry guard under the caller's ops lock —
126+
// roll a leased tombstone back, drive a deleting one to completion and refuse —
127+
// returning the record from the guard's own transaction, sparing lock-held
128+
// entry paths a second whole-namespace read.
127129
func (b *Backend) EntryGuardLoad(ctx context.Context, id string) (VMRecord, error) {
128130
rec, err := b.entryGuard(ctx, id)
129131
if err != nil {

0 commit comments

Comments
 (0)