@@ -141,12 +141,28 @@ pub(super) enum VmStartReason {
141
141
ExplicitRequest ,
142
142
}
143
143
144
+ /// The outcome of a request to start a VM.
144
145
enum VmStartOutcome {
145
146
Succeeded ,
146
147
Failed ,
147
148
Aborted ,
148
149
}
149
150
151
+ impl VmStartOutcome {
152
+ /// If this start outcome implies that the state driver should return
153
+ /// immediately and allow the VM to be torn down, this routine returns
154
+ /// `Some(state)` where `state` is the final VM state to return from the
155
+ /// driver. If the driver should continue running the VM, this routine
156
+ /// returns `None`.
157
+ fn final_vm_state ( & self ) -> Option < InstanceState > {
158
+ match self {
159
+ Self :: Succeeded => None ,
160
+ Self :: Failed => Some ( InstanceState :: Failed ) ,
161
+ Self :: Aborted => Some ( InstanceState :: Destroyed ) ,
162
+ }
163
+ }
164
+ }
165
+
150
166
/// A kind of event the state driver can handle.
151
167
#[ derive( Debug ) ]
152
168
enum InputQueueEvent {
@@ -489,10 +505,16 @@ impl StateDriver {
489
505
info ! ( self . log, "state driver launched" ) ;
490
506
491
507
let final_state = if migrated_in {
492
- match self . start_vm ( VmStartReason :: MigratedIn ) . await {
493
- VmStartOutcome :: Succeeded => self . event_loop ( ) . await ,
494
- VmStartOutcome :: Failed => InstanceState :: Failed ,
495
- VmStartOutcome :: Aborted => InstanceState :: Destroyed ,
508
+ // If the final state is known merely from the attempt to start the
509
+ // VM, return it immediately; otherwise, run the event loop and wait
510
+ // for it to return the final state.
511
+ match self
512
+ . start_vm ( VmStartReason :: MigratedIn )
513
+ . await
514
+ . final_vm_state ( )
515
+ {
516
+ None => self . event_loop ( ) . await ,
517
+ Some ( s) => s,
496
518
}
497
519
} else {
498
520
self . event_loop ( ) . await
@@ -575,7 +597,12 @@ impl StateDriver {
575
597
info ! ( self . log, "sending start request to {}" , name) ;
576
598
let res = dev. start ( ) ;
577
599
if let Err ( e) = res {
578
- error ! ( self . log, "startup failed for {}: {:?}" , name, e) ;
600
+ error ! (
601
+ self . log, "device start() returned an error" ;
602
+ "device" => %name,
603
+ "error" => %e
604
+ ) ;
605
+
579
606
return VmStartOutcome :: Failed ;
580
607
}
581
608
}
@@ -599,7 +626,9 @@ impl StateDriver {
599
626
if let Err ( e) = & res {
600
627
error ! (
601
628
log,
602
- "startup failed for block backend {}: {:?}" , name, e
629
+ "block backend start() returned an error" ;
630
+ "backend" => %name,
631
+ "error" => %e
603
632
) ;
604
633
605
634
return res;
@@ -712,6 +741,9 @@ impl StateDriver {
712
741
result_tx,
713
742
} ,
714
743
) => {
744
+ // The API caller who requested this operation can hang up
745
+ // and drop the receiver. This isn't fatal; just keep
746
+ // starting the VM if it happens.
715
747
let _ = result_tx. send (
716
748
self . reconfigure_crucible_volume (
717
749
& backend_id,
@@ -795,14 +827,17 @@ impl StateDriver {
795
827
) -> HandleEventOutcome {
796
828
match request {
797
829
ExternalRequest :: State ( StateChangeRequest :: Start ) => {
798
- match self . start_vm ( VmStartReason :: ExplicitRequest ) . await {
799
- VmStartOutcome :: Succeeded => HandleEventOutcome :: Continue ,
800
- VmStartOutcome :: Failed => HandleEventOutcome :: Exit {
801
- final_state : InstanceState :: Failed ,
802
- } ,
803
- VmStartOutcome :: Aborted => HandleEventOutcome :: Exit {
804
- final_state : InstanceState :: Destroyed ,
805
- } ,
830
+ // If this start attempt produces a terminal VM state, return it
831
+ // to the driver and indicate that the driver should exit.
832
+ match self
833
+ . start_vm ( VmStartReason :: ExplicitRequest )
834
+ . await
835
+ . final_vm_state ( )
836
+ {
837
+ None => HandleEventOutcome :: Continue ,
838
+ Some ( final_state) => {
839
+ HandleEventOutcome :: Exit { final_state }
840
+ }
806
841
}
807
842
}
808
843
ExternalRequest :: State ( StateChangeRequest :: MigrateAsSource {
0 commit comments