[RFC PATCH v2 3/4] liveupdate: Replace compatibility string with a 2-bit pair feature header
Tarun Sahu
tarunsahu at google.com
Mon Oct 26 17:55:34 PDT 2026
On Tue, Oct 27, 2026 at 1:01 AM David Matlack <dmatlack at google.com> wrote:
>
> On 2026-10-26 11:28 PM, tarunsahu at google.com wrote:
> > David Matlack <dmatlack at google.com> writes:
>
> > > But looking at this again, I think the required bit is redundant. Whether
> > > a feature can be safely ignored is a property of the feature itself, not
> > > of any particular file. Every file that has a feature present will have
> > > the same required bit for it. The only thing that actually varies per
> > > file is whether the feature is present.
> >
> > The required bit is subsystem property not the per-file. e.g. memfd_luo,
> > it is set at compile time for a kernel. So every file will get that required
> > bit set. It is not per file property.
> >
> > struct u8 memfd_luo_feature_state {
> > [MEMFD_LUO_CORE_FEATURE] = LUO_FEATURE_REQUIRED
> > }
>
> Right, whether a feature is required is a static property of the
> feature. That's exactly why it's redundant to send it in every header.
I meant the different thing.I was saying if a Feature in a kernel will have
constant value either required or optional which is fixed at compile time.
But the same feature can have different values in two different kernels.
I am not finding a good example, But I am skeptical about making the
assumption for all future kernels that the features will always be
required if they were required before.
Maybe a seal added in kernel version M. Later in kernel version N this seal is
deprecated and replaced by a new seal.
So transition from M->N
source kernel will preserve the seal values and flag the feature as required.
target kernel will mark it supported and use its value to translate
into a new seal.
>From N -> Z (latest)
Old seal is no longer required, But the new seal is required, so kernel N will
mark the new seal as required. and Z will support it.
This is hypothetical example. I'm not sure this is enough to convince the point.
So, I will rely on others to chime in with their thoughts.
>
> > > The required bit still has to be conveyed to the target somehow, since
> > > the kernel that needs it is the one that doesn't know about the feature.
> > > But it can be conveyed by the feature's number rather than an extra bit:
> > > split the flag space into required features and optional features, and
> > > assign each feature to one of them when it is defined. This is similar
> > > to the required_flags and optional_flags approach in struct pci_ser [1].
> > >
> > > Keeping the same header shape as discussed with Pasha:
> > >
> > > struct kho_ser_hdr {
> > > __u32 size; /* Size of header + payload in bytes */
> > > __u16 nr_required; /* Number of required feature bits */
> > > __u16 nr_optional; /* Number of optional feature bits */
> > > __u64 flags[]; /* Required bits, followed by optional bits */
> > > };
> > >
> > > Required feature N is bit N of flags[], and optional feature N is bit
> > > nr_required + N (using nr_required from the incoming header). The length
> > > of flags[] is DIV_ROUND_UP(nr_required + nr_optional, 64). Both spaces
> > > are numbered contiguously, so there are no gaps, and up to 64 features
> > > still fit in a 16-byte header.
> > >
> > > Each bit just means the feature is present, so the truth table becomes:
> > >
> > > Source bit Target supports Action
> > > --------------- --------------- ------------------------------
> > > Not set - Accept: feature absent
> > > Optional set No Accept: ignore the feature data
> > > Optional set Yes Accept: use the feature data
> > > Required set No Reject: -EOPNOTSUPP
> > > Required set Yes Accept: use the feature data
> > >
> > > There is no invalid encoding left to check.
> >
> >
> > IIUC, I believe this will not work.
> >
> > To Communicate between source and target, We are defining a protocol, A
> > protocol which will be standard for all the kernel. And each bit location in
> > flags must have the same meaning in both the source and target kernel.
> >
> > Now in you approach, If Source kernel send feature N to target kernel,
> > target kernel must understand Nth bit as the same feature. Even though
> > the bit position in your approach is not fixed but they are fixed
> > relative to their starting point.
>
> I think you misunderstood the proposal. I'm not proposing to pack only
> the set bits, and I'm not proposing that each feature have a bit in both
> ranges.
>
> In my proposal, there is no such thing as "feature N", there is
> "required feature N" and "optional feature N". Required feature N can
> be found at bit position flags[N]. Optional feature N can be found at
> flags[nr_required + N].
>
> In more detail:
>
> - Each feature is defined as either required or optional, once, when
> the feature is added. That choice is permanent.
>
> - Each feature gets exactly one bit, in its range, and that bit is
> always at the same position whether or not it is set. Required
> feature N is bit N. Optional feature N is bit nr_required + N.
>
> - nr_required and nr_optional are the number of features of each kind
> the source kernel knows about, not the number of bits set. They tell
> the target where the optional range starts and how long flags[] is.
>
> - A set bit means the feature is present in this file's payload. A clear
> bit means it is absent.
So For #NR number of features, We will end up using 2*NR bits which
is exactly same number of bits, V3 [2] uses. So this is just a different
way of encoding in implementation perspective.
>
> - There is no invalid or reserved encoding to define. Each bit just
> means "present".
What if a buggy source sets both required and optional for a feature?
That is an invalid case here. Same as 0b10 is an invalid value set by
buggy kernel.
>
> - The target doesn't need a supported table. Required features are only
> ever appended, so it rejects any required bit at or beyond its own
> MEMFD_LUO_NR_REQUIRED. Optional bits need no validation; the target
> just checks the ones it knows about.
>
As I explained above, incase a feature is replaced by another feature,
new kernel
can support it deserialization but it will not be required from there on. So
The supported table will still be needed.
> > For the current appraoch and V3 [2]. Think the below one as msb is
> > required bit and lsb is feature present in payload bit.
> >
> > 00 FEATURE_ABSENT / DEPRECATED
> > 01 FEATURE_OPTIONAL
> > 11 FEATURE_REQUIRED
> > 10 IS INVALID (analogy: required set but feature is not present) which can
> > have different meaning in future if in future, a need arises to reuse this
> > field.
>
> In v3, 0b10 is reserved and not checked by the target. That means an
> older kernel will silently accept it, so the only meaning it could ever
> safely take on is "safe to ignore", which is what 0b01 already means.
> A reserved encoding is only useful if older kernels reject it, and at
> that point it's no different from adding a new required feature.
Yes, because I thought 0b10 could be used in the future. And Currently
If it is set by a source kernel, it is buggy source kernel. But I can change
back to INVALID, As you said, it overlaps with valid field 0b00.
~Tarun
>
> > Deserialization can happen per feature from right to left. without
> > jumping back and forth.
> >
> > Because of all these reasons, I believe current approach presented in
> > V3 [2] is the better. It is close to your PCI series with two flags
> > field for required and optional except I combined both field into one
> > flags. In your above approach you do have two counts but not having gaps
> > (which is wrong) and the way you proposed to parse with an offset is different.
More information about the kexec
mailing list