@@ -1357,6 +1357,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
@@ -17,6 +17,8 @@
#include <linux/init_syscalls.h>
#include <linux/umh.h>
+#include "initramfs_mtime.h"
+
static ssize_t __init xwrite(struct file *file, const char *p, size_t count,
loff_t *pos)
{
@@ -116,46 +118,6 @@ static void __init free_hash(void)
}
}
-static long __init do_utime(char *filename, time64_t mtime)
-{
- struct timespec64 t[2];
-
- 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 __initdata LIST_HEAD(dir_list);
-struct dir_entry {
- struct list_head list;
- char *name;
- time64_t mtime;
-};
-
-static void __init dir_add(const char *name, time64_t mtime)
-{
- struct dir_entry *de = kmalloc(sizeof(struct dir_entry), GFP_KERNEL);
- if (!de)
- panic_show_mem("can't allocate dir_entry buffer");
- INIT_LIST_HEAD(&de->list);
- de->name = kstrdup(name, GFP_KERNEL);
- de->mtime = mtime;
- list_add(&de->list, &dir_list);
-}
-
-static void __init dir_utime(void)
-{
- struct dir_entry *de, *tmp;
- list_for_each_entry_safe(de, tmp, &dir_list, list) {
- list_del(&de->list);
- do_utime(de->name, de->mtime);
- kfree(de->name);
- kfree(de);
- }
-}
-
static __initdata time64_t mtime;
/* cpio header parsing */
@@ -379,14 +341,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;
new file mode 100644
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifdef CONFIG_INITRAMFS_PRESERVE_MTIME
+static void __init do_utime(char *filename, time64_t mtime)
+{
+ struct timespec64 t[2] = { { .tv_sec = mtime }, { .tv_sec = mtime } };
+ 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);
+struct dir_entry {
+ struct list_head list;
+ char *name;
+ time64_t mtime;
+};
+
+static void __init dir_add(const char *name, time64_t mtime)
+{
+ struct dir_entry *de = kmalloc(sizeof(struct dir_entry), GFP_KERNEL);
+ if (!de)
+ panic("can't allocate dir_entry buffer");
+ INIT_LIST_HEAD(&de->list);
+ de->name = kstrdup(name, GFP_KERNEL);
+ de->mtime = mtime;
+ list_add(&de->list, &dir_list);
+}
+
+static void __init dir_utime(void)
+{
+ struct dir_entry *de, *tmp;
+
+ list_for_each_entry_safe(de, tmp, &dir_list, list) {
+ list_del(&de->list);
+ do_utime(de->name, de->mtime);
+ kfree(de->name);
+ 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