Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 Oct 2009 19:31:22 +0200
From:      Hans Petter Selasky <hselasky@c2i.net>
To:        freebsd-current@freebsd.org
Subject:   Re: [PATCH] Fix for USB media not found at boot
Message-ID:  <200910031931.24600.hselasky@c2i.net>
In-Reply-To: <D04BD0AA-F598-40AF-998A-1D07A3C90837@samsco.org>
References:  <20091002150931.K35591@pooker.samsco.org> <200910031800.24896.hselasky@c2i.net> <D04BD0AA-F598-40AF-998A-1D07A3C90837@samsco.org>

next in thread | previous in thread | raw e-mail | index | archive | help
--Boundary-00=_sp4xKvPSgaU5kXU
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Saturday 03 October 2009 18:05:32 Scott Long wrote:
> That's an interesting idea.  If you can make this work, go for it.  
> Meanwhile, I'm going to continue to look at the usb enumeration code.

Please find attached an outline. I need one more hour to finalize the patch.

All existing mount root features have been kept. The only difference is that 
the system will not panic before 3 minutes, if no root disk is present. I 
think that is acceptable.

--HPS


--Boundary-00=_sp4xKvPSgaU5kXU
Content-Type: text/x-patch; charset="iso-8859-1";
	name="mount_root_outline.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
	filename="mount_root_outline.diff"

==== //depot/projects/usb/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c#9 - /home/some_dir/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c ====
@@ -3058,7 +3058,6 @@
 		destroy_dev(zfsdev);
 }
 
-static struct root_hold_token *zfs_root_token;
 struct proc *zfsproc;
 
 uint_t zfs_fsyncer_key;
@@ -3071,8 +3070,6 @@
 
 	switch (type) {
 	case MOD_LOAD:
-		zfs_root_token = root_mount_hold("ZFS");
-
 		mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL);
 
 		spa_init(FREAD | FWRITE);
@@ -3083,7 +3080,6 @@
 		tsd_create(&rrw_tsd_key, NULL);
 
 		printf("ZFS storage pool version " SPA_VERSION_STRING "\n");
-		root_mount_rel(zfs_root_token);
 
 		zfsdev_init();
 		break;
==== //depot/projects/usb/src/sys/dev/pccbb/pccbb.c#14 - /home/some_dir/src/sys/dev/pccbb/pccbb.c ====
@@ -500,15 +500,6 @@
 		mtx_unlock(&Giant);
 
 		/*
-		 * First time through we need to tell mountroot that we're
-		 * done.
-		 */
-		if (sc->sc_root_token) {
-			root_mount_rel(sc->sc_root_token);
-			sc->sc_root_token = NULL;
-		}
-
-		/*
 		 * Wait until it has been 250ms since the last time we
 		 * get an interrupt.  We handle the rest of the interrupt
 		 * at the top of the loop.  Although we clear the bit in the
==== //depot/projects/usb/src/sys/dev/pccbb/pccbb_pci.c#11 - /home/some_dir/src/sys/dev/pccbb/pccbb_pci.c ====
@@ -439,7 +439,6 @@
 		device_printf(brdev, "unable to create event thread.\n");
 		panic("cbb_create_event_thread");
 	}
-	sc->sc_root_token = root_mount_hold(device_get_nameunit(sc->dev));
 	return (0);
 err:
 	if (sc->irq_res)
==== //depot/projects/usb/src/sys/dev/pccbb/pccbbvar.h#8 - /home/some_dir/src/sys/dev/pccbb/pccbbvar.h ====
@@ -88,7 +88,6 @@
 	struct proc	*event_thread;
 	void (*chipinit)(struct cbb_softc *);
 	int	powerintr;
-	struct root_hold_token *sc_root_token;
 };
 
 /* result of detect_card */
==== //depot/projects/usb/src/sys/dev/usb/controller/usb_controller.c#32 - /home/some_dir/src/sys/dev/usb/controller/usb_controller.c ====
@@ -78,11 +78,6 @@
     "Debug level");
 #endif
 
-static int usb_no_boot_wait = 0;
-TUNABLE_INT("hw.usb.no_boot_wait", &usb_no_boot_wait);
-SYSCTL_INT(_hw_usb, OID_AUTO, no_boot_wait, CTLFLAG_RDTUN, &usb_no_boot_wait, 0,
-    "No device enumerate waiting at boot.");
-
 static devclass_t usb_devclass;
 
 static device_method_t usb_methods[] = {
@@ -134,11 +129,6 @@
 		return (ENXIO);
 	}
 
-	if (usb_no_boot_wait == 0) {
-		/* delay vfs_mountroot until the bus is explored */
-		bus->bus_roothold = root_mount_hold(device_get_nameunit(dev));
-	}
-
 	usb_attach_sub(dev, bus);
 
 	return (0);			/* return success */
@@ -161,12 +151,6 @@
 	/* Stop power watchdog */
 	usb_callout_drain(&bus->power_wdog);
 
-	/* Let the USB explore process detach all devices. */
-	if (bus->bus_roothold != NULL) {
-		root_mount_rel(bus->bus_roothold);
-		bus->bus_roothold = NULL;
-	}
-
 	USB_BUS_LOCK(bus);
 	if (usb_proc_msignal(&bus->explore_proc,
 	    &bus->detach_msg[0], &bus->detach_msg[1])) {
@@ -239,10 +223,6 @@
 		(udev->hub->explore) (udev);
 		USB_BUS_LOCK(bus);
 	}
-	if (bus->bus_roothold != NULL) {
-		root_mount_rel(bus->bus_roothold);
-		bus->bus_roothold = NULL;
-	}
 }
 
 /*------------------------------------------------------------------------*
==== //depot/projects/usb/src/sys/dev/usb/input/ukbd.c#32 - /home/some_dir/src/sys/dev/usb/input/ukbd.c ====
@@ -67,6 +67,7 @@
 #include <sys/callout.h>
 #include <sys/malloc.h>
 #include <sys/priv.h>
+#include <sys/kdb.h>
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
@@ -328,6 +329,9 @@
 {
 	DPRINTFN(2, "polling\n");
 
+	if (kdb_active == 0)
+		return;		/* Only poll if KDB is active */
+
 	while (sc->sc_inputs == 0) {
 
 		usbd_transfer_poll(sc->sc_xfer, UKBD_N_TRANSFER);
==== //depot/projects/usb/src/sys/dev/usb/usb_bus.h#15 - /home/some_dir/src/sys/dev/usb/usb_bus.h ====
@@ -51,7 +51,6 @@
 struct usb_bus {
 	struct usb_bus_stat stats_err;
 	struct usb_bus_stat stats_ok;
-	struct root_hold_token *bus_roothold;
 	/*
 	 * There are two callback processes. One for Giant locked
 	 * callbacks. One for non-Giant locked callbacks. This should
==== //depot/projects/usb/src/sys/geom/journal/g_journal.c#12 - /home/some_dir/src/sys/geom/journal/g_journal.c ====
@@ -2108,12 +2108,6 @@
 	g_topology_unlock();
 	last_write = time_second;
 
-	if (sc->sc_rootmount != NULL) {
-		GJ_DEBUG(1, "root_mount_rel %p", sc->sc_rootmount);
-		root_mount_rel(sc->sc_rootmount);
-		sc->sc_rootmount = NULL;
-	}
-
 	for (;;) {
 		/* Get first request from the queue. */
 		mtx_lock(&sc->sc_mtx);
@@ -2311,9 +2305,6 @@
 		sc->sc_inactive.jj_queue = NULL;
 		sc->sc_active.jj_queue = NULL;
 
-		sc->sc_rootmount = root_mount_hold("GJOURNAL");
-		GJ_DEBUG(1, "root_mount_hold %p", sc->sc_rootmount);
-
 		callout_init(&sc->sc_callout, CALLOUT_MPSAFE);
 		if (md->md_type != GJ_TYPE_COMPLETE) {
 			/*
@@ -2445,12 +2436,6 @@
 
 	g_topology_unlock();
 
-	if (sc->sc_rootmount != NULL) {
-		GJ_DEBUG(1, "root_mount_rel %p", sc->sc_rootmount);
-		root_mount_rel(sc->sc_rootmount);
-		sc->sc_rootmount = NULL;
-	}
-
 	callout_drain(&sc->sc_callout);
 	mtx_lock(&sc->sc_mtx);
 	wakeup(sc);
==== //depot/projects/usb/src/sys/geom/journal/g_journal.h#2 - /home/some_dir/src/sys/geom/journal/g_journal.h ====
@@ -163,8 +163,6 @@
 
 	struct callout	 sc_callout;
 	struct proc	*sc_worker;
-
-	struct root_hold_token *sc_rootmount;
 };
 #define	sc_dprovider	sc_dconsumer->provider
 #define	sc_jprovider	sc_jconsumer->provider
==== //depot/projects/usb/src/sys/geom/mirror/g_mirror.c#7 - /home/some_dir/src/sys/geom/mirror/g_mirror.c ====
@@ -1726,13 +1726,6 @@
 static int
 g_mirror_try_destroy(struct g_mirror_softc *sc)
 {
-
-	if (sc->sc_rootmount != NULL) {
-		G_MIRROR_DEBUG(1, "root_mount_rel[%u] %p", __LINE__,
-		    sc->sc_rootmount);
-		root_mount_rel(sc->sc_rootmount);
-		sc->sc_rootmount = NULL;
-	}
 	g_topology_lock();
 	if (!g_mirror_can_destroy(sc)) {
 		g_topology_unlock();
@@ -2190,10 +2183,6 @@
 			 */
 			callout_drain(&sc->sc_callout);
 			sc->sc_flags |= G_MIRROR_DEVICE_FLAG_DESTROY;
-			G_MIRROR_DEBUG(1, "root_mount_rel[%u] %p", __LINE__,
-			    sc->sc_rootmount);
-			root_mount_rel(sc->sc_rootmount);
-			sc->sc_rootmount = NULL;
 			return;
 		} else {
 			return;
@@ -2217,10 +2206,6 @@
 			if (ndisks == 0) {
 				/* No valid disks found, destroy device. */
 				sc->sc_flags |= G_MIRROR_DEVICE_FLAG_DESTROY;
-				G_MIRROR_DEBUG(1, "root_mount_rel[%u] %p",
-				    __LINE__, sc->sc_rootmount);
-				root_mount_rel(sc->sc_rootmount);
-				sc->sc_rootmount = NULL;
 				return;
 			}
 		} else {
@@ -2374,12 +2359,6 @@
 			 */
 			if (sc->sc_provider == NULL)
 				g_mirror_launch_provider(sc);
-			if (sc->sc_rootmount != NULL) {
-				G_MIRROR_DEBUG(1, "root_mount_rel[%u] %p",
-				    __LINE__, sc->sc_rootmount);
-				root_mount_rel(sc->sc_rootmount);
-				sc->sc_rootmount = NULL;
-			}
 		}
 		/*
 		 * Genid should be bumped immediately, so do it here.
@@ -2907,8 +2886,6 @@
 	G_MIRROR_DEBUG(1, "Device %s created (%u components, id=%u).",
 	    sc->sc_name, sc->sc_ndisks, sc->sc_id);
 
-	sc->sc_rootmount = root_mount_hold("GMIRROR");
-	G_MIRROR_DEBUG(1, "root_mount_hold %p", sc->sc_rootmount);
 	/*
 	 * Run timeout.
 	 */
==== //depot/projects/usb/src/sys/geom/mirror/g_mirror.h#2 - /home/some_dir/src/sys/geom/mirror/g_mirror.h ====
@@ -207,8 +207,6 @@
 	struct mtx	sc_events_mtx;
 
 	struct callout	sc_callout;
-
-	struct root_hold_token *sc_rootmount;
 };
 #define	sc_name	sc_geom->name
 
==== //depot/projects/usb/src/sys/geom/part/g_part.c#19 - /home/some_dir/src/sys/geom/part/g_part.c ====
@@ -1448,7 +1448,6 @@
 	struct g_geom *gp;
 	struct g_part_entry *entry;
 	struct g_part_table *table;
-	struct root_hold_token *rht;
 	int attr, depth;
 	int error;
 
@@ -1470,7 +1469,6 @@
 		return (NULL);
 	}
 
-	rht = root_mount_hold(mp->name);
 	g_topology_unlock();
 
 	/*
@@ -1515,13 +1513,11 @@
 			g_part_new_provider(gp, table, entry);
 	}
 
-	root_mount_rel(rht);
 	g_access(cp, -1, 0, 0);
 	return (gp);
 
  fail:
 	g_topology_lock();
-	root_mount_rel(rht);
 	g_access(cp, -1, 0, 0);
 	g_part_wither(gp, error);
 	return (NULL);
==== //depot/projects/usb/src/sys/geom/raid3/g_raid3.c#7 - /home/some_dir/src/sys/geom/raid3/g_raid3.c ====
@@ -1974,13 +1974,6 @@
 	g_topology_assert_not();
 	sx_assert(&sc->sc_lock, SX_XLOCKED);
 
-	if (sc->sc_rootmount != NULL) {
-		G_RAID3_DEBUG(1, "root_mount_rel[%u] %p", __LINE__,
-		    sc->sc_rootmount);
-		root_mount_rel(sc->sc_rootmount);
-		sc->sc_rootmount = NULL;
-	}
-
 	g_topology_lock();
 	if (!g_raid3_can_destroy(sc)) {
 		g_topology_unlock();
@@ -2464,10 +2457,6 @@
 				 * Timeout expired, so destroy device.
 				 */
 				sc->sc_flags |= G_RAID3_DEVICE_FLAG_DESTROY;
-				G_RAID3_DEBUG(1, "root_mount_rel[%u] %p",
-				    __LINE__, sc->sc_rootmount);
-				root_mount_rel(sc->sc_rootmount);
-				sc->sc_rootmount = NULL;
 			}
 			return;
 		}
@@ -2610,12 +2599,6 @@
 		}
 		if (sc->sc_provider == NULL)
 			g_raid3_launch_provider(sc);
-		if (sc->sc_rootmount != NULL) {
-			G_RAID3_DEBUG(1, "root_mount_rel[%u] %p", __LINE__,
-			    sc->sc_rootmount);
-			root_mount_rel(sc->sc_rootmount);
-			sc->sc_rootmount = NULL;
-		}
 		break;
 	case G_RAID3_DEVICE_STATE_COMPLETE:
 		/*
@@ -2643,12 +2626,6 @@
 		}
 		if (sc->sc_provider == NULL)
 			g_raid3_launch_provider(sc);
-		if (sc->sc_rootmount != NULL) {
-			G_RAID3_DEBUG(1, "root_mount_rel[%u] %p", __LINE__,
-			    sc->sc_rootmount);
-			root_mount_rel(sc->sc_rootmount);
-			sc->sc_rootmount = NULL;
-		}
 		break;
 	default:
 		KASSERT(1 == 0, ("Wrong device state (%s, %s).", sc->sc_name,
@@ -3193,9 +3170,6 @@
 	G_RAID3_DEBUG(1, "Device %s created (%u components, id=%u).",
 	    sc->sc_name, sc->sc_ndisks, sc->sc_id);
 
-	sc->sc_rootmount = root_mount_hold("GRAID3");
-	G_RAID3_DEBUG(1, "root_mount_hold %p", sc->sc_rootmount);
-
 	/*
 	 * Run timeout.
 	 */
==== //depot/projects/usb/src/sys/geom/raid3/g_raid3.h#2 - /home/some_dir/src/sys/geom/raid3/g_raid3.h ====
@@ -240,8 +240,6 @@
 	struct mtx	sc_events_mtx;
 
 	struct callout	sc_callout;
-
-	struct root_hold_token *sc_rootmount;
 };
 #define	sc_name	sc_geom->name
 
==== //depot/projects/usb/src/sys/kern/kern_cons.c#3 - /home/some_dir/src/sys/kern/kern_cons.c ====
@@ -353,8 +353,10 @@
 
 	if (cn_mute)
 		return (-1);
-	while ((c = cncheckc()) == -1)
-		;
+	while ((c = cncheckc()) == -1) {
+		if (!kdb_active)
+			pause("WKEY", hz / 100);	/* give USB a chance */
+	}
 	if (c == '\r')
 		c = '\n';		/* console input is always ICRNL */
 	return (c);
==== //depot/projects/usb/src/sys/kern/vfs_mount.c#29 - /home/some_dir/src/sys/kern/vfs_mount.c ====
@@ -1344,82 +1344,9 @@
  *
  */
 
-struct root_hold_token {
-	const char			*who;
-	LIST_ENTRY(root_hold_token)	list;
-};
-
-static LIST_HEAD(, root_hold_token)	root_holds =
-    LIST_HEAD_INITIALIZER(&root_holds);
-
 static int root_mount_complete;
 
 /*
- * Hold root mount.
- */
-struct root_hold_token *
-root_mount_hold(const char *identifier)
-{
-	struct root_hold_token *h;
-
-	if (root_mounted())
-		return (NULL);
-
-	h = malloc(sizeof *h, M_DEVBUF, M_ZERO | M_WAITOK);
-	h->who = identifier;
-	mtx_lock(&mountlist_mtx);
-	LIST_INSERT_HEAD(&root_holds, h, list);
-	mtx_unlock(&mountlist_mtx);
-	return (h);
-}
-
-/*
- * Release root mount.
- */
-void
-root_mount_rel(struct root_hold_token *h)
-{
-
-	if (h == NULL)
-		return;
-	mtx_lock(&mountlist_mtx);
-	LIST_REMOVE(h, list);
-	wakeup(&root_holds);
-	mtx_unlock(&mountlist_mtx);
-	free(h, M_DEVBUF);
-}
-
-/*
- * Wait for all subsystems to release root mount.
- */
-static void
-root_mount_prepare(void)
-{
-	struct root_hold_token *h;
-	struct timeval lastfail;
-	int curfail = 0;
-
-	for (;;) {
-		DROP_GIANT();
-		g_waitidle();
-		PICKUP_GIANT();
-		mtx_lock(&mountlist_mtx);
-		if (LIST_EMPTY(&root_holds)) {
-			mtx_unlock(&mountlist_mtx);
-			break;
-		}
-		if (ppsratecheck(&lastfail, &curfail, 1)) {
-			printf("Root mount waiting for:");
-			LIST_FOREACH(h, &root_holds, list)
-				printf(" %s", h->who);
-			printf("\n");
-		}
-		msleep(&root_holds, &mountlist_mtx, PZERO | PDROP, "roothold",
-		    hz);
-	}
-}
-
-/*
  * Root was mounted, share the good news.
  */
 static void
@@ -1452,27 +1379,6 @@
 	return (root_mount_complete);
 }
 
-/*
- * Wait until root is mounted.
- */
-void
-root_mount_wait(void)
-{
-
-	/*
-	 * Panic on an obvious deadlock - the function can't be called from
-	 * a thread which is doing the whole SYSINIT stuff.
-	 */
-	KASSERT(curthread->td_proc->p_pid != 0,
-	    ("root_mount_wait: cannot be called from the swapper thread"));
-	mtx_lock(&mountlist_mtx);
-	while (!root_mount_complete) {
-		msleep(&root_mount_complete, &mountlist_mtx, PZERO, "rootwait",
-		    hz);
-	}
-	mtx_unlock(&mountlist_mtx);
-}
-
 static void
 set_rootvnode()
 {
@@ -1644,24 +1550,24 @@
 vfs_mountroot(void)
 {
 	char *cp, *options;
-	int error, i, asked = 0;
+	int error, i, t, asked = 0;
 
 	options = NULL;
 
-	root_mount_prepare();
-
 	mount_zone = uma_zcreate("Mountpoints", sizeof(struct mount),
 	    NULL, NULL, mount_init, mount_fini,
 	    UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
 	devfs_first();
 
+repeat:
+
 	/*
 	 * We are booted with instructions to prompt for the root filesystem.
 	 */
 	if (boothowto & RB_ASKNAME) {
 		if (!vfs_mountroot_ask())
 			goto mounted;
-		asked = 1;
+		asked++;
 	}
 
 	options = getenv("vfs.root.mountfrom.options");
@@ -1715,14 +1621,35 @@
 	if (ctrootdevname != NULL)
 		if (!vfs_mountroot_try(ctrootdevname, options))
 			goto mounted;
+
+	if (!asked) {
+		printf("\nWaiting for boot disk to appear. "
+		    "Press CTRL+C to abort.\n");
+	}
+
+	asked ++;
+
+	t = 16;
+	i = -1;
+	while (t-- && (i == -1)) {
+		pause("WKEY", hz / 16);		/* give USB a chance */
+		i = cncheckc();
+	}
+
+	if (i != -1)
+		printf("Got key: %d, %c\n", i, i);
+
 	/*
 	 * Everything so far has failed, prompt on the console if we haven't
 	 * already tried that.
 	 */
-	if (!asked)
+	if (i == 'c')
 		if (!vfs_mountroot_ask())
 			goto mounted;
 
+	if (asked < (3 * 60))	/* Wait a maximum of 3 minutes */
+		goto repeat;
+
 	panic("Root mount failed, startup aborted.");
 
 mounted:
@@ -1875,6 +1802,7 @@
 	char *options;
 
 	for(;;) {
+		printf("\n");
 		printf("Loader variables:\n");
 		printf("vfs.root.mountfrom=");
 		mountfrom = getenv("vfs.root.mountfrom");
==== //depot/projects/usb/src/sys/sys/systm.h#19 - /home/some_dir/src/sys/sys/systm.h ====
@@ -333,15 +333,8 @@
 /* XXX: Should be void nanodelay(u_int nsec); */
 void	DELAY(int usec);
 
-/* Root mount holdback API */
-struct root_hold_token;
-
-struct root_hold_token *root_mount_hold(const char *identifier);
-void root_mount_rel(struct root_hold_token *h);
-void root_mount_wait(void);
 int root_mounted(void);
 
-
 /*
  * Unit number allocation API. (kern/subr_unit.c)
  */

--Boundary-00=_sp4xKvPSgaU5kXU--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200910031931.24600.hselasky>