fix(vhost-user-block): honour a readonly backend - #6083
ShadowCurse merged 2 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6083 +/- ##
=======================================
Coverage 83.04% 83.04%
=======================================
Files 277 277
Lines 31438 31439 +1
=======================================
+ Hits 26107 26108 +1
Misses 5331 5331
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
71d04f6 to
cbaeea1
Compare
cbaeea1 to
70e9c01
Compare
70e9c01 to
3af1a30
Compare
JamesC1305
left a comment
There was a problem hiding this comment.
Thanks for the PR, the change LGTM. Just one suggestion which could maybe improve readability.
3af1a30 to
fe7fda1
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. Two different values sharing one name is the actual fault, so they are named apart. negotiate_features now returns backend_acked_features, and acked_features keeps its meaning of what the guest driver has acked, so read_only reads the backend set and no ordering constraint is needed. 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>
fe7fda1 to
003c1b5
Compare
eaba0ed
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: