This commit is contained in:
Alex Lyn 2025-08-12 01:49:39 +08:00 committed by GitHub
commit 691ecaade3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -541,9 +541,67 @@ impl Qmp {
is_readonly: bool,
no_drop: bool,
) -> Result<(Option<PciPath>, Option<String>)> {
// Helper closure to decode a flattened u16 SCSI index into an (ID, LUN) pair.
let get_scsi_id_lun = |index_u16: u16| -> Result<(u8, u8)> {
// Uses bitwise operations for efficient and clear conversion.
let scsi_id = (index_u16 >> 8) as u8; // Equivalent to index_u16 / 256
let lun = (index_u16 & 0xFF) as u8; // Equivalent to index_u16 % 256
Ok((scsi_id, lun))
};
// `blockdev-add`
let node_name = format!("drive-{index}");
// Pre-check block drive and block device with qapi
{
let node_exists = self
.qmp
.execute(&qapi_qmp::query_named_block_nodes { flat: Some(true) })?
.into_iter()
.any(|d| d.node_name == Some(node_name.clone()));
let device_exists = self
.qmp
.execute(&qapi_qmp::query_block {})?
.into_iter()
.any(|d| match d.inserted {
Some(node) => node.node_name == Some(node_name.clone()),
None => false,
});
if node_exists && device_exists {
if block_driver == VIRTIO_SCSI {
// Safely convert the u64 index to u16, ensuring it does not exceed `u16::MAX` (65535).
let (scsi_id, lun) = get_scsi_id_lun(u16::try_from(index)?)?;
let scsi_addr = format!("{}:{}", scsi_id, lun);
return Ok((None, Some(scsi_addr)));
} else {
let pci_path = self
.get_device_by_qdev_id(&node_name)
.context("get device by qdev_id failed")?;
info!(
sl!(),
"hotplug block device return pci path: {:?}", &pci_path
);
return Ok((Some(pci_path), None));
}
}
if node_exists && !device_exists {
warn!(
sl!(),
"Found orphaned backend node {:?}, do cleanup before retry.", &node_name
);
self.qmp
.execute(&qapi_qmp::blockdev_del {
node_name: node_name.clone(),
})
.ok();
}
}
let create_base_options = || qapi_qmp::BlockdevOptionsBase {
auto_read_only: None,
cache: if is_direct.is_none() {
@ -618,15 +676,6 @@ impl Qmp {
blkdev_add_args.insert("drive".to_owned(), node_name.clone().into());
if block_driver == VIRTIO_SCSI {
// Helper closure to decode a flattened u16 SCSI index into an (ID, LUN) pair.
let get_scsi_id_lun = |index_u16: u16| -> Result<(u8, u8)> {
// Uses bitwise operations for efficient and clear conversion.
let scsi_id = (index_u16 >> 8) as u8; // Equivalent to index_u16 / 256
let lun = (index_u16 & 0xFF) as u8; // Equivalent to index_u16 % 256
Ok((scsi_id, lun))
};
// Safely convert the u64 index to u16, ensuring it does not exceed `u16::MAX` (65535).
let (scsi_id, lun) = get_scsi_id_lun(u16::try_from(index)?)?;
let scsi_addr = format!("{}:{}", scsi_id, lun);
@ -634,6 +683,7 @@ impl Qmp {
// add SCSI frontend device
blkdev_add_args.insert("scsi-id".to_string(), scsi_id.into());
blkdev_add_args.insert("lun".to_string(), lun.into());
blkdev_add_args.insert("share-rw".to_string(), true.into());
self.qmp
.execute(&qmp::device_add {
@ -654,6 +704,7 @@ impl Qmp {
} else {
let (bus, slot) = self.find_free_slot()?;
blkdev_add_args.insert("addr".to_owned(), format!("{:02}", slot).into());
blkdev_add_args.insert("share-rw".to_string(), true.into());
self.qmp
.execute(&qmp::device_add {