Skip to content

feat(virtio-block): Add fallocate support#5511

Open
LDagnachew wants to merge 4 commits intofirecracker-microvm:mainfrom
LDagnachew:unmap_fstrim_discard
Open

feat(virtio-block): Add fallocate support#5511
LDagnachew wants to merge 4 commits intofirecracker-microvm:mainfrom
LDagnachew:unmap_fstrim_discard

Conversation

@LDagnachew
Copy link
Contributor

@LDagnachew LDagnachew commented Nov 11, 2025

Changes

Reason

Attempting to resolve Issue #2708.

License Acceptance

By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache 2.0 license. For more information on following Developer
Certificate of Origin and signing off your commits, please check
CONTRIBUTING.md.

PR Checklist

  • I have read and understand CONTRIBUTING.md.
  • I have run tools/devtool checkbuild --all to verify that the PR passes
    build checks on all supported architectures.
  • I have run tools/devtool checkstyle to verify that the PR passes the
    automated style checks.
  • I have described what is done in these changes, why they are needed, and
    how they are solving the problem in a clear and encompassing way.
  • I have updated any relevant documentation (both in code and in the docs)
    in the PR.
  • I have mentioned all user-facing changes in CHANGELOG.md.
  • If a specific issue led to this PR, this PR closes the issue.
  • When making API changes, I have followed the
    Runbook for Firecracker API changes.
  • I have tested all new and changed functionalities in unit tests and/or
    integration tests.
  • I have linked an issue to every new TODO.

  • This functionality cannot be added in rust-vmm.

@LDagnachew
Copy link
Contributor Author

also disclaimer this still needs to be style checked, but this should be the near final implementation, other than writing a more rigorous testing suite.

@LDagnachew LDagnachew force-pushed the unmap_fstrim_discard branch 2 times, most recently from 41e7941 to abda29f Compare November 15, 2025 02:37
@LDagnachew LDagnachew marked this pull request as ready for review November 15, 2025 02:39
@LDagnachew LDagnachew changed the title feat(virtio-block): Add fallocate support (draft) feat(virtio-block): Add fallocate support Nov 15, 2025
@LDagnachew
Copy link
Contributor Author

@bchalios @ShadowCurse whenever you have time do y'all mind taking a look? I really want to bring this issue to the finish line, thanks!

Copy link
Contributor

@ShadowCurse ShadowCurse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for late review. Did a first pass and left some comments. One thing we need to think about is the fact that fallocate is not supported on all filesystems, so either we need to make this feature optional for the device, or make failures to fallocate to just print error logs and not return actual errors.

Comment on lines +366 to +368
if end_sector > num_disk_sectors {
return Err(VirtioBlockError::BeyondDiskSize);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of returnning an error, you can just ignore invalid segment and print an error log.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, this was incorrect suggestion, we better to abort the whole request if we find invalid segment, so Err(..) this should be.

@LDagnachew
Copy link
Contributor Author

Hi, sorry for the late response, but I will get this handled within the next day or two and mark for another review. Thanks!

@JamesC1305 JamesC1305 added the Status: Awaiting author Indicates that an issue or pull request requires author action label Dec 10, 2025
@LDagnachew LDagnachew force-pushed the unmap_fstrim_discard branch 2 times, most recently from 8fd863f to dacdcff Compare January 6, 2026 21:07
- Updated unmap/fstrim/discard deprecated logic.
Signed-off-by: LDagnachew <leulmdagnachew@gmail.com>
- fallocate unblocked in seccomp, thus allowing discard requests.
Signed-off-by: LDagnachew <leulmdagnachew@gmail.com>
Update Python files to comply with Black and pylint checks. These
changes are formatting-only and do not alter functionality.

Signed-off-by: LDagnachew <leulmdagnachew@gmail.com>
- added safety comments + minor error handling.
Signed-off-by: LDagnachew <leulmdagnachew@gmail.com>
@LDagnachew LDagnachew force-pushed the unmap_fstrim_discard branch from f23cb9b to dd0a7e1 Compare January 7, 2026 02:19
@LDagnachew LDagnachew requested a review from ShadowCurse January 7, 2026 02:20
Copy link
Contributor

@ShadowCurse ShadowCurse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On top of everything, we need to figure out the way to test if we can even call fallocate on the file since some filesystems do not support this operation. Most likely we should do a dummy fallocate call that does not actually change the file as a check.
Also this feature should be user configurable, just like others, so the block API should have a new field to enable this feature.

@@ -27,7 +27,7 @@ use crate::devices::virtio::block::CacheType;
use crate::devices::virtio::block::virtio::metrics::{BlockDeviceMetrics, BlockMetricsPerDevice};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commit: style: fix Python formatting and lint issues
everything here belongs to the first implementation commit. Please don't do separate "running a formatter" type of commits

@@ -110,6 +110,7 @@ impl AsyncFileEngine {
Ok(())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commit: style: replace errors for fallocate/discard with error logs
same here, merge this into main implementation commit.

opcode: OpCode::Fallocate,
addr: None,
len: Some(len),
flags: 0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

libc::FALLOC_FL_PUNCH_HOLE | libc::FALLOC_FL_KEEP_SIZE should be in flags

if req.r#type != RequestType::Flush {
return Err(VirtioBlockError::DescriptorChainTooShort);
}
data_desc = desc;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems wrong

Comment on lines +379 to +384
status_desc = data_desc
.next_descriptor()
.ok_or(VirtioBlockError::DescriptorChainTooShort)?;
if !status_desc.is_write_only() {
return Err(VirtioBlockError::UnexpectedReadOnlyDescriptor);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

status_desc is already obtained from the data_desc above and there is a check for status_desc just bellow.

Comment on lines +91 to +96
let off_i64 = i64::try_from(offset).map_err(|_| {
SyncIoError::Discard(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"offset overflow",
))
})?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there is a way to remove this. The syscall wants, i64, but in reality it is just 64 bit value which will be checked by the kernel in any case.

Comment on lines +36 to +44
vm.ssh.run("mount -o remount,discard /")
exit_code, stdout, _ = vm.ssh.run("mount | grep /dev/vda")
assert (
exit_code == 0
), f"Failed to remount root filesystem with discard option: {stdout}"

exit_code, stdout, _ = vm.ssh.run("fstrim -v /")
assert exit_code == 0, f"fstrim -v failed: {stdout}"
assert "trimmed" in stdout, f"Unexpected fstrim output: {stdout}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • You test wrong block device (should be vdb for the test_disk you added).
  • There is no check for the actual discard capability after mount | grep ...command.
  • What should happen after fstrim is called? How do you test that the discrard was correctly executed? Maybe you can check FC metrics and check the underlying test_disk with stat or smth to see if the hole was successfully created.

exit_code, stdout, _ = vm.ssh.run("fstrim -v /")
assert exit_code == 0, f"fstrim -v failed: {stdout}"
assert "trimmed" in stdout, f"Unexpected fstrim output: {stdout}"
vm.kill()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to explicitly kill the vm. It will be killed automatically at the end of the test

import host_tools.drive as drive_tools


def test_discard_support(uvm_plain_rw):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because discard is implemented in both sync and async engines, you need to parametrize the test.

Comment on lines +366 to +368
if end_sector > num_disk_sectors {
return Err(VirtioBlockError::BeyondDiskSize);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, this was incorrect suggestion, we better to abort the whole request if we find invalid segment, so Err(..) this should be.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Status: Awaiting author Indicates that an issue or pull request requires author action

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants