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