mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-27 19:35:32 +00:00
agent: Move device code with virtio scsi driver to scsi_device_handler
Move scsi device code to scsi_device_handler to simplify the code. Signed-off-by: ChengyuZhu6 <chengyu.zhu@intel.com>
This commit is contained in:
parent
0738d75a92
commit
0cb87767ae
@ -28,9 +28,7 @@ use oci_spec::runtime as oci;
|
||||
use protocols::agent::Device;
|
||||
use tracing::instrument;
|
||||
|
||||
use kata_types::device::{
|
||||
DRIVER_SCSI_TYPE, DRIVER_VFIO_AP_TYPE, DRIVER_VFIO_PCI_GK_TYPE, DRIVER_VFIO_PCI_TYPE,
|
||||
};
|
||||
use kata_types::device::{DRIVER_VFIO_AP_TYPE, DRIVER_VFIO_PCI_GK_TYPE, DRIVER_VFIO_PCI_TYPE};
|
||||
|
||||
// Convenience function to obtain the scope logger.
|
||||
fn sl() -> slog::Logger {
|
||||
@ -171,39 +169,6 @@ pub fn pcipath_to_sysfs(root_bus_sysfs: &str, pcipath: &pci::Path) -> Result<Str
|
||||
Ok(relpath)
|
||||
}
|
||||
|
||||
// FIXME: This matcher is only correct if the guest has at most one
|
||||
// SCSI host.
|
||||
#[derive(Debug)]
|
||||
struct ScsiBlockMatcher {
|
||||
search: String,
|
||||
}
|
||||
|
||||
impl ScsiBlockMatcher {
|
||||
fn new(scsi_addr: &str) -> ScsiBlockMatcher {
|
||||
let search = format!(r"/0:0:{}/block/", scsi_addr);
|
||||
|
||||
ScsiBlockMatcher { search }
|
||||
}
|
||||
}
|
||||
|
||||
impl UeventMatcher for ScsiBlockMatcher {
|
||||
fn is_match(&self, uev: &Uevent) -> bool {
|
||||
uev.subsystem == BLOCK && uev.devpath.contains(&self.search) && !uev.devname.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
pub async fn get_scsi_device_name(
|
||||
sandbox: &Arc<Mutex<Sandbox>>,
|
||||
scsi_addr: &str,
|
||||
) -> Result<String> {
|
||||
let matcher = ScsiBlockMatcher::new(scsi_addr);
|
||||
|
||||
scan_scsi_bus(scsi_addr)?;
|
||||
let uev = wait_for_uevent(sandbox, matcher).await?;
|
||||
Ok(format!("{}/{}", SYSTEM_DEV_PATH, &uev.devname))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PciMatcher {
|
||||
devpath: String,
|
||||
@ -362,39 +327,6 @@ async fn wait_for_ap_device(sandbox: &Arc<Mutex<Sandbox>>, address: ap::Address)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Scan SCSI bus for the given SCSI address(SCSI-Id and LUN)
|
||||
#[instrument]
|
||||
fn scan_scsi_bus(scsi_addr: &str) -> Result<()> {
|
||||
let tokens: Vec<&str> = scsi_addr.split(':').collect();
|
||||
if tokens.len() != 2 {
|
||||
return Err(anyhow!(
|
||||
"Unexpected format for SCSI Address: {}, expect SCSIID:LUA",
|
||||
scsi_addr
|
||||
));
|
||||
}
|
||||
|
||||
// Scan scsi host passing in the channel, SCSI id and LUN.
|
||||
// Channel is always 0 because we have only one SCSI controller.
|
||||
let scan_data = &format!("0 {} {}", tokens[0], tokens[1]);
|
||||
|
||||
for entry in fs::read_dir(SYSFS_SCSI_HOST_PATH)? {
|
||||
let host = entry?.file_name();
|
||||
|
||||
let host_str = host.to_str().ok_or_else(|| {
|
||||
anyhow!(
|
||||
"failed to convert directory entry to unicode for file {:?}",
|
||||
host
|
||||
)
|
||||
})?;
|
||||
|
||||
let scan_path = PathBuf::from(&format!("{}/{}/{}", SYSFS_SCSI_HOST_PATH, host_str, "scan"));
|
||||
|
||||
fs::write(scan_path, scan_data)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DeviceInfo {
|
||||
// Device type, "b" for block device and "c" for character device
|
||||
@ -654,19 +586,6 @@ pub fn update_env_pci(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// device.Id should be the SCSI address of the disk in the format "scsiID:lunID"
|
||||
#[instrument]
|
||||
async fn virtio_scsi_device_handler(
|
||||
device: &Device,
|
||||
sandbox: &Arc<Mutex<Sandbox>>,
|
||||
) -> Result<SpecUpdate> {
|
||||
let vm_path = get_scsi_device_name(sandbox, &device.id).await?;
|
||||
|
||||
Ok(DeviceInfo::new(&vm_path, true)
|
||||
.context("New device info")?
|
||||
.into())
|
||||
}
|
||||
|
||||
fn split_vfio_pci_option(opt: &str) -> Option<(&str, &str)> {
|
||||
let mut tokens = opt.split('=');
|
||||
let hostbdf = tokens.next()?;
|
||||
|
98
src/agent/src/device/scsi_device_handler.rs
Normal file
98
src/agent/src/device/scsi_device_handler.rs
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright (c) 2019 Ant Financial
|
||||
// Copyright (c) 2024 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use crate::device::{DeviceContext, DeviceHandler, DeviceInfo, SpecUpdate, BLOCK};
|
||||
use crate::linux_abi::*;
|
||||
use crate::sandbox::Sandbox;
|
||||
use crate::uevent::{wait_for_uevent, Uevent, UeventMatcher};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use protocols::agent::Device;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use tracing::instrument;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ScsiDeviceHandler {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl DeviceHandler for ScsiDeviceHandler {
|
||||
#[instrument]
|
||||
async fn device_handler(&self, device: &Device, ctx: &mut DeviceContext) -> Result<SpecUpdate> {
|
||||
let vm_path = get_scsi_device_name(ctx.sandbox, &device.id).await?;
|
||||
|
||||
Ok(DeviceInfo::new(&vm_path, true)
|
||||
.context("New device info")?
|
||||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
pub async fn get_scsi_device_name(
|
||||
sandbox: &Arc<Mutex<Sandbox>>,
|
||||
scsi_addr: &str,
|
||||
) -> Result<String> {
|
||||
let matcher = ScsiBlockMatcher::new(scsi_addr);
|
||||
|
||||
scan_scsi_bus(scsi_addr)?;
|
||||
let uev = wait_for_uevent(sandbox, matcher).await?;
|
||||
Ok(format!("{}/{}", SYSTEM_DEV_PATH, &uev.devname))
|
||||
}
|
||||
|
||||
// FIXME: This matcher is only correct if the guest has at most one
|
||||
// SCSI host.
|
||||
#[derive(Debug)]
|
||||
pub struct ScsiBlockMatcher {
|
||||
search: String,
|
||||
}
|
||||
|
||||
impl ScsiBlockMatcher {
|
||||
pub fn new(scsi_addr: &str) -> ScsiBlockMatcher {
|
||||
let search = format!(r"/0:0:{}/block/", scsi_addr);
|
||||
|
||||
ScsiBlockMatcher { search }
|
||||
}
|
||||
}
|
||||
|
||||
impl UeventMatcher for ScsiBlockMatcher {
|
||||
fn is_match(&self, uev: &Uevent) -> bool {
|
||||
uev.subsystem == BLOCK && uev.devpath.contains(&self.search) && !uev.devname.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
/// Scan SCSI bus for the given SCSI address(SCSI-Id and LUN)
|
||||
#[instrument]
|
||||
fn scan_scsi_bus(scsi_addr: &str) -> Result<()> {
|
||||
let tokens: Vec<&str> = scsi_addr.split(':').collect();
|
||||
if tokens.len() != 2 {
|
||||
return Err(anyhow!(
|
||||
"Unexpected format for SCSI Address: {}, expect SCSIID:LUA",
|
||||
scsi_addr
|
||||
));
|
||||
}
|
||||
|
||||
// Scan scsi host passing in the channel, SCSI id and LUN.
|
||||
// Channel is always 0 because we have only one SCSI controller.
|
||||
let scan_data = &format!("0 {} {}", tokens[0], tokens[1]);
|
||||
|
||||
for entry in fs::read_dir(SYSFS_SCSI_HOST_PATH)? {
|
||||
let host = entry?.file_name();
|
||||
|
||||
let host_str = host.to_str().ok_or_else(|| {
|
||||
anyhow!(
|
||||
"failed to convert directory entry to unicode for file {:?}",
|
||||
host
|
||||
)
|
||||
})?;
|
||||
|
||||
let scan_path = PathBuf::from(&format!("{}/{}/{}", SYSFS_SCSI_HOST_PATH, host_str, "scan"));
|
||||
|
||||
fs::write(scan_path, scan_data)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue
Block a user