diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index d2ce2973ba57..e3b27bfc70fb 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -81,6 +81,7 @@ int ata_wc = 1;
 
 /* local vars */
 static struct intr_config_hook *ata_delayed_attach = NULL;
+static struct root_hold_token *ata_root_hold_token;
 static int ata_dma = 1;
 static int atapi_dma = 1;
 
@@ -559,6 +560,7 @@ ata_boot_attach(void)
 	    ata_identify(ch->dev);
 	}
     }
+    root_mount_rel(ata_root_hold_token);
 }
 
 /*
@@ -814,6 +816,7 @@ ata_module_event_handler(module_t mod, int what, void *arg)
 		return EIO;
 	    }
 	    ata_delayed_attach->ich_func = (void*)ata_boot_attach;
+	    ata_root_hold_token = root_mount_hold("ATA");
 	    if (config_intrhook_establish(ata_delayed_attach) != 0) {
 		printf("ata: config_intrhook_establish failed\n");
 		free(ata_delayed_attach, M_TEMP);
diff --git a/sys/geom/geom_kern.c b/sys/geom/geom_kern.c
index 1308799f2ab3..29080e9db23c 100644
--- a/sys/geom/geom_kern.c
+++ b/sys/geom/geom_kern.c
@@ -132,13 +132,19 @@ g_event_procbody(void)
 {
 	struct proc *p = g_event_proc;
 	struct thread *tp = FIRST_THREAD_IN_PROC(p);
+	struct root_hold_token *t;
 
 	mtx_assert(&Giant, MA_NOTOWNED);
 	mtx_lock_spin(&sched_lock);
 	sched_prio(tp, PRIBIO);
 	mtx_unlock_spin(&sched_lock);
+	t = root_mount_hold("GEOM");
 	for(;;) {
 		g_run_events();
+		if (t != 0) {
+			root_mount_rel(t);
+			t = NULL;
+		}
 		tsleep(&g_wait_event, PRIBIO, "-", hz/10);
 	}
 }
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 04bf1284c155..fbbf4841144c 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -1004,6 +1004,54 @@ dounmount(mp, flags, td)
  *
  */
 
+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);
+
+struct root_hold_token *
+root_mount_hold(const char *identifier)
+{
+	struct root_hold_token *h;
+
+	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);
+}
+
+void
+root_mount_rel(struct root_hold_token *h)
+{
+
+	mtx_lock(&mountlist_mtx);
+	LIST_REMOVE(h, list);
+	wakeup(&root_holds);
+	mtx_unlock(&mountlist_mtx);
+	free(h, M_DEVBUF);
+}
+
+static void
+root_mount_wait(void)
+{
+	struct root_hold_token *h;
+
+	mtx_lock(&mountlist_mtx);
+	while (!LIST_EMPTY(&root_holds)) {
+		printf("Root mount waiting for:");
+		LIST_FOREACH(h, &root_holds, list)
+			printf(" %s", h->who);
+		printf("\n");
+		msleep(&root_holds, &mountlist_mtx, PZERO, "roothold", hz);
+	}
+	mtx_unlock(&mountlist_mtx);
+}
+
 static void
 set_rootvnode(struct thread *td)
 {
@@ -1140,12 +1188,7 @@ vfs_mountroot(void)
 	int error, i, asked = 0;
 	struct mount *mp;
 
-	/*
-	 * Wait for GEOM to settle down
-	 */
-	DROP_GIANT();
-	g_waitidle();
-	PICKUP_GIANT();
+	root_mount_wait();
 
 	mp = devfs_first();
 
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index e8b923f6fd84..0c114b3f7362 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -315,6 +315,13 @@ const char *devtoname(struct cdev *cdev);
 /* 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);
+
+
 /*
  * Unit number allocation API. (kern/subr_unit.c)
  */