From fd8ded9d787a67843fd5c3d46c03f4e1c6afa042 Mon Sep 17 00:00:00 2001 From: Vincent Thomas Date: Thu, 9 Apr 2026 14:45:12 +0000 Subject: [PATCH] block: Fix resize for block device backends Block devices (LVM volumes, loop devices, RBD, etc.) cannot be resized via ftruncate - they are resized externally. When vm.resize-disk is called for a block device backend, verify the device size matches the requested size instead of attempting ftruncate. This enables the resize-disk API to work with block device backends by validating the externally-resized device matches the expected size. Signed-off-by: Vincent Thomas --- block/src/raw_async.rs | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/block/src/raw_async.rs b/block/src/raw_async.rs index 90332aa4b..7fa3208f4 100644 --- a/block/src/raw_async.rs +++ b/block/src/raw_async.rs @@ -3,7 +3,8 @@ // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause use std::fs::File; -use std::io::Error; +use std::io::{self, Error}; +use std::os::unix::fs::FileTypeExt; use std::os::unix::io::{AsRawFd, RawFd}; use io_uring::{IoUring, opcode, types}; @@ -68,9 +69,30 @@ impl disk_file::SparseCapable for RawFileDisk { impl disk_file::Resizable for RawFileDisk { fn resize(&mut self, size: u64) -> BlockResult<()> { - self.file - .set_len(size) - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::ResizeError(e))) + let fd_metadata = self + .file + .metadata() + .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::ResizeError(e)))?; + + if fd_metadata.file_type().is_block_device() { + // Block devices cannot be resized via ftruncate - they are resized + // externally (LVM, losetup -c, etc.). Verify the size matches. + let (actual_size, _) = query_device_size(&self.file) + .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::ResizeError(e)))?; + if actual_size != size { + return Err(BlockError::new( + BlockErrorKind::Io, + DiskFileError::ResizeError(io::Error::other(format!( + "Block device size {actual_size} does not match requested size {size}" + ))), + )); + } + Ok(()) + } else { + self.file + .set_len(size) + .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::ResizeError(e))) + } } }