Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 246d6635 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Greg Kroah-Hartman
Browse files

initramfs: switch initramfs unpacking to struct file based APIs



[ Upstream commit bf6419e4d5440c6d414a320506c5488857a5b001 ]

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: default avatarChristoph Hellwig <hch@lst.de>
Acked-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Stable-dep-of: 4624b346cf67 ("init: open /initrd.image with O_LARGEFILE")
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent b78a7226
Loading
Loading
Loading
Loading
+26 −21
Original line number Diff line number Diff line
@@ -11,13 +11,14 @@
#include <linux/utime.h>
#include <linux/file.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)
@@ -315,7 +316,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)
{
@@ -332,17 +334,18 @@ static int __init do_name(void)
			int openflags = O_WRONLY|O_CREAT;
			if (ml != 1)
				openflags |= O_TRUNC;
			wfd = ksys_open(collected, openflags, mode);
			wfile = filp_open(collected, openflags, mode);
			if (IS_ERR(wfile))
				return 0;
			wfile_pos = 0;

			if (wfd >= 0) {
				ksys_fchown(wfd, uid, gid);
				ksys_fchmod(wfd, mode);
			vfs_fchown(wfile, uid, gid);
			vfs_fchmod(wfile, mode);
			if (body_len)
					ksys_ftruncate(wfd, 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);
		ksys_chown(collected, uid, gid);
@@ -363,16 +366,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);
@@ -603,21 +606,23 @@ static void __init clean_rootfs(void)
static void 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 */