diff options
author | Robin Appelman <robin@icewind.nl> | 2025-06-23 16:25:05 +0200 |
---|---|---|
committer | backportbot[bot] <backportbot[bot]@users.noreply.github.com> | 2025-06-25 11:38:30 +0000 |
commit | 881abecd34d4f142540a715fa522563e119604bc (patch) | |
tree | d058de10edd306dfed540787e56d0338b80721f5 | |
parent | e9ce122b85cde2d788613934321297336fb51e3c (diff) | |
download | nextcloud-server-backport/53647/stable31.tar.gz nextcloud-server-backport/53647/stable31.zip |
fix: don't scan the same storage multiple timesbackport/53647/stable31
Signed-off-by: Robin Appelman <robin@icewind.nl>
-rw-r--r-- | apps/files/lib/Command/Scan.php | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/apps/files/lib/Command/Scan.php b/apps/files/lib/Command/Scan.php index 89018e4191a..0116d77fb6f 100644 --- a/apps/files/lib/Command/Scan.php +++ b/apps/files/lib/Command/Scan.php @@ -11,6 +11,7 @@ use OC\Core\Command\Base; use OC\Core\Command\InterruptedException; use OC\DB\Connection; use OC\DB\ConnectionAdapter; +use OC\Files\Storage\Wrapper\Jail; use OC\Files\Utils\Scanner; use OC\FilesMetadata\FilesMetadataManager; use OC\ForbiddenException; @@ -98,7 +99,15 @@ class Scan extends Base { ); } - protected function scanFiles(string $user, string $path, ?string $scanMetadata, OutputInterface $output, bool $backgroundScan = false, bool $recursive = true, bool $homeOnly = false): void { + protected function scanFiles( + string $user, + string $path, + ?string $scanMetadata, + OutputInterface $output, + callable $mountFilter, + bool $backgroundScan = false, + bool $recursive = true, + ): void { $connection = $this->reconnectToDatabase($output); $scanner = new Scanner( $user, @@ -152,7 +161,7 @@ class Scan extends Base { if ($backgroundScan) { $scanner->backgroundScan($path); } else { - $scanner->scan($path, $recursive, $homeOnly ? [$this, 'filterHomeMount'] : null); + $scanner->scan($path, $recursive, $mountFilter); } } catch (ForbiddenException $e) { $output->writeln("<error>Home storage for user $user not writable or 'files' subdirectory missing</error>"); @@ -178,7 +187,7 @@ class Scan extends Base { } } - public function filterHomeMount(IMountPoint $mountPoint): bool { + public function isHomeMount(IMountPoint $mountPoint): bool { // any mountpoint inside '/$user/files/' return substr_count($mountPoint->getMountPoint(), '/') <= 3; } @@ -210,6 +219,29 @@ class Scan extends Base { $metadata = $input->getOption('generate-metadata') ?? ''; } + $homeOnly = $input->getOption('home-only'); + $scannedStorages = []; + $mountFilter = function (IMountPoint $mount) use ($homeOnly, &$scannedStorages) { + if ($homeOnly && !$this->isHomeMount($mount)) { + return false; + } + + // when scanning multiple users, the scanner might encounter the same storage multiple times (e.g. external storages, or group folders) + // we can filter out any storage we've already scanned to avoid double work + $storage = $mount->getStorage(); + $storageKey = $storage->getId(); + while ($storage->instanceOfStorage(Jail::class)) { + $storageKey .= '/' . $storage->getUnjailedPath(''); + $storage = $storage->getUnjailedStorage(); + } + if (array_key_exists($storageKey, $scannedStorages)) { + return false; + } + + $scannedStorages[$storageKey] = true; + return true; + }; + $user_count = 0; foreach ($users as $user) { if (is_object($user)) { @@ -219,7 +251,15 @@ class Scan extends Base { ++$user_count; if ($this->userManager->userExists($user)) { $output->writeln("Starting scan for user $user_count out of $users_total ($user)"); - $this->scanFiles($user, $path, $metadata, $output, $input->getOption('unscanned'), !$input->getOption('shallow'), $input->getOption('home-only')); + $this->scanFiles( + $user, + $path, + $metadata, + $output, + $mountFilter, + $input->getOption('unscanned'), + !$input->getOption('shallow'), + ); $output->writeln('', OutputInterface::VERBOSITY_VERBOSE); } else { $output->writeln("<error>Unknown user $user_count $user</error>"); |