mirror of
https://github.com/joleuger/vuinputd.git
synced 2026-07-17 16:36:03 +00:00
Split inject_in_container into emit_udev_event and mknod_device
This commit is contained in:
parent
32119fbf92
commit
25623bf636
4 changed files with 151 additions and 26 deletions
|
|
@ -14,7 +14,8 @@ use uinput_ioctls::*;
|
|||
|
||||
use crate::cuse_device::{get_vuinput_state, VuFileHandle};
|
||||
use crate::job_engine::JOB_DISPATCHER;
|
||||
use crate::jobs::inject_in_container_job::InjectInContainerJob;
|
||||
use crate::jobs::emit_udev_event_in_container_job::EmitUdevEventInContainerJob;
|
||||
use crate::jobs::mknod_device_in_container_job::MknodDeviceInContainerJob;
|
||||
use crate::jobs::remove_from_container_job::RemoveFromContainerJob;
|
||||
use crate::process_tools::SELF_NAMESPACES;
|
||||
use crate::{cuse_device::*, jobs};
|
||||
|
|
@ -181,25 +182,40 @@ pub unsafe extern "C" fn vuinput_ioctl(
|
|||
.unwrap()
|
||||
.equal_mnt_and_net(&vuinput_state.requesting_process.namespaces)
|
||||
{
|
||||
let inject_job = InjectInContainerJob::new(
|
||||
let mknod_job = MknodDeviceInContainerJob::new(
|
||||
vuinput_state.requesting_process.clone(),
|
||||
devnode.clone(),
|
||||
sysname.clone(),
|
||||
major,
|
||||
minor,
|
||||
);
|
||||
let awaiter = inject_job.get_awaiter_for_state();
|
||||
let awaiter = mknod_job.get_awaiter_for_state();
|
||||
JOB_DISPATCHER
|
||||
.get()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.dispatch(Box::new(inject_job));
|
||||
awaiter(&jobs::inject_in_container_job::State::Finished);
|
||||
.dispatch(Box::new(mknod_job));
|
||||
awaiter(&jobs::mknod_device_in_container_job::State::Finished);
|
||||
debug!(
|
||||
"fh {}: injecting dev-nodes in container has been finished ",
|
||||
"fh {}: mknod_device in container has been finished ",
|
||||
fh
|
||||
);
|
||||
|
||||
// we do not wait for the udev stuff
|
||||
let emit_udev_event_job = EmitUdevEventInContainerJob::new(
|
||||
vuinput_state.requesting_process.clone(),
|
||||
devnode.clone(),
|
||||
sysname.clone(),
|
||||
major,
|
||||
minor,
|
||||
);
|
||||
JOB_DISPATCHER
|
||||
.get()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.dispatch(Box::new(emit_udev_event_job));
|
||||
}
|
||||
|
||||
// write a SYN-event (which is just zeros) just for validation
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ pub enum State {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct InjectInContainerJob {
|
||||
pub struct EmitUdevEventInContainerJob {
|
||||
requesting_process: RequestingProcess,
|
||||
target: JobTarget,
|
||||
dev_path: String,
|
||||
|
|
@ -41,7 +41,7 @@ pub struct InjectInContainerJob {
|
|||
sync_state: Arc<(Mutex<State>, Condvar)>,
|
||||
}
|
||||
|
||||
impl InjectInContainerJob {
|
||||
impl EmitUdevEventInContainerJob {
|
||||
pub fn new(
|
||||
requesting_process: RequestingProcess,
|
||||
dev_path: String,
|
||||
|
|
@ -82,16 +82,16 @@ impl InjectInContainerJob {
|
|||
}
|
||||
}
|
||||
|
||||
impl Job for InjectInContainerJob {
|
||||
impl Job for EmitUdevEventInContainerJob {
|
||||
fn desc(&self) -> &str {
|
||||
"Inject input device into container"
|
||||
"emit udev event into container"
|
||||
}
|
||||
|
||||
fn execute_after_cancellation(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn create_task(self: &InjectInContainerJob) -> Pin<Box<dyn Future<Output = ()>>> {
|
||||
fn create_task(self: &EmitUdevEventInContainerJob) -> Pin<Box<dyn Future<Output = ()>>> {
|
||||
Box::pin(self.clone().inject_in_container())
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ impl Job for InjectInContainerJob {
|
|||
}
|
||||
}
|
||||
|
||||
impl InjectInContainerJob {
|
||||
impl EmitUdevEventInContainerJob {
|
||||
async fn inject_in_container(self) {
|
||||
// temporary hack that needs to be replaced. We try 50 times
|
||||
// Should be: Wait for the device to be created, the runtime data to be written and the
|
||||
|
|
@ -148,16 +148,6 @@ impl InjectInContainerJob {
|
|||
let netlink_data = netlink_data.unwrap();
|
||||
let dev_path = self.dev_path.clone();
|
||||
|
||||
let mknod_device_action = Action::MknodDevice {
|
||||
path: dev_path.clone(),
|
||||
major: self.major,
|
||||
minor: self.minor,
|
||||
};
|
||||
|
||||
let child_pid_1 =
|
||||
process_tools::start_action(mknod_device_action, &self.requesting_process)
|
||||
.expect("subprocess should work");
|
||||
|
||||
let emit_udev_event_action = Action::EmitUdevEvent {
|
||||
netlink_message: netlink_data.clone(),
|
||||
runtime_data: Some(runtime_data),
|
||||
|
|
@ -165,12 +155,11 @@ impl InjectInContainerJob {
|
|||
minor: self.minor,
|
||||
};
|
||||
|
||||
let child_pid_2 =
|
||||
let child_pid =
|
||||
process_tools::start_action(emit_udev_event_action, &self.requesting_process)
|
||||
.expect("subprocess should work");
|
||||
|
||||
let _exit_info = await_process(Pid::Pid(child_pid_1)).await.unwrap();
|
||||
let _exit_info = await_process(Pid::Pid(child_pid_2)).await.unwrap();
|
||||
let _exit_info = await_process(Pid::Pid(child_pid)).await.unwrap();
|
||||
self.set_state(&State::Finished);
|
||||
}
|
||||
}
|
||||
119
vuinputd/src/jobs/mknod_device_in_container_job.rs
Normal file
119
vuinputd/src/jobs/mknod_device_in_container_job.rs
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Author: Johannes Leupolz <dev@leupolz.eu>
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
sync::{Arc, Condvar, Mutex},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use async_io::Timer;
|
||||
use log::debug;
|
||||
|
||||
use crate::{
|
||||
actions::{
|
||||
action::Action,
|
||||
runtime_data::{read_udev_data},
|
||||
},
|
||||
job_engine::job::{Job, JobTarget},
|
||||
jobs::monitor_udev_job::EVENT_STORE,
|
||||
process_tools::{self, await_process, Pid, RequestingProcess},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Copy, PartialOrd, PartialEq)]
|
||||
pub enum State {
|
||||
Initialized,
|
||||
Started,
|
||||
Finished,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MknodDeviceInContainerJob {
|
||||
requesting_process: RequestingProcess,
|
||||
target: JobTarget,
|
||||
dev_path: String,
|
||||
sys_path: String,
|
||||
major: u64,
|
||||
minor: u64,
|
||||
sync_state: Arc<(Mutex<State>, Condvar)>,
|
||||
}
|
||||
|
||||
impl MknodDeviceInContainerJob {
|
||||
pub fn new(
|
||||
requesting_process: RequestingProcess,
|
||||
dev_path: String,
|
||||
sys_path: String,
|
||||
major: u64,
|
||||
minor: u64,
|
||||
) -> Self {
|
||||
Self {
|
||||
requesting_process: requesting_process.clone(),
|
||||
target: JobTarget::Container(requesting_process),
|
||||
dev_path: dev_path,
|
||||
sys_path: sys_path,
|
||||
major: major,
|
||||
minor: minor,
|
||||
sync_state: Arc::new((Mutex::new(State::Initialized), Condvar::new())),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_state(&self, new_state: &State) -> () {
|
||||
let (lock, cvar) = &*self.sync_state;
|
||||
let mut current_state = lock.lock().unwrap();
|
||||
*current_state = *new_state;
|
||||
// We notify the condvar that the value has changed.
|
||||
cvar.notify_all();
|
||||
}
|
||||
|
||||
pub fn get_awaiter_for_state(&self) -> impl FnOnce(&State) -> () {
|
||||
// pattern is described on https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html
|
||||
let sync_state = self.sync_state.clone();
|
||||
let awaiter = move |state: &State| {
|
||||
let (lock, cvar) = &*sync_state;
|
||||
let mut current_state = lock.lock().unwrap();
|
||||
while *current_state < *state {
|
||||
current_state = cvar.wait(current_state).unwrap();
|
||||
}
|
||||
};
|
||||
awaiter
|
||||
}
|
||||
}
|
||||
|
||||
impl Job for MknodDeviceInContainerJob {
|
||||
fn desc(&self) -> &str {
|
||||
"mknod input device in container"
|
||||
}
|
||||
|
||||
fn execute_after_cancellation(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn create_task(self: &MknodDeviceInContainerJob) -> Pin<Box<dyn Future<Output = ()>>> {
|
||||
Box::pin(self.clone().inject_in_container())
|
||||
}
|
||||
|
||||
fn job_target(&self) -> JobTarget {
|
||||
self.target.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl MknodDeviceInContainerJob {
|
||||
async fn inject_in_container(self) {
|
||||
|
||||
let mknod_device_action = Action::MknodDevice {
|
||||
path: self.dev_path.clone(),
|
||||
major: self.major,
|
||||
minor: self.minor,
|
||||
};
|
||||
|
||||
let child_pid =
|
||||
process_tools::start_action(mknod_device_action, &self.requesting_process)
|
||||
.expect("subprocess should work");
|
||||
|
||||
let _exit_info = await_process(Pid::Pid(child_pid)).await.unwrap();
|
||||
self.set_state(&State::Finished);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
//
|
||||
// Author: Johannes Leupolz <dev@leupolz.eu>
|
||||
|
||||
pub mod inject_in_container_job;
|
||||
pub mod mknod_device_in_container_job;
|
||||
pub mod emit_udev_event_in_container_job;
|
||||
pub mod monitor_udev_job;
|
||||
pub mod remove_from_container_job;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue