init: flush async file closing

When unpacking the initramfs or when mounting block devices we need to
ensure that any delayed fput() finished to prevent spurious errors.
The init process can be a proper kernel thread or a user mode helper.
In the latter case PF_KTHREAD isn't set. So we need to do both
flush_delayed_work() and task_work_run().

Since we'll port block device opening and closing to regular file open
and closing we need to ensure the same as for the initramfs. So just
make that a little helper.

Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Tested-by: Srikanth Aithal <sraithal@amd.com>
Link: https://lore.kernel.org/r/CA+G9fYttTwsbFuVq10igbSvP5xC6bf_XijM=mpUqrJV=uvUirQ@mail.gmail.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Christian Brauner 2024-02-06 16:18:43 +01:00
parent 6613476e22
commit 386dc41cf5
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2
3 changed files with 15 additions and 3 deletions

View File

@ -208,6 +208,9 @@ retry:
goto out;
case -EACCES:
case -EINVAL:
#ifdef CONFIG_BLOCK
init_flush_fput();
#endif
continue;
}
/*

View File

@ -9,6 +9,8 @@
#include <linux/major.h>
#include <linux/root_dev.h>
#include <linux/init_syscalls.h>
#include <linux/task_work.h>
#include <linux/file.h>
void mount_root_generic(char *name, char *pretty_name, int flags);
void mount_root(char *root_device_name);
@ -41,3 +43,10 @@ static inline bool initrd_load(char *root_device_name)
}
#endif
/* Ensure that async file closing finished to prevent spurious errors. */
static inline void init_flush_fput(void)
{
flush_delayed_fput();
task_work_run();
}

View File

@ -16,9 +16,10 @@
#include <linux/mm.h>
#include <linux/namei.h>
#include <linux/init_syscalls.h>
#include <linux/task_work.h>
#include <linux/umh.h>
#include "do_mounts.h"
static __initdata bool csum_present;
static __initdata u32 io_csum;
@ -736,8 +737,7 @@ done:
initrd_start = 0;
initrd_end = 0;
flush_delayed_fput();
task_work_run();
init_flush_fput();
}
static ASYNC_DOMAIN_EXCLUSIVE(initramfs_domain);