]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
freezer,umh: Clean up freezer/initrd interaction
authorPeter Zijlstra <peterz@infradead.org>
Mon, 22 Aug 2022 11:18:18 +0000 (13:18 +0200)
committerPeter Zijlstra <peterz@infradead.org>
Wed, 7 Sep 2022 19:53:48 +0000 (21:53 +0200)
handle_initrd() marks itself as PF_FREEZER_SKIP in order to ensure
that the UMH, which is going to freeze the system, doesn't
indefinitely wait for it's caller.

Rework things by adding UMH_FREEZABLE to indicate the completion is
freezable.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://lore.kernel.org/r/20220822114648.791019324@infradead.org
include/linux/umh.h
init/do_mounts_initrd.c
kernel/umh.c

index 244aff6382208824e64c6387a38bb60e967f0548..5d1f6129b84703bf4252ab3ac8206f5037cda9f4 100644 (file)
 struct cred;
 struct file;
 
-#define UMH_NO_WAIT    0       /* don't wait at all */
-#define UMH_WAIT_EXEC  1       /* wait for the exec, but not the process */
-#define UMH_WAIT_PROC  2       /* wait for the process to complete */
-#define UMH_KILLABLE   4       /* wait for EXEC/PROC killable */
+#define UMH_NO_WAIT    0x00    /* don't wait at all */
+#define UMH_WAIT_EXEC  0x01    /* wait for the exec, but not the process */
+#define UMH_WAIT_PROC  0x02    /* wait for the process to complete */
+#define UMH_KILLABLE   0x04    /* wait for EXEC/PROC killable */
+#define UMH_FREEZABLE  0x08    /* wait for EXEC/PROC freezable */
 
 struct subprocess_info {
        struct work_struct work;
index 327962ea354c096fd56e4b7aa03cc5928440279f..34731241377d3097826799bd4464bfc91245d340 100644 (file)
@@ -99,19 +99,11 @@ static void __init handle_initrd(void)
        init_mkdir("/old", 0700);
        init_chdir("/old");
 
-       /*
-        * In case that a resume from disk is carried out by linuxrc or one of
-        * its children, we need to tell the freezer not to wait for us.
-        */
-       current->flags |= PF_FREEZER_SKIP;
-
        info = call_usermodehelper_setup("/linuxrc", argv, envp_init,
                                         GFP_KERNEL, init_linuxrc, NULL, NULL);
        if (!info)
                return;
-       call_usermodehelper_exec(info, UMH_WAIT_PROC);
-
-       current->flags &= ~PF_FREEZER_SKIP;
+       call_usermodehelper_exec(info, UMH_WAIT_PROC|UMH_FREEZABLE);
 
        /* move initrd to rootfs' /old */
        init_mount("..", ".", NULL, MS_MOVE, NULL);
index b989736e8707473e42541d75ea99e306a21f3f3f..8945eaf4c67179827fe7c571047ced851d448fcc 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/async.h>
 #include <linux/uaccess.h>
 #include <linux/initrd.h>
+#include <linux/freezer.h>
 
 #include <trace/events/module.h>
 
@@ -436,6 +437,9 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
        if (wait == UMH_NO_WAIT)        /* task has freed sub_info */
                goto unlock;
 
+       if (wait & UMH_FREEZABLE)
+               freezer_do_not_count();
+
        if (wait & UMH_KILLABLE) {
                retval = wait_for_completion_killable(&done);
                if (!retval)
@@ -448,6 +452,10 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
        }
 
        wait_for_completion(&done);
+
+       if (wait & UMH_FREEZABLE)
+               freezer_count();
+
 wait_done:
        retval = sub_info->retval;
 out: