Skip to content

Commit

Permalink
initramfs: add INITRAMFS_PRESERVE_MTIME Kconfig option
Browse files Browse the repository at this point in the history
initramfs cpio mtime preservation, as implemented in commit 889d51a
("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

The above extraction times were measured using ftrace (initcall_finish -
initcall_start) values for populate_rootfs() with initramfs_async
disabled.

[[email protected]: rebase atop dir_entry.name flexible array member and drop separate initramfs_mtime.h header]
Link: https://lkml.org/lkml/2008/9/3/424
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: David Disseldorp <[email protected]>
Reviewed-by: Martin Wilck <[email protected]>
Cc: Al Viro <[email protected]>
Cc: Christian Brauner <[email protected]>
Cc: Matthew Wilcox (Oracle) <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
  • Loading branch information
ddiss authored and akpm00 committed May 10, 2022
1 parent fcb7aed commit 1274aea
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 12 deletions.
10 changes: 10 additions & 0 deletions init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 16 additions & 12 deletions init/initramfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 1274aea

Please sign in to comment.