Revert "devices: refactor proxy to use msg_socket"

This reverts commit 142ce3efd9.

Reason for revert: <INSERT REASONING HERE>

Original change's description:
> devices: refactor proxy to use msg_socket
> 
> Use msg socket in proxy.
> 
> BUG=None
> TEST=None
> 
> Change-Id: Ia5ebc4410918a261fe525abc1051ebbbdc66a876
> Reviewed-on: https://chromium-review.googlesource.com/1260259
> Commit-Ready: Jingkui Wang <jkwang@google.com>
> Tested-by: Jingkui Wang <jkwang@google.com>
> Reviewed-by: Zach Reizner <zachr@chromium.org>

Bug: None
Change-Id: Ic7827969e9ad508cd1b65cb7b8747e81e0cd02d0
Reviewed-on: https://chromium-review.googlesource.com/c/1313014
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Commit-Queue: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Jingkui Wang <jkwang@google.com>
This commit is contained in:
Jingkui Wang 2018-11-01 16:53:47 +00:00
parent 142ce3efd9
commit 9d5e8f34ad
4 changed files with 125 additions and 114 deletions

1
Cargo.lock generated
View file

@ -135,7 +135,6 @@ dependencies = [
"io_jail 0.1.0", "io_jail 0.1.0",
"kvm 0.1.0", "kvm 0.1.0",
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
"msg_socket 0.1.0",
"net_sys 0.1.0", "net_sys 0.1.0",
"net_util 0.1.0", "net_util 0.1.0",
"p9 0.1.0", "p9 0.1.0",

View file

@ -15,7 +15,6 @@ gpu_display = { path = "../gpu_display", optional = true }
gpu_renderer = { path = "../gpu_renderer", optional = true } gpu_renderer = { path = "../gpu_renderer", optional = true }
kvm = { path = "../kvm" } kvm = { path = "../kvm" }
libc = "*" libc = "*"
msg_socket = { path = "../msg_socket" }
io_jail = { path = "../io_jail" } io_jail = { path = "../io_jail" }
net_sys = { path = "../net_sys" } net_sys = { path = "../net_sys" }
net_util = { path = "../net_util" } net_util = { path = "../net_util" }

View file

@ -18,8 +18,6 @@ extern crate sys_util;
extern crate vhost; extern crate vhost;
extern crate virtio_sys; extern crate virtio_sys;
extern crate vm_control; extern crate vm_control;
#[macro_use]
extern crate msg_socket;
mod bus; mod bus;
mod cmos; mod cmos;

View file

@ -12,7 +12,7 @@ use std::process;
use std::time::Duration; use std::time::Duration;
use std::{self, fmt, io}; use std::{self, fmt, io};
use msg_socket::{MsgError, MsgOnSocket, MsgReceiver, MsgResult, MsgSender, MsgSocket}; use byteorder::{ByteOrder, LittleEndian, NativeEndian};
use io_jail::{self, Minijail}; use io_jail::{self, Minijail};
use BusDevice; use BusDevice;
@ -35,80 +35,74 @@ impl fmt::Display for Error {
} }
const SOCKET_TIMEOUT_MS: u64 = 2000; const SOCKET_TIMEOUT_MS: u64 = 2000;
const MSG_SIZE: usize = 24;
#[derive(MsgOnSocket)]
enum Command { enum Command {
Read { Read = 0,
len: u32, Write = 1,
offset: u64, ReadConfig = 2,
}, WriteConfig = 3,
Write { Shutdown = 4,
len: u32,
offset: u64,
data: [u8; 8],
},
ReadConfig(u32),
WriteConfig {
reg_idx: u32,
offset: u32,
len: u32,
data: [u8; 4],
},
Shutdown,
}
#[derive(MsgOnSocket)]
enum CommandResult {
Ok,
ReadResult([u8; 8]),
ReadConfigResult(u32),
} }
fn child_proc(sock: UnixDatagram, device: &mut BusDevice) { fn child_proc(sock: UnixDatagram, device: &mut BusDevice) {
let mut running = true; let mut running = true;
let sock = MsgSocket::<CommandResult, Command>::new(sock);
while running { while running {
let cmd = match sock.recv() { let mut buf = [0; MSG_SIZE];
Ok(cmd) => cmd, match handle_eintr!(sock.recv(&mut buf)) {
Err(err) => { Ok(c) if c != buf.len() => {
error!("child device process failed recv: {:?}", err); error!(
"child device process incorrect recv size: got {}, expected {}",
c,
buf.len()
);
break; break;
} }
Err(e) => {
error!("child device process failed recv: {}", e);
break;
}
_ => {}
}
let cmd = NativeEndian::read_u32(&buf[0..]);
let res = if cmd == Command::Read as u32 {
let len = NativeEndian::read_u32(&buf[4..]) as usize;
let offset = NativeEndian::read_u64(&buf[8..]);
device.read(offset, &mut buf[16..16 + len]);
handle_eintr!(sock.send(&buf))
} else if cmd == Command::Write as u32 {
let len = NativeEndian::read_u32(&buf[4..]) as usize;
let offset = NativeEndian::read_u64(&buf[8..]);
device.write(offset, &buf[16..16 + len]);
handle_eintr!(sock.send(&buf))
} else if cmd == Command::ReadConfig as u32 {
let reg_idx = NativeEndian::read_u32(&buf[4..]) as usize;
let val = device.config_register_read(reg_idx);
buf[16] = val as u8;
buf[17] = (val >> 8) as u8;
buf[18] = (val >> 16) as u8;
buf[19] = (val >> 24) as u8;
handle_eintr!(sock.send(&buf))
} else if cmd == Command::WriteConfig as u32 {
let reg_idx = NativeEndian::read_u32(&buf[4..]) as usize;
let offset = u64::from(NativeEndian::read_u32(&buf[8..]));
let len = u64::from(NativeEndian::read_u32(&buf[16..]));
device.config_register_write(reg_idx, offset, &buf[20..(20 + len as usize)]);
handle_eintr!(sock.send(&buf))
} else if cmd == Command::Shutdown as u32 {
running = false;
handle_eintr!(sock.send(&buf))
} else {
error!("child device process unknown command: {}", cmd);
break;
}; };
let res = match cmd {
Command::Read { len, offset } => {
let mut buffer = [0u8; 8];
device.read(offset, &mut buffer[0..len as usize]);
sock.send(&CommandResult::ReadResult(buffer))
}
Command::Write { len, offset, data } => {
let len = len as usize;
device.write(offset, &data[0..len]);
sock.send(&CommandResult::Ok)
}
Command::ReadConfig(idx) => {
let val = device.config_register_read(idx as usize);
sock.send(&CommandResult::ReadConfigResult(val))
}
Command::WriteConfig {
reg_idx,
offset,
len,
data,
} => {
let len = len as usize;
device.config_register_write(reg_idx as usize, offset as u64, &data[0..len]);
sock.send(&CommandResult::Ok)
}
Command::Shutdown => {
running = false;
sock.send(&CommandResult::Ok)
}
};
if let Err(e) = res { if let Err(e) = res {
error!("child device process failed send: {:?}", e); error!("error: child device process failed send: {}", e);
break;
} }
} }
} }
@ -118,7 +112,7 @@ fn child_proc(sock: UnixDatagram, device: &mut BusDevice) {
/// Because forks are very unfriendly to destructors and all memory mappings and file descriptors /// Because forks are very unfriendly to destructors and all memory mappings and file descriptors
/// are inherited, this should be used as early as possible in the main process. /// are inherited, this should be used as early as possible in the main process.
pub struct ProxyDevice { pub struct ProxyDevice {
sock: MsgSocket<Command, CommandResult>, sock: UnixDatagram,
pid: pid_t, pid: pid_t,
} }
@ -158,7 +152,7 @@ impl ProxyDevice {
.set_read_timeout(Some(Duration::from_millis(SOCKET_TIMEOUT_MS))) .set_read_timeout(Some(Duration::from_millis(SOCKET_TIMEOUT_MS)))
.map_err(Error::Io)?; .map_err(Error::Io)?;
Ok(ProxyDevice { Ok(ProxyDevice {
sock: MsgSocket::<Command, CommandResult>::new(parent_sock), sock: parent_sock,
pid, pid,
}) })
} }
@ -167,69 +161,90 @@ impl ProxyDevice {
self.pid self.pid
} }
fn sync_send(&self, cmd: Command) -> Option<CommandResult> { fn send_cmd(&self, cmd: Command, offset: u64, len: u32, data: &[u8]) -> Result<()> {
let res = self.sock.send(&cmd); let mut buf = [0; MSG_SIZE];
if let Err(e) = res { NativeEndian::write_u32(&mut buf[0..], cmd as u32);
error!("failed write to child device process: {:?}", e); NativeEndian::write_u32(&mut buf[4..], len);
}; NativeEndian::write_u64(&mut buf[8..], offset);
match self.sock.recv() { buf[16..16 + data.len()].clone_from_slice(data);
Err(e) => { handle_eintr!(self.sock.send(&buf))
error!("failed read from child device process: {:?}", e); .map(|_| ())
None .map_err(Error::Io)
} }
Ok(r) => Some(r),
} fn send_config_cmd(&self, cmd: Command, reg_idx: u32, offset: u64, data: &[u8]) -> Result<()> {
let mut buf = [0; MSG_SIZE];
NativeEndian::write_u32(&mut buf[0..], cmd as u32);
NativeEndian::write_u32(&mut buf[4..], reg_idx);
NativeEndian::write_u64(&mut buf[8..], offset);
NativeEndian::write_u32(&mut buf[16..], data.len() as u32);
buf[20..20 + data.len()].clone_from_slice(data);
handle_eintr!(self.sock.send(&buf))
.map(|_| ())
.map_err(Error::Io)
}
fn recv_resp(&self, data: &mut [u8]) -> Result<()> {
let mut buf = [0; MSG_SIZE];
handle_eintr!(self.sock.recv(&mut buf)).map_err(Error::Io)?;
let len = data.len();
data.clone_from_slice(&buf[16..16 + len]);
Ok(())
}
fn wait(&self) -> Result<()> {
let mut buf = [0; MSG_SIZE];
handle_eintr!(self.sock.recv(&mut buf))
.map(|_| ())
.map_err(Error::Io)
} }
} }
impl BusDevice for ProxyDevice { impl BusDevice for ProxyDevice {
fn config_register_write(&mut self, reg_idx: usize, offset: u64, data: &[u8]) { fn config_register_write(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
let len = data.len() as u32; let res = self
let mut buffer = [0u8; 4]; .send_config_cmd(Command::WriteConfig, reg_idx as u32, offset, data)
buffer[0..data.len()].clone_from_slice(data); .and_then(|_| self.wait());
let reg_idx = reg_idx as u32; if let Err(e) = res {
let offset = offset as u32; error!("failed write to child device process: {}", e);
self.sync_send(Command::WriteConfig {
reg_idx,
offset,
len,
data: buffer,
});
}
fn config_register_read(&self, reg_idx: usize) -> u32 {
let res = self.sync_send(Command::ReadConfig(reg_idx as u32));
if let Some(CommandResult::ReadConfigResult(val)) = res {
val
} else {
0
} }
} }
fn config_register_read(&self, reg_idx: usize) -> u32 {
let mut data = [0u8; 4];
let res = self
.send_config_cmd(Command::ReadConfig, reg_idx as u32, 0, &[])
.and_then(|_| self.recv_resp(&mut data));
if let Err(e) = res {
error!("failed write to child device process: {}", e);
}
LittleEndian::read_u32(&data)
}
fn read(&mut self, offset: u64, data: &mut [u8]) { fn read(&mut self, offset: u64, data: &mut [u8]) {
let len = data.len() as u32; let res = self
if let Some(CommandResult::ReadResult(buffer)) = .send_cmd(Command::Read, offset, data.len() as u32, &[])
self.sync_send(Command::Read { len, offset }) .and_then(|_| self.recv_resp(data));
{ if let Err(e) = res {
let len = data.len(); error!("failed read from child device process: {}", e);
data.clone_from_slice(&buffer[0..len]);
} }
} }
fn write(&mut self, offset: u64, data: &[u8]) { fn write(&mut self, offset: u64, data: &[u8]) {
let mut buffer = [0u8; 8]; let res = self
let len = data.len() as u32; .send_cmd(Command::Write, offset, data.len() as u32, data)
buffer[0..data.len()].clone_from_slice(data); .and_then(|_| self.wait());
self.sync_send(Command::Write { if let Err(e) = res {
len, error!("failed write to child device process: {}", e);
offset, }
data: buffer,
});
} }
} }
impl Drop for ProxyDevice { impl Drop for ProxyDevice {
fn drop(&mut self) { fn drop(&mut self) {
self.sync_send(Command::Shutdown); let res = self.send_cmd(Command::Shutdown, 0, 0, &[]);
if let Err(e) = res {
error!("failed to shutdown child device process: {}", e);
}
} }
} }