Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2022-03-08 19:14:15 +0300
committerRobin Appelman <robin@icewind.nl>2022-03-24 19:01:46 +0300
commit19c64cf8b6782cf69b8e7330f27580451a8965e7 (patch)
tree4848145a7efbe472206f39c40dfd057440217779 /lib
parent55d943fd4b35c9df3e3639d6f264e4f8d8df82f0 (diff)
setup only relevant mounts when possible
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'lib')
-rw-r--r--lib/private/Files/Mount/Manager.php2
-rw-r--r--lib/private/Files/SetupManager.php119
2 files changed, 106 insertions, 15 deletions
diff --git a/lib/private/Files/Mount/Manager.php b/lib/private/Files/Mount/Manager.php
index 66832690363..ecd97760f17 100644
--- a/lib/private/Files/Mount/Manager.php
+++ b/lib/private/Files/Mount/Manager.php
@@ -125,7 +125,7 @@ class Manager implements IMountManager {
* @return IMountPoint[]
*/
public function findIn(string $path): array {
- $this->setupManager->setupForPath($path);
+ $this->setupManager->setupForPath($path, true);
$path = $this->formatPath($path);
if (isset($this->inPathCache[$path])) {
diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php
index 9726fbef428..6e246aeb821 100644
--- a/lib/private/Files/SetupManager.php
+++ b/lib/private/Files/SetupManager.php
@@ -45,6 +45,7 @@ use OCP\Files\Config\IUserMountCache;
use OCP\Files\Events\Node\FilesystemTornDownEvent;
use OCP\Files\Mount\IMountManager;
use OCP\Files\Mount\IMountPoint;
+use OCP\Files\NotFoundException;
use OCP\Files\Storage\IStorage;
use OCP\IUser;
use OCP\IUserManager;
@@ -57,7 +58,12 @@ class SetupManager {
private MountProviderCollection $mountProviderCollection;
private IMountManager $mountManager;
private IUserManager $userManager;
+ // List of users for which at least one mount is setup
private array $setupUsers = [];
+ // List of users for which all mounts are setup
+ private array $setupUsersComplete = [];
+ /** @var array<string, string[]> */
+ private array $setupUserMountProviders = [];
private IEventDispatcher $eventDispatcher;
private IUserMountCache $userMountCache;
private ILockdownManager $lockdownManager;
@@ -85,6 +91,14 @@ class SetupManager {
$this->listeningForProviders = false;
}
+ private function isSetupStarted(IUser $user): bool {
+ return in_array($user->getUID(), $this->setupUsers, true);
+ }
+
+ private function isSetupComplete(IUser $user): bool {
+ return in_array($user->getUID(), $this->setupUsersComplete, true);
+ }
+
private function setupBuiltinWrappers() {
Filesystem::addStorageWrapper('mount_options', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
if ($storage->instanceOfStorage(Common::class)) {
@@ -159,15 +173,25 @@ class SetupManager {
* Setup the full filesystem for the specified user
*/
public function setupForUser(IUser $user): void {
- $this->setupRoot();
+ if ($this->isSetupComplete($user)) {
+ return;
+ }
+ $this->setupUsersComplete[] = $user->getUID();
+ $this->setupForUserWith($user, function () use ($user) {
+ $this->mountProviderCollection->addMountForUser($user, $this->mountManager);
+ });
+ $this->userFullySetup($user);
+ }
+
+ /**
+ * part of the user setup that is run only once per user
+ */
+ private function oneTimeUserSetup(IUser $user) {
if (in_array($user->getUID(), $this->setupUsers, true)) {
return;
}
$this->setupUsers[] = $user->getUID();
-
- $this->eventLogger->start('setup_fs', 'Setup filesystem');
-
$prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
OC_Hook::emit('OC_Filesystem', 'preSetup', ['user' => $user->getUID()]);
@@ -176,7 +200,7 @@ class SetupManager {
$userDir = '/' . $user->getUID() . '/files';
- Filesystem::init($user, $userDir);
+ Filesystem::initInternal($userDir);
if ($this->lockdownManager->canAccessFilesystem()) {
// home mounts are handled separate since we need to ensure this is mounted before we call the other mount providers
@@ -187,13 +211,6 @@ class SetupManager {
$homeMount->getStorage()->mkdir('');
$homeMount->getStorage()->getScanner()->scan('');
}
-
- // Chance to mount for other storages
- $mounts = $this->mountProviderCollection->addMountForUser($user, $this->mountManager);
- $mounts[] = $homeMount;
- $this->userMountCache->registerMounts($user, $mounts);
-
- $this->listenForNewMountProviders();
} else {
$this->mountManager->addMount(new MountPoint(
new NullStorage([]),
@@ -203,9 +220,43 @@ class SetupManager {
new NullStorage([]),
'/' . $user->getUID() . '/files'
));
+ $this->setupUsersComplete[] = $user->getUID();
+ }
+
+ $this->listenForNewMountProviders();
+ }
+
+ private function userFullySetup(IUser $user) {
+ $userRoot = '/' . $user->getUID() . '/';
+ $mounts = $this->mountManager->getAll();
+ $mounts = array_filter($mounts, function (IMountPoint $mount) use ($userRoot) {
+ return strpos($mount->getMountPoint(), $userRoot) === 0;
+ });
+ $this->userMountCache->registerMounts($user, $mounts);
+ }
+
+ /**
+ * @param IUser $user
+ * @param IMountPoint $mounts
+ * @return void
+ * @throws \OCP\HintException
+ * @throws \OC\ServerNotAvailableException
+ */
+ private function setupForUserWith(IUser $user, callable $mountCallback): void {
+ $this->setupRoot();
+
+ if (!$this->isSetupStarted($user)) {
+ $this->oneTimeUserSetup($user);
+ }
+
+ $this->eventLogger->start('setup_fs', 'Setup filesystem');
+
+ if ($this->lockdownManager->canAccessFilesystem()) {
+ $mountCallback();
}
\OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user->getUID()]);
+ $userDir = '/' . $user->getUID() . '/files';
OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $user->getUID(), 'user_dir' => $userDir]);
$this->eventLogger->end('setup_fs');
@@ -242,7 +293,7 @@ class SetupManager {
/**
* Set up the filesystem for the specified path
*/
- public function setupForPath(string $path): void {
+ public function setupForPath(string $path, bool $includeChildren = false): void {
if (substr_count($path, '/') < 2) {
if ($user = $this->userSession->getUser()) {
$this->setupForUser($user);
@@ -264,11 +315,51 @@ class SetupManager {
return;
}
- $this->setupForUser($user);
+ if ($this->isSetupComplete($user)) {
+ return;
+ }
+
+ if (!isset($this->setupUserMountProviders[$user->getUID()])) {
+ $this->setupUserMountProviders[$user->getUID()] = [];
+ }
+ $setupProviders = &$this->setupUserMountProviders[$user->getUID()];
+
+ try {
+ $cachedMount = $this->userMountCache->getMountForPath($user, $path);
+ } catch (NotFoundException $e) {
+ $this->setupForUser($user);
+ return;
+ }
+
+ $mounts = [];
+ if (!in_array($cachedMount->getMountProvider(), $setupProviders)) {
+ $setupProviders[] = $cachedMount->getMountProvider();
+ $mounts = $this->mountProviderCollection->getMountsFromProvider($user, $cachedMount->getMountProvider());
+ }
+
+ if ($includeChildren) {
+ $subCachedMounts = $this->userMountCache->getMountsInForPath($user, $path);
+ foreach ($subCachedMounts as $cachedMount) {
+ if (!in_array($cachedMount->getMountProvider(), $setupProviders)) {
+ $setupProviders[] = $cachedMount->getMountProvider();
+ $mounts = array_merge($mounts, $this->mountProviderCollection->getMountsFromProvider($user, $cachedMount->getMountProvider()));
+ }
+ }
+ }
+
+ if (count($mounts)) {
+ $this->setupForUserWith($user, function () use ($mounts) {
+ array_walk($mounts, [$this->mountManager, 'addMount']);
+ });
+ } elseif (!$this->isSetupStarted($user)) {
+ $this->oneTimeUserSetup($user);
+ }
}
public function tearDown() {
$this->setupUsers = [];
+ $this->setupUsersComplete = [];
+ $this->setupUserMountProviders = [];
$this->rootSetup = false;
$this->mountManager->clear();
$this->eventDispatcher->dispatchTyped(new FilesystemTornDownEvent());