[RFC PATCH v2 4/7] lib/cpio: Allow use outside of initramfs creation

From: Jonathan McDowell
Date: Thu Jul 28 2022 - 10:10:12 EST


Now we no longer depend on anything that lives in __init add a Kconfig
option to allow the cpio code to be used by other code within the
kernel. If not selected the code will continue to be placed within the
__init section and discarded after boot.

Signed-off-by: Jonathan McDowell <noodles@xxxxxx>
---
v2:
- Move directory EEXIST checking to patch 3
---
include/linux/cpio.h | 20 ++++++++++++---
lib/Kconfig | 3 +++
lib/cpio.c | 60 ++++++++++++++++++++++----------------------
3 files changed, 49 insertions(+), 34 deletions(-)

diff --git a/include/linux/cpio.h b/include/linux/cpio.h
index 69a15fffa5c6..7e9888e6a1ad 100644
--- a/include/linux/cpio.h
+++ b/include/linux/cpio.h
@@ -12,6 +12,18 @@

#define N_ALIGN(len) ((((len) + 1) & ~3) + 2)

+/*
+ * If nothing explicitly wants us then we can live in the __init section as
+ * only the initramfs code will call us.
+ */
+#ifdef CONFIG_CPIO
+#define __cpio
+#define __cpiodata
+#else
+#define __cpio __init
+#define __cpiodata __initdata
+#endif
+
enum cpio_state {
CPIO_START,
CPIO_COLLECT,
@@ -68,11 +80,11 @@ struct cpio_context {
struct list_head dir_list;
};

-int __init cpio_start(struct cpio_context *ctx);
-void __init cpio_finish(struct cpio_context *ctx);
-long __init cpio_write_buffer(struct cpio_context *ctx, char *buf,
+int __cpio cpio_start(struct cpio_context *ctx);
+void __cpio cpio_finish(struct cpio_context *ctx);
+long __cpio cpio_write_buffer(struct cpio_context *ctx, char *buf,
unsigned long len);
-long __init cpio_process_buffer(struct cpio_context *ctx, void *bufv,
+long __cpio cpio_process_buffer(struct cpio_context *ctx, void *bufv,
unsigned long len);

#endif /* _LINUX_CPIO_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index eaaad4d85bf2..fad66ee4caed 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -743,3 +743,6 @@ config ASN1_ENCODER

config POLYNOMIAL
tristate
+
+config CPIO
+ bool
diff --git a/lib/cpio.c b/lib/cpio.c
index 9a0120c638db..03967e063c76 100644
--- a/lib/cpio.c
+++ b/lib/cpio.c
@@ -8,7 +8,7 @@
#include <linux/security.h>
#include <linux/slab.h>

-static ssize_t __init xwrite(struct cpio_context *ctx, struct file *file,
+static ssize_t __cpio xwrite(struct cpio_context *ctx, struct file *file,
const unsigned char *p, size_t count, loff_t *pos)
{
ssize_t out = 0;
@@ -50,7 +50,7 @@ static inline int hash(int major, int minor, int ino)
return tmp & (CPIO_LINK_HASH_SIZE - 1);
}

-static char __init *find_link(struct cpio_context *ctx, int major, int minor,
+static char __cpio *find_link(struct cpio_context *ctx, int major, int minor,
int ino, umode_t mode, char *name)
{
struct cpio_link_hash **p, *q;
@@ -79,7 +79,7 @@ static char __init *find_link(struct cpio_context *ctx, int major, int minor,
return NULL;
}

-static void __init free_hash(struct cpio_context *ctx)
+static void __cpio free_hash(struct cpio_context *ctx)
{
struct cpio_link_hash **p, *q;

@@ -93,14 +93,14 @@ static void __init free_hash(struct cpio_context *ctx)
}

#ifdef CONFIG_INITRAMFS_PRESERVE_MTIME
-static void __init do_utime_path(const struct path *path, time64_t mtime)
+static void __cpio 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 int __init do_utime(char *filename, time64_t mtime)
+static int __cpio do_utime(char *filename, time64_t mtime)
{
struct path path;
int error;
@@ -114,7 +114,7 @@ static int __init do_utime(char *filename, time64_t mtime)
return error;
}

-static int __init dir_add(struct cpio_context *ctx, const char *name, time64_t mtime)
+static int __cpio dir_add(struct cpio_context *ctx, const char *name, time64_t mtime)
{
size_t nlen = strlen(name) + 1;
struct cpio_dir_entry *de;
@@ -130,7 +130,7 @@ static int __init dir_add(struct cpio_context *ctx, const char *name, time64_t m
return 0;
}

-static void __init dir_utime(struct cpio_context *ctx)
+static void __cpio dir_utime(struct cpio_context *ctx)
{
struct cpio_dir_entry *de, *tmp;

@@ -141,13 +141,13 @@ static void __init dir_utime(struct cpio_context *ctx)
}
}
#else
-static int __init do_utime(char *filename, time64_t mtime) { return 0; }
-static void __init do_utime_path(const struct path *path, time64_t mtime) {}
-static int __init dir_add(struct cpio_context *ctx, const char *name, time64_t mtime) { return 0; }
-static void __init dir_utime(struct cpio_context *ctx) {}
+static int __cpio do_utime(char *filename, time64_t mtime) { return 0; }
+static void __cpio do_utime_path(const struct path *path, time64_t mtime) {}
+static int __cpio dir_add(struct cpio_context *ctx, const char *name, time64_t mtime) { return 0; }
+static void __cpio dir_utime(struct cpio_context *ctx) {}
#endif

-static int __init cpio_chown(const char *filename, uid_t user, gid_t group,
+static int __cpio cpio_chown(const char *filename, uid_t user, gid_t group,
int flags)
{
int lookup_flags = (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
@@ -168,7 +168,7 @@ static int __init cpio_chown(const char *filename, uid_t user, gid_t group,

/* cpio header parsing */

-static void __init parse_header(struct cpio_context *ctx, char *s)
+static void __cpio parse_header(struct cpio_context *ctx, char *s)
{
unsigned long parsed[13];
char buf[9];
@@ -195,14 +195,14 @@ static void __init parse_header(struct cpio_context *ctx, char *s)

/* FSM */

-static inline void __init eat(struct cpio_context *ctx, unsigned int n)
+static inline void __cpio eat(struct cpio_context *ctx, unsigned int n)
{
ctx->victim += n;
ctx->this_header += n;
ctx->byte_count -= n;
}

-static void __init read_into(struct cpio_context *ctx, char *buf,
+static void __cpio read_into(struct cpio_context *ctx, char *buf,
unsigned int size, enum cpio_state next)
{
if (ctx->byte_count >= size) {
@@ -218,13 +218,13 @@ static void __init read_into(struct cpio_context *ctx, char *buf,
}
}

-static int __init do_start(struct cpio_context *ctx)
+static int __cpio do_start(struct cpio_context *ctx)
{
read_into(ctx, ctx->header_buf, 110, CPIO_GOTHEADER);
return 0;
}

-static int __init do_collect(struct cpio_context *ctx)
+static int __cpio do_collect(struct cpio_context *ctx)
{
unsigned long n = ctx->remains;

@@ -242,7 +242,7 @@ static int __init do_collect(struct cpio_context *ctx)
return 0;
}

-static int __init do_header(struct cpio_context *ctx)
+static int __cpio do_header(struct cpio_context *ctx)
{
if (!memcmp(ctx->collected, "070701", 6)) {
ctx->csum_present = false;
@@ -274,7 +274,7 @@ static int __init do_header(struct cpio_context *ctx)
return 0;
}

-static int __init do_skip(struct cpio_context *ctx)
+static int __cpio do_skip(struct cpio_context *ctx)
{
if (ctx->this_header + ctx->byte_count < ctx->next_header) {
eat(ctx, ctx->byte_count);
@@ -286,7 +286,7 @@ static int __init do_skip(struct cpio_context *ctx)
return 0;
}

-static int __init do_reset(struct cpio_context *ctx)
+static int __cpio do_reset(struct cpio_context *ctx)
{
while (ctx->byte_count && *ctx->victim == '\0')
eat(ctx, 1);
@@ -296,7 +296,7 @@ static int __init do_reset(struct cpio_context *ctx)
return 1;
}

-static void __init clean_path(char *pathname, umode_t fmode)
+static void __cpio clean_path(char *pathname, umode_t fmode)
{
struct path path;
struct kstat st;
@@ -318,7 +318,7 @@ static void __init clean_path(char *pathname, umode_t fmode)
}
}

-static int __init maybe_link(struct cpio_context *ctx)
+static int __cpio maybe_link(struct cpio_context *ctx)
{
struct dentry *new_dentry;
struct path old_path, new_path;
@@ -362,7 +362,7 @@ static int __init maybe_link(struct cpio_context *ctx)
return 0;
}

-static int __init do_name(struct cpio_context *ctx)
+static int __cpio do_name(struct cpio_context *ctx)
{
struct dentry *dentry;
struct path path;
@@ -444,7 +444,7 @@ static int __init do_name(struct cpio_context *ctx)
return 0;
}

-static int __init do_copy(struct cpio_context *ctx)
+static int __cpio do_copy(struct cpio_context *ctx)
{
int ret;

@@ -474,7 +474,7 @@ static int __init do_copy(struct cpio_context *ctx)
return 1;
}

-static int __init do_symlink(struct cpio_context *ctx)
+static int __cpio do_symlink(struct cpio_context *ctx)
{
struct dentry *dentry;
struct path path;
@@ -503,7 +503,7 @@ static int __init do_symlink(struct cpio_context *ctx)
return 0;
}

-static __initdata int (*actions[])(struct cpio_context *) = {
+static __cpiodata int (*actions[])(struct cpio_context *) = {
[CPIO_START] = do_start,
[CPIO_COLLECT] = do_collect,
[CPIO_GOTHEADER] = do_header,
@@ -514,7 +514,7 @@ static __initdata int (*actions[])(struct cpio_context *) = {
[CPIO_RESET] = do_reset,
};

-long __init cpio_write_buffer(struct cpio_context *ctx, char *buf,
+long __cpio cpio_write_buffer(struct cpio_context *ctx, char *buf,
unsigned long len)
{
int ret;
@@ -532,7 +532,7 @@ long __init cpio_write_buffer(struct cpio_context *ctx, char *buf,
return len - ctx->byte_count;
}

-long __init cpio_process_buffer(struct cpio_context *ctx, void *bufv,
+long __cpio cpio_process_buffer(struct cpio_context *ctx, void *bufv,
unsigned long len)
{
char *buf = (char *)bufv;
@@ -563,7 +563,7 @@ long __init cpio_process_buffer(struct cpio_context *ctx, void *bufv,
return len;
}

-int __init cpio_start(struct cpio_context *ctx)
+int __cpio cpio_start(struct cpio_context *ctx)
{
ctx->header_buf = kmalloc(110, GFP_KERNEL);
ctx->symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
@@ -579,7 +579,7 @@ int __init cpio_start(struct cpio_context *ctx)
return 0;
}

-void __init cpio_finish(struct cpio_context *ctx)
+void __cpio cpio_finish(struct cpio_context *ctx)
{
dir_utime(ctx);
kfree(ctx->name_buf);
--
2.30.2