Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 58 additions & 21 deletions lib/private/Files/SetupManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
use OCP\Constants;
use OCP\Diagnostics\IEventLogger;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IAuthoritativeMountProvider;
use OCP\Files\Config\ICachedMountInfo;
use OCP\Files\Config\IHomeMountProvider;
use OCP\Files\Config\IMountProvider;
Expand Down Expand Up @@ -84,7 +85,8 @@ class SetupManager {
private bool $listeningForProviders;
private array $fullSetupRequired = [];
private bool $setupBuiltinWrappersDone = false;
private bool $forceFullSetup = false;
private bool $forceFullSetup;
private bool $optimizeAuthoritativeProviders;
private const SETUP_WITH_CHILDREN = 1;
private const SETUP_WITHOUT_CHILDREN = 0;

Expand All @@ -107,6 +109,7 @@ public function __construct(
$this->cache = $cacheFactory->createDistributed('setupmanager::');
$this->listeningForProviders = false;
$this->forceFullSetup = $this->config->getSystemValueBool('debug.force-full-fs-setup');
$this->optimizeAuthoritativeProviders = $this->config->getSystemValueBool('debug.optimize-authoritative-providers', true);

$this->setupListeners();
}
Expand Down Expand Up @@ -226,6 +229,33 @@ function ($mountPoint, IStorage $storage, IMountPoint $mount) use ($reSharingEna
Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
}

/**
* Update the cached mounts for all non-authoritative mount providers for a user.
*/
private function updateNonAuthoritativeProviders(IUser $user): void {
// prevent recursion loop from when getting mounts from providers ends up setting up the filesystem
static $updatingProviders = false;
if ($updatingProviders) {
return;
}
$updatingProviders = true;

$providers = $this->mountProviderCollection->getProviders();
$nonAuthoritativeProviders = array_filter(
$providers,
fn (IMountProvider $provider) => !(
$provider instanceof IAuthoritativeMountProvider
|| $provider instanceof IRootMountProvider
|| $provider instanceof IHomeMountProvider
)
);
$providerNames = array_map(fn (IMountProvider $provider) => get_class($provider), $nonAuthoritativeProviders);
$mount = $this->mountProviderCollection->getUserMountsForProviderClasses($user, $providerNames);
$this->userMountCache->registerMounts($user, $mount, $providerNames);

$updatingProviders = false;
}

/**
* Setup the full filesystem for the specified user
*/
Expand Down Expand Up @@ -335,12 +365,16 @@ private function afterUserFullySetup(IUser $user, array $previouslySetupProvider
});
$this->registerMounts($user, $mounts, $newProviders);

$this->markUserMountsCached($user);
$this->eventLogger->end('fs:setup:user:full:post');
}

private function markUserMountsCached(IUser $user): void {
$cacheDuration = $this->config->getSystemValueInt('fs_mount_cache_duration', 5 * 60);
if ($cacheDuration > 0) {
$this->cache->set($user->getUID(), true, $cacheDuration);
$this->fullSetupRequired[$user->getUID()] = false;
}
$this->eventLogger->end('fs:setup:user:full:post');
}

/**
Expand Down Expand Up @@ -434,8 +468,13 @@ public function setupForPath(string $path, bool $includeChildren = false): void
}

if ($this->fullSetupRequired($user)) {
$this->setupForUser($user);
return;
if ($this->optimizeAuthoritativeProviders) {
$this->updateNonAuthoritativeProviders($user);
$this->markUserMountsCached($user);
} else {
$this->setupForUser($user);
return;
}
}

// for the user's home folder, and includes children we need everything always
Expand Down Expand Up @@ -505,11 +544,10 @@ public function setupForPath(string $path, bool $includeChildren = false): void
$subCachedMounts = $this->userMountCache->getMountsInPath($user, $path);
$this->eventLogger->end('fs:setup:user:path:find');

$needsFullSetup
= array_any(
$subCachedMounts,
fn (ICachedMountInfo $info) => $info->getMountProvider() === ''
);
$needsFullSetup = array_any(
$subCachedMounts,
fn (ICachedMountInfo $info) => $info->getMountProvider() === ''
);

if ($needsFullSetup) {
$this->logger->debug('mount has no provider set, performing full setup');
Expand Down Expand Up @@ -542,11 +580,10 @@ public function setupForPath(string $path, bool $includeChildren = false): void

$currentProviders[] = $mountProvider;
$setupProviders[] = $mountProvider;
$fullProviderMounts[]
= $this->mountProviderCollection->getUserMountsForProviderClasses(
$user,
[$mountProvider]
);
$fullProviderMounts[] = $this->mountProviderCollection->getUserMountsForProviderClasses(
$user,
[$mountProvider]
);
}

if (!empty($authoritativeCachedMounts)) {
Expand All @@ -573,13 +610,12 @@ static function (ICachedMountInfo $info) use ($rootsMetadata) {
},
$cachedMounts
));
$authoritativeMounts[]
= $this->mountProviderCollection->getUserMountsFromProviderByPath(
$providerClass,
$path,
true,
$providerArgs,
);
$authoritativeMounts[] = $this->mountProviderCollection->getUserMountsFromProviderByPath(
$providerClass,
$path,
true,
$providerArgs,
);
}
}
} else {
Expand Down Expand Up @@ -758,6 +794,7 @@ private function registerMounts(IUser $user, array $mounts, ?array $mountProvide

/**
* Drops partially set-up mounts for the given user
*
* @param class-string<IMountProvider>[] $providers
*/
public function dropPartialMountsForUser(IUser $user, array $providers = []): void {
Expand Down
Loading