Commit bf6419e4 authored by Christoph Hellwig's avatar Christoph Hellwig

initramfs: switch initramfs unpacking to struct file based APIs

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>
parent b2a74d5f
...@@ -13,13 +13,14 @@ ...@@ -13,13 +13,14 @@
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/namei.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; ssize_t out = 0;
/* sys_write only can write MAX_RW_COUNT aka 2G-4K bytes at most */ /* sys_write only can write MAX_RW_COUNT aka 2G-4K bytes at most */
while (count) { while (count) {
ssize_t rv = ksys_write(fd, p, count); ssize_t rv = kernel_write(file, p, count, pos);
if (rv < 0) { if (rv < 0) {
if (rv == -EINTR || rv == -EAGAIN) if (rv == -EINTR || rv == -EAGAIN)
...@@ -317,7 +318,8 @@ static int __init maybe_link(void) ...@@ -317,7 +318,8 @@ static int __init maybe_link(void)
return 0; return 0;
} }
static __initdata int wfd; static __initdata struct file *wfile;
static __initdata loff_t wfile_pos;
static int __init do_name(void) static int __init do_name(void)
{ {
...@@ -334,17 +336,18 @@ static int __init do_name(void) ...@@ -334,17 +336,18 @@ static int __init do_name(void)
int openflags = O_WRONLY|O_CREAT; int openflags = O_WRONLY|O_CREAT;
if (ml != 1) if (ml != 1)
openflags |= O_TRUNC; 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) { vfs_fchown(wfile, uid, gid);
ksys_fchown(wfd, uid, gid); vfs_fchmod(wfile, mode);
ksys_fchmod(wfd, mode);
if (body_len) if (body_len)
ksys_ftruncate(wfd, body_len); vfs_truncate(&wfile->f_path, body_len);
vcollected = kstrdup(collected, GFP_KERNEL); vcollected = kstrdup(collected, GFP_KERNEL);
state = CopyFile; state = CopyFile;
} }
}
} else if (S_ISDIR(mode)) { } else if (S_ISDIR(mode)) {
ksys_mkdir(collected, mode); ksys_mkdir(collected, mode);
ksys_chown(collected, uid, gid); ksys_chown(collected, uid, gid);
...@@ -365,16 +368,16 @@ static int __init do_name(void) ...@@ -365,16 +368,16 @@ static int __init do_name(void)
static int __init do_copy(void) static int __init do_copy(void)
{ {
if (byte_count >= body_len) { 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"); error("write error");
ksys_close(wfd); fput(wfile);
do_utime(vcollected, mtime); do_utime(vcollected, mtime);
kfree(vcollected); kfree(vcollected);
eat(body_len); eat(body_len);
state = SkipIt; state = SkipIt;
return 0; return 0;
} else { } else {
if (xwrite(wfd, victim, byte_count) != byte_count) if (xwrite(wfile, victim, byte_count, &wfile_pos) != byte_count)
error("write error"); error("write error");
body_len -= byte_count; body_len -= byte_count;
eat(byte_count); eat(byte_count);
...@@ -576,21 +579,23 @@ static inline bool kexec_free_initrd(void) ...@@ -576,21 +579,23 @@ static inline bool kexec_free_initrd(void)
static void __init populate_initrd_image(char *err) static void __init populate_initrd_image(char *err)
{ {
ssize_t written; ssize_t written;
int fd; struct file *file;
loff_t pos = 0;
unpack_to_rootfs(__initramfs_start, __initramfs_size); unpack_to_rootfs(__initramfs_start, __initramfs_size);
printk(KERN_INFO "rootfs image is not initramfs (%s); looks like an initrd\n", printk(KERN_INFO "rootfs image is not initramfs (%s); looks like an initrd\n",
err); err);
fd = ksys_open("/initrd.image", O_WRONLY | O_CREAT, 0700); file = filp_open("/initrd.image", O_WRONLY | O_CREAT, 0700);
if (fd < 0) if (IS_ERR(file))
return; 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) if (written != initrd_end - initrd_start)
pr_err("/initrd.image: incomplete write (%zd != %ld)\n", pr_err("/initrd.image: incomplete write (%zd != %ld)\n",
written, initrd_end - initrd_start); written, initrd_end - initrd_start);
ksys_close(fd); fput(file);
} }
#endif /* CONFIG_BLK_DEV_RAM */ #endif /* CONFIG_BLK_DEV_RAM */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment