fix(vhost-user-block): honour a readonly backend - #6083
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Please upload reports for the commit cbaeea1 to get more accurate results. Additional details and impacted files@@ Coverage Diff @@
## main #6083 +/- ##
==========================================
- Coverage 82.98% 82.82% -0.17%
==========================================
Files 277 276 -1
Lines 30884 30770 -114
==========================================
- Hits 25630 25486 -144
- Misses 5254 5284 +30
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
74072c9 to
4a7441f
Compare
|
The earlier CI failure here was nothing to do with the change. Build #18251 failed on I've rebased onto current main since then, so there's a fresh build queued. Whenever someone has a moment to unblock it, it'd be good to get a clean run on the record. |
4a7441f to
71d04f6
Compare
The VIRTIO_BLK_F_RO check read acked_features after it had been reassigned to acked_features & PROTOCOL_FEATURES, so it tested bit 5 against 0x4000_0000 and never matched. read_only was therefore always false, even though the device does ask the backend for VIRTIO_BLK_F_RO, and docs/api_requests/block-vhost-user.md documents the backend as the place a readonly vhost-user drive is configured. read_only feeds Block::read_only(), which decides whether a root device gets ro or rw on the guest kernel cmdline, so a readonly vhost-user root device was given rw. The guest still sees VIRTIO_BLK_F_RO and retries the root mount readonly, so it boots, but /proc/cmdline is wrong and a later remount,rw fails. There is no way to correct this from config: VhostUserBlockConfig::try_from rejects is_read_only, which leaves the backend as the only source of the flag. Compute read_only before acked_features is narrowed, so the shadowing cannot swallow the bit again. test_new_all_features already advertises VIRTIO_BLK_F_RO from its mock backend and asserted the broken result, so it now asserts read_only is set, and test_vhost_user_block asserts ro reaches the guest cmdline. Signed-off-by: Wes Mason <wes@1stvamp.org>
71d04f6 to
cbaeea1
Compare
Description
A vhost-user-block device backed by a readonly backend isn't treated as readonly.
read_onlyis alwaysfalse.In
VhostUserBlockImpl::new:The
VIRTIO_BLK_F_ROcheck readsacked_featuresafter it has been reassigned toacked_features & PROTOCOL_FEATURES, so it tests bit 5 against0x4000_0000and never matches.That goes against what the device sets out to do.
AVAILABLE_FEATURESincludesVIRTIO_BLK_F_ROwith the comment "We always try to negotiate readonly with the backend. If the backend is configured as readonly, we will accept it.", and the docs say the same: "Whenever the backend advertises theVIRTIO_BLK_F_ROfeature, Firecracker will accept it, and the device will act as readonly." So the documented behaviour was never implemented.read_onlyfeedsBlock::read_only(), whichattach_block_devicespasses toappend_root_device_cmdline, so a readonly vhost-user root device is givenrw. To be clear about the blast radius: the guest still seesVIRTIO_BLK_F_RO(that bit reaches it viaavail_features) so it retries the root mount readonly and does boot, which is whytest_vhost_user_blockpasses today. What you're left with is a/proc/cmdlinethat disagrees with reality and a laterremount,rwthat fails. There's no working around it from config either, sinceVhostUserBlockConfig::try_fromrejectsis_read_onlyfor vhost-user drives (it must beNone), which leaves the backend as the only intended source of the flag.The fix computes
read_onlybeforeacked_featuresis narrowed, rather than readingavail_features, so the shadowing can't swallow the bit again.test_new_all_featuresalready advertisesVIRTIO_BLK_F_ROfrom its mock backend and assertsavail_featurescontains it, so it was asserting the broken result. It now assertsread_onlyis set.test_new_no_featuresuses a backend with no features and keeps asserting it is not.test_vhost_user_blockalready boots a readonly-backend root device via theuvm_vhost_user_booted_rofixture, so it now also assertsroreaches the guest cmdline, which is the part no existing test covered.I found this while working on the generic vhost-user device (#6072), which shares this negotiation code.
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
tools/devtool checkbuild --allto verify that the PR passesbuild checks on all supported architectures.
tools/devtool checkstyleto verify that the PR passes theautomated style checks.
how they are solving the problem in a clear and encompassing way.
in the PR.
CHANGELOG.md.Runbook for Firecracker API changes.
integration tests.
TODO.rust-vmm.This is part 1 of 4 in a stack made with GitButler: