Commit Graph

3 Commits

Author SHA1 Message Date
Feng Ruohang 04c657d03f test(pools): cover aliases of other sets in a shared lock table
The implementation review of the lock fixes found two gaps in the merge
test of lockObjects:

- Where the sets share one local table, it only tried an alias of the
  clean name's own set, so dropping the shared-table normalization of
  the lock domain still passed. It now tries an alias of another set in
  every mode; with that mutation the shared case times out.
- In a split distributed domain it probed readers before writers. The
  reader probe releases asynchronously and could hold off the writer
  probe right after it, so a missing alias read lock passed some runs.
  Writers are probed first now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Feng Ruohang <rh@vonng.com>
2026-11-06 19:41:32 +08:00
Feng Ruohang 1780eb8ffc test(pools): make the copy and bulk lock tests race-free and stricter
The implementation review of the lock fixes found test flaws, which are
corrected here; the production behavior is unchanged.

- The alias and merge tests replaced globalOperationTimeout while
  background healing reads it, a data race under -race. They now bound
  each request with its own context instead.
- The alias test now holds the cleaned name's write lock while the copy
  runs, so it proves the names are checked before anything is locked;
  it checks both objects before any later write, and covers a/./x as a
  destination.
- The merge test picks aliases that hash to the clean name's set and,
  where sets have their own lockers, ones that do not, and requires the
  alias's own table to hold a read lock: readers admitted, writers
  excluded.
- Release polling creates a fresh lock instance for every probe.
- The getNSLocks event hook and the bulk delete group limit are atomic,
  so tests can set them while other goroutines read them.

Without the name check and the resource merge, both tests now fail in
every lock layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Feng Ruohang <rh@vonng.com>
2026-11-06 19:25:56 +08:00
Feng Ruohang 617d8ed67b fix(pools): check copy names before locking them
CopyObject locks its source and destination before it reads the source,
and lockObjects merged two requests only when their raw names were equal.
A lock is taken on the cleaned name, so an invalid source such as a//x or
a/./x and the destination a/x asked for a read lock and a write lock on
one resource: the copy waited on itself until the operation timeout and
answered 503, holding the key's lock in short windows meanwhile. Before
the lock-domain change the invalid source was refused at once, when the
source was read. This reached single nodes, multi-pool deployments and
single pools whose sets share hosts.

- Check the source with checkGetObjArgs before any lock, the first check
  and the first error the release reported. Lock the destination only
  when its name is valid. An invalid destination fails at the copy's own
  destination check before it writes, after a missing source (404) or a
  failed source precondition (412), as before.
- lockObjects merges requests by the resource the lockers see, the
  cleaned bucket/object, within one lock table: the object's set where
  the sets of a pool have their own lockers, else one table. This keeps
  aliases on a shared local table from conflicting and never merges
  requests of different distributed domains.

Tests: aliased sources and destinations are refused with 400 at once in
every lock layout and two pools; an invalid destination keeps the 404
and 412 precedence; lockObjects merges an alias with its clean name. The
alias and merge tests fail without the change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Feng Ruohang <rh@vonng.com>
2026-11-06 18:28:27 +08:00