diff mbox series

[v3,2/5] vhost-user.rst: Clarify enabling/disabling vrings

Message ID 20230915102531.55894-3-hreitz@redhat.com (mailing list archive)
State New, archived
Headers show
Series vhost-user: Back-end state migration | expand

Commit Message

Hanna Czenczek Sept. 15, 2023, 10:25 a.m. UTC
Currently, the vhost-user documentation says that rings are to be
initialized in a disabled state when VHOST_USER_F_PROTOCOL_FEATURES is
negotiated.  However, by the time of feature negotiation, all rings have
already been initialized, so it is not entirely clear what this means.

At least the vhost-user-backend Rust crate's implementation interpreted
it to mean that whenever this feature is negotiated, all rings are to
put into a disabled state, which means that every SET_FEATURES call
would disable all rings, effectively halting the device.  This is
problematic because the VHOST_F_LOG_ALL feature is also set or cleared
this way, which happens during migration.  Doing so should not halt the
device.

Other implementations have interpreted this to mean that the device is
to be initialized with all rings disabled, and a subsequent SET_FEATURES
call that does not set VHOST_USER_F_PROTOCOL_FEATURES will enable all of
them.  Here, SET_FEATURES will never disable any ring.

This interpretation does not suffer the problem of unintentionally
halting the device whenever features are set or cleared, so it seems
better and more reasonable.

We should clarify this in the documentation.

Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
---
 docs/interop/vhost-user.rst | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

Comments

Stefan Hajnoczi Sept. 25, 2023, 7:15 p.m. UTC | #1
On Fri, Sep 15, 2023 at 12:25:27PM +0200, Hanna Czenczek wrote:
> Currently, the vhost-user documentation says that rings are to be
> initialized in a disabled state when VHOST_USER_F_PROTOCOL_FEATURES is
> negotiated.  However, by the time of feature negotiation, all rings have
> already been initialized, so it is not entirely clear what this means.
> 
> At least the vhost-user-backend Rust crate's implementation interpreted
> it to mean that whenever this feature is negotiated, all rings are to
> put into a disabled state, which means that every SET_FEATURES call
> would disable all rings, effectively halting the device.  This is
> problematic because the VHOST_F_LOG_ALL feature is also set or cleared
> this way, which happens during migration.  Doing so should not halt the
> device.
> 
> Other implementations have interpreted this to mean that the device is
> to be initialized with all rings disabled, and a subsequent SET_FEATURES
> call that does not set VHOST_USER_F_PROTOCOL_FEATURES will enable all of
> them.  Here, SET_FEATURES will never disable any ring.
> 
> This interpretation does not suffer the problem of unintentionally
> halting the device whenever features are set or cleared, so it seems
> better and more reasonable.
> 
> We should clarify this in the documentation.
> 
> Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
> ---
>  docs/interop/vhost-user.rst | 20 ++++++++++++++------
>  1 file changed, 14 insertions(+), 6 deletions(-)
> 
> diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
> index bb4dd0fd60..9b9b802c60 100644
> --- a/docs/interop/vhost-user.rst
> +++ b/docs/interop/vhost-user.rst
> @@ -409,12 +409,20 @@ and stop ring upon receiving ``VHOST_USER_GET_VRING_BASE``.
>  
>  Rings can be enabled or disabled by ``VHOST_USER_SET_VRING_ENABLE``.
>  
> -If ``VHOST_USER_F_PROTOCOL_FEATURES`` has not been negotiated, the
> -ring starts directly in the enabled state.
> -
> -If ``VHOST_USER_F_PROTOCOL_FEATURES`` has been negotiated, the ring is
> -initialized in a disabled state and is enabled by
> -``VHOST_USER_SET_VRING_ENABLE`` with parameter 1.
> +If ``VHOST_USER_SET_FEATURES`` does not negotiate
> +``VHOST_USER_F_PROTOCOL_FEATURES``, rings are enabled immediately when
> +started.
> +
> +If ``VHOST_USER_SET_FEATURES`` does negotiate
> +``VHOST_USER_F_PROTOCOL_FEATURES``, each ring will remain in the disabled
> +state until ``VHOST_USER_SET_VRING_ENABLE`` enables it with parameter 1.
> +
> +Back-end implementations that support ``VHOST_USER_F_PROTOCOL_FEATURES``
> +should implement this by initializing each ring in a disabled state, and
> +enabling them when ``VHOST_USER_SET_FEATURES`` is used without
> +negotiating ``VHOST_USER_F_PROTOCOL_FEATURES``.  Other than that, rings
> +should only be enabled and disabled through
> +``VHOST_USER_SET_VRING_ENABLE``.

The "Ring states" section starts by saying there are three states:
"stopped", "started but disabled", and "started and enabled". But this
patch talks about a "disabled state". Can you rephrase this patch to use
the exact state names defined earlier in the spec?

>  
>  While processing the rings (whether they are enabled or not), the back-end
>  must support changing some configuration aspects on the fly.
> -- 
> 2.41.0
>
Hanna Czenczek Sept. 26, 2023, 1:54 p.m. UTC | #2
On 25.09.23 21:15, Stefan Hajnoczi wrote:
> On Fri, Sep 15, 2023 at 12:25:27PM +0200, Hanna Czenczek wrote:
>> Currently, the vhost-user documentation says that rings are to be
>> initialized in a disabled state when VHOST_USER_F_PROTOCOL_FEATURES is
>> negotiated.  However, by the time of feature negotiation, all rings have
>> already been initialized, so it is not entirely clear what this means.
>>
>> At least the vhost-user-backend Rust crate's implementation interpreted
>> it to mean that whenever this feature is negotiated, all rings are to
>> put into a disabled state, which means that every SET_FEATURES call
>> would disable all rings, effectively halting the device.  This is
>> problematic because the VHOST_F_LOG_ALL feature is also set or cleared
>> this way, which happens during migration.  Doing so should not halt the
>> device.
>>
>> Other implementations have interpreted this to mean that the device is
>> to be initialized with all rings disabled, and a subsequent SET_FEATURES
>> call that does not set VHOST_USER_F_PROTOCOL_FEATURES will enable all of
>> them.  Here, SET_FEATURES will never disable any ring.
>>
>> This interpretation does not suffer the problem of unintentionally
>> halting the device whenever features are set or cleared, so it seems
>> better and more reasonable.
>>
>> We should clarify this in the documentation.
>>
>> Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
>> ---
>>   docs/interop/vhost-user.rst | 20 ++++++++++++++------
>>   1 file changed, 14 insertions(+), 6 deletions(-)
>>
>> diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
>> index bb4dd0fd60..9b9b802c60 100644
>> --- a/docs/interop/vhost-user.rst
>> +++ b/docs/interop/vhost-user.rst
>> @@ -409,12 +409,20 @@ and stop ring upon receiving ``VHOST_USER_GET_VRING_BASE``.
>>   
>>   Rings can be enabled or disabled by ``VHOST_USER_SET_VRING_ENABLE``.
>>   
>> -If ``VHOST_USER_F_PROTOCOL_FEATURES`` has not been negotiated, the
>> -ring starts directly in the enabled state.
>> -
>> -If ``VHOST_USER_F_PROTOCOL_FEATURES`` has been negotiated, the ring is
>> -initialized in a disabled state and is enabled by
>> -``VHOST_USER_SET_VRING_ENABLE`` with parameter 1.
>> +If ``VHOST_USER_SET_FEATURES`` does not negotiate
>> +``VHOST_USER_F_PROTOCOL_FEATURES``, rings are enabled immediately when
>> +started.
>> +
>> +If ``VHOST_USER_SET_FEATURES`` does negotiate
>> +``VHOST_USER_F_PROTOCOL_FEATURES``, each ring will remain in the disabled
>> +state until ``VHOST_USER_SET_VRING_ENABLE`` enables it with parameter 1.
>> +
>> +Back-end implementations that support ``VHOST_USER_F_PROTOCOL_FEATURES``
>> +should implement this by initializing each ring in a disabled state, and
>> +enabling them when ``VHOST_USER_SET_FEATURES`` is used without
>> +negotiating ``VHOST_USER_F_PROTOCOL_FEATURES``.  Other than that, rings
>> +should only be enabled and disabled through
>> +``VHOST_USER_SET_VRING_ENABLE``.
> The "Ring states" section starts by saying there are three states:
> "stopped", "started but disabled", and "started and enabled". But this
> patch talks about a "disabled state". Can you rephrase this patch to use
> the exact state names defined earlier in the spec?

I would not want to do that.  We had the exact problem that the spec 
wanted to remain high-level, and was not reflecting exactly what 
existing implementations did, which resulted in confusion (at least for 
me and the vhost Rust crates authors).

Notably, the existing implementations I’m aware of track 
enabled/disabled even before the ring is started, exactly as formulated 
here.

If we changed this to read something like “If VHOST_USER_SET_FEATURES is 
ever called without negotiating VHOST_USER_F_PROTOCOL_FEATURES, the ring 
must be enabled immediately when it is started; otherwise, when the ring 
is started and VHOST_USER_F_PROTOCOL_FEATURES has always been set in 
every VHOST_USER_SET_FEATURES call, the ring should be disabled when 
started.” then this would conflict with the existing implementations:

We never disallow VHOST_USER_SET_VRING_ENABLE when the ring is stopped.  
Existing implementations track enabled/disabled before the rings are 
started, and they initialize this state to “disabled”, setting it to 
“enabled” on receiving VHOST_USER_SET_FEATURES without 
VHOST_USER_F_PROTOCOL_FEATURES, as described above.  Therefore, if you 
call VHOST_USER_SET_VRING_ENABLE 1 before the ring is started, the ring 
will start enabled even with VHOST_USER_F_PROTOCOL_FEATURES.  This is 
not possible if you only have three states.

Maybe we should rather clarify that enabled/disabled is tracked even 
while the ring is stopped.

Hanna
Stefan Hajnoczi Sept. 26, 2023, 7:30 p.m. UTC | #3
On Tue, 26 Sept 2023 at 09:55, Hanna Czenczek <hreitz@redhat.com> wrote:
>
> On 25.09.23 21:15, Stefan Hajnoczi wrote:
> > On Fri, Sep 15, 2023 at 12:25:27PM +0200, Hanna Czenczek wrote:
> >> Currently, the vhost-user documentation says that rings are to be
> >> initialized in a disabled state when VHOST_USER_F_PROTOCOL_FEATURES is
> >> negotiated.  However, by the time of feature negotiation, all rings have
> >> already been initialized, so it is not entirely clear what this means.
> >>
> >> At least the vhost-user-backend Rust crate's implementation interpreted
> >> it to mean that whenever this feature is negotiated, all rings are to
> >> put into a disabled state, which means that every SET_FEATURES call
> >> would disable all rings, effectively halting the device.  This is
> >> problematic because the VHOST_F_LOG_ALL feature is also set or cleared
> >> this way, which happens during migration.  Doing so should not halt the
> >> device.
> >>
> >> Other implementations have interpreted this to mean that the device is
> >> to be initialized with all rings disabled, and a subsequent SET_FEATURES
> >> call that does not set VHOST_USER_F_PROTOCOL_FEATURES will enable all of
> >> them.  Here, SET_FEATURES will never disable any ring.
> >>
> >> This interpretation does not suffer the problem of unintentionally
> >> halting the device whenever features are set or cleared, so it seems
> >> better and more reasonable.
> >>
> >> We should clarify this in the documentation.
> >>
> >> Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
> >> ---
> >>   docs/interop/vhost-user.rst | 20 ++++++++++++++------
> >>   1 file changed, 14 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
> >> index bb4dd0fd60..9b9b802c60 100644
> >> --- a/docs/interop/vhost-user.rst
> >> +++ b/docs/interop/vhost-user.rst
> >> @@ -409,12 +409,20 @@ and stop ring upon receiving ``VHOST_USER_GET_VRING_BASE``.
> >>
> >>   Rings can be enabled or disabled by ``VHOST_USER_SET_VRING_ENABLE``.
> >>
> >> -If ``VHOST_USER_F_PROTOCOL_FEATURES`` has not been negotiated, the
> >> -ring starts directly in the enabled state.
> >> -
> >> -If ``VHOST_USER_F_PROTOCOL_FEATURES`` has been negotiated, the ring is
> >> -initialized in a disabled state and is enabled by
> >> -``VHOST_USER_SET_VRING_ENABLE`` with parameter 1.
> >> +If ``VHOST_USER_SET_FEATURES`` does not negotiate
> >> +``VHOST_USER_F_PROTOCOL_FEATURES``, rings are enabled immediately when
> >> +started.
> >> +
> >> +If ``VHOST_USER_SET_FEATURES`` does negotiate
> >> +``VHOST_USER_F_PROTOCOL_FEATURES``, each ring will remain in the disabled
> >> +state until ``VHOST_USER_SET_VRING_ENABLE`` enables it with parameter 1.
> >> +
> >> +Back-end implementations that support ``VHOST_USER_F_PROTOCOL_FEATURES``
> >> +should implement this by initializing each ring in a disabled state, and
> >> +enabling them when ``VHOST_USER_SET_FEATURES`` is used without
> >> +negotiating ``VHOST_USER_F_PROTOCOL_FEATURES``.  Other than that, rings
> >> +should only be enabled and disabled through
> >> +``VHOST_USER_SET_VRING_ENABLE``.
> > The "Ring states" section starts by saying there are three states:
> > "stopped", "started but disabled", and "started and enabled". But this
> > patch talks about a "disabled state". Can you rephrase this patch to use
> > the exact state names defined earlier in the spec?
>
> I would not want to do that.  We had the exact problem that the spec
> wanted to remain high-level, and was not reflecting exactly what
> existing implementations did, which resulted in confusion (at least for
> me and the vhost Rust crates authors).
>
> Notably, the existing implementations I’m aware of track
> enabled/disabled even before the ring is started, exactly as formulated
> here.
>
> If we changed this to read something like “If VHOST_USER_SET_FEATURES is
> ever called without negotiating VHOST_USER_F_PROTOCOL_FEATURES, the ring
> must be enabled immediately when it is started; otherwise, when the ring
> is started and VHOST_USER_F_PROTOCOL_FEATURES has always been set in
> every VHOST_USER_SET_FEATURES call, the ring should be disabled when
> started.” then this would conflict with the existing implementations:
>
> We never disallow VHOST_USER_SET_VRING_ENABLE when the ring is stopped.
> Existing implementations track enabled/disabled before the rings are
> started, and they initialize this state to “disabled”, setting it to
> “enabled” on receiving VHOST_USER_SET_FEATURES without
> VHOST_USER_F_PROTOCOL_FEATURES, as described above.  Therefore, if you
> call VHOST_USER_SET_VRING_ENABLE 1 before the ring is started, the ring
> will start enabled even with VHOST_USER_F_PROTOCOL_FEATURES.  This is
> not possible if you only have three states.
>
> Maybe we should rather clarify that enabled/disabled is tracked even
> while the ring is stopped.

Yes, please. The beginning of the "Ring states" section is confusing
because it claims there are three states but later text doesn't use
those states. Instead it treats started/stopped and enabled/disabled
as independent.

If the entire "Ring states" section consistently talks about
started/stopped and enabled/disabled as independent, then that would
make it easier to understand.

Stefan
diff mbox series

Patch

diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
index bb4dd0fd60..9b9b802c60 100644
--- a/docs/interop/vhost-user.rst
+++ b/docs/interop/vhost-user.rst
@@ -409,12 +409,20 @@  and stop ring upon receiving ``VHOST_USER_GET_VRING_BASE``.
 
 Rings can be enabled or disabled by ``VHOST_USER_SET_VRING_ENABLE``.
 
-If ``VHOST_USER_F_PROTOCOL_FEATURES`` has not been negotiated, the
-ring starts directly in the enabled state.
-
-If ``VHOST_USER_F_PROTOCOL_FEATURES`` has been negotiated, the ring is
-initialized in a disabled state and is enabled by
-``VHOST_USER_SET_VRING_ENABLE`` with parameter 1.
+If ``VHOST_USER_SET_FEATURES`` does not negotiate
+``VHOST_USER_F_PROTOCOL_FEATURES``, rings are enabled immediately when
+started.
+
+If ``VHOST_USER_SET_FEATURES`` does negotiate
+``VHOST_USER_F_PROTOCOL_FEATURES``, each ring will remain in the disabled
+state until ``VHOST_USER_SET_VRING_ENABLE`` enables it with parameter 1.
+
+Back-end implementations that support ``VHOST_USER_F_PROTOCOL_FEATURES``
+should implement this by initializing each ring in a disabled state, and
+enabling them when ``VHOST_USER_SET_FEATURES`` is used without
+negotiating ``VHOST_USER_F_PROTOCOL_FEATURES``.  Other than that, rings
+should only be enabled and disabled through
+``VHOST_USER_SET_VRING_ENABLE``.
 
 While processing the rings (whether they are enabled or not), the back-end
 must support changing some configuration aspects on the fly.