Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ and this project adheres to
new VIRTIO_BLK_F_BLK_SIZE and VIRTIO_BLK_F_TOPOLOGY features to the
virtio-block device. More information is in the new [block](docs/block.md)
documentation.
- [#5908](https://github.com/firecracker-microvm/firecracker/pull/5908): Add

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.

If we are touching this PR anyway, how about moving CHANGELOG and docs changes into a separate commits?

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.

done

opt-in virtio-blk discard support for writable `Sync` IO engine drives through
the `discard` drive configuration field. See the
[block discard documentation](docs/api_requests/block-discard.md).

### Changed

Expand Down
56 changes: 56 additions & 0 deletions docs/api_requests/block-discard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Block device discard

Firecracker can expose virtio-blk discard support to Linux guests. When enabled,
the guest can issue discard/TRIM requests, for example through `fstrim`, and
Firecracker forwards those requests to the backing storage.

Discard is configured per virtio-block device through the `discard` field in the
`PUT /drives/{drive_id}` request. It is disabled by default.

## Supported configuration

Discard is currently supported only for writable virtio-block devices using the
`Sync` IO engine. It is not supported for:

- read-only drives;
- `Async` IO engine drives;
- vhost-user block devices.

For regular backing files, Firecracker uses hole punching. For block-device
backends, Firecracker uses `BLKDISCARD`.

## Discard alignment and drive updates

The discard alignment is measured in 512-byte sectors. Firecracker sets it to
the advertised [logical block size](../block.md#logical-block-size) divided by
the 512-byte sector size.

For a disk update, the new backend discard alignment must divide the advertised
alignment. Firecracker does not check this requirement, so the user must provide
a compatible backend. Otherwise, the backend can reject a valid guest request,
and Firecracker returns `VIRTIO_BLK_S_IOERR`. For example, replacing a regular
file with alignment `1` by a block file with 4096-byte logical sectors having
alignment `8` is invalid because `1 % 8 != 0`.

## Example configuration

```bash
curl --unix-socket ${socket} -i \
-X PUT "http://localhost/drives/rootfs" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-d "{
\"drive_id\": \"rootfs\",
\"path_on_host\": \"${drive_path}\",
\"is_root_device\": true,
\"is_read_only\": false,
\"discard\": true,
\"io_engine\": \"Sync\"
}"
```

After the guest boots, Linux guests can usually issue discard requests with:

```bash
fstrim -av
```
4 changes: 4 additions & 0 deletions docs/api_requests/patch-block.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ The following guarantees need to be provided:
- guest did not mount the device
- guest does not read or write from the raw block device `/dev/vdX` during the
update sequence
- when discard is enabled, the new discard alignment divides the advertised
alignment. Firecracker does not check this requirement. See
[block-discard.md](block-discard.md#discard-alignment-and-drive-updates) for
details.

Example sequence that configures a microVM with a placeholder drive and then
updates it with the real one:
Expand Down
11 changes: 9 additions & 2 deletions docs/block.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ See [block-io-engine.md](api_requests/block-io-engine.md) for more information.
Setting `is_read_only` to `true` causes Firecracker to open the backing file
`O_RDONLY` and tell the guest to mark the device as read-only as well.

### Discard

The `discard` field enables the `VIRTIO_BLK_F_DISCARD` feature for a drive.
Discard is disabled by default and is available only for writable drives that
use the `Sync` IO engine. See [block-discard.md](api_requests/block-discard.md)
for configuration details and backend behavior.

### Rate Limiting

The optional `rate_limiter` field caps IO bandwidth and/or request rate:
Expand Down Expand Up @@ -263,8 +270,8 @@ A `PATCH /drives/{drive_id}` request can change the `path_on_host` and/or

> [!NOTE]
>
> Patching block device does not change already configured `blk_size` or
> `topology` fileds.
> Patching a block device does not change the configured `blk_size` or
> `topology` fields.

## Examples

Expand Down
28 changes: 27 additions & 1 deletion resources/seccomp/aarch64-unknown-linux-musl.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,19 @@
{
"syscall": "fsync"
},
{
"syscall": "fallocate",
"comment": "Used by the VirtIO block device to punch holes for discard on regular backing files",
"args": [
{
"index": 1,
"type": "dword",
"op": "eq",
"val": 3,
"comment": "FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE"
}
]
},
{
"syscall": "close"
},
Expand Down Expand Up @@ -519,6 +532,19 @@
}
]
},
{
"syscall": "ioctl",
"comment": "Used by the VirtIO block device to pass discard through to block-device backing files",
"args": [
{
"index": 1,
"type": "dword",
"op": "eq",
"val": 4727,
"comment": "BLKDISCARD"
}
]
},
{
"syscall": "ioctl",
"comment": "Used to make vsock UDS nonblocking",
Expand Down Expand Up @@ -686,7 +712,7 @@
},
{
"syscall": "ioctl",
"comment": "Needed for querying the logical sector size of a block-device backing file during virtio-block init",
"comment": "Needed for querying the logical sector size when opening or replacing a virtio-block backing file",
"args": [
{
"index": 1,
Expand Down
28 changes: 27 additions & 1 deletion resources/seccomp/x86_64-unknown-linux-musl.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,19 @@
{
"syscall": "fsync"
},
{
"syscall": "fallocate",
"comment": "Used by the VirtIO block device to punch holes for discard on regular backing files",
"args": [
{
"index": 1,
"type": "dword",
"op": "eq",
"val": 3,
"comment": "FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE"
}
]
},
{
"syscall": "close"
},
Expand Down Expand Up @@ -571,6 +584,19 @@
}
]
},
{
"syscall": "ioctl",
"comment": "Used by the VirtIO block device to pass discard through to block-device backing files",
"args": [
{
"index": 1,
"type": "dword",
"op": "eq",
"val": 4727,
"comment": "BLKDISCARD"
}
]
},
{
"syscall": "ioctl",
"args": [
Expand Down Expand Up @@ -698,7 +724,7 @@
},
{
"syscall": "ioctl",
"comment": "Needed for querying the logical sector size of a block-device backing file during virtio-block init",
"comment": "Needed for querying the logical sector size when opening or replacing a virtio-block backing file",
"args": [
{
"index": 1,
Expand Down
8 changes: 8 additions & 0 deletions src/firecracker/swagger/firecracker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,14 @@ definitions:
description:
Is block read only.
This field is required for virtio-block config and should be omitted for vhost-user-block configuration.
discard:
type: boolean
description:
Enables virtio-blk discard support. When enabled, the guest can issue
discard/TRIM requests for this drive. Only supported for writable
virtio-block devices using the Sync IO engine.
This field is optional for virtio-block config and should be omitted for vhost-user-block configuration.
default: false
path_on_host:
type: string
description:
Expand Down
1 change: 1 addition & 0 deletions src/vmm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,7 @@ pub(crate) mod tests {
cache_type: custom_block_cfg.cache_type,

is_read_only: Some(custom_block_cfg.is_read_only),
discard: None,
path_on_host: Some(
block_files
.last()
Expand Down
1 change: 1 addition & 0 deletions src/vmm/src/device_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,7 @@ pub(crate) mod tests {
is_root_device: is_root,
cache_type: CacheType::Unsafe,
is_read_only: Some(false),
discard: None,
path_on_host: Some(f.as_path().to_str().unwrap().to_string()),
rate_limiter: None,
file_engine_type: None,
Expand Down
1 change: 1 addition & 0 deletions src/vmm/src/device_manager/pci_mngr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,7 @@ mod tests {
"is_root_device": true,
"cache_type": "Unsafe",
"is_read_only": true,
"discard": false,
"path_on_host": "{}",
"rate_limiter": null,
"io_engine": "Sync",
Expand Down
1 change: 1 addition & 0 deletions src/vmm/src/device_manager/persist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,7 @@ mod tests {
"is_root_device": true,
"cache_type": "Unsafe",
"is_read_only": true,
"discard": false,
"path_on_host": "{}",
"rate_limiter": null,
"io_engine": "Sync",
Expand Down
7 changes: 6 additions & 1 deletion src/vmm/src/devices/virtio/block/vhost_user/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,10 @@ impl TryFrom<&BlockDeviceConfig> for VhostUserBlockConfig {
type Error = VhostUserBlockError;

fn try_from(value: &BlockDeviceConfig) -> Result<Self, Self::Error> {
if let (Some(socket), None, None, None, None, None, None) = (
if let (Some(socket), None, None, None, None, None, None, None) = (
&value.socket,
&value.is_read_only,
&value.discard,
&value.path_on_host,
&value.rate_limiter,
&value.file_engine_type,
Expand Down Expand Up @@ -99,6 +100,7 @@ impl From<VhostUserBlockConfig> for BlockDeviceConfig {
cache_type: value.cache_type,

is_read_only: None,
discard: None,
path_on_host: None,
rate_limiter: None,
file_engine_type: None,
Expand Down Expand Up @@ -417,6 +419,7 @@ mod tests {
cache_type: CacheType::Unsafe,

is_read_only: None,
discard: None,
path_on_host: None,
rate_limiter: None,
file_engine_type: None,
Expand All @@ -434,6 +437,7 @@ mod tests {
cache_type: CacheType::Unsafe,

is_read_only: Some(true),
discard: None,
path_on_host: Some("path".to_string()),
rate_limiter: None,
file_engine_type: Some(FileEngineType::Sync),
Expand All @@ -451,6 +455,7 @@ mod tests {
cache_type: CacheType::Unsafe,

is_read_only: Some(true),
discard: None,
path_on_host: Some("path".to_string()),
rate_limiter: None,
file_engine_type: Some(FileEngineType::Sync),
Expand Down
Loading
Loading