return 0;
 }
 
-extern void thaw_some_processes(int all);
+/*
+ * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it
+ * calls wait_for_completion(&vfork) and reset right after it returns from this
+ * function.  Next, the parent should call try_to_freeze() to freeze itself
+ * appropriately in case the child has exited before the freezing of tasks is
+ * complete.  However, we don't want kernel threads to be frozen in unexpected
+ * places, so we allow them to block freeze_processes() instead or to set
+ * PF_NOFREEZE if needed and PF_FREEZER_SKIP is only set for userland vfork
+ * parents.  Fortunately, in the ____call_usermodehelper() case the parent won't
+ * really block freeze_processes(), since ____call_usermodehelper() (the child)
+ * does a little before exec/exit and it can't be frozen before waking up the
+ * parent.
+ */
+
+/*
+ * If the current task is a user space one, tell the freezer not to count it as
+ * freezable.
+ */
+static inline void freezer_do_not_count(void)
+{
+       if (current->mm)
+               current->flags |= PF_FREEZER_SKIP;
+}
+
+/*
+ * If the current task is a user space one, tell the freezer to count it as
+ * freezable again and try to freeze it.
+ */
+static inline void freezer_count(void)
+{
+       if (current->mm) {
+               current->flags &= ~PF_FREEZER_SKIP;
+               try_to_freeze();
+       }
+}
+
+/*
+ * Check if the task should be counted as freezeable by the freezer
+ */
+static inline int freezer_should_skip(struct task_struct *p)
+{
+       return !!(p->flags & PF_FREEZER_SKIP);
+}
 
 #else
 static inline int frozen(struct task_struct *p) { return 0; }
 
 static inline int try_to_freeze(void) { return 0; }
 
-
+static inline void freezer_do_not_count(void) {}
+static inline void freezer_count(void) {}
+static inline int freezer_should_skip(struct task_struct *p) { return 0; }
 #endif
 
 #define PF_SPREAD_SLAB 0x02000000      /* Spread some slab caches over cpuset */
 #define PF_MEMPOLICY   0x10000000      /* Non-default NUMA mempolicy */
 #define PF_MUTEX_TESTER        0x20000000      /* Thread belongs to the rt mutex tester */
+#define PF_FREEZER_SKIP        0x40000000      /* Freezer should not count it as freezeable */
 
 /*
  * Only the _current_ task can read/write to tsk->flags, but other
 
 #include <linux/acct.h>
 #include <linux/tsacct_kern.h>
 #include <linux/cn_proc.h>
+#include <linux/freezer.h>
 #include <linux/delayacct.h>
 #include <linux/taskstats_kern.h>
 #include <linux/random.h>
                }
 
                if (clone_flags & CLONE_VFORK) {
+                       freezer_do_not_count();
                        wait_for_completion(&vfork);
+                       freezer_count();
                        if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) {
                                current->ptrace_message = nr;
                                ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
 
                                cancel_freezing(p);
                                continue;
                        }
-                       if (is_user_space(p)) {
-                               if (!freeze_user_space)
-                                       continue;
-
-                               /* Freeze the task unless there is a vfork
-                                * completion pending
-                                */
-                               if (!p->vfork_done)
-                                       freeze_process(p);
-                       } else {
-                               if (freeze_user_space)
-                                       continue;
-
-                               freeze_process(p);
-                       }
-                       todo++;
+                       if (is_user_space(p) == !freeze_user_space)
+                               continue;
+
+                       freeze_process(p);
+                       if (!freezer_should_skip(p))
+                               todo++;
                } while_each_thread(g, p);
                read_unlock(&tasklist_lock);
                yield();                        /* Yield is okay here */
                                continue;
 
                        task_lock(p);
-                       if (freezeable(p) && !frozen(p))
+                       if (freezeable(p) && !frozen(p) &&
+                           !freezer_should_skip(p))
                                printk(KERN_ERR " %s\n", p->comm);
 
                        cancel_freezing(p);
                if (is_user_space(p) == !thaw_user_space)
                        continue;
 
-               if (!thaw_process(p))
-                       printk(KERN_WARNING " Strange, %s not stopped\n",
-                               p->comm );
+               thaw_process(p);
        } while_each_thread(g, p);
        read_unlock(&tasklist_lock);
 }