NACK/Cmnt: [SRU][N/hwe-7.0-lmm][PATCH 1/2] UBUNTU: [Packaging] lmm: Add flavour migration support

Alessio Faina alessio.faina at canonical.com
Wed Sep 9 08:53:29 UTC 2026


On Wed, Sep 09, 2026 at 04:30:39PM +0800, Kuan-Ying Lee via kernel-team wrote:
> BugLink: https://bugs.launchpad.net/bugs/1786013
> 
> When a kernel is retired, the module packages of its flavour need to be
> transitioned onto the module packages of the kernel replacing it. Now
> that the module packages are built by LMM instead of linux-meta, LMM has
> to provide those transitional packages itself.
> 
> Add a "migrate <module> <source flavour> <target flavour> <arch>..."
> directive to debian/package.config, mirroring the syntax already used by
> linux-restricted-modules, and emit an oldlibs transitional package for
> every entry.
> 
> The transitional packages are only emitted for the signed source package,
> as those are the packages users actually have installed. An entry is
> skipped, with a note, when the module is not built by this source package,
> when the target flavour does not exist, or when the module and the target
> flavour have no architecture in common.
> 
> Signed-off-by: Kuan-Ying Lee <kuan-ying.lee at canonical.com>
> ---
>  debian/scripts/control_craft.py         | 67 +++++++++++++++++++++++++
>  debian/scripts/migration_helper.py      | 54 ++++++++++++++++++++
>  debian/scripts/parameterise-ancillaries |  1 +
>  3 files changed, 122 insertions(+)
>  create mode 100644 debian/scripts/migration_helper.py
> 
> diff --git a/debian/scripts/control_craft.py b/debian/scripts/control_craft.py
> index fb29d9d33ddd..4ea4a5c158fb 100755
> --- a/debian/scripts/control_craft.py
> +++ b/debian/scripts/control_craft.py
> @@ -6,6 +6,7 @@ import shutil
>  
>  from dkms_helper import dkms_modules
>  from flavour_finder import find_flavours
> +from migration_helper import find_migrations
>  from variant_helper import find_variants
>  
>  if sys.version_info >= (3, 9):
> @@ -53,6 +54,16 @@ Description: Extra drivers for @DKMS_OLD_NAME at -@KERNEL_FLAVOUR@@KERNEL_VARIANT@
>   Transitional package for upgrades of @DKMS_OLD_NAME@ to [@ARCHITECTURE@]
>  """
>  
> +default_migration_package_template = """
> +Package: linux-modules- at DKMS_NAME@- at SOURCE_FLAVOUR@
> +Architecture: @ARCHITECTURE@
> +Section: oldlibs
> +Multi-Arch: no
> +Depends: linux-modules- at DKMS_NAME@- at TARGET_FLAVOUR@
> +Description: Extra drivers for @DKMS_NAME@ for the @SOURCE_FLAVOUR@ flavour (transitional package)
> + Transitional package for upgrades. This package can be safely removed.
> +"""
> +
>  
>  def create_new_variant_package(dkms_name:str, archs:str, kernel_flavour:str, kernel_abi:str, unsigned_prefix:str):
>      control_variants=""
> @@ -146,6 +157,60 @@ def create_transitional_packages(full_template: str, modules, kernel_arch: str,
>      return full_template
>  
>  
> +def create_migration_packages(full_template: str, modules,
> +                              kernel_flavours: List[str]):
> +    """Build the transitional packages that migrate the module packages of a
> +    retired kernel (e.g. linux-modules-ipu6-oem-24.04d) onto the module
> +    packages built by this source (e.g. linux-modules-ipu6-generic-hwe-24.04).
> +
> +    Driven by the "migrate <module> <source> <target> <arch>..." lines of
> +    debian/package.config.
> +    """
> +    variants = find_variants()
> +    # The target of a migration is a <flavour><variant> pair, which is what
> +    # create_new_variant_package() names its packages after.
> +    target_flavours = {}
> +    for kernel_flavour in kernel_flavours:
> +        for variant in variants:
> +            target_flavours[kernel_flavour.flavour + variant] = kernel_flavour
> +
> +    dkms_by_name = {}
> +    for item in modules.items:
> +        dkms_by_name[item.modulename] = item
> +
> +    for migration in find_migrations():
> +        item = dkms_by_name.get(migration.module)
> +        if item is None:
> +            print(f"Skipping migration of {migration.module} for "
> +                  f"{migration.source}: not built by this source package")
> +            continue
> +        kernel_flavour = target_flavours.get(migration.target)
> +        if kernel_flavour is None:
> +            print(f"Skipping migration of {migration.module} for "
> +                  f"{migration.source}: no such target {migration.target}")
> +            continue
> +        if kernel_flavour.flavour in item.skip_flavours:
> +            print(f"Skipping migration of {migration.module} for "
> +                  f"{migration.source}: skipped for {kernel_flavour.flavour}")
> +            continue
> +        # The transitional package can only exist on architectures where both
> +        # the DKMS module and the target flavour are built.
> +        archs = intersect_archs(migration.archs, item.arch)
> +        archs = intersect_archs(archs.split(), kernel_flavour.archs)
> +        if archs == "":
> +            print(f"Skipping migration of {migration.module} for "
> +                  f"{migration.source}: no architectures in common")
> +            continue
> +        template = default_migration_package_template
> +        template = re.sub("@DKMS_NAME@", migration.module, template)
> +        template = re.sub("@SOURCE_FLAVOUR@", migration.source, template)
> +        template = re.sub("@TARGET_FLAVOUR@", migration.target, template)
> +        template = re.sub("@ARCHITECTURE@", archs, template)
> +        template += "\n"
> +        full_template += template
> +    return full_template
> +
> +
>  def create_temporary_stub_file(pkgs_dkms_modules: str, is_signed: bool):
>      control_file = ""
>      if is_signed:
> @@ -173,4 +238,6 @@ if is_signed:
>      pkgs_dkms_modules = create_transitional_packages(pkgs_dkms_modules,
>                                              modules, arg_deb_host_arch,
>                                              arg_kernel_abi, flavours)
> +    pkgs_dkms_modules = create_migration_packages(pkgs_dkms_modules,
> +                                            modules, flavours)
>  create_temporary_stub_file(pkgs_dkms_modules, is_signed)
> diff --git a/debian/scripts/migration_helper.py b/debian/scripts/migration_helper.py
> new file mode 100644
> index 000000000000..66953bfaa76a
> --- /dev/null
> +++ b/debian/scripts/migration_helper.py
> @@ -0,0 +1,54 @@
> +#! /usr/bin/python3 -B
> +
> +import sys
> +
> +if sys.version_info >= (3, 9):
> +    List = list
> +else:
> +    from typing import List
> +
> +
> +class migration_item:
> +    module: str = ""
> +    source: str = ""
> +    target: str = ""
> +    archs = []
> +
> +    def __init__(self, package_config_line: List[str]):
> +        self.module = package_config_line[1]
> +        self.source = package_config_line[2]
> +        self.target = package_config_line[3]
> +        self.archs = []
> +        for item in package_config_line[4:]:
> +            self.archs.append(item.replace("\n", ""))
> +
> +
> +class migrations:
> +    items: migration_item = []
> +
> +    def __init__(self):
> +        self.items = []
> +        with open("debian/package.config", "r") as fp_dpc:
> +            for line in fp_dpc:
> +                # Split on runs of whitespace so that the entries may be
> +                # column aligned, as they are in the LRM package.config.
> +                parms = line.split()
> +                if not parms or parms[0] != "migrate":
> +                    continue
> +                if len(parms) < 5:
> +                    raise ValueError(
> +                        "debian/package.config: malformed migrate line: "
> +                        + line.strip()
> +                    )
> +                self.items.append(migration_item(parms))
> +
> +
> +def find_migrations():
> +    migs = migrations()
> +    return migs.items
> +
> +
> +#===============================  DEBUG  =======================================
> +if __name__ == "__main__":
> +    for m in find_migrations():
> +        print(f"{m.module}: {m.source} -> {m.target} [{' '.join(m.archs)}]")
> diff --git a/debian/scripts/parameterise-ancillaries b/debian/scripts/parameterise-ancillaries
> index 9d0b1343c2a0..dc2d08b9eac9 100755
> --- a/debian/scripts/parameterise-ancillaries
> +++ b/debian/scripts/parameterise-ancillaries
> @@ -52,6 +52,7 @@ def build_ancillary(family, package):
>          os.path.join("debian", "scripts", "flavour_finder.py"),
>          os.path.join("debian", "scripts", "auto_install.py"),
>          os.path.join("debian", "scripts", "control_craft.py"),
> +        os.path.join("debian", "scripts", "migration_helper.py"),
>          os.path.join("debian", "scripts", "variant_helper.py"),
>          os.path.join("debian", "templates", "postinst.in"),
>          os.path.join("debian", "templates", "postrm.in"),
> -- 
> 2.43.0
> 
> 
> -- 
> kernel-team mailing list
> kernel-team at lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team

Rejected for the following reason:

Any modification in LMM needs to pass through cranky fix, so all the
kernels will benefit from them.
Please fork and submit a merge request to 
https://kernel.ubuntu.com/forgejo/alessiofaina/linux-main-modules

    -Alessio Faina



More information about the kernel-team mailing list