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> --- include/linux/cpio.h | 20 ++++++++--- lib/Kconfig | 3 ++ lib/cpio.c | 80 +++++++++++++++++++++++--------------------- 3 files changed, 61 insertions(+), 42 deletions(-) diff --git a/include/linux/cpio.h b/include/linux/cpio.h index d8c1344a6cc3..b05140a565cb 100644 --- a/include/linux/cpio.h +++ b/include/linux/cpio.h @@ -11,6 +11,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, @@ -67,11 +79,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 6ae443a1c103..16629ad1e339 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; @@ -397,14 +397,18 @@ static int __init do_name(struct cpio_context *ctx) } } else if (S_ISDIR(ctx->mode)) { dentry = kern_path_create(AT_FDCWD, ctx->collected, &path, LOOKUP_DIRECTORY); - if (IS_ERR(dentry)) - return PTR_ERR(dentry); - error = security_path_mkdir(&path, dentry, ctx->mode); - if (!error) - error = vfs_mkdir(mnt_user_ns(path.mnt), path.dentry->d_inode, - dentry, ctx->mode); - done_path_create(&path, dentry); - if (error) + if (!IS_ERR(dentry)) { + error = security_path_mkdir(&path, dentry, ctx->mode); + if (!error) + error = vfs_mkdir(mnt_user_ns(path.mnt), + path.dentry->d_inode, + dentry, ctx->mode); + done_path_create(&path, dentry); + } else { + error = PTR_ERR(dentry); + } + + if (error && error != -EEXIST) return error; cpio_chown(ctx->collected, ctx->uid, ctx->gid, 0); @@ -438,7 +442,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; @@ -468,7 +472,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; @@ -497,7 +501,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, @@ -508,7 +512,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; @@ -526,7 +530,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; @@ -557,7 +561,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); @@ -573,7 +577,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.36.1