diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php
index 853bc1eda69c9bacb99e5a85cb43ba612a659097..b30ea7c69f8b5f678bb692d872e410f477b734ef 100644
--- a/apps/files_trashbin/lib/trashbin.php
+++ b/apps/files_trashbin/lib/trashbin.php
@@ -55,6 +55,16 @@ class Trashbin {
 	 */
 	private static $scannedVersions = false;
 
+	/**
+	 * Ensure we dont need to scan the file during the move to trash
+	 * by triggering the scan in the pre-hook
+	 *
+	 * @param array $params
+	 */
+	public static function ensureFileScannedHook($params) {
+		self::getUidAndFilename($params['path']);
+	}
+
 	public static function getUidAndFilename($filename) {
 		$uid = \OC\Files\Filesystem::getOwner($filename);
 		\OC\Files\Filesystem::initMountPoints($uid);
@@ -870,6 +880,7 @@ class Trashbin {
 		//Listen to post write hook
 		\OCP\Util::connectHook('OC_Filesystem', 'post_write', 'OCA\Files_Trashbin\Hooks', 'post_write_hook');
 		// pre and post-rename, disable trash logic for the copy+unlink case
+		\OCP\Util::connectHook('OC_Filesystem', 'delete', 'OCA\Files_Trashbin\Trashbin', 'ensureFileScannedHook');
 		\OCP\Util::connectHook('OC_Filesystem', 'rename', 'OCA\Files_Trashbin\Storage', 'preRenameHook');
 		\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Files_Trashbin\Storage', 'postRenameHook');
 	}
diff --git a/lib/private/connector/sabre/file.php b/lib/private/connector/sabre/file.php
index 5aef30cc577e2593fa05dc3b5e3b27ca3a9a1096..740660f466bd7594f08821112eb46ab424d502ca 100644
--- a/lib/private/connector/sabre/file.php
+++ b/lib/private/connector/sabre/file.php
@@ -216,15 +216,15 @@ class File extends Node implements IFile {
 				}
 			}
 
-			// since we skipped the view we need to scan and emit the hooks ourselves
-			$partStorage->getScanner()->scanFile($internalPath);
-
 			try {
 				$this->fileView->changeLock($this->path, ILockingProvider::LOCK_SHARED);
 			} catch (LockedException $e) {
 				throw new FileLocked($e->getMessage(), $e->getCode(), $e);
 			}
 
+			// since we skipped the view we need to scan and emit the hooks ourselves
+			$partStorage->getScanner()->scanFile($internalPath);
+
 			if ($view) {
 				$this->fileView->getUpdater()->propagate($hookPath);
 				if (!$exists) {
@@ -249,12 +249,11 @@ class File extends Node implements IFile {
 				}
 			}
 			$this->refreshInfo();
+			$this->fileView->unlockFile($this->path, ILockingProvider::LOCK_SHARED);
 		} catch (StorageNotAvailableException $e) {
 			throw new ServiceUnavailable("Failed to check file size: " . $e->getMessage());
 		}
 
-		$this->fileView->unlockFile($this->path, ILockingProvider::LOCK_SHARED);
-
 		return '"' . $this->info->getEtag() . '"';
 	}
 
diff --git a/lib/private/files/cache/scanner.php b/lib/private/files/cache/scanner.php
index d253afbfa1d0ab1e7f291e6c6c4ce8f8c1e269cc..e8f7bd9990220096cbc86121dcdad6a437ca6b0e 100644
--- a/lib/private/files/cache/scanner.php
+++ b/lib/private/files/cache/scanner.php
@@ -34,6 +34,7 @@ namespace OC\Files\Cache;
 use OC\Files\Filesystem;
 use OC\Hooks\BasicEmitter;
 use OCP\Config;
+use OCP\Lock\ILockingProvider;
 
 /**
  * Class Scanner
@@ -72,6 +73,11 @@ class Scanner extends BasicEmitter {
 	 */
 	protected $useTransactions = true;
 
+	/**
+	 * @var \OCP\Lock\ILockingProvider
+	 */
+	protected $lockingProvider;
+
 	const SCAN_RECURSIVE = true;
 	const SCAN_SHALLOW = false;
 
@@ -83,6 +89,7 @@ class Scanner extends BasicEmitter {
 		$this->storageId = $this->storage->getId();
 		$this->cache = $storage->getCache();
 		$this->cacheActive = !Config::getSystemValue('filesystem_cache_readonly', false);
+		$this->lockingProvider = \OC::$server->getLockingProvider();
 	}
 
 	/**
@@ -123,6 +130,7 @@ class Scanner extends BasicEmitter {
 		if (!self::isPartialFile($file)
 			and !Filesystem::isFileBlacklisted($file)
 		) {
+			$this->storage->acquireLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
 			$this->emit('\OC\Files\Cache\Scanner', 'scanFile', array($file, $this->storageId));
 			\OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId));
 			$data = $this->getData($file);
@@ -179,6 +187,7 @@ class Scanner extends BasicEmitter {
 			} else {
 				$this->removeFromCache($file);
 			}
+			$this->storage->releaseLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
 			return $data;
 		}
 		return null;
@@ -242,11 +251,13 @@ class Scanner extends BasicEmitter {
 		if ($reuse === -1) {
 			$reuse = ($recursive === self::SCAN_SHALLOW) ? self::REUSE_ETAG | self::REUSE_SIZE : self::REUSE_ETAG;
 		}
+		$this->storage->acquireLock($path, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
 		$data = $this->scanFile($path, $reuse);
 		if ($data and $data['mimetype'] === 'httpd/unix-directory') {
 			$size = $this->scanChildren($path, $recursive, $reuse, $data);
 			$data['size'] = $size;
 		}
+		$this->storage->releaseLock($path, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
 		return $data;
 	}
 
diff --git a/lib/private/files/view.php b/lib/private/files/view.php
index 39e2fe6bfce26283b93fbdee6fcb8a3ac66ffaf7..0a597aee216fc5e029cb753f4ccd328b9ee609c8 100644
--- a/lib/private/files/view.php
+++ b/lib/private/files/view.php
@@ -786,9 +786,12 @@ class View {
 				} else {
 					$result = $storage2->copyFromStorage($storage1, $internalPath1, $internalPath2);
 				}
+
+				$this->changeLock($path2, ILockingProvider::LOCK_SHARED);
+
 				$this->updater->update($path2);
 
-				$this->unlockFile($path2, ILockingProvider::LOCK_EXCLUSIVE);
+				$this->unlockFile($path2, ILockingProvider::LOCK_SHARED);
 				$this->unlockFile($path1, ILockingProvider::LOCK_SHARED);
 
 				if ($this->shouldEmitHooks() && $result !== false) {
@@ -1011,6 +1014,10 @@ class View {
 					throw $e;
 				}
 
+				if ((in_array('write', $hooks) || in_array('delete', $hooks)) && ($operation !== 'fopen' || $result === false)) {
+					$this->changeLock($path, ILockingProvider::LOCK_SHARED);
+				}
+
 				if (in_array('delete', $hooks) and $result) {
 					$this->updater->remove($path);
 				}
@@ -1021,7 +1028,7 @@ class View {
 					$this->updater->update($path, $extraParam);
 				}
 
-				if ($operation === 'fopen' and $result) {
+				if ($operation === 'fopen' and is_resource($result)) {
 					$result = CallbackWrapper::wrap($result, null, null, function () use ($hooks, $path) {
 						if (in_array('write', $hooks)) {
 							$this->unlockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
@@ -1029,12 +1036,8 @@ class View {
 							$this->unlockFile($path, ILockingProvider::LOCK_SHARED);
 						}
 					});
-				} else {
-					if (in_array('write', $hooks) || in_array('delete', $hooks)) {
-						$this->unlockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
-					} else if (in_array('read', $hooks)) {
-						$this->unlockFile($path, ILockingProvider::LOCK_SHARED);
-					}
+				} else if (in_array('write', $hooks) || in_array('delete', $hooks) || in_array('read', $hooks)) {
+					$this->unlockFile($path, ILockingProvider::LOCK_SHARED);
 				}
 
 
@@ -1717,6 +1720,7 @@ class View {
 	 * @throws \OCP\Lock\LockedException if the path is already locked
 	 */
 	public function changeLock($path, $type) {
+		$path = Filesystem::normalizePath($path);
 		$absolutePath = $this->getAbsolutePath($path);
 		$absolutePath = Filesystem::normalizePath($absolutePath);
 		if (!$this->shouldLockFile($absolutePath)) {