Message ID | 20250211214328.640374-11-kwolf@redhat.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | rust/block: Add minimal block driver bindings | expand |
On 11/2/25 22:43, Kevin Wolf wrote: > This adds a separate block driver for the bochs image format called > 'bochs-rs' so that for the moment both the C implementation and the Rust > implementation can be present in the same build. The intention is to > remove the C implementation eventually and rename this one into 'bochs'. > This can only happen once Rust can be a hard build dependency for QEMU. > > Signed-off-by: Kevin Wolf <kwolf@redhat.com> > --- > rust/block/Cargo.toml | 2 +- > rust/block/src/bochs.rs | 296 +++++++++++++++++++++++++++++++++++++++ > rust/block/src/driver.rs | 5 - > rust/block/src/lib.rs | 1 + > 4 files changed, 298 insertions(+), 6 deletions(-) > create mode 100644 rust/block/src/bochs.rs > diff --git a/rust/block/src/bochs.rs b/rust/block/src/bochs.rs > new file mode 100644 > index 0000000000..388ac5ef03 > --- /dev/null > +++ b/rust/block/src/bochs.rs > @@ -0,0 +1,296 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Block driver for the various disk image formats used by Bochs > + * Currently only for "growing" type in read-only mode > + * > + * Copyright (c) 2005 Alex Beregszaszi > + * Copyright (c) 2024 Red Hat > + * > + * Authors: > + * Alex Beregszaszi > + * Kevin Wolf <kwolf@redhat.com> > + * > + * Permission is hereby granted, free of charge, to any person obtaining a copy > + * of this software and associated documentation files (the "Software"), to deal > + * in the Software without restriction, including without limitation the rights > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell > + * copies of the Software, and to permit persons to whom the Software is > + * furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN > + * THE SOFTWARE. > + */ As an addition, we don't have to add the full license boilerplate IMO...
On Tue, Feb 11, 2025 at 10:43:27PM +0100, Kevin Wolf wrote: > This adds a separate block driver for the bochs image format called > 'bochs-rs' so that for the moment both the C implementation and the Rust > implementation can be present in the same build. The intention is to > remove the C implementation eventually and rename this one into 'bochs'. > This can only happen once Rust can be a hard build dependency for QEMU. > > Signed-off-by: Kevin Wolf <kwolf@redhat.com> > --- > rust/block/Cargo.toml | 2 +- > rust/block/src/bochs.rs | 296 +++++++++++++++++++++++++++++++++++++++ > rust/block/src/driver.rs | 5 - > rust/block/src/lib.rs | 1 + > 4 files changed, 298 insertions(+), 6 deletions(-) > create mode 100644 rust/block/src/bochs.rs > > diff --git a/rust/block/Cargo.toml b/rust/block/Cargo.toml > index 70ee02f429..1c06f3a00c 100644 > --- a/rust/block/Cargo.toml > +++ b/rust/block/Cargo.toml > @@ -3,7 +3,7 @@ name = "block" > version = "0.1.0" > edition = "2021" > authors = ["Kevin Wolf <kwolf@redhat.com>"] > -license = "GPL-2.0-or-later" > +license = "GPL-2.0-or-later AND MIT" > readme = "README.md" > description = "Block backends for QEMU" > repository = "https://gitlab.com/qemu-project/qemu/" > diff --git a/rust/block/src/bochs.rs b/rust/block/src/bochs.rs > new file mode 100644 > index 0000000000..388ac5ef03 > --- /dev/null > +++ b/rust/block/src/bochs.rs > @@ -0,0 +1,296 @@ > +// SPDX-License-Identifier: MIT Why MIT instead of our normal GPL-2.0-or-later. Using Rust conversion to eliminate GPL usage for permissive licenses like MIT is not something I'd like to see us doing. With regards, Daniel
On Wed, Feb 12, 2025 at 09:14:57AM +0000, Daniel P. Berrangé wrote: > On Tue, Feb 11, 2025 at 10:43:27PM +0100, Kevin Wolf wrote: > > This adds a separate block driver for the bochs image format called > > 'bochs-rs' so that for the moment both the C implementation and the Rust > > implementation can be present in the same build. The intention is to > > remove the C implementation eventually and rename this one into 'bochs'. > > This can only happen once Rust can be a hard build dependency for QEMU. > > > > Signed-off-by: Kevin Wolf <kwolf@redhat.com> > > --- > > rust/block/Cargo.toml | 2 +- > > rust/block/src/bochs.rs | 296 +++++++++++++++++++++++++++++++++++++++ > > rust/block/src/driver.rs | 5 - > > rust/block/src/lib.rs | 1 + > > 4 files changed, 298 insertions(+), 6 deletions(-) > > create mode 100644 rust/block/src/bochs.rs > > > > diff --git a/rust/block/Cargo.toml b/rust/block/Cargo.toml > > index 70ee02f429..1c06f3a00c 100644 > > --- a/rust/block/Cargo.toml > > +++ b/rust/block/Cargo.toml > > @@ -3,7 +3,7 @@ name = "block" > > version = "0.1.0" > > edition = "2021" > > authors = ["Kevin Wolf <kwolf@redhat.com>"] > > -license = "GPL-2.0-or-later" > > +license = "GPL-2.0-or-later AND MIT" > > readme = "README.md" > > description = "Block backends for QEMU" > > repository = "https://gitlab.com/qemu-project/qemu/" > > diff --git a/rust/block/src/bochs.rs b/rust/block/src/bochs.rs > > new file mode 100644 > > index 0000000000..388ac5ef03 > > --- /dev/null > > +++ b/rust/block/src/bochs.rs > > @@ -0,0 +1,296 @@ > > +// SPDX-License-Identifier: MIT > > Why MIT instead of our normal GPL-2.0-or-later. > > Using Rust conversion to eliminate GPL usage for permissive licenses > like MIT is not something I'd like to see us doing. My bad. I should have noticed that the original bochs.c was also MIT, so I presume you're considering this Rust impl to be a derived work. With regards, Daniel
Am 12.02.2025 um 10:41 hat Daniel P. Berrangé geschrieben: > On Wed, Feb 12, 2025 at 09:14:57AM +0000, Daniel P. Berrangé wrote: > > On Tue, Feb 11, 2025 at 10:43:27PM +0100, Kevin Wolf wrote: > > > This adds a separate block driver for the bochs image format called > > > 'bochs-rs' so that for the moment both the C implementation and the Rust > > > implementation can be present in the same build. The intention is to > > > remove the C implementation eventually and rename this one into 'bochs'. > > > This can only happen once Rust can be a hard build dependency for QEMU. > > > > > > Signed-off-by: Kevin Wolf <kwolf@redhat.com> > > > --- > > > rust/block/Cargo.toml | 2 +- > > > rust/block/src/bochs.rs | 296 +++++++++++++++++++++++++++++++++++++++ > > > rust/block/src/driver.rs | 5 - > > > rust/block/src/lib.rs | 1 + > > > 4 files changed, 298 insertions(+), 6 deletions(-) > > > create mode 100644 rust/block/src/bochs.rs > > > > > > diff --git a/rust/block/Cargo.toml b/rust/block/Cargo.toml > > > index 70ee02f429..1c06f3a00c 100644 > > > --- a/rust/block/Cargo.toml > > > +++ b/rust/block/Cargo.toml > > > @@ -3,7 +3,7 @@ name = "block" > > > version = "0.1.0" > > > edition = "2021" > > > authors = ["Kevin Wolf <kwolf@redhat.com>"] > > > -license = "GPL-2.0-or-later" > > > +license = "GPL-2.0-or-later AND MIT" > > > readme = "README.md" > > > description = "Block backends for QEMU" > > > repository = "https://gitlab.com/qemu-project/qemu/" > > > diff --git a/rust/block/src/bochs.rs b/rust/block/src/bochs.rs > > > new file mode 100644 > > > index 0000000000..388ac5ef03 > > > --- /dev/null > > > +++ b/rust/block/src/bochs.rs > > > @@ -0,0 +1,296 @@ > > > +// SPDX-License-Identifier: MIT > > > > Why MIT instead of our normal GPL-2.0-or-later. > > > > Using Rust conversion to eliminate GPL usage for permissive licenses > > like MIT is not something I'd like to see us doing. > > My bad. I should have noticed that the original bochs.c was also MIT, > so I presume you're considering this Rust impl to be a derived work. Yes, this is essentially a translation of the existing C bochs driver, which is also why I kept the original copyright notice and the full license text. Kevin
Am 12.02.2025 um 08:45 hat Philippe Mathieu-Daudé geschrieben: > On 11/2/25 22:43, Kevin Wolf wrote: > > This adds a separate block driver for the bochs image format called > > 'bochs-rs' so that for the moment both the C implementation and the Rust > > implementation can be present in the same build. The intention is to > > remove the C implementation eventually and rename this one into 'bochs'. > > This can only happen once Rust can be a hard build dependency for QEMU. > > > > Signed-off-by: Kevin Wolf <kwolf@redhat.com> > > --- > > rust/block/Cargo.toml | 2 +- > > rust/block/src/bochs.rs | 296 +++++++++++++++++++++++++++++++++++++++ > > rust/block/src/driver.rs | 5 - > > rust/block/src/lib.rs | 1 + > > 4 files changed, 298 insertions(+), 6 deletions(-) > > create mode 100644 rust/block/src/bochs.rs > > > > diff --git a/rust/block/src/bochs.rs b/rust/block/src/bochs.rs > > new file mode 100644 > > index 0000000000..388ac5ef03 > > --- /dev/null > > +++ b/rust/block/src/bochs.rs > > @@ -0,0 +1,296 @@ > > +// SPDX-License-Identifier: MIT > > +/* > > + * Block driver for the various disk image formats used by Bochs > > + * Currently only for "growing" type in read-only mode > > + * > > + * Copyright (c) 2005 Alex Beregszaszi > > + * Copyright (c) 2024 Red Hat > > + * > > + * Authors: > > + * Alex Beregszaszi > > + * Kevin Wolf <kwolf@redhat.com> > > + * > > + * Permission is hereby granted, free of charge, to any person obtaining a copy > > + * of this software and associated documentation files (the "Software"), to deal > > + * in the Software without restriction, including without limitation the rights > > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell > > + * copies of the Software, and to permit persons to whom the Software is > > + * furnished to do so, subject to the following conditions: > > + * > > + * The above copyright notice and this permission notice shall be included in > > + * all copies or substantial portions of the Software. > > + * > > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, > > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN > > + * THE SOFTWARE. > > + */ > > As an addition, we don't have to add the full license boilerplate IMO... IANAL, but the license says "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.", so keeping it feels like the safe option. Kevin
On Wed, Feb 12, 2025 at 01:58:15PM +0100, Kevin Wolf wrote: > Am 12.02.2025 um 10:41 hat Daniel P. Berrangé geschrieben: > > On Wed, Feb 12, 2025 at 09:14:57AM +0000, Daniel P. Berrangé wrote: > > > On Tue, Feb 11, 2025 at 10:43:27PM +0100, Kevin Wolf wrote: > > > > This adds a separate block driver for the bochs image format called > > > > 'bochs-rs' so that for the moment both the C implementation and the Rust > > > > implementation can be present in the same build. The intention is to > > > > remove the C implementation eventually and rename this one into 'bochs'. > > > > This can only happen once Rust can be a hard build dependency for QEMU. > > > > > > > > Signed-off-by: Kevin Wolf <kwolf@redhat.com> > > > > --- > > > > rust/block/Cargo.toml | 2 +- > > > > rust/block/src/bochs.rs | 296 +++++++++++++++++++++++++++++++++++++++ > > > > rust/block/src/driver.rs | 5 - > > > > rust/block/src/lib.rs | 1 + > > > > 4 files changed, 298 insertions(+), 6 deletions(-) > > > > create mode 100644 rust/block/src/bochs.rs > > > > > > > > diff --git a/rust/block/Cargo.toml b/rust/block/Cargo.toml > > > > index 70ee02f429..1c06f3a00c 100644 > > > > --- a/rust/block/Cargo.toml > > > > +++ b/rust/block/Cargo.toml > > > > @@ -3,7 +3,7 @@ name = "block" > > > > version = "0.1.0" > > > > edition = "2021" > > > > authors = ["Kevin Wolf <kwolf@redhat.com>"] > > > > -license = "GPL-2.0-or-later" > > > > +license = "GPL-2.0-or-later AND MIT" > > > > readme = "README.md" > > > > description = "Block backends for QEMU" > > > > repository = "https://gitlab.com/qemu-project/qemu/" > > > > diff --git a/rust/block/src/bochs.rs b/rust/block/src/bochs.rs > > > > new file mode 100644 > > > > index 0000000000..388ac5ef03 > > > > --- /dev/null > > > > +++ b/rust/block/src/bochs.rs > > > > @@ -0,0 +1,296 @@ > > > > +// SPDX-License-Identifier: MIT > > > > > > Why MIT instead of our normal GPL-2.0-or-later. > > > > > > Using Rust conversion to eliminate GPL usage for permissive licenses > > > like MIT is not something I'd like to see us doing. > > > > My bad. I should have noticed that the original bochs.c was also MIT, > > so I presume you're considering this Rust impl to be a derived work. > > Yes, this is essentially a translation of the existing C bochs driver, > which is also why I kept the original copyright notice and the full > license text. Agreed, I think including both is the right thing in this particular case, especially given that we don't include the MIT text at all in a LICENSE file at the top level. With regards, Daniel
On 12/2/25 13:59, Kevin Wolf wrote: > Am 12.02.2025 um 08:45 hat Philippe Mathieu-Daudé geschrieben: >> On 11/2/25 22:43, Kevin Wolf wrote: >>> This adds a separate block driver for the bochs image format called >>> 'bochs-rs' so that for the moment both the C implementation and the Rust >>> implementation can be present in the same build. The intention is to >>> remove the C implementation eventually and rename this one into 'bochs'. >>> This can only happen once Rust can be a hard build dependency for QEMU. >>> >>> Signed-off-by: Kevin Wolf <kwolf@redhat.com> >>> --- >>> rust/block/Cargo.toml | 2 +- >>> rust/block/src/bochs.rs | 296 +++++++++++++++++++++++++++++++++++++++ >>> rust/block/src/driver.rs | 5 - >>> rust/block/src/lib.rs | 1 + >>> 4 files changed, 298 insertions(+), 6 deletions(-) >>> create mode 100644 rust/block/src/bochs.rs >> >> >>> diff --git a/rust/block/src/bochs.rs b/rust/block/src/bochs.rs >>> new file mode 100644 >>> index 0000000000..388ac5ef03 >>> --- /dev/null >>> +++ b/rust/block/src/bochs.rs >>> @@ -0,0 +1,296 @@ >>> +// SPDX-License-Identifier: MIT >>> +/* >>> + * Block driver for the various disk image formats used by Bochs >>> + * Currently only for "growing" type in read-only mode >>> + * >>> + * Copyright (c) 2005 Alex Beregszaszi >>> + * Copyright (c) 2024 Red Hat >>> + * >>> + * Authors: >>> + * Alex Beregszaszi >>> + * Kevin Wolf <kwolf@redhat.com> >>> + * >>> + * Permission is hereby granted, free of charge, to any person obtaining a copy >>> + * of this software and associated documentation files (the "Software"), to deal >>> + * in the Software without restriction, including without limitation the rights >>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell >>> + * copies of the Software, and to permit persons to whom the Software is >>> + * furnished to do so, subject to the following conditions: >>> + * >>> + * The above copyright notice and this permission notice shall be included in >>> + * all copies or substantial portions of the Software. >>> + * >>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR >>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, >>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL >>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER >>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, >>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN >>> + * THE SOFTWARE. >>> + */ >> >> As an addition, we don't have to add the full license boilerplate IMO... > > IANAL, but the license says "The above copyright notice and this > permission notice shall be included in all copies or substantial > portions of the Software.", so keeping it feels like the safe option. OK (and as Daniel clarified, you consider your work a derivative).
diff --git a/rust/block/Cargo.toml b/rust/block/Cargo.toml index 70ee02f429..1c06f3a00c 100644 --- a/rust/block/Cargo.toml +++ b/rust/block/Cargo.toml @@ -3,7 +3,7 @@ name = "block" version = "0.1.0" edition = "2021" authors = ["Kevin Wolf <kwolf@redhat.com>"] -license = "GPL-2.0-or-later" +license = "GPL-2.0-or-later AND MIT" readme = "README.md" description = "Block backends for QEMU" repository = "https://gitlab.com/qemu-project/qemu/" diff --git a/rust/block/src/bochs.rs b/rust/block/src/bochs.rs new file mode 100644 index 0000000000..388ac5ef03 --- /dev/null +++ b/rust/block/src/bochs.rs @@ -0,0 +1,296 @@ +// SPDX-License-Identifier: MIT +/* + * Block driver for the various disk image formats used by Bochs + * Currently only for "growing" type in read-only mode + * + * Copyright (c) 2005 Alex Beregszaszi + * Copyright (c) 2024 Red Hat + * + * Authors: + * Alex Beregszaszi + * Kevin Wolf <kwolf@redhat.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +use crate::driver::{block_driver, BdrvChild, BlockDriver, Mapping, MappingTarget, Request}; +use crate::SizedIoBuffer; +use qemu_api::bindings; +use qemu_api::futures::qemu_run_future; +use std::cmp::min; +use std::io::{self, Error, ErrorKind}; +use std::mem::MaybeUninit; +use std::ptr; + +const BDRV_SECTOR_SIZE: u64 = 512; + +const HEADER_MAGIC: [u8; 32] = *b"Bochs Virtual HD Image\0\0\0\0\0\0\0\0\0\0"; +const HEADER_VERSION: u32 = 0x00020000; +const HEADER_V1: u32 = 0x00010000; +const HEADER_SIZE: usize = 512; + +const HEADER_TYPE_REDOLOG: [u8; 16] = *b"Redolog\0\0\0\0\0\0\0\0\0"; +const HEADER_SUBTYPE_GROWING: [u8; 16] = *b"Growing\0\0\0\0\0\0\0\0\0"; + +// TODO Use u64.div_ceil() when MSRV is updated to at least 1.73.0 +fn div_ceil(a: u64, b: u64) -> u64 { + (a + b - 1) / b +} + +// TODO Use little endian enforcing type for integers + +#[repr(C, packed)] +struct BochsHeader { + pub magic: [u8; 32], + pub imgtype: [u8; 16], + pub subtype: [u8; 16], + pub version: u32, + pub header_size: u32, + pub catalog_entries: u32, + pub bitmap_size: u32, + pub extent_size: u32, + pub extra: BochsHeaderExtra, +} +unsafe impl SizedIoBuffer for BochsHeader {} + +#[repr(C, packed)] +union BochsHeaderExtra { + v2: BochsHeaderExtraRedolog, + v1: BochsHeaderExtraRedologV1, + padding: [u8; HEADER_SIZE - 84], +} + +#[repr(C, packed)] +#[derive(Clone, Copy)] +struct BochsHeaderExtraRedolog { + pub timestamp: u32, + pub disk_size: u64, +} + +#[repr(C, packed)] +#[derive(Clone, Copy)] +struct BochsHeaderExtraRedologV1 { + pub disk_size: u64, +} + +pub struct BochsImage { + file: BdrvChild, + size: u64, + data_offset: u64, + bitmap_blocks: u64, + extent_size: u64, + extent_blocks: u64, + catalog_bitmap: Vec<u32>, // TODO Rename +} + +impl BochsImage { + pub async fn new(file: BdrvChild) -> io::Result<Self> { + let header = file + .read_uninit(0, MaybeUninit::<BochsHeader>::uninit()) + .await?; + + if header.magic != HEADER_MAGIC + || header.imgtype != HEADER_TYPE_REDOLOG + || header.subtype != HEADER_SUBTYPE_GROWING + { + return Err(Error::new( + ErrorKind::InvalidInput, + "Image not in Bochs format", + )); + } + + let size = match u32::from_le(header.version) { + HEADER_VERSION => unsafe { header.extra.v2.disk_size.to_le() }, + HEADER_V1 => unsafe { header.extra.v1.disk_size.to_le() }, + _ => return Err(Error::new(ErrorKind::InvalidInput, "Version not supported")), + }; + + let header_size: u64 = header.header_size.to_le().into(); + let extent_size: u64 = header.extent_size.to_le().into(); + + if extent_size < BDRV_SECTOR_SIZE { + // bximage actually never creates extents smaller than 4k + return Err(Error::new( + ErrorKind::InvalidInput, + "Extent size must be at least 512", + )); + } else if !extent_size.is_power_of_two() { + return Err(Error::new( + ErrorKind::InvalidInput, + format!("Extent size {extent_size} is not a power of two"), + )); + } else if extent_size > 0x800000 { + return Err(Error::new( + ErrorKind::InvalidInput, + format!("Extent size {extent_size} is too large"), + )); + } + + // Limit to 1M entries to avoid unbounded allocation. This is what is + // needed for the largest image that bximage can create (~8 TB). + let catalog_entries: usize = header + .catalog_entries + .to_le() + .try_into() + .map_err(|e| Error::new(ErrorKind::InvalidInput, e))?; + if catalog_entries > 0x100000 { + return Err(Error::new(ErrorKind::Other, "Catalog size is too large")); + } else if (catalog_entries as u64) < div_ceil(size, extent_size) { + return Err(Error::new( + ErrorKind::InvalidInput, + "Catalog size is too small for this disk size", + )); + } + + // FIXME This was g_try_malloc() in C + let mut catalog_bitmap = vec![0u32; catalog_entries]; + file.read(header_size, catalog_bitmap.as_mut_slice()) + .await?; + + for entry in &mut catalog_bitmap { + *entry = entry.to_le(); + } + + let data_offset = header_size + (catalog_entries as u64 * 4); + let bitmap_blocks = (1 + (header.bitmap_size.to_le() - 1) / 512).into(); + let extent_blocks = 1 + (extent_size - 1) / 512; + + Ok(Self { + file, + size, + data_offset, + bitmap_blocks, + extent_size, + extent_blocks, + catalog_bitmap, + }) + } +} + +impl BlockDriver for BochsImage { + type Options = bindings::BlockdevOptionsGenericFormat; + + unsafe fn parse_options( + v: &mut bindings::Visitor, + opts: &mut *mut Self::Options, + errp: *mut *mut bindings::Error, + ) { + unsafe { + bindings::visit_type_BlockdevOptionsGenericFormat(v, ptr::null(), opts as *mut _, errp); + } + } + + unsafe fn free_options(opts: *mut Self::Options) { + unsafe { + bindings::qapi_free_BlockdevOptionsGenericFormat(opts); + } + } + + unsafe fn open( + bs: *mut bindings::BlockDriverState, + opts: &Self::Options, + errp: *mut *mut bindings::Error, + ) -> std::os::raw::c_int { + let file_child; + unsafe { + /* No write support yet */ + bindings::bdrv_graph_rdlock_main_loop(); + let ret = bindings::bdrv_apply_auto_read_only(bs, ptr::null(), errp); + bindings::bdrv_graph_rdunlock_main_loop(); + if ret < 0 { + return ret; + } + + file_child = match BdrvChild::new(bs, opts.file, errp) { + Some(c) => c, + None => return -(bindings::EINVAL as std::os::raw::c_int), + }; + } + + qemu_run_future(async { + match BochsImage::new(file_child).await { + Ok(bdrv) => unsafe { + (*bs).total_sectors = + div_ceil(bdrv.size(), BDRV_SECTOR_SIZE).try_into().unwrap(); + let state = (*bs).opaque as *mut BochsImage; + *state = bdrv; + 0 + }, + // FIXME This is not a good default error code + Err(e) => e.raw_os_error().unwrap_or(-1), + } + }) + } + + fn size(&self) -> u64 { + self.size + } + + async fn map(&self, req: &Request) -> io::Result<Mapping> { + let (offset, len) = match *req { + Request::Read { offset, len } => (offset, len), + }; + + let extent_index: usize = (offset / self.extent_size).try_into().unwrap(); + let extent_offset = (offset % self.extent_size) / 512; + + if self.catalog_bitmap[extent_index] == 0xffffffff { + return Ok(Mapping { + offset: (extent_index as u64) * self.extent_size, + len: self.extent_size, + target: MappingTarget::Unmapped, + }); + } + + let bitmap_offset = self.data_offset + + (512 + * (self.catalog_bitmap[extent_index] as u64) + * (self.extent_blocks + self.bitmap_blocks)); + + // Read in bitmap for current extent + // TODO This should be cached + let mut bitmap_entry = 0x8; + self.file + .read(bitmap_offset + (extent_offset / 8), &mut bitmap_entry) + .await?; + + // We checked only a single sector + let offset = offset & !511; + let len = min(len, 512); + + if (bitmap_entry >> (extent_offset % 8)) & 1 == 0 { + return Ok(Mapping { + offset, + len, + target: MappingTarget::Unmapped, + }); + } + + Ok(Mapping { + offset, + len, + target: MappingTarget::Data { + node: (), + offset: bitmap_offset + (512 * (self.bitmap_blocks + extent_offset)), + }, + }) + } +} + +block_driver!("bochs-rs", BochsImage); diff --git a/rust/block/src/driver.rs b/rust/block/src/driver.rs index 2849ef6949..740e9266aa 100644 --- a/rust/block/src/driver.rs +++ b/rust/block/src/driver.rs @@ -2,11 +2,6 @@ // Author(s): Kevin Wolf <kwolf@redhat.com> // SPDX-License-Identifier: GPL-2.0-or-later -// All of this is unused until the first block driver is added -#![allow(dead_code)] -#![allow(unused_macros)] -#![allow(unused_imports)] - use crate::{IoBuffer, SizedIoBuffer}; use qemu_api::bindings; use qemu_api::futures::qemu_co_run_future; diff --git a/rust/block/src/lib.rs b/rust/block/src/lib.rs index 54ebd480ec..ff528609bc 100644 --- a/rust/block/src/lib.rs +++ b/rust/block/src/lib.rs @@ -1,3 +1,4 @@ +mod bochs; mod driver; mod iobuffer;
This adds a separate block driver for the bochs image format called 'bochs-rs' so that for the moment both the C implementation and the Rust implementation can be present in the same build. The intention is to remove the C implementation eventually and rename this one into 'bochs'. This can only happen once Rust can be a hard build dependency for QEMU. Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- rust/block/Cargo.toml | 2 +- rust/block/src/bochs.rs | 296 +++++++++++++++++++++++++++++++++++++++ rust/block/src/driver.rs | 5 - rust/block/src/lib.rs | 1 + 4 files changed, 298 insertions(+), 6 deletions(-) create mode 100644 rust/block/src/bochs.rs