diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index d28d1e3..2cf982e 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -2404,20 +2404,24 @@ function drupal_get_bootstrap_phase() {
  *
  * @see Drupal\Core\DrupalKernel
  *
- * @param $reset
- *   A new container instance to reset the Drupal container to.
+ * @param Symfony\Component\DependencyInjection\Container $new_container
+ *   A new container instance to replace the current.
+ * @param bool $reset
+ *   (optional) Internal use only. Whether to enforce a reset of the statically
+ *   cached container. Pass NULL for $new_container to create a fresh Container
+ *   in a subsequent call to this function. Used by tests.
  *
  * @return Symfony\Component\DependencyInjection\Container
  *   The instance of the Container used to set up and maintain object
  *   instances.
  */
-function drupal_container(Container $reset = NULL) {
+function drupal_container(Container $new_container = NULL, $reset = FALSE) {
   // We do not use drupal_static() here because we do not have a mechanism by
   // which to reinitialize the stored objects, so a drupal_static_reset() call
   // would leave Drupal in a nonfunctional state.
   static $container = NULL;
-  if (isset($reset)) {
-    $container = $reset;
+  if (isset($new_container) || $reset) {
+    $container = $new_container;
   }
   elseif (!isset($container)) {
     // Return a ContainerBuilder instance with the bare essentials needed for any
@@ -2426,25 +2430,38 @@ function drupal_container(Container $reset = NULL) {
     // requests.
     $container = new ContainerBuilder();
 
-    // Register configuration storage class and options.
+    // Register active configuration storage.
     // @todo The active store and its options need to be configurable.
     //   Use either global $conf (recursion warning) or global $config, or a
     //   bootstrap configuration *file* to allow to set/override this very
     //   lowest of low level configuration.
-    $container->setParameter('config.storage.options', array(
-      'connection' => 'default',
-      'target' => 'default',
+    $container->setParameter('config.storage.active.options', array(
+      'Drupal\Core\Config\FileStorage' => array(
+        'directory' => config_get_config_directory(CONFIG_ACTIVE_DIRECTORY),
+      ),
+      'Drupal\Core\Config\CacheStorage' => array(
+        'backend' => 'Drupal\Core\Cache\DatabaseBackend',
+        'bin' => 'config',
+      ),
     ));
-    $container->register('config.storage', 'Drupal\Core\Config\DatabaseStorage')
-      ->addArgument('%config.storage.options%');
+    $container->register('config.storage.active', 'Drupal\Core\Config\CachedFileStorage')
+      ->addArgument('%config.storage.active.options%');
 
     $container->register('config.subscriber.globalconf', 'Drupal\Core\EventSubscriber\ConfigGlobalOverrideSubscriber');
     $container->register('dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher')
       ->addMethodCall('addSubscriber', array(new Reference('config.subscriber.globalconf')));
+
     // Register configuration object factory.
     $container->register('config.factory', 'Drupal\Core\Config\ConfigFactory')
-      ->addArgument(new Reference('config.storage'))
+      ->addArgument(new Reference('config.storage.active'))
       ->addArgument(new Reference('dispatcher'));
+
+    // Register staging configuration storage.
+    $container->setParameter('config.storage.staging.options', array(
+      'directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY),
+    ));
+    $container->register('config.storage.staging', 'Drupal\Core\Config\FileStorage')
+      ->addArgument('%config.storage.staging.options%');
   }
   return $container;
 }
diff --git a/core/includes/config.inc b/core/includes/config.inc
index 369a0d1..2bc77c0 100644
--- a/core/includes/config.inc
+++ b/core/includes/config.inc
@@ -17,15 +17,12 @@
  *   The extension type; e.g., 'module' or 'theme'.
  * @param string $name
  *   The name of the module or theme to install default configuration for.
- *
- * @todo Make this acknowledge other storage engines rather than having
- *   SQL be hardcoded.
  */
 function config_install_default_config($type, $name) {
   $config_dir = drupal_get_path($type, $name) . '/config';
   if (is_dir($config_dir)) {
     $source_storage = new FileStorage(array('directory' => $config_dir));
-    $target_storage = drupal_container()->get('config.storage');
+    $target_storage = drupal_container()->get('config.storage.active');
     $null_storage = new NullStorage();
 
     // Upon installation, only new config objects need to be created.
@@ -43,10 +40,12 @@ function config_install_default_config($type, $name) {
 }
 
 /**
- * @todo Modules need a way to access the active store, whatever it is.
+ * Gets configuration object names starting with a given prefix.
+ *
+ * @see Drupal\Core\Config\StorageInterface::listAll()
  */
 function config_get_storage_names_with_prefix($prefix = '') {
-  return drupal_container()->get('config.storage')->listAll($prefix);
+  return drupal_container()->get('config.storage.active')->listAll($prefix);
 }
 
 /**
@@ -137,8 +136,8 @@ function config_sync_changes(array $config_changes, StorageInterface $source_sto
  */
 function config_import() {
   // Retrieve a list of differences between staging and the active store.
-  $source_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY)));
-  $target_storage = drupal_container()->get('config.storage');
+  $source_storage = drupal_container()->get('config.storage.staging');
+  $target_storage = drupal_container()->get('config.storage.active');
 
   $config_changes = config_sync_get_changes($source_storage, $target_storage);
   if (empty($config_changes)) {
@@ -218,8 +217,8 @@ function config_import_invoke_owner(array $config_changes, StorageInterface $sou
  */
 function config_export() {
   // Retrieve a list of differences between the active store and staging.
-  $source_storage = drupal_container()->get('config.storage');
-  $target_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY)));
+  $source_storage = drupal_container()->get('config.storage.active');
+  $target_storage = drupal_container()->get('config.storage.staging');
 
   $config_changes = config_sync_get_changes($source_storage, $target_storage);
   if (empty($config_changes)) {
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index c15107c..039f007 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -5,6 +5,8 @@
 use Drupal\Core\Database\Install\TaskException;
 use Drupal\Core\Language\Language;
 
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 
@@ -272,6 +274,42 @@ function install_begin_request(&$install_state) {
   include_once DRUPAL_ROOT . '/core/includes/module.inc';
   include_once DRUPAL_ROOT . '/core/includes/session.inc';
 
+  // Determine whether the configuration system is ready to operate.
+  $install_state['config_verified'] = install_verify_config_directory(CONFIG_ACTIVE_DIRECTORY) && install_verify_config_directory(CONFIG_STAGING_DIRECTORY);
+
+  // If it is not, replace the configuration storage with the InstallStorage
+  // implementation, for the following reasons:
+  // - The first call into drupal_container() will try to set up the regular
+  //   runtime configuration storage, using the CachedFileStorage. The storage
+  //   controller options require to pass in the config directory name, but that
+  //   directory does not exist yet.
+  // - The installer outputs maintenance theme pages and performs many other
+  //   operations, which try to load configuration. Since there is no active
+  //   configuration yet, and because the configuration system does not have a
+  //   notion of default values at runtime, data is missing in many places. The
+  //   lack of data does not trigger errors, but results in a broken user
+  //   interface (e.g., missing page title, etc).
+  // - The actual configuration data to read during installation is essentially
+  //   the default configuration provided by the installation profile and
+  //   modules (most notably System module). The InstallStorage therefore reads
+  //   from the default configuration directories of extensions.
+  // This override is reverted as soon as the config directory has been set up
+  // successfully.
+  // @see drupal_install_config_directory()
+  // @todo Move this into a proper Drupal\Core\DependencyInjection\InstallContainerBuilder.
+  if (!$install_state['config_verified']) {
+    $container = new ContainerBuilder();
+
+    $container->register('dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher');
+
+    $container->register('config.storage.active', 'Drupal\Core\Config\InstallStorage');
+    $container->register('config.factory', 'Drupal\Core\Config\ConfigFactory')
+      ->addArgument(new Reference('config.storage.active'))
+      ->addArgument(new Reference('dispatcher'));
+
+    drupal_container($container);
+  }
+
   // Set up $language, so t() caller functions will still work.
   drupal_language_initialize();
 
@@ -316,7 +354,6 @@ function install_begin_request(&$install_state) {
 
   // Check existing settings.php.
   $install_state['database_verified'] = install_verify_database_settings();
-  $install_state['config_verified'] = install_verify_config_directory(CONFIG_ACTIVE_DIRECTORY) && install_verify_config_directory(CONFIG_STAGING_DIRECTORY);
   $install_state['settings_verified'] = $install_state['config_verified'] && $install_state['database_verified'];
 
   if ($install_state['database_verified']) {
@@ -1054,6 +1091,11 @@ function install_settings_form_submit($form, &$form_state) {
   // Add the config directories to settings.php.
   drupal_install_config_directories();
 
+  // We have valid configuration directories in settings.php.
+  // Reset the service container, so the config.storage.active service will use
+  // the actual active storage for installing configuration.
+  drupal_container(NULL, TRUE);
+
   // Indicate that the settings file has been verified, and check the database
   // for the last completed task, now that we have a valid connection. This
   // last step is important since we want to trigger an error if the new
diff --git a/core/includes/install.inc b/core/includes/install.inc
index 2c95bf3..3ae0144 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -7,6 +7,7 @@
 
 use Drupal\Core\Database\Database;
 use Drupal\locale\Gettext;
+use Exception;
 
 /**
  * Indicates that a module has not been installed yet.
@@ -275,7 +276,7 @@ function drupal_install_config_directories() {
     drupal_rewrite_settings($settings);
   }
 
-  // Ensure that the config directory exists or can be created, and is writable.
+  // Ensure the config directories exist or can be created, and are writable.
   foreach (array(CONFIG_ACTIVE_DIRECTORY, CONFIG_STAGING_DIRECTORY) as $config_type) {
     // This should never fail, since if the config directory was specified in
     // settings.php it will have already been created and verified earlier, and
@@ -296,7 +297,7 @@ function drupal_install_config_directories() {
  * Checks whether a config directory name is defined, and if so, whether it
  * exists and is writable.
  *
- * This partically duplicates install_ensure_config_directory(), but is required
+ * This partially duplicates install_ensure_config_directory(), but is required
  * since the installer would create the config directory too early in the
  * installation process otherwise (e.g., when only visiting install.php when
  * there is a settings.php already, but not actually executing the installation).
@@ -313,9 +314,16 @@ function install_verify_config_directory($type) {
   if (!isset($config_directories[$type])) {
     return FALSE;
   }
-  $config_directory = config_get_config_directory($type);
-  if (is_dir($config_directory) && is_writable($config_directory)) {
-    return TRUE;
+  // config_get_config_directory() throws an exception when there is a prepared
+  // settings.php that defines $config_directories already and the directories
+  // do not exist yet.
+  try {
+    $config_directory = config_get_config_directory($type);
+    if (is_dir($config_directory) && is_writable($config_directory)) {
+      return TRUE;
+    }
+  }
+  catch (Exception $e) {
   }
   return FALSE;
 }
diff --git a/core/includes/module.inc b/core/includes/module.inc
index d9eab10..c3399c0 100644
--- a/core/includes/module.inc
+++ b/core/includes/module.inc
@@ -6,7 +6,7 @@
  */
 
 use Drupal\Component\Graph\Graph;
-use Drupal\Core\Config\DatabaseStorage;
+use Drupal\Core\Config\NullStorage;
 
 /**
  * Loads all the modules that have been enabled in the system table.
@@ -617,19 +617,26 @@ function module_uninstall($module_list = array(), $uninstall_dependents = TRUE)
     $module_list = array_keys($module_list);
   }
 
-  $storage = new DatabaseStorage();
+  $source_storage = new NullStorage();
+  $target_storage = drupal_container()->get('config.storage.active');
   foreach ($module_list as $module) {
+    // Remove all configuration belonging to the module.
+    $config_changes = $target_storage->listAll($module . '.');
+    if (!empty($config_changes)) {
+      $config_changes = array(
+        'delete' => $config_changes,
+        'change' => array(),
+        'create' => array(),
+      );
+      $remaining_changes = config_import_invoke_owner($config_changes, $source_storage, $target_storage);
+      config_sync_changes($remaining_changes, $source_storage, $target_storage);
+    }
+
     // Uninstall the module.
     module_load_install($module);
     module_invoke($module, 'uninstall');
     drupal_uninstall_schema($module);
 
-    // Remove all configuration belonging to the module.
-    $config_names = $storage->listAll($module . '.');
-    foreach ($config_names as $config_name) {
-      config($config_name)->delete();
-    }
-
     watchdog('system', '%module module uninstalled.', array('%module' => $module), WATCHDOG_INFO);
     drupal_set_installed_schema_version($module, SCHEMA_UNINSTALLED);
   }
diff --git a/core/includes/theme.maintenance.inc b/core/includes/theme.maintenance.inc
index 12de2a7..4b3e80c 100644
--- a/core/includes/theme.maintenance.inc
+++ b/core/includes/theme.maintenance.inc
@@ -122,7 +122,7 @@ function theme_task_list($variables) {
     }
     else {
       $class = $done ? 'done' : '';
-      $status = $done ? '(' . t('done') . ')' : '';
+      $status = $done ? '(' . $t('done') . ')' : '';
     }
     $output .= '<li';
     $output .= ($class ? ' class="' . $class . '"' : '') . '>';
diff --git a/core/lib/Drupal/Core/Config/CacheStorage.php b/core/lib/Drupal/Core/Config/CacheStorage.php
new file mode 100644
index 0000000..a2effc8
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/CacheStorage.php
@@ -0,0 +1,143 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Config\CacheStorage.
+ */
+
+namespace Drupal\Core\Config;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+
+/**
+ * Defines the Cache storage controller.
+ *
+ * This storage controller essentially just bridges the configuration system
+ * storage to a backend of the cache system. All StorageInterface method calls
+ * are forwarded to the corresponding CacheBackendInterface methods.
+ *
+ * @see Drupal\Core\Cache\CacheBackendInterface
+ *
+ * While this causes a level of indirection and the functionality could
+ * technically be embedded into a configuration storage controller directly,
+ * a separate bridge is architecturally cleaner and also allows for alternative
+ * setups.
+ *
+ * By default, the configuration system uses this controller in the
+ * CachedFileStorage implementation.
+ *
+ * @see Drupal\Core\Config\CachedFileStorage
+ */
+class CacheStorage implements StorageInterface {
+
+  /**
+   * Cache backend options for this storage controller.
+   *
+   * - backend: The cache backend to use.
+   * - bin: The cache bin to use.
+   *
+   * @var array
+   */
+  protected $options;
+
+  /**
+   * The instantiated Cache backend.
+   *
+   * @var Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $storage;
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::__construct().
+   */
+  public function __construct(array $options = array()) {
+    $options += array(
+      'backend' => 'Drupal\Core\Cache\DatabaseBackend',
+      'bin' => 'config',
+    );
+    $this->options = $options;
+  }
+
+  /**
+   * Returns the instantiated Cache backend to use.
+   */
+  protected function getBackend() {
+    if (!isset($this->storage)) {
+      $this->storage = new $this->options['backend']($this->options['bin']);
+    }
+    return $this->storage;
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::exists().
+   */
+  public function exists($name) {
+    return (bool) $this->getBackend()->get($name);
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::read().
+   */
+  public function read($name) {
+    if ($cache = $this->getBackend()->get($name)) {
+      // The cache backend supports primitive data types, but only an array
+      // represents valid config object data.
+      if (is_array($cache->data)) {
+        return $cache->data;
+      }
+    }
+    return FALSE;
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::write().
+   */
+  public function write($name, array $data) {
+    $this->getBackend()->set($name, $data, CacheBackendInterface::CACHE_PERMANENT, array('config' => array($name)));
+    return TRUE;
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::delete().
+   */
+  public function delete($name) {
+    $this->getBackend()->delete($name);
+    return TRUE;
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::rename().
+   */
+  public function rename($name, $new_name) {
+    $this->getBackend()->delete($name);
+    $this->getBackend()->delete($new_name);
+    return TRUE;
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::encode().
+   */
+  public static function encode($data) {
+    return serialize($data);
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::decode().
+   *
+   * @throws ErrorException
+   *   unserialize() triggers E_NOTICE if the string cannot be unserialized.
+   */
+  public static function decode($raw) {
+    $data = @unserialize($raw);
+    return is_array($data) ? $data : FALSE;
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::listAll().
+   *
+   * Not supported by CacheBackendInterface.
+   */
+  public function listAll($prefix = '') {
+    return array();
+  }
+}
diff --git a/core/lib/Drupal/Core/Config/CachedFileStorage.php b/core/lib/Drupal/Core/Config/CachedFileStorage.php
new file mode 100644
index 0000000..0fc0cfe
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/CachedFileStorage.php
@@ -0,0 +1,134 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Config\CachedFileStorage.
+ */
+
+namespace Drupal\Core\Config;
+
+use Drupal\Core\Config\FileStorage;
+
+/**
+ * Storage controller that uses FileStorage as canonical storage and
+ * CacheStorage as a cache.
+ */
+class CachedFileStorage implements StorageInterface {
+
+  /**
+   * The configuration options for the sub-storage controllers.
+   *
+   * An associative array whose keys are the class names of the storage
+   * controllers to use, and whose values are the respective configuration
+   * options for each storage controller.
+   *
+   * Two array elements are expected. A key and definition for
+   * Drupal\Core\Config\FileStorage is required. The other element should point
+   * to another storage controller that is used as cache.
+   *
+   * @var array
+   */
+  protected $options;
+
+  /**
+   * The instantiated sub-storage controllers.
+   *
+   * @var array
+   */
+  protected $storages = array();
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::__construct().
+   */
+  public function __construct(array $options = array()) {
+    $this->options = $options;
+
+    $this->storages['file'] = new FileStorage($options['Drupal\Core\Config\FileStorage']);
+
+    unset($options['Drupal\Core\Config\FileStorage']);
+    list($cache_class, $cache_options) = each($options);
+    $this->storages['cache'] = new $cache_class($cache_options);
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::exists().
+   */
+  public function exists($name) {
+    // A single filestat is faster than a complex cache lookup and possibly
+    // subsequent filestat.
+    return $this->storages['file']->exists($name);
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::read().
+   */
+  public function read($name) {
+    // Check the cache.
+    $data = $this->storages['cache']->read($name);
+    // If the cache returns no result, check the file storage.
+    if ($data === FALSE) {
+      $data = $this->storages['file']->read($name);
+      // @todo Should the config object be cached if it does not exist?
+      if ($data !== FALSE) {
+        $this->storages['cache']->write($name, $data);
+      }
+    }
+    return $data;
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::write().
+   */
+  public function write($name, array $data) {
+    $success = $this->storages['file']->write($name, $data);
+    $this->storages['cache']->delete($name);
+    return $success;
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::delete().
+   */
+  public function delete($name) {
+    $success = TRUE;
+    foreach ($this->storages as $storage) {
+      if (!$storage->delete($name)) {
+        $success = FALSE;
+      }
+    }
+    return $success;
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::rename().
+   */
+  public function rename($name, $new_name) {
+    $success = $this->storages['file']->rename($name, $new_name);
+    $this->storages['cache']->rename($name, $new_name);
+    return $success;
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::encode().
+   *
+   * @todo Remove encode() from StorageInterface.
+   */
+  public static function encode($data) {
+    return $this->storages['file']->encode($data);
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::decode().
+   *
+   * @todo Remove decode() from StorageInterface.
+   */
+  public static function decode($raw) {
+    return $this->storages['file']->decode($raw);
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::listAll().
+   */
+  public function listAll($prefix = '') {
+    return $this->storages['file']->listAll($prefix);
+  }
+}
diff --git a/core/lib/Drupal/Core/Config/DatabaseStorage.php b/core/lib/Drupal/Core/Config/DatabaseStorage.php
index ad8c155..e4a1934 100644
--- a/core/lib/Drupal/Core/Config/DatabaseStorage.php
+++ b/core/lib/Drupal/Core/Config/DatabaseStorage.php
@@ -44,6 +44,15 @@ protected function getConnection() {
   }
 
   /**
+   * Implements Drupal\Core\Config\StorageInterface::exists().
+   */
+  public function exists($name) {
+    return (bool) $this->getConnection()->queryRange('SELECT 1 FROM {config} WHERE name = :name', 0, 1, array(
+      ':name' => $name,
+    ), $this->options)->fetchField();
+  }
+
+  /**
    * Implements Drupal\Core\Config\StorageInterface::read().
    *
    * @throws PDOException
@@ -56,8 +65,6 @@ public function read($name) {
     // read without actually having the database available. In this case,
     // catch the exception and just return an empty array so the caller can
     // handle it if need be.
-    // @todo Remove this and use appropriate config.storage service definition
-    //   in the installer instead.
     try {
       $raw = $this->getConnection()->query('SELECT data FROM {config} WHERE name = :name', array(':name' => $name), $this->options)->fetchField();
       if ($raw !== FALSE) {
diff --git a/core/lib/Drupal/Core/Config/FileStorage.php b/core/lib/Drupal/Core/Config/FileStorage.php
index d96af7e..cbad07f 100644
--- a/core/lib/Drupal/Core/Config/FileStorage.php
+++ b/core/lib/Drupal/Core/Config/FileStorage.php
@@ -28,7 +28,7 @@ class FileStorage implements StorageInterface {
    */
   public function __construct(array $options = array()) {
     if (!isset($options['directory'])) {
-      $options['directory'] = config_get_config_directory();
+      $options['directory'] = config_get_config_directory(CONFIG_ACTIVE_DIRECTORY);
     }
     $this->options = $options;
   }
@@ -54,10 +54,7 @@ public static function getFileExtension() {
   }
 
   /**
-   * Returns whether the configuration file exists.
-   *
-   * @return bool
-   *   TRUE if the configuration file exists, FALSE otherwise.
+   * Implements Drupal\Core\Config\StorageInterface::exists().
    */
   public function exists($name) {
     return file_exists($this->getFilePath($name));
diff --git a/core/lib/Drupal/Core/Config/InstallStorage.php b/core/lib/Drupal/Core/Config/InstallStorage.php
new file mode 100644
index 0000000..b2ee894
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/InstallStorage.php
@@ -0,0 +1,105 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Config\InstallStorage.
+ */
+
+namespace Drupal\Core\Config;
+
+/**
+ * Storage controller used by the Drupal installer.
+ *
+ * @see install_begin_request()
+ */
+class InstallStorage extends FileStorage {
+
+  /**
+   * Configuration options for this storage controller.
+   *
+   * @var array
+   */
+  protected $options;
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::__construct().
+   */
+  public function __construct(array $options = array()) {
+    // Intentionally not calling FileStorage's constructor, since that calls
+    // into config_get_config_directory(), which is not functional yet.
+    $this->options = $options;
+  }
+
+  /**
+   * Overrides Drupal\Core\Config\FileStorage::getFilePath().
+   *
+   * Returns the path to the configuration file.
+   *
+   * Determines the owner and path to the default configuration file of a
+   * requested config object name located in the installation profile, a module,
+   * or a theme (in this order).
+   *
+   * @return string
+   *   The path to the configuration file.
+   *
+   * @todo Improve this when figuring out how we want to handle configuration in
+   *   installation profiles. E.g., a config object actually has to be searched
+   *   in the profile first (whereas the profile is never the owner), only
+   *   afterwards check for a corresponding module or theme.
+   */
+  public function getFilePath($name) {
+    // Extract the owner.
+    $owner = strtok($name, '.');
+    // Determine the path to the owner.
+    $path = FALSE;
+    foreach (array('profile', 'module', 'theme') as $type) {
+      if ($path = drupal_get_path($type, $owner)) {
+        $file = $path . '/config/' . $name . '.' . self::getFileExtension();
+        if (file_exists($file)) {
+          return $file;
+        }
+      }
+    }
+    // If any code in the early installer requests a configuration object that
+    // does not exist anywhere as default config, then that must be mistake.
+    throw new StorageException(format_string('Missing configuration file: @name', array(
+      '@name' => $name,
+    )));
+  }
+
+  /**
+   * Overrides Drupal\Core\Config\FileStorage::write().
+   *
+   * @throws Drupal\Core\Config\StorageException
+   */
+  public function write($name, array $data) {
+    throw new StorageException('Write operations are not allowed.');
+  }
+
+  /**
+   * Overrides Drupal\Core\Config\FileStorage::delete().
+   *
+   * @throws Drupal\Core\Config\StorageException
+   */
+  public function delete($name) {
+    throw new StorageException('Write operations are not allowed.');
+  }
+
+  /**
+   * Overrides Drupal\Core\Config\FileStorage::rename().
+   *
+   * @throws Drupal\Core\Config\StorageException
+   */
+  public function rename($name, $new_name) {
+    throw new StorageException('Write operations are not allowed.');
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::listAll().
+   *
+   * @throws Drupal\Core\Config\StorageException
+   */
+  public function listAll($prefix = '') {
+    throw new StorageException('List operation is not supported.');
+  }
+}
diff --git a/core/lib/Drupal/Core/Config/NullStorage.php b/core/lib/Drupal/Core/Config/NullStorage.php
index ea21be1..aa81b73 100644
--- a/core/lib/Drupal/Core/Config/NullStorage.php
+++ b/core/lib/Drupal/Core/Config/NullStorage.php
@@ -29,6 +29,13 @@ public function __construct(array $options = array()) {
   }
 
   /**
+   * Implements Drupal\Core\Config\StorageInterface::exists().
+   */
+  public function exists($name) {
+    return FALSE;
+  }
+
+  /**
    * Implements Drupal\Core\Config\StorageInterface::read().
    */
   public function read($name) {
diff --git a/core/lib/Drupal/Core/Config/StorageInterface.php b/core/lib/Drupal/Core/Config/StorageInterface.php
index a466538..688ae46 100644
--- a/core/lib/Drupal/Core/Config/StorageInterface.php
+++ b/core/lib/Drupal/Core/Config/StorageInterface.php
@@ -25,6 +25,17 @@
   public function __construct(array $options = array());
 
   /**
+   * Returns whether a configuration object exists.
+   *
+   * @param string $name
+   *   The name of a configuration object to test.
+   *
+   * @return bool
+   *   TRUE if the configuration object exists, FALSE otherwise.
+   */
+  public function exists($name);
+
+  /**
    * Reads configuration data from the storage.
    *
    * @param string $name
diff --git a/core/modules/config/lib/Drupal/config/ConfigStorageController.php b/core/modules/config/lib/Drupal/config/ConfigStorageController.php
index 12d62b4..840c8fb 100644
--- a/core/modules/config/lib/Drupal/config/ConfigStorageController.php
+++ b/core/modules/config/lib/Drupal/config/ConfigStorageController.php
@@ -151,7 +151,7 @@ protected function buildQuery($ids, $revision_id = FALSE) {
 
     // Load all of the configurables.
     if ($ids === NULL) {
-      $names = drupal_container()->get('config.storage')->listAll($prefix);
+      $names = drupal_container()->get('config.storage.active')->listAll($prefix);
       $result = array();
       foreach ($names as $name) {
         $config = config($name);
@@ -273,7 +273,8 @@ public function save(StorableInterface $entity) {
     // Configuration objects do not have a schema. Extract all key names from
     // class properties.
     $class_info = new \ReflectionClass($entity);
-    foreach ($class_info->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
+    $properties = $class_info->getProperties(\ReflectionProperty::IS_PUBLIC);
+    foreach ($properties as $property) {
       $name = $property->getName();
       $config->set($name, $entity->$name);
     }
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index 9654f9c..253d4df 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -726,6 +726,10 @@ protected function prepareEnvironment() {
       $GLOBALS['config_directories'][$type] = 'simpletest/' . substr($this->databasePrefix, 10) . '/config_' . $type;
     }
 
+    // Reset and create a new service container.
+    drupal_container(NULL, TRUE);
+    $this->container = drupal_container();
+
     $this->configDirectories = array();
     include_once DRUPAL_ROOT . '/core/includes/install.inc';
     foreach ($GLOBALS['config_directories'] as $type => $path) {
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 486afba..dc8821f 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -724,6 +724,8 @@ function system_schema() {
   );
   $schema['cache_bootstrap'] = $schema['cache'];
   $schema['cache_bootstrap']['description'] = 'Cache table for data required to bootstrap Drupal, may be routed to a shared memory cache.';
+  $schema['cache_config'] = $schema['cache'];
+  $schema['cache_config']['description'] = 'Cache table for configuration data.';
   $schema['cache_form'] = $schema['cache'];
   $schema['cache_form']['description'] = 'Cache table for the form system to store recently built forms and their storage data, to be used in subsequent page requests.';
   $schema['cache_page'] = $schema['cache'];
@@ -733,28 +735,6 @@ function system_schema() {
   $schema['cache_path'] = $schema['cache'];
   $schema['cache_path']['description'] = 'Cache table for path alias lookup.';
 
-  $schema['config'] = array(
-    'description' => 'Default active store for the configuration system.',
-    'fields' => array(
-      'name' => array(
-        'description' => 'The identifier for the configuration entry, such as module.example (the name of the file, minus the file extension).',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'data' => array(
-        'description' => 'The raw data for this configuration entry.',
-        'type' => 'blob',
-        'not null' => TRUE,
-        'size' => 'big',
-        'translatable' => TRUE,
-      ),
-    ),
-    'primary key' => array('name'),
-  );
-
-
   $schema['date_format_type'] = array(
     'description' => 'Stores configured date format types.',
     'fields' => array(
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index f78f123..3efffd0 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -3506,7 +3506,7 @@ function system_cron() {
  */
 function system_cache_flush() {
   // Do NOT flush the 'form' cache bin to retain in-progress form submissions.
-  return array('bootstrap', 'cache', 'page', 'path');
+  return array('bootstrap', 'config', 'cache', 'page', 'path');
 }
 
 /**
