Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
Loading