Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions openhcl/diag_server/src/diag_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,9 +522,7 @@ impl DiagServiceHandler {
let mut inspection = InspectionBuilder::new(&request.path)
.depth(Some(request.depth as usize))
.sensitivity(self.inspect_sensitivity_level)
.inspect(inspect::adhoc(|req| {
self.request_send.send(DiagRequest::Inspect(req.defer()));
}));
.inspect(inspect::send(&self.request_send, DiagRequest::Inspect));

// Don't return early on cancel, as we want to return the partial
// inspection results.
Expand All @@ -544,9 +542,7 @@ impl DiagServiceHandler {
.sensitivity(self.inspect_sensitivity_level)
.update(
&request.value,
inspect::adhoc(|req| {
self.request_send.send(DiagRequest::Inspect(req.defer()));
}),
inspect::send(&self.request_send, DiagRequest::Inspect),
)
.await?;
Ok(UpdateResponse2 { new_value })
Expand Down
13 changes: 5 additions & 8 deletions openhcl/underhill_core/src/emuplat/netvsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,27 +825,24 @@ pub struct HclNetworkVFManagerEndpointInfo {
pub endpoint: Box<DisconnectableEndpoint>,
}

#[derive(Inspect)]
struct HclNetworkVFManagerSharedState {
#[inspect(flatten, send = "HclNetworkVfManagerMessage::Inspect")]
worker_channel: mesh::Sender<HclNetworkVfManagerMessage>,
}

enum HclNetworkVFUpdateNotification {
Update(Rpc<(), ()>),
}

#[derive(Inspect)]
pub struct HclNetworkVFManager {
#[inspect(flatten)]
shared_state: Arc<HclNetworkVFManagerSharedState>,
#[inspect(skip)]
_task: Task<()>,
}

impl Inspect for HclNetworkVFManager {
fn inspect(&self, req: inspect::Request<'_>) {
self.shared_state
.worker_channel
.send(HclNetworkVfManagerMessage::Inspect(req.defer()))
}
}

impl HclNetworkVFManager {
pub async fn new(
vtl2_vf_instance_id: Guid,
Expand Down
16 changes: 8 additions & 8 deletions openhcl/underhill_core/src/inspect_internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ use pal_async::task::Spawn;

pub(crate) fn inspect_internal_diagnostics(
req: Request<'_>,
reinspect: Sender<Deferred>,
driver: DefaultDriver,
reinspect: &Sender<Deferred>,
driver: &DefaultDriver,
) {
req.respond()
.sensitivity_field("build_info", SensitivityLevel::Safe, build_info::get())
.sensitivity_child("net", SensitivityLevel::Safe, |req| {
net(req, reinspect, driver)
net(req, reinspect.clone(), driver)
});
}

fn net(req: Request<'_>, reinspect: Sender<Deferred>, driver: DefaultDriver) {
fn net(req: Request<'_>, reinspect: Sender<Deferred>, driver: &DefaultDriver) {
let defer = req.defer();
let driver2 = driver.clone();
driver
Expand All @@ -64,7 +64,7 @@ fn net(req: Request<'_>, reinspect: Sender<Deferred>, driver: DefaultDriver) {
let mut vm_inspection = InspectionBuilder::new("vm")
.depth(Some(0))
.sensitivity(Some(SensitivityLevel::Sensitive))
.inspect(inspect::adhoc(|req| reinspect.send(req.defer())));
.inspect(inspect::send(&reinspect, |x| x));
vm_inspection.resolve().await;

let Node::Dir(nodes) = vm_inspection.results() else {
Expand All @@ -83,7 +83,7 @@ fn net(req: Request<'_>, reinspect: Sender<Deferred>, driver: DefaultDriver) {

// The existence of a mac address is always known to the host, so this can always be Safe.
resp.sensitivity_child(&mac_name, SensitivityLevel::Safe, |req| {
net_nic(req, nic_entry.name, reinspect.clone(), driver2.clone());
net_nic(req, nic_entry.name, reinspect.clone(), &driver2);
});
}
})
Expand All @@ -93,7 +93,7 @@ fn net(req: Request<'_>, reinspect: Sender<Deferred>, driver: DefaultDriver) {

// net/mac_address
// Format for mac address is no separators, lowercase letters, e.g. 00155d121212.
fn net_nic(req: Request<'_>, name: String, reinspect: Sender<Deferred>, driver: DefaultDriver) {
fn net_nic(req: Request<'_>, name: String, reinspect: Sender<Deferred>, driver: &DefaultDriver) {
let defer = req.defer();
driver
.spawn("inspect-diagnostics-net-nic", async move {
Expand All @@ -103,7 +103,7 @@ fn net_nic(req: Request<'_>, name: String, reinspect: Sender<Deferred>, driver:
let mut vm_inspection = InspectionBuilder::new(&format!("vm/{name}"))
.depth(Some(5))
.sensitivity(Some(SensitivityLevel::Sensitive))
.inspect(inspect::adhoc(|req| reinspect.send(req.defer())));
.inspect(inspect::send(&reinspect, |req| req));
vm_inspection.resolve().await;

if let Node::Dir(nodes) = vm_inspection.results() {
Expand Down
4 changes: 2 additions & 2 deletions openhcl/underhill_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,8 +545,8 @@ async fn run_control(
.sensitivity_child("uhdiag", SensitivityLevel::Safe, |req| {
inspect_internal::inspect_internal_diagnostics(
req,
diag_reinspect_send.clone(),
driver.clone(),
&diag_reinspect_send,
&driver,
)
});

Expand Down
7 changes: 2 additions & 5 deletions openhcl/underhill_core/src/nvme_manager/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,16 +334,13 @@ impl NvmeDriverManager {

#[derive(Inspect, Debug, Clone)]
pub struct NvmeDriverManagerClient {
pci_id: String,
#[inspect(skip)]
pci_id: String,
#[inspect(flatten, send = "NvmeDriverRequest::Inspect")]
sender: mesh::Sender<NvmeDriverRequest>,
}

impl NvmeDriverManagerClient {
pub fn send_inspect(&self, deferred: Deferred) {
self.sender.send(NvmeDriverRequest::Inspect(deferred));
}

pub async fn get_namespace(&self, nsid: u32) -> anyhow::Result<nvme_driver::Namespace> {
let span = tracing::info_span!(
"nvme_device_manager_get_namespace",
Expand Down
25 changes: 3 additions & 22 deletions openhcl/underhill_core/src/nvme_manager/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,40 +198,21 @@ struct NvmeWorkerContext {
save_restore_supported: bool,
#[inspect(skip)]
driver_source: VmTaskDriverSource,
#[inspect(skip)]
#[inspect(with = "|x| inspect::adhoc(|req| inspect::iter_by_key(&*x.read()).inspect(req))")]
devices: Arc<RwLock<HashMap<String, NvmeDriverManager>>>,
#[inspect(skip)]
nvme_driver_spawner: Arc<dyn CreateNvmeDriver>,
}

#[derive(Inspect)]
#[inspect(extra = "NvmeManagerWorker::inspect_extra")]
struct NvmeManagerWorker {
#[inspect(skip)]
#[inspect(with = "Vec::len")]
tasks: Vec<Task<()>>,
#[inspect(flatten)]
context: NvmeWorkerContext,
}

impl NvmeManagerWorker {
fn inspect_extra(&self, resp: &mut inspect::Response<'_>) {
resp.child("outstanding-tasks", |req| {
req.value(self.tasks.len());
});

resp.child("devices", |req| {
let devices = self.context.devices.read();
let mut resp = req.respond();
for (pci_id, driver) in devices.iter() {
resp.field(
pci_id,
inspect::adhoc(|req| {
driver.client().send_inspect(req.defer());
}),
);
}
});
}

async fn run(&mut self, mut recv: mesh::Receiver<Request>) {
let (join_span, nvme_keepalive) = loop {
let Some(req) = recv.next().await else {
Expand Down
5 changes: 2 additions & 3 deletions openvmm/hvlite_core/src/worker/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2690,9 +2690,8 @@ impl LoadedVm {
while let Some(rpc) = worker_rpc.next().await {
match rpc {
WorkerRpc::Inspect(req) => req.respond(|resp| {
resp.merge(&state_units).merge(inspect::adhoc(|req| {
worker_rpc_send.send(WorkerRpc::Inspect(req.defer()));
}));
resp.merge(&state_units)
.merge(inspect::send(&worker_rpc_send, WorkerRpc::Inspect));
}),
rpc => worker_rpc_send.send(rpc),
}
Expand Down
14 changes: 5 additions & 9 deletions openvmm/membacking/src/mapping_manager/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,15 @@ use slab::Slab;
use std::sync::Arc;

/// The mapping manager.
#[derive(Debug)]
#[derive(Debug, Inspect)]
pub struct MappingManager {
#[inspect(
flatten,
with = "|x| inspect::send(&x.req_send, MappingRequest::Inspect)"
)]
client: MappingManagerClient,
}

impl Inspect for MappingManager {
fn inspect(&self, req: inspect::Request<'_>) {
self.client
.req_send
.send(MappingRequest::Inspect(req.defer()));
}
}

impl MappingManager {
/// Returns a new mapping manager that can map addresses up to `max_addr`.
pub fn new(spawn: impl Spawn, max_addr: u64) -> Self {
Expand Down
14 changes: 5 additions & 9 deletions openvmm/membacking/src/region_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,15 @@ use thiserror::Error;
use vmcore::local_only::LocalOnly;

/// The region manager.
#[derive(Debug)]
#[derive(Debug, Inspect)]
pub struct RegionManager {
#[inspect(
flatten,
with = "|x| inspect::send(&x.req_send, RegionRequest::Inspect)"
)]
client: RegionManagerClient,
}

impl Inspect for RegionManager {
fn inspect(&self, req: inspect::Request<'_>) {
self.client
.req_send
.send(RegionRequest::Inspect(req.defer()));
}
}

/// Provides access to the region manager.
#[derive(Debug, MeshPayload, Clone)]
pub struct RegionManagerClient {
Expand Down
38 changes: 38 additions & 0 deletions support/inspect/src/defer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use super::Request;
use super::Response;
use super::SensitivityLevel;
use super::UpdateRequest;
use crate::Inspect;
use crate::NumberFormat;
use crate::RequestParams;
use crate::RootParams;
Expand All @@ -18,6 +19,43 @@ use alloc::boxed::Box;
use alloc::string::String;
use mesh::MeshPayload;

/// An [`Inspect`] implementation that defers the inspection to another
/// thread or context by sending the request on a [`mesh`] channel.
///
/// # Usage
///
/// ```rust
/// enum MyRpc {
/// Inspect(inspect::Deferred),
/// SomeWork(mesh::rpc::Rpc<u32, u32>),
/// }
///
/// fn inspect_remote(sender: &mesh::Sender<MyRpc>, req: inspect::Request<'_>) {
/// req.respond().merge(inspect::send(sender, MyRpc::Inspect));
/// }
/// ```
pub fn send<'a, S: 'a + mesh::rpc::RpcSend + Copy, F: 'a + Fn(Deferred) -> S::Message>(
sender: S,
map: F,
) -> AsDeferred<S, F> {
AsDeferred(sender, map)
}

/// The return type of [`send`].
pub struct AsDeferred<S, F>(S, F);

impl<S: mesh::rpc::RpcSend + Copy, F: Fn(Deferred) -> S::Message> Inspect for AsDeferred<S, F> {
fn inspect(&self, req: Request<'_>) {
self.0.send_rpc(self.1(req.defer()));
}
}

impl<S: mesh::rpc::RpcSend + Copy, F: Fn(Deferred) -> S::Message> InspectMut for AsDeferred<S, F> {
fn inspect_mut(&mut self, req: Request<'_>) {
self.0.send_rpc(self.1(req.defer()));
}
}

impl Request<'_> {
/// Defers the inspection request, producing a value that can be sent to
/// another thread or context to continue the inspection asynchronously.
Expand Down
12 changes: 12 additions & 0 deletions support/inspect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,18 @@ pub use initiate::*;
/// This can also be used to implement helper functions that implement
/// [`Inspect`] to allow complex types to use the the derive macro.
///
/// ### `send = "expr"`
///
/// Sends a deferred request message for the field so that it can be handled by
/// some remote asynchronous task (potentially on another thread or in another
/// process). The field must be a `mesh::Sender<T>`, and `expr` must be a
/// function that maps from a `Deferred` to `T` (the request type of the
/// sender).
///
/// This is shorthand for `with = "|x| inspect::send(x, expr)"`, which in turn
/// is roughly the same as `with = "|x| inspect::adhoc(|req|
/// x.send(expr(req.defer())))"`.
///
/// #### Examples
/// The following structure has a field that is not normally inspectable, but we
/// can use the derive macro with a helper pattern of making a new helper
Expand Down
Loading