agent/uevent: Report whole Uevents to device watchers

Currently, when Uevent::handle_block_add_event() receives an event matching
a registered watcher, it reports the /dev node name from the event back
to the watcher.

This changes it to report the entire uevent, not just the /dev node name.
This will allow various future extensions.  It also makes the client side
of the uevent watching - get_device_name() - more consistent between its
two paths: finding a past uevent in Sandbox::uevent_map() or waiting for
a new uevent via a watcher.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
David Gibson 2021-03-05 16:07:42 +11:00
parent 3642005479
commit 91e0ef5c90
3 changed files with 8 additions and 8 deletions

View File

@ -17,6 +17,7 @@ use crate::linux_abi::*;
use crate::mount::{DRIVER_BLK_TYPE, DRIVER_MMIO_BLK_TYPE, DRIVER_NVDIMM_TYPE, DRIVER_SCSI_TYPE};
use crate::pci;
use crate::sandbox::Sandbox;
use crate::uevent::Uevent;
use crate::AGENT_CONFIG;
use anyhow::{anyhow, Result};
use oci::{LinuxDeviceCgroup, LinuxResources, Spec};
@ -101,14 +102,14 @@ async fn get_device_name(sandbox: &Arc<Mutex<Sandbox>>, dev_addr: &str) -> Resul
// The key of the watchers map is the device we are interested in.
// Note this is done inside the lock, not to miss any events from the
// global udev listener.
let (tx, rx) = tokio::sync::oneshot::channel::<String>();
let (tx, rx) = tokio::sync::oneshot::channel::<Uevent>();
sb.dev_watcher.insert(dev_addr.to_string(), tx);
drop(sb); // unlock
info!(sl!(), "Waiting on channel for device notification\n");
let hotplug_timeout = AGENT_CONFIG.read().await.hotplug_timeout;
let dev_name = match tokio::time::timeout(hotplug_timeout, rx).await {
let uev = match tokio::time::timeout(hotplug_timeout, rx).await {
Ok(v) => v?,
Err(_) => {
let mut sb = sandbox.lock().await;
@ -122,7 +123,7 @@ async fn get_device_name(sandbox: &Arc<Mutex<Sandbox>>, dev_addr: &str) -> Resul
}
};
Ok(format!("{}/{}", SYSTEM_DEV_PATH, &dev_name))
Ok(format!("{}/{}", SYSTEM_DEV_PATH, &uev.devname))
}
pub async fn get_scsi_device_name(
@ -796,7 +797,7 @@ mod tests {
assert_eq!(name.unwrap(), format!("{}/{}", SYSTEM_DEV_PATH, devname));
let mut sb = sandbox.lock().await;
sb.uevent_map.remove(&devpath);
let uev = sb.uevent_map.remove(&devpath).unwrap();
drop(sb); // unlock
let watcher_sandbox = Arc::clone(&sandbox);
@ -812,7 +813,7 @@ mod tests {
if let Some(k) = matched_key {
let sender = sb.dev_watcher.remove(&k).unwrap();
let _ = sender.send(devname.to_string());
let _ = sender.send(uev);
return;
}
drop(sb); // unlock

View File

@ -38,7 +38,7 @@ pub struct Sandbox {
pub mounts: Vec<String>,
pub container_mounts: HashMap<String, Vec<String>>,
pub uevent_map: HashMap<String, Uevent>,
pub dev_watcher: HashMap<String, tokio::sync::oneshot::Sender<String>>,
pub dev_watcher: HashMap<String, tokio::sync::oneshot::Sender<Uevent>>,
pub shared_utsns: Namespace,
pub shared_ipcns: Namespace,
pub sandbox_pidns: Option<Namespace>,

View File

@ -98,12 +98,11 @@ impl Uevent {
.collect();
for k in keys {
let devname = self.devname.clone();
// unwrap() is safe because logic above ensures k exists
// in the map, and it's locked so no-one else can change
// that
let sender = sb.dev_watcher.remove(&k).unwrap();
let _ = sender.send(devname);
let _ = sender.send(self.clone());
}
}