s3: route single-entry object writes to the owner filer, off the DLM

For non-versioned, non-object-lock buckets, PutObject and unversioned
DeleteObject now send their metadata write straight to the object key's owner
filer (resolved from the lock-ring view) with the precondition attached. The
owner serializes the write with its local per-path lock and evaluates the
condition atomically, so these paths no longer acquire a distributed lock.

The fast path is opt-in per request and falls back to withObjectWriteLock for
anything it does not fully cover: versioned or object-lock buckets, conditions
that do not reduce to a single primitive (ETag lists, weak ETags, time-based,
combined headers), an unresolved owner, or an unreachable owner filer. So
behavior is unchanged outside the safe subset.

Multi-step finalizations (copy, CompleteMultipartUpload) and versioned writes
keep the distributed lock: they mutate several entries under one held lock,
which a single conditional create or delete does not cover.

DeleteEntry gains the same optional WriteCondition and per-path lock as
CreateEntry so a routed conditional delete is atomic on the owner.
This commit is contained in:
Chris Lu
2026-05-22 22:48:07 -07:00
parent 1e70bd3fc6
commit 21af729cb4
10 changed files with 512 additions and 125 deletions
@@ -304,11 +304,16 @@ message DeleteEntryRequest {
bool is_from_other_cluster = 7;
repeated int32 signatures = 8;
int64 if_not_modified_after = 9;
// Optional precondition evaluated against the current entry atomically with
// the delete, under the filer's per-path lock. Only honored for a
// non-recursive single-entry delete routed to the entry's owner filer.
WriteCondition condition = 10;
}
message DeleteEntryResponse {
string error = 1;
SubscribeMetadataResponse metadata_event = 2;
FilerError error_code = 3; // machine-readable error code (e.g. PRECONDITION_FAILED)
}
message AtomicRenameEntryRequest {