pagg
[Top] [All Lists]

Re: [patch] Minor PAGG attach/detach semantic change for 2.6.11

To: Kingsley Cheung <kingsley@xxxxxxxxxx>
Subject: Re: [patch] Minor PAGG attach/detach semantic change for 2.6.11
From: Erik Jacobson <erikj@xxxxxxx>
Date: Tue, 4 Oct 2005 08:54:23 -0500
Cc: Erik Jacobson <erikj@xxxxxxx>, pagg@xxxxxxxxxxx, tonyt@xxxxxxxxxx
In-reply-to: <20051004065215.GB4533@xxxxxxxxxx>
References: <20050617014512.GA10285@xxxxxxxxxx> <20050927201020.GA30433@xxxxxxx> <20050929051627.GC3404@xxxxxxxxxx> <20050929151205.GB7395@xxxxxxx> <20050929223827.GA2737@xxxxxxxxxx> <20050930205858.GA10565@xxxxxxx> <20051004063558.GA4533@xxxxxxxxxx> <20051004065215.GB4533@xxxxxxxxxx>
Sender: pagg-bounce@xxxxxxxxxxx
User-agent: Mutt/1.5.6i
Hi Again.  Unless I'm missing something (and that sure has happened in
this conversation so it's probably the case :) --

I wrote copy_process to skip the fork_exit on purpose.  

1. If there isn't enough memory for the pnotify_subscribe, we
   return -ENOMEM, which will be a fork failure.  In this case,
   the kernel module wasn't notified via the callout.  So it wouldn't
   make sense to pnotify_exit for this process in copy_process.

2. If the kernel module itself "vetoed" the subscriber, well, the kernel
   module is the one who directed the action and should know a 
   pnotify_exit will never be called for that process as that was the
   reason for the veto anyway.  So we just unsubscribe it.

3. If the kernel module returned a failure, the kernel module itself knows
   the process is going to fail in fork.  It wouldn't have allocated memory
   for data it knew would get tossed in just a moment anyway.  It seems wrong
   to have fork_exit called when the kernel module is who directed the 
   failure.  So we just unsubscribe it.

4. If the fork callout from the kernel module is a success and 
   __pnotify_fork is a success, we hop back in to copy_process all happy.
   But if, after the pnotify_fork, the fork fails...  In that case, we
   call pnotify_exit because there would be no way for the kernel module to
   know about the fork failing after pnotify_fork is completed.  

I think this covers all the cases,  If I'm wrong, please try again.  If that's
the case, I'm sorry it's taking me so long to understand :)

So the skipping of pnotify_exit is on purpose in copy_process.  We only
call pnotify_exit in the case that the kernel module doesn't know about
the failure for some reason because the failure happened after pnotify_fork
completed.

+__pnotify_fork(struct task_struct *to_task, struct task_struct *from_task)
+{
+  struct pnotify_subscriber *from_subscriber;
+  int ret;
+
+  /* lock the parents subscriber list we are copying from */
+  down_read(&from_task->pnotify_subscriber_list_sem);
+
+  list_for_each_entry(from_subscriber,
+            &from_task->pnotify_subscriber_list, entry) {
+     struct pnotify_subscriber *to_subscriber = NULL;
+
+     to_subscriber = pnotify_subscribe(to_task,
+                   from_subscriber->events);
+     if (!to_subscriber) {
+        /* Failed to get memory.
+         * we don't force __pnotify_exit to run here because
+         * the child is in-consturction and not running yet.
+         * We don't need a write lock on the subscriber
+         * list because the child is in construction.
+         */
+        pnotify_unsubscribe(to_task);
+        up_read(&from_task->pnotify_subscriber_list_sem);
+        return -ENOMEM;
+     }
+     ret = to_subscriber->events->fork(to_task, to_subscriber,
+                   from_subscriber->data);
+
+     if (ret < 0) {
+        /* Propagates to copy_process as a fork failure.
+         * Since the child is in consturction, we don't
+         * need a write lock on the subscriber list.
+         * __pnotify_exit isn't run because the child
+         * never got running, exit doesn't make sense.
+         */
+        pnotify_unsubscribe(to_task);
+        up_read(&from_task->pnotify_subscriber_list_sem);
+        return ret; /* Fork failure */
+     }
+     else if (ret > 0) {
+        /* Success, but fork function pointer in the
+         * pnotify_events structure doesn't want the kernel
+         * module subscribed.  This is an in-construction
+         * child so we don't need to write lock */
+        pnotify_unsubscribe(to_subscriber);
+     }
+  }
+
+  /* unlock parent's subscriber list */
+  up_read(&from_task->pnotify_subscriber_list_sem);
+
+  return 0; /* success */
+}


<Prev in Thread] Current Thread [Next in Thread>