Skip to content

Commit c051973

Browse files
committed
Support multiple hub devices
1 parent d9693ae commit c051973

File tree

3 files changed

+22
-16
lines changed

3 files changed

+22
-16
lines changed

src/dev/monitor.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ pub enum DeviceEvent {
2121
}
2222

2323
pub struct DeviceMonitor {
24-
/// Root path for devices to monitor. This is usually a USB hub.
25-
root: PathBuf,
24+
/// Root paths for devices to monitor. This is usually a USB hub.
25+
roots: Vec<PathBuf>,
2626
/// Udev monitor socket.
2727
// Use `Rc` to avoid lifecycle issues in async stream impl.
2828
socket: Rc<AsyncFd<udev::MonitorSocket>>,
@@ -38,15 +38,15 @@ impl DeviceMonitor {
3838
/// Create a new device monitor.
3939
///
4040
/// Devices that are already plugged will each generate an `Add` event immediately.
41-
pub fn new(root: PathBuf) -> Result<Self> {
41+
pub fn new(roots: Vec<PathBuf>) -> Result<Self> {
4242
// Create a socket before enumerating devices to avoid missing events.
4343
let socket = Rc::new(AsyncFd::new(udev::MonitorBuilder::new()?.listen()?)?);
4444

4545
// Process all devices that are already plugged.
4646
let mut enumerator = Enumerator::new()?;
4747
let enumerated = enumerator
4848
.scan_devices()?
49-
.filter(|device| device.syspath().starts_with(&root))
49+
.filter(|device| roots.iter().any(|root| device.syspath().starts_with(root)))
5050
.map(Device::from_udev)
5151
.collect::<VecDeque<_>>();
5252

@@ -56,7 +56,7 @@ impl DeviceMonitor {
5656
}
5757

5858
Ok(Self {
59-
root,
59+
roots,
6060
socket,
6161
seen,
6262
enumerated,
@@ -74,7 +74,12 @@ impl DeviceMonitor {
7474
};
7575

7676
match event.event_type() {
77-
EventType::Add if event.syspath().starts_with(&self.root) => {
77+
EventType::Add
78+
if self
79+
.roots
80+
.iter()
81+
.any(|root| event.syspath().starts_with(root)) =>
82+
{
7883
match self.seen.entry(event.syspath().to_owned()) {
7984
Entry::Occupied(occupied) => {
8085
log::info!("Device already seen: {}", occupied.key().display());

src/hotplug/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ pub struct HotPlug {
2828
impl HotPlug {
2929
pub fn new(
3030
container: Arc<Container>,
31-
hub_path: PathBuf,
31+
hub_path: Vec<PathBuf>,
3232
symlinks: Vec<cli::Symlink>,
3333
) -> Result<Self> {
34-
let monitor = DeviceMonitor::new(hub_path.clone())?;
34+
let monitor = DeviceMonitor::new(hub_path)?;
3535
let devices = Default::default();
3636

3737
let udev_sender = UdevSender::new(crate::util::namespace::NetNamespace::of_pid(

src/main.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,17 @@ async fn create(global: GlobalOptions, create: CreateOptions, notifier: OwnedFd)
5757
let mut notifier = Some(notifier);
5858

5959
let config = runc::config::Config::from_bundle(&create.bundle)?;
60-
let device: DeviceRef = config
60+
let mut devices = Vec::new();
61+
let device_annotation = config
6162
.annotations
6263
.get("org.lowrisc.hotplug.device")
6364
.context(
6465
"Cannot find annotation `org.lowrisc.hotplug.device`. Please use normal runc instead.",
65-
)?
66-
.parse()?;
66+
)?;
67+
for device in device_annotation.split(',') {
68+
let devref: DeviceRef = device.parse()?;
69+
devices.push(devref.device()?.syspath().to_owned());
70+
}
6771

6872
let mut symlinks = Vec::<Symlink>::new();
6973
if let Some(symlink_annotation) = config.annotations.get("org.lowrisc.hotplug.symlinks") {
@@ -72,9 +76,6 @@ async fn create(global: GlobalOptions, create: CreateOptions, notifier: OwnedFd)
7276
}
7377
}
7478

75-
// Run this before calling into runc to create the container.
76-
let hub_path = device.device()?.syspath().to_owned();
77-
7879
// Switch the logger to syslog. The runc logs are barely forwarded to the user or syslog by
7980
// container managers and orchestrators, while we do want to preserve the hotplug events.
8081
util::log::global_replace(Box::new(util::log::SyslogLogger::new()?));
@@ -107,7 +108,7 @@ async fn create(global: GlobalOptions, create: CreateOptions, notifier: OwnedFd)
107108
rustix::stdio::dup2_stdout(&null)?;
108109
rustix::stdio::dup2_stderr(null)?;
109110

110-
let mut hotplug = HotPlug::new(Arc::clone(&container), hub_path.clone(), symlinks)?;
111+
let mut hotplug = HotPlug::new(Arc::clone(&container), devices.clone(), symlinks)?;
111112
let hotplug_stream = hotplug.run();
112113

113114
let container_stream = {
@@ -133,7 +134,7 @@ async fn create(global: GlobalOptions, create: CreateOptions, notifier: OwnedFd)
133134
let notifier = notifier.take().context("Initialized event seen twice")?;
134135
rustix::io::write(notifier, &[0])?;
135136
}
136-
Event::Detach(dev) if dev.syspath() == hub_path => {
137+
Event::Detach(dev) if devices.iter().any(|hub| dev.syspath() == hub) => {
137138
info!("Hub device detached. Stopping container.");
138139
let _ = container.kill(Signal::KILL).await;
139140
container.wait().await?;

0 commit comments

Comments
 (0)