Re: init scripts problems ?

"Peter T. Breuer" <[email protected]> Wed, 7 Dec 2005 02:08:22 +0100 (MET)
Newsgroups gmane.linux.enbd.general
Message-ID <[email protected]>
"Also sprach Peter T. Breuer:"
> In a separate patch here I moved the array notifications into a
> tasklet, since I was worried about racing or deadlock in a circle.  I
> could give you that patch to see if it helps. If it doesn't, it at least
> eliminates the array communication as a problem. 

It's late, and I promised, but the patch is spread, so I'll give a
mixture of patch and directions. 

First add an extra field to the enbd_device struct defn in
include/linux/enbd.h (in kernel/linux-2.6.x):


     int md_notify_cmd;                  /* PTB will send to md devices */
+    struct tasklet_struct notify_md_tasklet;
                                          /* PTB for notifying devices */

    };

Then patch enbd_base.c as follows:


--- kernel/linux-2.6.x/drivers/block/enbd/enbd_base.c.oboe	Sun Dec  4 21:27:35 2005
+++ kernel/linux-2.6.x/drivers/block/enbd/enbd_base.c	Wed Dec  7 00:54:46 2005
@@ -241,6 +241,7 @@
 #if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
 #include <linux/supermount_media.h>
 #endif /* defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE) */
+#include <linux/interrupt.h> // PTB for tasklets
 
 /*                                                       *
  * PTB --------------- compatibility ------------------- *
@@ -2562,19 +2563,29 @@
 			if (slot->md_count <= 0)
 				continue;
 		}
                 md->notify(&enbd_md, enbd_dev, cmd);
 	}
 	return 0;
 }
 
+static void
+enbd_notify_tasklet_fn(unsigned long data) {
+
+    struct enbd_device *lo = (struct enbd_device *)data;
+    int cmd = lo->md_notify_cmd;
+
+    enbd_notify_md_devices(lo, cmd);
+}
 
 /*
  * PTB - set the enabled flag on a device (call without the spinlock held) 
+ *       and notify md devices
  *
  *   @lo the nbd device being treated
  */
 static void
 enbd_enable (struct enbd_device *lo) {
+
 	unsigned long flags;
         int did_enabled = 0;
 
@@ -2589,9 +2600,10 @@
 	write_unlock_irqrestore (&lo->meta_lock, flags);
 
         if (did_enabled) {
-                ENBD_ALERT("set VALID on nd%s\n", lo->devnam);
+                ENBD_ALERT("set ENABLED on nd%s\n", lo->devnam);
                 //__invalidate_device(lo->inode->i_bdev, 0);
-                 enbd_notify(lo, HOT_ADD_DISK);
+                lo->md_notify_cmd = HOT_ADD_DISK;
+                tasklet_schedule(&lo->notify_md_tasklet);
         }
 }
 
@@ -3191,7 +3218,8 @@
                 ENBD_ALERT ("disabled device nd%s\n", lo->devnam);
         }
 
-        enbd_notify(lo, SET_DISK_FAULTY);
+        lo->md_notify_cmd = SET_DISK_FAULTY;
+        tasklet_schedule(&lo->notify_md_tasklet);
 
         // PTB have to recheck partitions on next open
         if (atomic_test_and_clear_mask (&lo->flags, ENBD_VALIDATED)) {
@@ -5087,6 +5164,9 @@
         enbd_init_speed(&lo->wspeed);
         enbd_init_speed(&lo->tspeed);
 
+        tasklet_init(&lo->notify_md_tasklet,
+                enbd_notify_tasklet_fn, (unsigned long)lo);
+
         // PTB queuue has alreay been initialized, or will be
         lo->q = lo->disk ? lo->disk->queue : NULL;
 


Thirdly, go through all the .c files in the (linux-2.6.x)
drivers/block/enbd/ subdir, and put the include in the first hunk above
somewhere above that of enbd.h in them too, something like this:

 #include <linux/blkdev.h>
 #include <linux/sysctl.h>
+#include <linux/interrupt.h> // PTB for tasklets
 #include <linux/enbd.h>

This takes MD array definition "out of line" so it can't really
ever be involved in any deadlock.

Peter