Package: initramfs-tools Version: 0.99 Severity: normal File: /usr/sbin/update-initramfs
In the last few versions of initramfs-tools, update-initramfs started taking an excessively long time to generate the initramfs: ~$ time sudo update-initramfs -u update-initramfs: Generating /boot/initrd.img-3.1.0-1-amd64 real 0m26.197s user 0m14.785s sys 0m1.196s This results in a long delay every time I upgrade either a kernel or any package with an update-initramfs hook. As far as I can tell, a large part of this processing time seems to consist of the per-module processing for the ~500 kernel modules copied into the initramfs, forking off a pile of programs for each one. I tried optimizing the per-module hot path to eliminate as many forks as possible, and managed to speed it up considerably: ~$ time sudo update-initramfs -u update-initramfs: Generating /boot/initrd.img-3.1.0-1-amd64 real 0m21.385s user 0m14.393s sys 0m0.740s I've attached a patch implementing these optimizations. A few other possible improvements: - Generate a list of modules and processing them all in batch at the end of update-initramfs, to allow calling modprobe and modinfo only once. Likely to make a huge difference. - In the absence of the above, make manual_add_modules take a list of modules and process them all, and make the various hooks pass a list of modules to manual_add_modules rather than calling it repeatedly. - Avoid using copy_exec for firmware binaries, to avoid running ldd on them. - Cache the contents of /proc/modules and ${CONFDIR}/modules, and eliminating the call to grep via more magic shell variable tricks. - Rewrite the whole thing in something less glacial than shell; perhaps something with bindings to the new libkmod. Or, at least rewrite the hot paths, and use the shell only to string pieces together. Hope that helps, Josh Triplett -- Package-specific info: -- initramfs sizes -- lsmod Module Size Used by parport_pc 22364 0 ppdev 12763 0 lp 17149 0 parport 31858 3 parport_pc,ppdev,lp bnep 17567 2 rfcomm 33622 0 acpi_cpufreq 12935 1 mperf 12453 1 acpi_cpufreq cpufreq_powersave 12454 0 cpufreq_conservative 13147 0 cpufreq_stats 12866 0 cpufreq_userspace 12576 0 fuse 61981 1 ext3 161848 1 jbd 56928 1 ext3 loop 22597 0 kvm_intel 121792 0 kvm 278183 1 kvm_intel snd_hda_codec_hdmi 26548 1 snd_hda_codec_conexant 45245 1 joydev 17266 0 arc4 12458 2 thinkpad_acpi 61270 0 snd_seq_midi 12848 0 snd_rawmidi 23060 1 snd_seq_midi snd_seq_midi_event 13316 1 snd_seq_midi snd_seq 45093 2 snd_seq_midi,snd_seq_midi_event snd_hda_intel 26182 4 snd_hda_codec 72920 3 snd_hda_codec_hdmi,snd_hda_codec_conexant,snd_hda_intel snd_hwdep 13186 1 snd_hda_codec snd_pcm_oss 41081 0 iwlagn 166592 0 snd_mixer_oss 17916 1 snd_pcm_oss snd_seq_device 13176 3 snd_seq_midi,snd_rawmidi,snd_seq mac80211 183093 1 iwlagn ecb 12737 1 snd_pcm 63744 5 snd_hda_codec_hdmi,snd_hda_intel,snd_hda_codec,snd_pcm_oss i915 348449 2 psmouse 55543 0 evdev 17562 8 serio_raw 12850 0 drm_kms_helper 27227 1 i915 i2c_i801 16870 0 drm 167371 3 i915,drm_kms_helper cfg80211 132703 2 iwlagn,mac80211 btusb 17502 2 iTCO_wdt 17081 0 i2c_algo_bit 12841 1 i915 snd_timer 22917 3 snd_seq,snd_pcm iTCO_vendor_support 12704 1 iTCO_wdt bluetooth 119290 13 bnep,rfcomm,btusb snd 52798 19 snd_hda_codec_hdmi,snd_hda_codec_conexant,thinkpad_acpi,snd_rawmidi,snd_seq,snd_hda_intel,snd_hda_codec,snd_hwdep,snd_pcm_oss,snd_mixer_oss,snd_seq_device,snd_pcm,snd_timer snd_page_alloc 13003 2 snd_hda_intel,snd_pcm rfkill 19012 4 thinkpad_acpi,cfg80211,bluetooth battery 13109 0 i2c_core 23876 5 i915,drm_kms_helper,i2c_i801,drm,i2c_algo_bit soundcore 13065 1 snd wmi 13243 0 nvram 13049 1 thinkpad_acpi ac 12624 0 power_supply 13475 2 battery,ac video 17628 1 i915 button 12937 1 i915 processor 27949 1 acpi_cpufreq ext4 312988 1 mbcache 13065 2 ext3,ext4 jbd2 62015 1 ext4 crc16 12343 2 bluetooth,ext4 sha256_generic 16797 2 aesni_intel 50643 28 cryptd 14517 9 aesni_intel aes_x86_64 16796 1 aesni_intel aes_generic 33026 2 aesni_intel,aes_x86_64 cbc 12754 0 dm_crypt 22586 1 dm_mod 63353 9 dm_crypt sd_mod 36136 3 crc_t10dif 12348 1 sd_mod ahci 24997 2 libahci 22860 1 ahci libata 140545 2 ahci,libahci scsi_mod 162376 2 sd_mod,libata xhci_hcd 64215 0 sdhci_pci 13483 0 sdhci 26577 1 sdhci_pci ehci_hcd 40215 0 mmc_core 63754 1 sdhci thermal 17383 0 thermal_sys 18040 3 video,processor,thermal usbcore 124095 4 btusb,xhci_hcd,ehci_hcd e1000e 125122 0 -- /etc/initramfs-tools/modules -- /etc/kernel-img.conf # Kernel image management overrides # See kernel-img.conf(5) for details do_symlinks = no do_bootloader = no do_initrd = yes link_in_boot = no -- /etc/initramfs-tools/initramfs.conf MODULES=most BUSYBOX=y KEYMAP=n COMPRESS=gzip BOOT=local DEVICE= NFSROOT=auto -- /etc/initramfs-tools/update-initramfs.conf update_initramfs=yes backup_initramfs=no -- /etc/crypttab sda2_crypt UUID=346c3b45-ab3d-4a4b-a08c-4aa99b897132 none luks -- mkinitramfs hooks /etc/initramfs-tools/hooks/: /usr/share/initramfs-tools/hooks: busybox cryptgnupg cryptkeyctl cryptopenct cryptopensc cryptpassdev cryptroot dmsetup fuse keymap klibc lvm2 thermal udev -- System Information: Debian Release: wheezy/sid APT prefers unstable APT policy: (500, 'unstable'), (500, 'stable'), (1, 'experimental') Architecture: amd64 (x86_64) Kernel: Linux 3.1.0-1-amd64 (SMP w/4 CPU cores) Locale: LANG=C.UTF-8, LC_CTYPE=C.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages initramfs-tools depends on: ii cpio 2.11-7 ii findutils 4.4.2-1+b1 ii klibc-utils 1.5.25-1 ii module-init-tools 3.16-1 ii udev 175-3 Versions of packages initramfs-tools recommends: ii busybox 1:1.19.3-5 Versions of packages initramfs-tools suggests: ii bash-completion 1:1.3-1 -- no debconf information
--- /usr/share/initramfs-tools/hook-functions 2011-05-13 02:56:12.000000000 -0700 +++ hook-functions 2011-12-17 22:35:04.553348553 -0800 @@ -42,17 +42,20 @@ # Add dependent modules + eventual firmware manual_add_modules() { - local kmod firmware + local prefix kmod firmware + + modprobe --set-version="${version}" --ignore-install --quiet --show-depends "${1}" | + while read prefix kmod ; do + if [ "${prefix}" != "insmod" ]; then + continue + fi - for kmod in $(modprobe --set-version="${version}" --ignore-install \ - --quiet --show-depends "${1}" | awk '/^insmod/ { print $2 }'); do # Prune duplicates if [ -e "${DESTDIR}/${kmod}" ]; then continue fi - mkdir -p "${DESTDIR}/$(dirname "${kmod}")" - cp -pL "${kmod}" "${DESTDIR}/$(dirname "${kmod}")" + install -Dpm 644 "$kmod" "${DESTDIR}/$kmod" if [ "${verbose}" = "y" ]; then echo "Adding module ${kmod}" fi @@ -74,10 +77,9 @@ continue fi - if grep -q "^$(basename "${kmod}" .ko)[[:space:]]" \ - /proc/modules \ - || grep -q "^$(basename "${kmod}" .ko)" \ - "${CONFDIR}/modules"; then + kmod_modname="${kmod##*/}" + kmod_modname="${kmod_modname%.ko}" + if grep -q "^$kmod_modname\\>" /proc/modules "${CONFDIR}/modules"; then echo "W: Possible missing firmware /lib/firmware/${firmware} for module $(basename ${kmod} .ko)" >&2 fi continue