Skip to content

Commit

Permalink
initramfs: switch initramfs unpacking to struct file based APIs
Browse files Browse the repository at this point in the history
There is no good reason to mess with file descriptors from in-kernel
code, switch the initramfs unpacking to struct file based write
instead.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Christoph Hellwig committed Jul 31, 2020
1 parent b2a74d5 commit bf6419e
Showing 1 changed file with 26 additions and 21 deletions.
47 changes: 26 additions & 21 deletions init/initramfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
#include <linux/memblock.h>
#include <linux/namei.h>

static ssize_t __init xwrite(int fd, const char *p, size_t count)
static ssize_t __init xwrite(struct file *file, const char *p, size_t count,
loff_t *pos)
{
ssize_t out = 0;

/* sys_write only can write MAX_RW_COUNT aka 2G-4K bytes at most */
while (count) {
ssize_t rv = ksys_write(fd, p, count);
ssize_t rv = kernel_write(file, p, count, pos);

if (rv < 0) {
if (rv == -EINTR || rv == -EAGAIN)
Expand Down Expand Up @@ -317,7 +318,8 @@ static int __init maybe_link(void)
return 0;
}

static __initdata int wfd;
static __initdata struct file *wfile;
static __initdata loff_t wfile_pos;

static int __init do_name(void)
{
Expand All @@ -334,16 +336,17 @@ static int __init do_name(void)
int openflags = O_WRONLY|O_CREAT;
if (ml != 1)
openflags |= O_TRUNC;
wfd = ksys_open(collected, openflags, mode);

if (wfd >= 0) {
ksys_fchown(wfd, uid, gid);
ksys_fchmod(wfd, mode);
if (body_len)
ksys_ftruncate(wfd, body_len);
vcollected = kstrdup(collected, GFP_KERNEL);
state = CopyFile;
}
wfile = filp_open(collected, openflags, mode);
if (IS_ERR(wfile))
return 0;
wfile_pos = 0;

vfs_fchown(wfile, uid, gid);
vfs_fchmod(wfile, mode);
if (body_len)
vfs_truncate(&wfile->f_path, body_len);
vcollected = kstrdup(collected, GFP_KERNEL);
state = CopyFile;
}
} else if (S_ISDIR(mode)) {
ksys_mkdir(collected, mode);
Expand All @@ -365,16 +368,16 @@ static int __init do_name(void)
static int __init do_copy(void)
{
if (byte_count >= body_len) {
if (xwrite(wfd, victim, body_len) != body_len)
if (xwrite(wfile, victim, body_len, &wfile_pos) != body_len)
error("write error");
ksys_close(wfd);
fput(wfile);
do_utime(vcollected, mtime);
kfree(vcollected);
eat(body_len);
state = SkipIt;
return 0;
} else {
if (xwrite(wfd, victim, byte_count) != byte_count)
if (xwrite(wfile, victim, byte_count, &wfile_pos) != byte_count)
error("write error");
body_len -= byte_count;
eat(byte_count);
Expand Down Expand Up @@ -576,21 +579,23 @@ static inline bool kexec_free_initrd(void)
static void __init populate_initrd_image(char *err)
{
ssize_t written;
int fd;
struct file *file;
loff_t pos = 0;

unpack_to_rootfs(__initramfs_start, __initramfs_size);

printk(KERN_INFO "rootfs image is not initramfs (%s); looks like an initrd\n",
err);
fd = ksys_open("/initrd.image", O_WRONLY | O_CREAT, 0700);
if (fd < 0)
file = filp_open("/initrd.image", O_WRONLY | O_CREAT, 0700);
if (IS_ERR(file))
return;

written = xwrite(fd, (char *)initrd_start, initrd_end - initrd_start);
written = xwrite(file, (char *)initrd_start, initrd_end - initrd_start,
&pos);
if (written != initrd_end - initrd_start)
pr_err("/initrd.image: incomplete write (%zd != %ld)\n",
written, initrd_end - initrd_start);
ksys_close(fd);
fput(file);
}
#endif /* CONFIG_BLK_DEV_RAM */

Expand Down

0 comments on commit bf6419e

Please sign in to comment.