[PATCH v3 0/3] initrd: remove half of classic initrd support

Askar Safin posted 3 patches 3 months, 3 weeks ago
There is a newer version of this series
.../admin-guide/kernel-parameters.txt         |  12 +-
Documentation/admin-guide/sysctl/kernel.rst   |   6 -
arch/arm/configs/neponset_defconfig           |   2 +-
fs/init.c                                     |  14 ---
include/linux/init_syscalls.h                 |   1 -
include/linux/initrd.h                        |   2 -
include/uapi/linux/sysctl.h                   |   1 -
init/do_mounts.c                              |  11 +-
init/do_mounts.h                              |  18 +--
init/do_mounts_initrd.c                       | 107 ++----------------
init/do_mounts_rd.c                           |  24 +---
11 files changed, 23 insertions(+), 175 deletions(-)
[PATCH v3 0/3] initrd: remove half of classic initrd support
Posted by Askar Safin 3 months, 3 weeks ago
Intro
====
This patchset removes half of classic initrd (initial RAM disk) support,
i. e. linuxrc code path, which was deprecated in 2020.
Initramfs still stays, RAM disk itself (brd) still stays.
And other half of initrd stays, too.
init/do_mounts* are listed in VFS entry in
MAINTAINERS, so I think this patchset should go through VFS tree.
I tested the patchset on 8 (!!!) archs in Qemu (see details below).
If you still use initrd, see below for workaround.

In 2020 deprecation notice was put to linuxrc initrd code path.
In v1 I tried to remove initrd
fully, but Nicolas Schichan reported that he still uses
other code path (root=/dev/ram0 one) on million devices [4].
root=/dev/ram0 code path did not contain deprecation notice.

So, in this version of patchset I remove deprecated code path,
i. e. linuxrc one, while keeping other, i. e. root=/dev/ram0 one.

Also I put deprecation notice to remaining code path, i. e. to
root=/dev/ram0 one. I plan to send patches for full removal
of initrd after one year, i. e. in September 2026 (of course,
initramfs will still work).

Also, I tried to make this patchset small to make sure it
can be reverted easily. I plan to send cleanups later.

Details
====
Other user-visible changes:

- Removed kernel command line parameters "load_ramdisk" and
"prompt_ramdisk", which did nothing and were deprecated
- Removed /proc/sys/kernel/real-root-dev . It was used
for initrd only
- Command line parameters "noinitrd" and "ramdisk_start=" are deprecated

This patchset is based on v6.18-rc1.

Testing
====
I tested my patchset on many architectures in Qemu using my Rust
program, heavily based on mkroot [1].

I used the following cross-compilers:

aarch64-linux-musleabi
armv4l-linux-musleabihf
armv5l-linux-musleabihf
armv7l-linux-musleabihf
i486-linux-musl
i686-linux-musl
mips-linux-musl
mips64-linux-musl
mipsel-linux-musl
powerpc-linux-musl
powerpc64-linux-musl
powerpc64le-linux-musl
riscv32-linux-musl
riscv64-linux-musl
s390x-linux-musl
sh4-linux-musl
sh4eb-linux-musl
x86_64-linux-musl

taken from this directory [2].

So, as you can see, there are 18 triplets, which correspond to 8 subdirs in arch/.

For every triplet I tested that:
- Initramfs still works (both builtin and external)
- Direct boot from disk still works
- Remaining initrd code path (root=/dev/ram0) still works

Workaround
====
If "retain_initrd" is passed to kernel, then initramfs/initrd,
passed by bootloader, is retained and becomes available after boot
as read-only magic file /sys/firmware/initrd [3].

No copies are involved. I. e. /sys/firmware/initrd is simply
a reference to original blob passed by bootloader.

This works even if initrd/initramfs is not recognized by kernel
in any way, i. e. even if it is not valid cpio archive, nor
a fs image supported by classic initrd.

This works both with my patchset and without it.

This means that you can emulate classic initrd so:
link builtin initramfs to kernel; in /init in this initramfs
copy /sys/firmware/initrd to some file in / and loop-mount it.

This is even better than classic initrd, because:
- You can use fs not supported by classic initrd, for example erofs
- One copy is involved (from /sys/firmware/initrd to some file in /)
as opposed to two when using classic initrd

Still, I don't recommend using this workaround, because
I want everyone to migrate to proper modern initramfs.
But still you can use this workaround if you want.

Also: it is not possible to directly loop-mount
/sys/firmware/initrd . Theoretically kernel can be changed
to allow this (and/or to make it writable), but I think nobody needs this.
And I don't want to implement this.

On Qemu's -initrd and GRUB's initrd
====
Don't panic, this patchset doesn't remove initramfs
(which is used by nearly all Linux distros). And I don't
have plans to remove it.

Qemu's -initrd option and GRUB's initrd command refer
to initrd bootloader mechanism, which is used to
load both initrd and (external) initramfs.

So, if you use Qemu's -initrd or GRUB's initrd,
then you likely use them to pass initramfs, and thus
you are safe.

v1: https://lore.kernel.org/lkml/20250913003842.41944-1-safinaskar@gmail.com/

v1 -> v2 changes:
- A lot. I removed most patches, see cover letter for details

v2: https://lore.kernel.org/lkml/20251010094047.3111495-1-safinaskar@gmail.com/

v2 -> v3 changes:
- Commit messages
- Expanded docs for "noinitrd"
- Added link to /sys/firmware/initrd workaround to pr_warn

[1] https://github.com/landley/toybox/tree/master/mkroot
[2] https://landley.net/toybox/downloads/binaries/toolchains/latest
[3] https://lore.kernel.org/all/20231207235654.16622-1-graf@amazon.com/
[4] https://lore.kernel.org/lkml/20250918152830.438554-1-nschichan@freebox.fr/

Askar Safin (3):
  init: remove deprecated "load_ramdisk" and "prompt_ramdisk" command
    line parameters
  initrd: remove deprecated code path (linuxrc)
  init: remove /proc/sys/kernel/real-root-dev

 .../admin-guide/kernel-parameters.txt         |  12 +-
 Documentation/admin-guide/sysctl/kernel.rst   |   6 -
 arch/arm/configs/neponset_defconfig           |   2 +-
 fs/init.c                                     |  14 ---
 include/linux/init_syscalls.h                 |   1 -
 include/linux/initrd.h                        |   2 -
 include/uapi/linux/sysctl.h                   |   1 -
 init/do_mounts.c                              |  11 +-
 init/do_mounts.h                              |  18 +--
 init/do_mounts_initrd.c                       | 107 ++----------------
 init/do_mounts_rd.c                           |  24 +---
 11 files changed, 23 insertions(+), 175 deletions(-)


base-commit: 3a8660878839faadb4f1a6dd72c3179c1df56787
-- 
2.47.3
Re: [PATCH v3 0/3] initrd: remove half of classic initrd support
Posted by Christian Brauner 3 months, 2 weeks ago
On Fri, Oct 17, 2025 at 06:09:53AM +0000, Askar Safin wrote:
> Intro
> ====
> This patchset removes half of classic initrd (initial RAM disk) support,
> i. e. linuxrc code path, which was deprecated in 2020.
> Initramfs still stays, RAM disk itself (brd) still stays.
> And other half of initrd stays, too.
> init/do_mounts* are listed in VFS entry in
> MAINTAINERS, so I think this patchset should go through VFS tree.
> I tested the patchset on 8 (!!!) archs in Qemu (see details below).
> If you still use initrd, see below for workaround.
> 
> In 2020 deprecation notice was put to linuxrc initrd code path.
> In v1 I tried to remove initrd
> fully, but Nicolas Schichan reported that he still uses
> other code path (root=/dev/ram0 one) on million devices [4].
> root=/dev/ram0 code path did not contain deprecation notice.

Without Acks or buy-in from other maintainers this is not a change we
can just do given that a few people already piped up and expressed
reservations that this would be doable for them.

@Christoph, you marked this as deprecated years ago.
What's your take on this?

> 
> So, in this version of patchset I remove deprecated code path,
> i. e. linuxrc one, while keeping other, i. e. root=/dev/ram0 one.
> 
> Also I put deprecation notice to remaining code path, i. e. to
> root=/dev/ram0 one. I plan to send patches for full removal
> of initrd after one year, i. e. in September 2026 (of course,
> initramfs will still work).
> 
> Also, I tried to make this patchset small to make sure it
> can be reverted easily. I plan to send cleanups later.
> 
> Details
> ====
> Other user-visible changes:
> 
> - Removed kernel command line parameters "load_ramdisk" and
> "prompt_ramdisk", which did nothing and were deprecated
> - Removed /proc/sys/kernel/real-root-dev . It was used
> for initrd only
> - Command line parameters "noinitrd" and "ramdisk_start=" are deprecated
> 
> This patchset is based on v6.18-rc1.
> 
> Testing
> ====
> I tested my patchset on many architectures in Qemu using my Rust
> program, heavily based on mkroot [1].
> 
> I used the following cross-compilers:
> 
> aarch64-linux-musleabi
> armv4l-linux-musleabihf
> armv5l-linux-musleabihf
> armv7l-linux-musleabihf
> i486-linux-musl
> i686-linux-musl
> mips-linux-musl
> mips64-linux-musl
> mipsel-linux-musl
> powerpc-linux-musl
> powerpc64-linux-musl
> powerpc64le-linux-musl
> riscv32-linux-musl
> riscv64-linux-musl
> s390x-linux-musl
> sh4-linux-musl
> sh4eb-linux-musl
> x86_64-linux-musl
> 
> taken from this directory [2].
> 
> So, as you can see, there are 18 triplets, which correspond to 8 subdirs in arch/.
> 
> For every triplet I tested that:
> - Initramfs still works (both builtin and external)
> - Direct boot from disk still works
> - Remaining initrd code path (root=/dev/ram0) still works
> 
> Workaround
> ====
> If "retain_initrd" is passed to kernel, then initramfs/initrd,
> passed by bootloader, is retained and becomes available after boot
> as read-only magic file /sys/firmware/initrd [3].
> 
> No copies are involved. I. e. /sys/firmware/initrd is simply
> a reference to original blob passed by bootloader.
> 
> This works even if initrd/initramfs is not recognized by kernel
> in any way, i. e. even if it is not valid cpio archive, nor
> a fs image supported by classic initrd.
> 
> This works both with my patchset and without it.
> 
> This means that you can emulate classic initrd so:
> link builtin initramfs to kernel; in /init in this initramfs
> copy /sys/firmware/initrd to some file in / and loop-mount it.
> 
> This is even better than classic initrd, because:
> - You can use fs not supported by classic initrd, for example erofs
> - One copy is involved (from /sys/firmware/initrd to some file in /)
> as opposed to two when using classic initrd
> 
> Still, I don't recommend using this workaround, because
> I want everyone to migrate to proper modern initramfs.
> But still you can use this workaround if you want.
> 
> Also: it is not possible to directly loop-mount
> /sys/firmware/initrd . Theoretically kernel can be changed
> to allow this (and/or to make it writable), but I think nobody needs this.
> And I don't want to implement this.
> 
> On Qemu's -initrd and GRUB's initrd
> ====
> Don't panic, this patchset doesn't remove initramfs
> (which is used by nearly all Linux distros). And I don't
> have plans to remove it.
> 
> Qemu's -initrd option and GRUB's initrd command refer
> to initrd bootloader mechanism, which is used to
> load both initrd and (external) initramfs.
> 
> So, if you use Qemu's -initrd or GRUB's initrd,
> then you likely use them to pass initramfs, and thus
> you are safe.
> 
> v1: https://lore.kernel.org/lkml/20250913003842.41944-1-safinaskar@gmail.com/
> 
> v1 -> v2 changes:
> - A lot. I removed most patches, see cover letter for details
> 
> v2: https://lore.kernel.org/lkml/20251010094047.3111495-1-safinaskar@gmail.com/
> 
> v2 -> v3 changes:
> - Commit messages
> - Expanded docs for "noinitrd"
> - Added link to /sys/firmware/initrd workaround to pr_warn
> 
> [1] https://github.com/landley/toybox/tree/master/mkroot
> [2] https://landley.net/toybox/downloads/binaries/toolchains/latest
> [3] https://lore.kernel.org/all/20231207235654.16622-1-graf@amazon.com/
> [4] https://lore.kernel.org/lkml/20250918152830.438554-1-nschichan@freebox.fr/
> 
> Askar Safin (3):
>   init: remove deprecated "load_ramdisk" and "prompt_ramdisk" command
>     line parameters
>   initrd: remove deprecated code path (linuxrc)
>   init: remove /proc/sys/kernel/real-root-dev
> 
>  .../admin-guide/kernel-parameters.txt         |  12 +-
>  Documentation/admin-guide/sysctl/kernel.rst   |   6 -
>  arch/arm/configs/neponset_defconfig           |   2 +-
>  fs/init.c                                     |  14 ---
>  include/linux/init_syscalls.h                 |   1 -
>  include/linux/initrd.h                        |   2 -
>  include/uapi/linux/sysctl.h                   |   1 -
>  init/do_mounts.c                              |  11 +-
>  init/do_mounts.h                              |  18 +--
>  init/do_mounts_initrd.c                       | 107 ++----------------
>  init/do_mounts_rd.c                           |  24 +---
>  11 files changed, 23 insertions(+), 175 deletions(-)
> 
> 
> base-commit: 3a8660878839faadb4f1a6dd72c3179c1df56787
> -- 
> 2.47.3
>
Re: [PATCH v3 0/3] initrd: remove half of classic initrd support
Posted by Christoph Hellwig 3 months, 2 weeks ago
On Tue, Oct 21, 2025 at 03:05:35PM +0200, Christian Brauner wrote:
> Without Acks or buy-in from other maintainers this is not a change we
> can just do given that a few people already piped up and expressed
> reservations that this would be doable for them.
> 
> @Christoph, you marked this as deprecated years ago.
> What's your take on this?

I'd love to see it go obviously.  But IIRC we had various users show
up, which speaks against removing it.  Maybe the first step would be
a separate config option just for block-based initrd?
Re: [PATCH v3 0/3] initrd: remove half of classic initrd support
Posted by Askar Safin 3 months, 2 weeks ago
Christoph Hellwig <hch@infradead.org>:
> On Tue, Oct 21, 2025 at 03:05:35PM +0200, Christian Brauner wrote:
> > Without Acks or buy-in from other maintainers this is not a change we
> > can just do given that a few people already piped up and expressed
> > reservations that this would be doable for them.
> > 
> > @Christoph, you marked this as deprecated years ago.
> > What's your take on this?
> 
> I'd love to see it go obviously.  But IIRC we had various users show
> up, which speaks against removing it.  Maybe the first step would be
> a separate config option just for block-based initrd?

So far in recent months 3 people spoke against initrd removal. All they are in Cc. They are:

- Julian Stecklina. He planned to use initrd with erofs, which is currently
not supported anyway. Also, he replied to v1:
"You have all my support for nuking so much legacy code!"
"Acked-by: Julian Stecklina <julian.stecklina@cyberus-technology.de>"
( https://lore.kernel.org/lkml/1f9aee6090716db537e9911685904786b030111f.camel@cyberus-technology.de/ )

- Gao Xiang, maintainer of erofs. He also planned to use initrd with erofs,
which is currently not supported anyway. Also, he said to me:
> Again, I don't have any strong opinion to kill initrd entirely because
> I think initdax may be more efficient and I don't have any time to work
> on this part -- it's unrelated to my job.
( https://lore.kernel.org/all/79315382-5ba8-42c1-ad03-5cb448b23b72@linux.alibaba.com/ )

- Nicolas Schichan. He has million devices, which use initrd. But they use
root=/dev/ram code path, not linuxrc code path, which I'm removing. He
explained this here:
https://lore.kernel.org/lkml/20250918152830.438554-1-nschichan@freebox.fr/

So, this patchset will not impact these people. So, I think it is okay
to remove linuxrc now. We can revert this patchset if needed.

-- 
Askar Safin