diff --git a/lib/private/files/filesystem.php b/lib/private/files/filesystem.php
index 351483d59c1b6ee62699f34c4cc373b55405e144..eef76125311e14ebf5b3a95f55a60f29361f04e8 100644
--- a/lib/private/files/filesystem.php
+++ b/lib/private/files/filesystem.php
@@ -201,11 +201,13 @@ class Filesystem {
 	private static $loader;
 
 	/**
+	 * @param string $wrapperName
 	 * @param callable $wrapper
+	 * @param int $priority
 	 */
-	public static function addStorageWrapper($wrapperName, $wrapper) {
+	public static function addStorageWrapper($wrapperName, $wrapper, $priority = 50) {
 		$mounts = self::getMountManager()->getAll();
-		if (!self::getLoader()->addStorageWrapper($wrapperName, $wrapper, $mounts)) {
+		if (!self::getLoader()->addStorageWrapper($wrapperName, $wrapper, $priority, $mounts)) {
 			// do not re-wrap if storage with this name already existed
 			return;
 		}
diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php
index 700164bdc3d8c1ef461d3ca8ac2173cf8d9ceeca..9fef53fa95a0c8956e44dd9a74f36e6345f9afc2 100644
--- a/lib/private/files/storage/common.php
+++ b/lib/private/files/storage/common.php
@@ -37,7 +37,6 @@ namespace OC\Files\Storage;
 
 use OC\Files\Cache\Cache;
 use OC\Files\Cache\Scanner;
-use OC\Files\Cache\Storage;
 use OC\Files\Filesystem;
 use OC\Files\Cache\Watcher;
 use OCP\Files\FileNameTooLongException;
@@ -56,7 +55,7 @@ use OCP\Files\ReservedWordException;
  * Some \OC\Files\Storage\Common methods call functions which are first defined
  * in classes which extend it, e.g. $this->stat() .
  */
-abstract class Common implements \OC\Files\Storage\Storage {
+abstract class Common implements Storage {
 	protected $cache;
 	protected $scanner;
 	protected $watcher;
@@ -370,7 +369,7 @@ abstract class Common implements \OC\Files\Storage\Storage {
 			$storage = $this;
 		}
 		if (!isset($this->storageCache)) {
-			$this->storageCache = new Storage($storage);
+			$this->storageCache = new \OC\Files\Cache\Storage($storage);
 		}
 		return $this->storageCache;
 	}
diff --git a/lib/private/files/storage/storagefactory.php b/lib/private/files/storage/storagefactory.php
index 5da192e4c727a50b07c7f69edbabe6226af2d4ec..31b4090eda2812465b18f60735174663eadde191 100644
--- a/lib/private/files/storage/storagefactory.php
+++ b/lib/private/files/storage/storagefactory.php
@@ -31,9 +31,9 @@ use OCP\Files\Storage\IStorageFactory;
 
 class StorageFactory implements IStorageFactory {
 	/**
-	 * @var callable[] $storageWrappers
+	 * @var array[] [$name=>['priority'=>$priority, 'wrapper'=>$callable] $storageWrappers
 	 */
-	private $storageWrappers = array();
+	private $storageWrappers = [];
 
 	/**
 	 * allow modifier storage behaviour by adding wrappers around storages
@@ -42,11 +42,12 @@ class StorageFactory implements IStorageFactory {
 	 *
 	 * @param string $wrapperName name of the wrapper
 	 * @param callable $callback callback
+	 * @param int $priority wrappers with the lower priority are applied last (meaning they get called first)
 	 * @param \OCP\Files\Mount\IMountPoint[] $existingMounts existing mount points to apply the wrapper to
 	 * @return bool true if the wrapper was added, false if there was already a wrapper with this
 	 * name registered
 	 */
-	public function addStorageWrapper($wrapperName, $callback, $existingMounts = []) {
+	public function addStorageWrapper($wrapperName, $callback, $priority = 50, $existingMounts = []) {
 		if (isset($this->storageWrappers[$wrapperName])) {
 			return false;
 		}
@@ -56,7 +57,7 @@ class StorageFactory implements IStorageFactory {
 			$mount->wrapStorage($callback);
 		}
 
-		$this->storageWrappers[$wrapperName] = $callback;
+		$this->storageWrappers[$wrapperName] = ['wrapper' => $callback, 'priority' => $priority];
 		return true;
 	}
 
@@ -89,7 +90,15 @@ class StorageFactory implements IStorageFactory {
 	 * @return \OCP\Files\Storage
 	 */
 	public function wrap(IMountPoint $mountPoint, $storage) {
-		foreach ($this->storageWrappers as $wrapper) {
+		$wrappers = array_values($this->storageWrappers);
+		usort($wrappers, function ($a, $b) {
+			return $b['priority'] - $a['priority'];
+		});
+		/** @var callable[] $wrappers */
+		$wrappers = array_map(function ($wrapper) {
+			return $wrapper['wrapper'];
+		}, $wrappers);
+		foreach ($wrappers as $wrapper) {
 			$storage = $wrapper($mountPoint->getMountPoint(), $storage, $mountPoint);
 		}
 		return $storage;
diff --git a/tests/lib/files/storage/storagefactory.php b/tests/lib/files/storage/storagefactory.php
index 15519ef83fbda70dd89d1d416797b2a915910f3d..fcdff577dd59519bd9a98b0b49ee2f9c7ef834c5 100644
--- a/tests/lib/files/storage/storagefactory.php
+++ b/tests/lib/files/storage/storagefactory.php
@@ -15,7 +15,14 @@ use Test\TestCase;
 use OC\Files\Storage\Wrapper\Wrapper;
 
 class DummyWrapper extends Wrapper {
+	public $data;
 
+	public function __construct($arguments) {
+		parent::__construct($arguments);
+		if (isset($arguments['data'])) {
+			$this->data = $arguments['data'];
+		}
+	}
 }
 
 class StorageFactory extends TestCase {
@@ -42,4 +49,24 @@ class StorageFactory extends TestCase {
 		$wrapped = $mount->getStorage();
 		$this->assertInstanceOf('\OC\Files\Storage\Temporary', $wrapped);
 	}
+
+	public function testWrapperPriority() {
+		$instance = new \OC\Files\Storage\StorageFactory();
+		$mount = new MountPoint('\OC\Files\Storage\Temporary', '/foo', [[]], $instance);
+		$instance->addStorageWrapper('dummy1', function ($mountPoint, IStorage $storage) {
+			return new DummyWrapper(['storage' => $storage, 'data' => 1]);
+		}, 1);
+		$instance->addStorageWrapper('dummy2', function ($mountPoint, IStorage $storage) {
+			return new DummyWrapper(['storage' => $storage, 'data' => 100]);
+		}, 100);
+		$instance->addStorageWrapper('dummy3', function ($mountPoint, IStorage $storage) {
+			return new DummyWrapper(['storage' => $storage, 'data' => 50]);
+		}, 50);
+		/** @var \Test\Files\Storage\DummyWrapper $wrapped */
+		$wrapped = $mount->getStorage();
+		$this->assertInstanceOf('\Test\Files\Storage\DummyWrapper', $wrapped);
+		$this->assertEquals(1, $wrapped->data);// lowest priority is applied last, called first
+		$this->assertEquals(50, $wrapped->getWrapperStorage()->data);
+		$this->assertEquals(100, $wrapped->getWrapperStorage()->getWrapperStorage()->data);
+	}
 }