Index: uspace/srv/fs/devfs/devfs_ops.c
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.c	(revision 8b4e203e814436ee0c71d7631df8ffdd38fc11b2)
+++ uspace/srv/fs/devfs/devfs_ops.c	(revision a7e04d168c109fc1341d8b9209991296351d3228)
@@ -60,7 +60,8 @@
 typedef struct {
 	devmap_handle_t handle;
-	int phone;
+	int phone;		/**< When < 0, the structure is incomplete. */
 	size_t refcount;
 	link_t link;
+	fibril_condvar_t cv;	/**< Broadcast when completed. */
 } device_t;
 
@@ -227,7 +228,9 @@
 			[DEVICES_KEY_HANDLE] = (unsigned long) node->handle
 		};
-		
+		link_t *lnk;
+
 		fibril_mutex_lock(&devices_mutex);
-		link_t *lnk = hash_table_find(&devices, key);
+restart:
+		lnk = hash_table_find(&devices, key);
 		if (lnk == NULL) {
 			device_t *dev = (device_t *) malloc(sizeof(device_t));
@@ -237,18 +240,60 @@
 			}
 			
+			dev->handle = node->handle;
+			dev->phone = -1;	/* mark as incomplete */
+			dev->refcount = 1;
+			fibril_condvar_initialize(&dev->cv);
+
+			/*
+			 * Insert the incomplete device structure so that other
+			 * fibrils will not race with us when we drop the mutex
+			 * below.
+			 */
+			hash_table_insert(&devices, key, &dev->link);
+
+			/*
+			 * Drop the mutex to allow recursive devfs requests.
+			 */
+			fibril_mutex_unlock(&devices_mutex);
+
 			int phone = devmap_device_connect(node->handle, 0);
+
+			fibril_mutex_lock(&devices_mutex);
+
+			/*
+			 * Notify possible waiters about this device structure
+			 * being completed (or destroyed).
+			 */
+			fibril_condvar_broadcast(&dev->cv);
+
 			if (phone < 0) {
+				/*
+				 * Connecting failed, need to remove the
+				 * entry and free the device structure.
+				 */
+				hash_table_remove(&devices, key, DEVICES_KEYS);
 				fibril_mutex_unlock(&devices_mutex);
+
 				free(dev);
 				return ENOENT;
 			}
 			
-			dev->handle = node->handle;
+			/* Set the correct phone. */
 			dev->phone = phone;
-			dev->refcount = 1;
-			
-			hash_table_insert(&devices, key, &dev->link);
 		} else {
 			device_t *dev = hash_table_get_instance(lnk, device_t, link);
+
+			if (dev->phone < 0) {
+				/*
+				 * Wait until the device structure is completed
+				 * and start from the beginning as the device
+				 * structure might have entirely disappeared
+				 * while we were not holding the mutex in
+				 * fibril_condvar_wait().
+				 */
+				fibril_condvar_wait(&dev->cv, &devices_mutex);
+				goto restart;
+			}
+
 			dev->refcount++;
 		}
@@ -564,4 +609,5 @@
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
+		assert(dev->phone >= 0);
 		
 		ipc_callid_t callid;
@@ -627,4 +673,5 @@
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
+		assert(dev->phone >= 0);
 		
 		ipc_callid_t callid;
@@ -696,4 +743,5 @@
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
+		assert(dev->phone >= 0);
 		dev->refcount--;
 		
@@ -743,4 +791,5 @@
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
+		assert(dev->phone >= 0);
 		
 		/* Make a request at the driver */
