On Tue 21-10-14 15:42:23, Rafael J. Wysocki wrote:
> On Tuesday, October 21, 2014 03:14:45 PM Michal Hocko wrote:
> > On Tue 21-10-14 14:09:27, Rafael J. Wysocki wrote:
> > [...]
> > > > @@ -131,12 +132,40 @@ int freeze_processes(void)
> > > >  
> > > >         printk("Freezing user space processes ... ");
> > > >         pm_freezing = true;
> > > > +       oom_kills_saved = oom_kills_count();
> > > >         error = try_to_freeze_tasks(true);
> > > >         if (!error) {
> > > > -               printk("done.");
> > > >                 __usermodehelper_set_disable_depth(UMH_DISABLED);
> > > >                 oom_killer_disable();
> > > > +
> > > > +               /*
> > > > +                * There might have been an OOM kill while we were
> > > > +                * freezing tasks and the killed task might be still
> > > > +                * on the way out so we have to double check for race.
> > > > +                */
> > > > +               if (oom_kills_count() != oom_kills_saved) {
> > > > +                       struct task_struct *g, *p;
> > > > +
> > > > +                       read_lock(&tasklist_lock);
> > > > +                       for_each_process_thread(g, p) {
> > > > +                               if (p == current || 
> > > > freezer_should_skip(p) ||
> > > > +                                   frozen(p))
> > > > +                                       continue;
> > > > +                               error = -EBUSY;
> > > > +                               goto out_loop;
> > > > +                       }
> > > > +out_loop:
> > > 
> > > Well, it looks like this will work here too:
> > > 
> > >                   for_each_process_thread(g, p)
> > >                           if (p != current && !frozen(p) &&
> > >                               !freezer_should_skip(p)) {
> > >                                   error = -EBUSY;
> > >                                   break;
> > >                           }
> > > 
> > > or I am helplessly misreading the code.
> > 
> > break will not work because for_each_process_thread is a double loop.
> 
> I see.  In that case I'd do:
> 
>                         for_each_process_thread(g, p)
>                                 if (p != current && !frozen(p) &&
>                                     !freezer_should_skip(p)) {
> 
>                                       read_unlock(&tasklist_lock);
> 
>                                       
> __usermodehelper_set_disable_depth(UMH_ENABLED);
>                                       printk("OOM in progress.");
>                                         error = -EBUSY;
>                                         goto done;
>                                 }
> 
> to avoid adding the new label that looks odd.

OK, incremental diff on top. I will post the complete patch if you are
happier with this change
---
diff --git a/kernel/power/process.c b/kernel/power/process.c
index a397fa161d11..7a37cf3eb1a2 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -108,6 +108,28 @@ static int try_to_freeze_tasks(bool user_only)
        return todo ? -EBUSY : 0;
 }
 
+/*
+ * Returns true if all freezable tasks (except for current) are frozen already
+ */
+static bool check_frozen_processes(void)
+{
+       struct task_struct *g, *p;
+       bool ret = true;
+
+       read_lock(&tasklist_lock);
+       for_each_process_thread(g, p) {
+               if (p != current && !freezer_should_skip(p) &&
+                   !frozen(p)) {
+                       ret = false;
+                       goto done;
+               }
+       }
+done:
+       read_unlock(&tasklist_lock);
+
+       return ret;
+}
+
 /**
  * freeze_processes - Signal user space processes to enter the refrigerator.
  * The current thread will not be frozen.  The same process that calls
@@ -143,25 +165,12 @@ int freeze_processes(void)
                 * freezing tasks and the killed task might be still
                 * on the way out so we have to double check for race.
                 */
-               if (oom_kills_count() != oom_kills_saved) {
-                       struct task_struct *g, *p;
-
-                       read_lock(&tasklist_lock);
-                       for_each_process_thread(g, p) {
-                               if (p == current || freezer_should_skip(p) ||
-                                   frozen(p))
-                                       continue;
-                               error = -EBUSY;
-                               goto out_loop;
-                       }
-out_loop:
-                       read_unlock(&tasklist_lock);
-
-                       if (error) {
-                               __usermodehelper_set_disable_depth(UMH_ENABLED);
-                               printk("OOM in progress.");
-                               goto done;
-                       }
+               if (oom_kills_count() != oom_kills_saved &&
+                               !check_frozen_processes()) {
+                       __usermodehelper_set_disable_depth(UMH_ENABLED);
+                       printk("OOM in progress.");
+                       error = -EBUSY;
+                       goto done;
                }
                printk("done.");
        }
-- 
Michal Hocko
SUSE Labs
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to