From: Rusty Russell <rusty@rustcorp.com.au>

MODULE_ALIAS_BLOCK() and MODULE_ALIAS_CHAR() define aliases of form
"XXX-<major>-<minor>", so we should probe for modules using this form. 
Unfortunately in 2.4, block aliases were "XXX-<major>" and char aliases
were of both forms.

Ideally, all modules would now be using MODULE_ALIAS() macros to define
their aliases, and the old configuration files wouldn't matter as much. 
Unfortunately, this hasn't happened, so we make request_module() return the
exit status of modprobe, and then do fallback when probing for char and
block devices.

(Kudos to Chris Wright, I stole his kernel_thread flags).



 drivers/block/genhd.c |    4 +++-
 fs/char_dev.c         |    4 +++-
 include/linux/kmod.h  |    2 ++
 kernel/kmod.c         |   17 +++++++++++------
 4 files changed, 19 insertions(+), 8 deletions(-)

diff -puN drivers/block/genhd.c~call_usermodehelper-retval-fix-4 drivers/block/genhd.c
--- 25/drivers/block/genhd.c~call_usermodehelper-retval-fix-4	2003-12-21 22:41:10.000000000 -0800
+++ 25-akpm/drivers/block/genhd.c	2003-12-21 22:41:10.000000000 -0800
@@ -296,7 +296,9 @@ extern int blk_dev_init(void);
 
 static struct kobject *base_probe(dev_t dev, int *part, void *data)
 {
-	request_module("block-major-%d", MAJOR(dev));
+	if (request_module("block-major-%d-%d", MAJOR(dev), MINOR(dev)) > 0)
+		/* Make old-style 2.4 aliases work */
+		request_module("block-major-%d", MAJOR(dev));
 	return NULL;
 }
 
diff -puN fs/char_dev.c~call_usermodehelper-retval-fix-4 fs/char_dev.c
--- 25/fs/char_dev.c~call_usermodehelper-retval-fix-4	2003-12-21 22:41:10.000000000 -0800
+++ 25-akpm/fs/char_dev.c	2003-12-21 22:41:10.000000000 -0800
@@ -434,7 +434,9 @@ void cdev_init(struct cdev *cdev, struct
 
 static struct kobject *base_probe(dev_t dev, int *part, void *data)
 {
-	request_module("char-major-%d-%d", MAJOR(dev), MINOR(dev));
+	if (request_module("char-major-%d-%d", MAJOR(dev), MINOR(dev)) > 0)
+		/* Make old-style 2.4 aliases work */
+		request_module("char-major-%d", MAJOR(dev));
 	return NULL;
 }
 
diff -puN include/linux/kmod.h~call_usermodehelper-retval-fix-4 include/linux/kmod.h
--- 25/include/linux/kmod.h~call_usermodehelper-retval-fix-4	2003-12-21 22:41:10.000000000 -0800
+++ 25-akpm/include/linux/kmod.h	2003-12-21 22:41:10.000000000 -0800
@@ -24,6 +24,8 @@
 #include <linux/compiler.h>
 
 #ifdef CONFIG_KMOD
+/* modprobe exit status on success, -ve on error.  Return value
+ * usually useless though. */
 extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2)));
 #else
 static inline int request_module(const char * name, ...) { return -ENOSYS; }
diff -puN kernel/kmod.c~call_usermodehelper-retval-fix-4 kernel/kmod.c
--- 25/kernel/kmod.c~call_usermodehelper-retval-fix-4	2003-12-21 22:41:10.000000000 -0800
+++ 25-akpm/kernel/kmod.c	2003-12-21 22:41:10.000000000 -0800
@@ -182,16 +182,21 @@ static int wait_for_helper(void *data)
 {
 	struct subprocess_info *sub_info = data;
 	pid_t pid;
+	struct k_sigaction sa;
+
+	/* Install a handler: if SIGCLD isn't handled sys_wait4 won't
+	 * populate the status, but will return -ECHILD. */
+	sa.sa.sa_handler = SIG_IGN;
+	sa.sa.sa_flags = 0;
+	siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD));
+	do_sigaction(SIGCHLD, &sa, (struct k_sigaction *)0);
+	allow_signal(SIGCHLD);
 
-	sub_info->retval = 0;
 	pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD);
 	if (pid < 0)
 		sub_info->retval = pid;
 	else
-		/* We don't have a SIGCHLD signal handler, so this
-		 * always returns -ECHILD, but the important thing is
-		 * that it blocks. */
-		sys_wait4(pid, NULL, 0, NULL);
+		sys_wait4(pid, &sub_info->retval, 0, NULL);
 
 	complete(sub_info->complete);
 	return 0;
@@ -210,7 +215,7 @@ static void __call_usermodehelper(void *
 	 * until that is done.  */
 	if (sub_info->wait)
 		pid = kernel_thread(wait_for_helper, sub_info,
-				    CLONE_KERNEL | SIGCHLD);
+				    CLONE_FS | CLONE_FILES | SIGCHLD);
 	else
 		pid = kernel_thread(____call_usermodehelper, sub_info,
 				    CLONE_VFORK | SIGCHLD);

_