livepatch: Documentation of the new API for tracking system state changes
Documentation explaining the motivation, capabilities, and usage of the new API for tracking system state changes. Link: http://lkml.kernel.org/r/20191030154313.13263-5-pmladek@suse.com To: Jiri Kosina <jikos@kernel.org> Cc: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com> Cc: Nicolai Stange <nstange@suse.de> Cc: live-patching@vger.kernel.org Cc: linux-kernel@vger.kernel.org Acked-by: Miroslav Benes <mbenes@suse.cz> Acked-by: Joe Lawrence <joe.lawrence@redhat.com> Acked-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Petr Mladek <pmladek@suse.com>
This commit is contained in:
parent
92c9abf5e5
commit
e553d2a53d
@ -12,6 +12,7 @@ Kernel Livepatching
|
||||
cumulative-patches
|
||||
module-elf-format
|
||||
shadow-vars
|
||||
system-state
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
|
167
Documentation/livepatch/system-state.rst
Normal file
167
Documentation/livepatch/system-state.rst
Normal file
@ -0,0 +1,167 @@
|
||||
====================
|
||||
System State Changes
|
||||
====================
|
||||
|
||||
Some users are really reluctant to reboot a system. This brings the need
|
||||
to provide more livepatches and maintain some compatibility between them.
|
||||
|
||||
Maintaining more livepatches is much easier with cumulative livepatches.
|
||||
Each new livepatch completely replaces any older one. It can keep,
|
||||
add, and even remove fixes. And it is typically safe to replace any version
|
||||
of the livepatch with any other one thanks to the atomic replace feature.
|
||||
|
||||
The problems might come with shadow variables and callbacks. They might
|
||||
change the system behavior or state so that it is no longer safe to
|
||||
go back and use an older livepatch or the original kernel code. Also
|
||||
any new livepatch must be able to detect what changes have already been
|
||||
done by the already installed livepatches.
|
||||
|
||||
This is where the livepatch system state tracking gets useful. It
|
||||
allows to:
|
||||
|
||||
- store data needed to manipulate and restore the system state
|
||||
|
||||
- define compatibility between livepatches using a change id
|
||||
and version
|
||||
|
||||
|
||||
1. Livepatch system state API
|
||||
=============================
|
||||
|
||||
The state of the system might get modified either by several livepatch callbacks
|
||||
or by the newly used code. Also it must be possible to find changes done by
|
||||
already installed livepatches.
|
||||
|
||||
Each modified state is described by struct klp_state, see
|
||||
include/linux/livepatch.h.
|
||||
|
||||
Each livepatch defines an array of struct klp_states. They mention
|
||||
all states that the livepatch modifies.
|
||||
|
||||
The livepatch author must define the following two fields for each
|
||||
struct klp_state:
|
||||
|
||||
- *id*
|
||||
|
||||
- Non-zero number used to identify the affected system state.
|
||||
|
||||
- *version*
|
||||
|
||||
- Number describing the variant of the system state change that
|
||||
is supported by the given livepatch.
|
||||
|
||||
The state can be manipulated using two functions:
|
||||
|
||||
- *klp_get_state(patch, id)*
|
||||
|
||||
- Get struct klp_state associated with the given livepatch
|
||||
and state id.
|
||||
|
||||
- *klp_get_prev_state(id)*
|
||||
|
||||
- Get struct klp_state associated with the given feature id and
|
||||
already installed livepatches.
|
||||
|
||||
2. Livepatch compatibility
|
||||
==========================
|
||||
|
||||
The system state version is used to prevent loading incompatible livepatches.
|
||||
The check is done when the livepatch is enabled. The rules are:
|
||||
|
||||
- Any completely new system state modification is allowed.
|
||||
|
||||
- System state modifications with the same or higher version are allowed
|
||||
for already modified system states.
|
||||
|
||||
- Cumulative livepatches must handle all system state modifications from
|
||||
already installed livepatches.
|
||||
|
||||
- Non-cumulative livepatches are allowed to touch already modified
|
||||
system states.
|
||||
|
||||
3. Supported scenarios
|
||||
======================
|
||||
|
||||
Livepatches have their life-cycle and the same is true for the system
|
||||
state changes. Every compatible livepatch has to support the following
|
||||
scenarios:
|
||||
|
||||
- Modify the system state when the livepatch gets enabled and the state
|
||||
has not been already modified by a livepatches that are being
|
||||
replaced.
|
||||
|
||||
- Take over or update the system state modification when is has already
|
||||
been done by a livepatch that is being replaced.
|
||||
|
||||
- Restore the original state when the livepatch is disabled.
|
||||
|
||||
- Restore the previous state when the transition is reverted.
|
||||
It might be the original system state or the state modification
|
||||
done by livepatches that were being replaced.
|
||||
|
||||
- Remove any already made changes when error occurs and the livepatch
|
||||
cannot get enabled.
|
||||
|
||||
4. Expected usage
|
||||
=================
|
||||
|
||||
System states are usually modified by livepatch callbacks. The expected
|
||||
role of each callback is as follows:
|
||||
|
||||
*pre_patch()*
|
||||
|
||||
- Allocate *state->data* when necessary. The allocation might fail
|
||||
and *pre_patch()* is the only callback that could stop loading
|
||||
of the livepatch. The allocation is not needed when the data
|
||||
are already provided by previously installed livepatches.
|
||||
|
||||
- Do any other preparatory action that is needed by
|
||||
the new code even before the transition gets finished.
|
||||
For example, initialize *state->data*.
|
||||
|
||||
The system state itself is typically modified in *post_patch()*
|
||||
when the entire system is able to handle it.
|
||||
|
||||
- Clean up its own mess in case of error. It might be done by a custom
|
||||
code or by calling *post_unpatch()* explicitly.
|
||||
|
||||
*post_patch()*
|
||||
|
||||
- Copy *state->data* from the previous livepatch when they are
|
||||
compatible.
|
||||
|
||||
- Do the actual system state modification. Eventually allow
|
||||
the new code to use it.
|
||||
|
||||
- Make sure that *state->data* has all necessary information.
|
||||
|
||||
- Free *state->data* from replaces livepatches when they are
|
||||
not longer needed.
|
||||
|
||||
*pre_unpatch()*
|
||||
|
||||
- Prevent the code, added by the livepatch, relying on the system
|
||||
state change.
|
||||
|
||||
- Revert the system state modification..
|
||||
|
||||
*post_unpatch()*
|
||||
|
||||
- Distinguish transition reverse and livepatch disabling by
|
||||
checking *klp_get_prev_state()*.
|
||||
|
||||
- In case of transition reverse, restore the previous system
|
||||
state. It might mean doing nothing.
|
||||
|
||||
- Remove any not longer needed setting or data.
|
||||
|
||||
.. note::
|
||||
|
||||
*pre_unpatch()* typically does symmetric operations to *post_patch()*.
|
||||
Except that it is called only when the livepatch is being disabled.
|
||||
Therefore it does not need to care about any previously installed
|
||||
livepatch.
|
||||
|
||||
*post_unpatch()* typically does symmetric operations to *pre_patch()*.
|
||||
It might be called also during the transition reverse. Therefore it
|
||||
has to handle the state of the previously installed livepatches.
|
Loading…
Reference in New Issue
Block a user