diff mbox series

[1/2] kernel/freezer: Add routine to read task's freezing reason

Message ID 20230227121318.2116638-2-md@chromium.org
State New
Headers show
Series [1/2] kernel/freezer: Add routine to read task's freezing reason | expand

Commit Message

Michal Dubiel Feb. 27, 2023, 12:13 p.m. UTC
There are few reasons why a task is freezing. It can be due to system
suspend, it can be due to explicit user request, etc.

For most cases, the actual reason is not important, but there are some that
it is useful to distinguish between what actually caused the task to
freeze.

One example is when user requests freezing of tasks belonging to a certain
cgroup. If for any reason, system goes suspend and resume when the cgroup
is frozen, the already frozen tasks should not be thawed but remain frozen
to ensure the suspend/resume cycle transparency. The system should not warn
about skipping thawing of such processes as it is normal situation.

The proposed function allows to obtain information about the freezing
reason and let the calling code decide what to do accordingly.

Signed-off-by: Michal Dubiel <md@chromium.org>
---
 include/linux/freezer.h | 17 +++++++++++++++
 kernel/freezer.c        | 23 ++++++++++++++------
 2 files changed, 33 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index b303472255b..b936a349e0d 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -28,6 +28,23 @@  extern bool frozen(struct task_struct *p);
 
 extern bool freezing_slow_path(struct task_struct *p);
 
+extern enum freezing_reason freezing_reason_slow_path(struct task_struct *p);
+
+enum freezing_reason {
+	FREEZING_NONE	  = 0,
+	FREEZING_CGROUP	  = (1 << 0),
+	FREEZING_PM	  = (1 << 1),
+	FREEZING_PM_NOSIG = (1 << 2),
+};
+
+static inline enum freezing_reason freezing_reason(struct task_struct *p)
+{
+	if (static_branch_unlikely(&freezer_active))
+		return freezing_reason_slow_path(p);
+
+	return FREEZING_NONE;
+}
+
 /*
  * Check if there is a request to freeze a process
  */
diff --git a/kernel/freezer.c b/kernel/freezer.c
index 4fad0e6fca6..2536054db60 100644
--- a/kernel/freezer.c
+++ b/kernel/freezer.c
@@ -26,6 +26,21 @@  bool pm_nosig_freezing;
 /* protects freezing and frozen transitions */
 static DEFINE_SPINLOCK(freezer_lock);
 
+enum freezing_reason freezing_reason_slow_path(struct task_struct *p)
+{
+	if (pm_nosig_freezing)
+		return FREEZING_PM_NOSIG;
+
+	if (cgroup_freezing(p))
+		return FREEZING_CGROUP;
+
+	if (pm_freezing && !(p->flags & PF_KTHREAD))
+		return FREEZING_PM;
+
+	return FREEZING_NONE;
+}
+EXPORT_SYMBOL(freezing_reason_slow_path);
+
 /**
  * freezing_slow_path - slow path for testing whether a task needs to be frozen
  * @p: task to be tested
@@ -43,13 +58,7 @@  bool freezing_slow_path(struct task_struct *p)
 	if (test_tsk_thread_flag(p, TIF_MEMDIE))
 		return false;
 
-	if (pm_nosig_freezing || cgroup_freezing(p))
-		return true;
-
-	if (pm_freezing && !(p->flags & PF_KTHREAD))
-		return true;
-
-	return false;
+	return (bool)freezing_reason_slow_path(p);
 }
 EXPORT_SYMBOL(freezing_slow_path);