schedule_work doesn't enforce that the work be done before prepare_namespace
tries to find a rootfs. If device probing is fast enough, we can panic with
"VFS: Unable to mount root fs" before the mtdconcat comes up.

prepare_namespace calls wait_for_device_probe first, which waits for all async
calls in the default domain (eg. scheduled with async_schedule) to finish.

The last catch is that plain mtd_device_register tries to load partition parsing
modules and module loading is prohibited in async calls. The fix is to prevent
mtd_device_register from trying any partition parsers by calling
mtd_device_parse_register directly and passing an empty parser list.

Signed-off-by: Catalin Patulea <c...@vv.carleton.ca>
---
 .../ar71xx/files/arch/mips/ath79/dev-m25p80.c      |   17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c 
b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c
index 9323b31..8cdb2f6 100644
--- a/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c
+++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-m25p80.c
@@ -6,6 +6,7 @@
  *  by the Free Software Foundation.
  */
 
+#include <linux/async.h>
 #include <linux/init.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
@@ -59,15 +60,20 @@ void __init ath79_register_m25p80(struct 
flash_platform_data *pdata)
 static struct flash_platform_data *multi_pdata;
 
 static struct mtd_info *concat_devs[2] = { NULL, NULL };
-static struct work_struct mtd_concat_work;
 
-static void mtd_concat_add_work(struct work_struct *work)
+static void mtd_concat_add_async(void *unused_data,
+                                async_cookie_t unused_cookie)
 {
+       /* don't try to load partition parser modules, module loading is
+        * disallowed in async */
+       const char *types[] = {NULL};
+
        struct mtd_info *mtd;
 
        mtd = mtd_concat_create(concat_devs, ARRAY_SIZE(concat_devs), "flash");
 
-       mtd_device_register(mtd, multi_pdata->parts, multi_pdata->nr_parts);
+       mtd_device_parse_register(mtd, types, NULL, multi_pdata->parts,
+                                 multi_pdata->nr_parts);
 }
 
 static void mtd_concat_add(struct mtd_info *mtd)
@@ -88,8 +94,9 @@ static void mtd_concat_add(struct mtd_info *mtd)
                return;
 
        registered = true;
-       INIT_WORK(&mtd_concat_work, mtd_concat_add_work);
-       schedule_work(&mtd_concat_work);
+
+       /* make sure we complete before prepare_namespace looks for rootfs */
+       async_schedule(&mtd_concat_add_async, NULL);
 }
 
 static void mtd_concat_remove(struct mtd_info *mtd)
-- 
1.7.9.5
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to