Skip to content

fix(trash): share the local storage instance of a separate-storage folder - #5100

Open
solracsf wants to merge 1 commit into
masterfrom
fix/separate-storage-trash-acl
Open

fix(trash): share the local storage instance of a separate-storage folder#5100
solracsf wants to merge 1 commit into
masterfrom
fix/separate-storage-trash-acl

Conversation

@solracsf

@solracsf solracsf commented Sep 11, 2026

Copy link
Copy Markdown
Member

For a team folder with its own storage, getBaseStorageForFolderSeparateStorageLocal() builds a new Local on every call, so the files, trash and versions storages of that folder are different objects. Common::moveFromStorage() only turns a move into a rename when both sides unwrap to the same instance, and Local::canDoCrossStorageMove() refuses ACL wrapped sources.

So, with ACL enabled, every move to or from the trash ends up as a recursive copy in PHP followed by a recursive delete of the source.

That has two effects:

  • It's slow. Every file costs an ACL lookup plus a full copy, so restoring a big tree keeps the database busy for minutes.
  • It loses data. The copy only sees what the acting user can read, but the delete removes everything, so files hidden from that user by ACL are gone once they trash or restore the parent folder.

Reusing one Local per folder makes these moves renames again, the same as for folders in the root storage. Object storage isn't affected, it already only moves the metadata.

Restoring a trashed folder as a user who can't read one of its files (MariaDB 11.8, local storage, min / median of 5 runs):

before after
1,000 files, 111 folders 562 / 647 ms, 1,170 queries 34 / 47 ms, 50 queries
5,000 files, 221 folders 2,498 / 3,071 ms, 5,297 queries 107 / 112 ms, 54 queries

Before the change 5,243 of those 5,297 queries went to oc_group_folders_acl, after it there are none.

The new test fails without the change on MariaDB and PostgreSQL with local storage, and passes with it with both local storage and S3, along with the rest of TrashBackendTest.

Fix #1574

…lder

Each call to getBaseStorageForFolderSeparateStorageLocal() created a new
Local instance, so the files, trash and versions storages of one team
folder never counted as the same storage. With ACL enabled, moving an
item to or from the trash therefore skipped the rename shortcut and fell
back to Common::copyFromStorage(): a recursive copy in PHP with an ACL
lookup per file, followed by a recursive delete of the source.

Besides being very slow for large folders (restoring a big tree hammers
the database with one ACL query per file), the copy goes through the
acting user's ACL view while the delete does not, so files the user
cannot read were silently deleted from disk when that user trashed or
restored their parent folder.

Reuse one Local instance per folder so these moves are plain renames, as
they already are for folders stored in the root storage.

Signed-off-by: Git'Fellow <12234510+solracsf@users.noreply.github.com>
@solracsf solracsf added 3. to review Items that need to be reviewed feature: trashbin Items related to the trashbin feature performance πŸš€ labels Sep 11, 2026
@solracsf solracsf self-assigned this Sep 11, 2026
@solracsf

Copy link
Copy Markdown
Member Author

/backport to stable35

@solracsf

Copy link
Copy Markdown
Member Author

/backport to stable34

@solracsf

Copy link
Copy Markdown
Member Author

/backport to stable33

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review Items that need to be reviewed backport-request feature: trashbin Items related to the trashbin feature performance πŸš€

Projects

None yet

Development

Successfully merging this pull request may close these issues.

High CPU Load and very long time when restoring files from trashbin

1 participant