Merge pull request #57370 from nextcloud/authoritative-mount-setup
Some checks are pending
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Integration sqlite / changes (push) Waiting to run
Integration sqlite / integration-sqlite (master, 8.4, main, --tags ~@large files_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, capabilities_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, collaboration_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, comments_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, dav_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, federation_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, file_conversions) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, files_reminders) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, filesdrop_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, ldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, openldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, openldap_numerical_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, remoteapi_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, routing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, setup_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, sharees_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, sharing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, theming_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (master, 8.4, main, videoverification_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite-summary (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis (push) Waiting to run
Psalm static code analysis / static-code-analysis-security (push) Waiting to run
Psalm static code analysis / static-code-analysis-ocp (push) Waiting to run
Psalm static code analysis / static-code-analysis-ncu (push) Waiting to run

Authoritative mount setup
This commit is contained in:
Robin Appelman 2026-01-14 14:19:03 +01:00 committed by GitHub
commit 62d7165124
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -31,6 +31,7 @@ use OCP\App\IAppManager;
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;
@ -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;
@ -107,6 +109,7 @@ class SetupManager {
$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();
}
@ -226,6 +229,33 @@ class SetupManager {
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
*/
@ -335,12 +365,16 @@ class SetupManager {
});
$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');
}
/**
@ -434,8 +468,13 @@ class SetupManager {
}
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
@ -505,11 +544,10 @@ class SetupManager {
$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');
@ -542,11 +580,10 @@ class SetupManager {
$currentProviders[] = $mountProvider;
$setupProviders[] = $mountProvider;
$fullProviderMounts[]
= $this->mountProviderCollection->getUserMountsForProviderClasses(
$user,
[$mountProvider]
);
$fullProviderMounts[] = $this->mountProviderCollection->getUserMountsForProviderClasses(
$user,
[$mountProvider]
);
}
if (!empty($authoritativeCachedMounts)) {
@ -573,13 +610,12 @@ class SetupManager {
},
$cachedMounts
));
$authoritativeMounts[]
= $this->mountProviderCollection->getUserMountsFromProviderByPath(
$providerClass,
$path,
true,
$providerArgs,
);
$authoritativeMounts[] = $this->mountProviderCollection->getUserMountsFromProviderByPath(
$providerClass,
$path,
true,
$providerArgs,
);
}
}
} else {
@ -758,6 +794,7 @@ class SetupManager {
/**
* Drops partially set-up mounts for the given user
*
* @param class-string<IMountProvider>[] $providers
*/
public function dropPartialMountsForUser(IUser $user, array $providers = []): void {