Skip to content

feat(virtio-block): Add support for VIRTIO_BLK_T_DISCARD request type#5168

Closed
LDagnachew wants to merge 5 commits into
firecracker-microvm:mainfrom
LDagnachew:discard_support
Closed

feat(virtio-block): Add support for VIRTIO_BLK_T_DISCARD request type#5168
LDagnachew wants to merge 5 commits into
firecracker-microvm:mainfrom
LDagnachew:discard_support

Conversation

@LDagnachew

Copy link
Copy Markdown
Contributor

(Reupload) Opening this as a Draft PR, as I am still working on fully integrating unmap/fstrim/discard. Right now I'm currently working on the functionality.

Changes

Expose discard feature bit

  • Added VIRTIO_BLK_F_DISCARD to the device’s advertised avail_features so guests can negotiate discard support

Extend RequestType enum

  • Introduced a new Discard variant and mapped VIRTIO_BLK_T_DISCARDRequestType::Discard in the request conversion

Update request parsing (Request::parse) in request.rs

  • Allowed Discard (alongside Flush) to skip the data descriptor
  • Enforced sector‑aligned length and bounds checks for Discard requests

Implement handle_discard backend

  • Created handle_discard(offset, len) to call fallocate() on the host file descriptor

Reason

Attempting to resolve Issue #2708

Next Steps

  • Checking for VIRTIO_BLK_F_DISCARD support (need suggestions for this, not sure of an efficient way to check for Discard Support within a given VirtIO block).
  • Writing Unit & Integration Tests.

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 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.

- Implemented parsing and validation for `VIRTIO_BLK_T_DISCARD` requests.
- Added `SyncIoError::Discard` to represent errors specific to discard operations.
- Updated `Request::process` to handle discard requests using `handle_discard` in `FileEngine`.
- Integrated discard metrics (`discard_count` and `invalid_reqs_count`) for successful and invalid discard operations.

Signed-off-by: Leul Dagnachew <leulmdagnachew@gmail.com>
Signed-off-by: LDagnachew <leulmdagnachew@gmail.com>
@LDagnachew

LDagnachew commented Apr 24, 2025

Copy link
Copy Markdown
Contributor Author

As far as checking whether the system even supports fstrim/unmap/discard, a trivial way would be to simply check whether fallocate() returns an error, however not entirely sure if there's a better way to do this. @ShadowCurse

@LDagnachew
LDagnachew marked this pull request as ready for review April 24, 2025 21:41

@ShadowCurse ShadowCurse left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Regarding the check if fallocate is supported: for now let's assume it is supported.
Doing a test fallocate call might not a bad idea. Alternatively, we can always make this an optional feature, so users will need to configure it manually (line read_only) if they know their fs supports it.

Also found a patch series for qemu with this feature: https://lore.kernel.org/all/20190208134950.187665-5-sgarzare@redhat.com/ might be useful for a reference.

Comment on lines +38 to +44
bitflags::bitflags! {
pub struct FallocateFlags: c_int {
const FALLOC_FL_KEEP_SIZE = 0x01;
const FALLOC_FL_PUNCH_HOLE = 0x02;
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

libc crate already has these constants

Comment on lines +186 to +197
let fd = self.file().as_raw_fd();
let result = Self::fallocate(
fd,
FallocateFlags::FALLOC_FL_PUNCH_HOLE | FallocateFlags::FALLOC_FL_KEEP_SIZE,
offset as i64,
len as i64,
);
if let Err(e) = result {
eprintln!("Discard failed: {}", e);
return Err(std::io::Error::last_os_error());
}
Ok(())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since we have 2 backends for block device, each need to implement it's own version of discard. For sync version this impl is basically what it needs to be, for io_uring backend there is IORING_OP_FALLOCATE op.

Comment on lines +246 to +250
pub struct DiscardSegment {
sector: u64,
num_sectors: u32,
flags: u32,
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

flags is not just a 32 bit integer, it is a struct with 2 u32 inside. Also it needs to have a C struct layout attribute.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sorry for delay, was busy with other things but- I thought that flags was a single 32-bit integer, where 1 bit was for unmap, and the other 31 bits are reserved for struct alignment I'm assuming.

For reference, I'm using VirtI/O 1.2 Documentation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Alright, you are right, I totally missed the bitfield syntax in C definition.
Still you need to add the [repr(C)] to the struct definition.

Comment thread src/vmm/src/devices/virtio/block/virtio/request.rs Outdated
Comment thread src/vmm/src/devices/virtio/block/virtio/request.rs Outdated
Comment thread src/vmm/src/devices/virtio/block/virtio/request.rs
Comment on lines +465 to +474
match res {
Ok(()) => Ok(block_io::FileEngineOk::Executed(block_io::RequestOk {
req: pending,
count: 0,
})),
Err(e) => Err(block_io::RequestError {
req: pending,
error: BlockIoError::Sync(SyncIoError::Discard(e)),
}),
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice hallucinations. The file_engine.handle_discard should return same result type as file_engine.read/file_engine.write and so on. And then it will be handled by the code bellow.

@LDagnachew LDagnachew Apr 28, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Gotcha, that checks out, I'll make that change.

LDagnachew added 3 commits May 1, 2025 12:04
- Added Test for ext4fs support
- Added Test for ensuring fstrim executes without error.

Signed-off-by: LDagnachew <leulmdagnachew@gmail.com>
- Utilized `IORING_OP_FALLOCATE` for Fallocate Implementation in `AsyncFileEngine`
- Resolved invalid return types for `discard`

Signed-off-by: LDagnachew <leulmdagnachew@gmail.com>
@ShadowCurse ShadowCurse added the Status: Awaiting author Indicates that an issue or pull request requires author action label Jun 12, 2025
@ShadowCurse

Copy link
Copy Markdown
Contributor

Hi @LDagnachew, are you still interested in finishing this?

@LDagnachew

Copy link
Copy Markdown
Contributor Author

Hi @ShadowCurse,

Sorry I completely forgot to wrap this up. I'm currently on vacation, though I will be back in a couple of days, so I should be able to finish this up by then.

@ShadowCurse

Copy link
Copy Markdown
Contributor

Hi @LDagnachew, since there is no activity in the PR I am closing it. Feel free to reopen if you want to finish this.

@ShadowCurse ShadowCurse closed this Aug 4, 2025
@LDagnachew

LDagnachew commented Nov 10, 2025

Copy link
Copy Markdown
Contributor Author

Hi @ShadowCurse, sorry for the hiatus, I came back from a lengthy internship. I would like to continue! My commit from a couple months back here handles ASYNC/SYNC Fallocate support on both file engines, though this code is outdated so I'll take a look at it and update the branch.

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.

2 participants