Message ID | 20220404093429.27570-4-ddiss@suse.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | initramfs: "crc" cpio format and INITRAMFS_PRESERVE_MTIME | expand |
On Mon, 4 Apr 2022 11:34:27 +0200 David Disseldorp <ddiss@suse.de> wrote: > initramfs cpio mtime preservation, as implemented in commit 889d51a10712 > ("initramfs: add option to preserve mtime from initramfs cpio images"), > uses a linked list to defer directory mtime processing until after all > other items in the cpio archive have been processed. This is done to > ensure that parent directory mtimes aren't overwritten via subsequent > child creation. > > The lkml link below indicates that the mtime retention use case was for > embedded devices with applications running exclusively out of initramfs, > where the 32-bit mtime value provided a rough file version identifier. > Linux distributions which discard an extracted initramfs immediately > after the root filesystem has been mounted may want to avoid the > unnecessary overhead. > > This change adds a new INITRAMFS_PRESERVE_MTIME Kconfig option, which > can be used to disable on-by-default mtime retention and in turn > speed up initramfs extraction, particularly for cpio archives with large > directory counts. > > Benchmarks with a one million directory cpio archive extracted 20 times > demonstrated: > mean extraction time (s) std dev > INITRAMFS_PRESERVE_MTIME=y 3.808 0.006 > INITRAMFS_PRESERVE_MTIME unset 3.056 0.004 So about 35 nsec per directory? By how much is this likely to reduce boot time in a real-world situation?
On Tue, 26 Apr 2022 13:39:08 -0700, Andrew Morton wrote: > On Mon, 4 Apr 2022 11:34:27 +0200 David Disseldorp <ddiss@suse.de> wrote: > > > initramfs cpio mtime preservation, as implemented in commit 889d51a10712 > > ("initramfs: add option to preserve mtime from initramfs cpio images"), > > uses a linked list to defer directory mtime processing until after all > > other items in the cpio archive have been processed. This is done to > > ensure that parent directory mtimes aren't overwritten via subsequent > > child creation. > > > > The lkml link below indicates that the mtime retention use case was for > > embedded devices with applications running exclusively out of initramfs, > > where the 32-bit mtime value provided a rough file version identifier. > > Linux distributions which discard an extracted initramfs immediately > > after the root filesystem has been mounted may want to avoid the > > unnecessary overhead. > > > > This change adds a new INITRAMFS_PRESERVE_MTIME Kconfig option, which > > can be used to disable on-by-default mtime retention and in turn > > speed up initramfs extraction, particularly for cpio archives with large > > directory counts. > > > > Benchmarks with a one million directory cpio archive extracted 20 times > > demonstrated: > > mean extraction time (s) std dev > > INITRAMFS_PRESERVE_MTIME=y 3.808 0.006 > > INITRAMFS_PRESERVE_MTIME unset 3.056 0.004 > > So about 35 nsec per directory? ~750 nsec - I should have clarified that the "20" refers to the number of runs over which the "mean extraction time" is averaged. > By how much is this likely to reduce boot time in a real-world situation? Not much, although my xfstests initramfs images tend to get into the hundreds of directories. These numbers were captured using QEMU/kvm on my laptop - I could rerun the benchmark on an old ARM SBC if more data points are needed. Cheers, David
diff --git a/init/Kconfig b/init/Kconfig index ddcbefe535e9..0fbaa07810a4 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1361,6 +1361,16 @@ config BOOT_CONFIG If unsure, say Y. +config INITRAMFS_PRESERVE_MTIME + bool "Preserve cpio archive mtimes in initramfs" + default y + help + Each entry in an initramfs cpio archive carries an mtime value. When + enabled, extracted cpio items take this mtime, with directory mtime + setting deferred until after creation of any child entries. + + If unsure, say Y. + choice prompt "Compiler optimization level" default CC_OPTIMIZE_FOR_PERFORMANCE diff --git a/init/initramfs.c b/init/initramfs.c index 656d2d71349f..b5bfed859fa9 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -116,15 +116,17 @@ static void __init free_hash(void) } } -static long __init do_utime(char *filename, time64_t mtime) +#ifdef CONFIG_INITRAMFS_PRESERVE_MTIME +static void __init do_utime(char *filename, time64_t mtime) { - struct timespec64 t[2]; + struct timespec64 t[2] = { { .tv_sec = mtime }, { .tv_sec = mtime } }; + init_utimes(filename, t); +} - t[0].tv_sec = mtime; - t[0].tv_nsec = 0; - t[1].tv_sec = mtime; - t[1].tv_nsec = 0; - return init_utimes(filename, t); +static void __init do_utime_path(const struct path *path, time64_t mtime) +{ + struct timespec64 t[2] = { { .tv_sec = mtime }, { .tv_sec = mtime } }; + vfs_utimes(path, t); } static __initdata LIST_HEAD(dir_list); @@ -157,6 +159,12 @@ static void __init dir_utime(void) kfree(de); } } +#else +static void __init do_utime(char *filename, time64_t mtime) {} +static void __init do_utime_path(const struct path *path, time64_t mtime) {} +static void __init dir_add(const char *name, time64_t mtime) {} +static void __init dir_utime(void) {} +#endif static __initdata time64_t mtime; @@ -381,14 +389,10 @@ static int __init do_name(void) static int __init do_copy(void) { if (byte_count >= body_len) { - struct timespec64 t[2] = { }; if (xwrite(wfile, victim, body_len, &wfile_pos) != body_len) error("write error"); - t[0].tv_sec = mtime; - t[1].tv_sec = mtime; - vfs_utimes(&wfile->f_path, t); - + do_utime_path(&wfile->f_path, mtime); fput(wfile); eat(body_len); state = SkipIt;