Skip to content

fix(caching): only cache negative entries from authoritative listings - #5025

Open
nk412 wants to merge 1 commit into
GoogleCloudPlatform:masterfrom
nk412:fix/windowed-listing-negative-cache
Open

fix(caching): only cache negative entries from authoritative listings#5025
nk412 wants to merge 1 commit into
GoogleCloudPlatform:masterfrom
nk412:fix/windowed-listing-negative-cache

Conversation

@nk412

@nk412 nk412 commented Aug 13, 2026

Copy link
Copy Markdown

Description

Prevent empty windowed or paginated object listings from creating a negative stat-cache entry for an entire implicit-directory prefix.

fastStatBucket.insertListing previously treated every empty listing as evidence that the requested directory did not exist. That is not authoritative when the request uses StartOffset or a continuation token, or when the response contains a continuation token. In those cases, the listing represents only part of the namespace, and inserting a negative entry can overwrite a valid positive directory entry and cause transient ENOENT responses.

This change:

  • passes the originating ListObjectsRequest to insertListing;
  • limits listing-derived negative entries to unwindowed, complete listings;
  • preserves negative caching for authoritative empty listings; and
  • adds request-level coverage for start offsets and continuation tokens, plus a regression test using the real LRU/stat-cache implementation.

Link to the issue in case of a bug fix.

Fixes #5018

Testing details

  1. Manual - Verified the deterministic regression fails on the unpatched implementation with gcs.NotFoundError: negative cache entry for dir/ and passes with this change. make build also passes.
  2. Unit tests - Passed in golang:1.26.5 Docker:
    • go test ./internal/storage/caching -count=1
    • CGO_ENABLED=0 go test ./internal/storage/... -count=1
    • go test -race ./internal/storage/caching -count=1
    • go vet ./internal/storage/caching
    • CGO_ENABLED=0 go build ./...
  3. Integration tests - Added TestIntegration_WindowedListingDoesNotPoisonExistingDirectory, which exercises fastStatBucket with the real LRU/stat cache and fake GCS backend. A live FUSE/GCS end-to-end test was not run.

Any backward incompatible change? If so, please explain.

N/A. The changed method is internal, and no exported API, configuration, or existing authoritative-listing behavior changes.

@nk412
nk412 requested a review from a team as a code owner August 13, 2026 19:51
@nk412
nk412 requested a review from charith87 August 13, 2026 19:51
@google-cla

google-cla Bot commented Aug 13, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modifies the caching behavior in fast_stat_bucket.go to prevent windowed or incomplete listings (such as those with a StartOffset or ContinuationToken) from triggering negative caching. This ensures that incomplete listings do not overwrite valid positive cache entries and cause incorrect ENOENT errors. Unit and integration tests have been added to verify this behavior. There are no review comments, so no additional feedback is provided.

An empty ListObjects result proves a directory does not exist only when
it covers the complete prefix. A windowed listing (StartOffset set) or a
continuation page covers part of the namespace, and inserting a negative
entry from it can overwrite a valid positive implicit-directory entry,
serving false ENOENT for the whole subtree until the negative TTL
expires.

Pass the originating ListObjectsRequest to insertListing and skip the
negative entry when the request has a StartOffset or continuation token,
or when the response carries a continuation token.

Fixes GoogleCloudPlatform#5018
@nk412
nk412 force-pushed the fix/windowed-listing-negative-cache branch from 0c3256d to 16eda58 Compare August 13, 2026 19:55
@meet2mky meet2mky added the kokoro:run Testing kokoro run label Aug 14, 2026
@kokoro-team kokoro-team removed the kokoro:run Testing kokoro run label Aug 14, 2026
@meet2mky meet2mky added execute-integration-tests Run only integration tests execute-integration-tests-on-zb To run E2E tests on zonal bucket. labels Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

execute-integration-tests Run only integration tests execute-integration-tests-on-zb To run E2E tests on zonal bucket.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windowed listings can poison the stat cache and cause false ENOENT for existing implicit directories

3 participants