Skip to content

Implement filesystem foundation milestones#996

Draft
bootjp wants to merge 7 commits into
mainfrom
design/filesystem-elastickv-foundation
Draft

Implement filesystem foundation milestones#996
bootjp wants to merge 7 commits into
mainfrom
design/filesystem-elastickv-foundation

Conversation

@bootjp

@bootjp bootjp commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Summary

  • add protocol-neutral filesystem core APIs and filesystem route-key helpers
  • add open-handle lease refresh/reaping, orphan cleanup, and capacity-aware StatFS
  • add a thin FUSE errno/session adapter and FILE_PINNED hotspot skip metric

Design doc

  • docs/design/2026_02_24_partial_filesystem_on_elastickv.md

Validation

  • go test ./internal/fskeys ./internal/filesystem/... ./adapter ./monitoring -run 'TestExtractRouteKey|TestNormalizeSplitBoundary|TestService|TestDistributionServerSplitRange|TestFileSystemMetrics|TestRegistryReturnsFileSystemObserver' -count=1
  • golangci-lint --config=.golangci.yaml run ./internal/fskeys ./internal/filesystem/... ./adapter ./monitoring --timeout=5m
  • git verify-commit for all branch commits

Author: bootjp

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8ba365c9-2933-476d-9c86-57d2e9cb91ef

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@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 introduces a filesystem layer on top of Elastickv, implementing a core filesystem service, a FUSE session adapter, key formatting utilities, and manual split boundary snapping with associated metrics. The review feedback highlights several critical issues: a bug in extracting gRPC status codes from wrapped errors, atomicity violations in SetAttr, Release, and lease reaping due to split transactions, a performance bottleneck in StatFS caused by scanning the entire keyspace, and an optimization opportunity in the Write path to avoid redundant reads on full chunk overwrites.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread adapter/distribution_server.go
Comment thread internal/filesystem/service.go
Comment thread internal/filesystem/service.go
Comment thread internal/filesystem/service.go
Comment thread internal/filesystem/service.go
Comment thread internal/filesystem/service.go
@bootjp

bootjp commented Jul 8, 2026

Copy link
Copy Markdown
Owner Author

Addressed the latest-head filesystem review blockers.

Changes:

  • unwrap stacked gRPC errors before checking split-boundary status codes
  • keep SetAttr size truncation and metadata updates in one filesystem transaction
  • keep Release / expired lease reaping ref deletion and orphan GC in one filesystem transaction
  • make Open touch the inode key so new refs conflict with concurrent orphan GC under OCC
  • replace StatFS full keyspace scans with a !fs|usage counter updated atomically with create/delete/write/truncate/GC
  • skip chunk read/readKey for full-chunk writes and add regression coverage

Validation run on this head:

  • go test ./internal/filesystem -count=1 -timeout=120s
  • go test ./adapter -run 'TestDistributionServerSplitRange' -count=1 -timeout=120s\n- go test ./internal/fskeys ./internal/filesystem/... ./adapter ./monitoring -run 'TestExtractRouteKey|TestNormalizeSplitBoundary|TestService|TestDistributionServerSplitRange|TestFileSystemMetrics|TestRegistryReturnsFileSystemObserver' -count=1 -timeout=240s\n- golangci-lint --config=.golangci.yaml run ./internal/fskeys ./internal/filesystem/... ./adapter ./monitoring --timeout=5m\n- go test ./... -run TestNonexistent -count=0\n- git diff --check\n- git verify-commit HEAD\n\nNote: an unfiltered go test ./internal/fskeys ./internal/filesystem/... ./adapter ./monitoring -count=1 -timeout=240s timed out in long-running adapter integration coverage after the targeted adapter/filesystem checks above passed.\n\n@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4f140605b5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/filesystem/service.go Outdated
Comment thread internal/filesystem/service.go Outdated
Comment thread internal/filesystem/service.go
Comment thread internal/filesystem/service.go Outdated
Comment thread internal/filesystem/service.go Outdated
Comment thread internal/filesystem/service.go Outdated
Comment thread internal/filesystem/service.go Outdated
Comment thread internal/filesystem/service.go
Comment thread internal/filesystem/fuseadapter/adapter.go
Comment thread internal/filesystem/fuseadapter/adapter.go
@bootjp

bootjp commented Jul 8, 2026

Copy link
Copy Markdown
Owner Author

Addressed the latest-head filesystem review findings on a7528bdd5f409c23b159df30a0aedae7acd6ca1a.

Changes:

  • revalidate current open-handle leases before expired-lease reaping deletes refs
  • page lease reaper scans so live refs at the front do not starve later expired refs
  • account full-chunk writes from the stored sparse/trimmed chunk length while keeping blind-write readKeys narrow
  • replace inode-touching open fencing with a ref fence key and retry write conflicts internally
  • propagate ref scan errors and fence observed refs before unlink/orphan GC
  • unlink or orphan overwritten rename targets and preserve no-op rename existence checks
  • preserve sparse tails and scan existing chunk keys for truncate/GC instead of logical sparse ranges
  • update mtime for size-only SetAttr
  • map filesystem OCC conflicts to EAGAIN and refresh FUSE handle leases before handle I/O

Validation:

  • go test ./internal/fskeys ./internal/filesystem/... -count=1 -timeout=180s
  • go test ./adapter -run 'TestDistributionServerSplitRange' -count=1 -timeout=120s
  • go test ./internal/fskeys ./internal/filesystem/... ./adapter ./monitoring -run 'TestRefFence|TestService|TestErrno|TestAdapter|TestDistributionServerSplitRange|TestFileSystemMetrics|TestRegistryReturnsFileSystemObserver' -count=1 -timeout=240s
  • golangci-lint --config=.golangci.yaml run ./internal/fskeys ./internal/filesystem/... ./adapter ./monitoring --timeout=5m
  • go test ./... -run TestNonexistent -count=0
  • git diff --check
  • git verify-commit HEAD

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a7528bdd5f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +797 to +799
if replacedEntry.Type == TypeDirectory {
return nil, ErrIsDir
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject directory renames over files

When the source entry is a directory and newName already names a regular file, this helper treats the target as replaceable because it only rejects directory targets. The caller then overwrites the file's dirent with the directory and unlinks/GCs the file, so rename(dir, file) succeeds instead of returning a type error; please compare the source and target types before allowing replacement.

Useful? React with 👍 / 👎.

Comment on lines +1517 to +1520
err := s.scanExistingChunks(ctx, meta, ts, start, func(pair *store.KVPair) error {
delta = delta.merge(usageDelta{bytesSub: uint64(len(pair.Value))})
elems = append(elems, &kv.Elem[kv.OP]{Op: kv.Del, Key: pair.Key})
readKeys = append(readKeys, pair.Key)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Page chunk deletes before building the transaction

For truncating a file with more than 10,000 stored chunks (about 40 GiB at the default 4 MiB chunk size), this loop appends every chunk key to ReadKeys; the coordinator rejects transactions once len(ReadKeys) > 10_000, so large-file truncation can fail instead of deleting the tail. The same unbounded read set is used by file GC below, so unlink/release/rename-over-target can hit the same limit; please page these deletes/usage updates or avoid a single read set that grows with the whole file.

Useful? React with 👍 / 👎.

Comment thread kv/shard_key.go
Comment on lines +77 to +79
if user := fskeys.ExtractRouteKey(key); user != nil {
return user
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Normalize filesystem keys in GetRoute too

This branch makes the data path route !fs|chk|... through the virtual !fs|route|chk|... domain, but DistributionServer.GetRoute still calls engine.GetRoute(req.Key) directly. After a filesystem boundary split, a GetRoute request for a raw chunk key can return the pre-boundary route or miss because !fs|chk|... sorts before !fs|route|chk|..., while reads and writes go to the normalized route; please reuse the same normalization for the distribution RPC so control-plane lookups match data-path routing.

Useful? React with 👍 / 👎.

}
end := prefixEnd(prefix)
for {
page, err := s.store.ScanAt(ctx, start, end, statFSScanPageSize, ts)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Route filesystem chunk scans through the chunk route domain

When this service is backed by kv.ShardStore, chunk writes are stored on the group selected by routeKey(fskeys.ChunkKey(...)) (the virtual !fs|route|chk|... key), but this raw !fs|chk|... range scan is routed by ShardStore.ScanAt using the raw scan bounds. In a multi-range deployment where the raw chunk prefix and the virtual chunk-route prefix resolve to different groups, truncate/GC scans return no chunks, leaving deleted file data behind and usage deltas wrong; route these chunk prefix scans through the same filesystem route domain or scan the owning group directly.

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant