Skip to content

Mds HLD - #4

Open
gmelikov wants to merge 4 commits into
mainfrom
mds
Open

Mds HLD#4
gmelikov wants to merge 4 commits into
mainfrom
mds

Conversation

@gmelikov

Copy link
Copy Markdown
Member

No description provided.

gmelikov added 4 commits July 6, 2026 21:09
Rewrite Mds.md from draft to approved state: single wire protocol with
OST (role subsets, session/data/metadata/volume opcode ranges, unified
{res,len,hash} response frame, version+feature handshake), explicit
chunk map + HRW placement, map_epoch with fence-as-watermark, two-phase
snapshots over native CoW, witness voting rules kept off the failure
hot path (counterexamples included), single MDS instance on SQLite in
v1. Protocol.md points to the shared command space.
Implementation of stage 1 showed the earlier claim wrong: create()
writes sync_id 0 deliberately and F10 recreate relies on it (a random
sync_id on a blank copy reads as split brain at the next open; the
current set's sync_id would claim data the copy does not have). Only
the .spec v0 acceptance is legacy; also record the SET_STATE -ENOSYS
tolerance removal.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces the design specification for the Rawstor Metadata Storage Target (MDS/MDT) specialized for block storage, outlining its architecture, data model, protocol changes, and implementation stages. The review feedback highlights a few areas for improvement in the design document, including a signature mismatch in the placement pseudocode, a potential inconsistency scenario if the MDS crashes during migration, and a missing OST-level opcode definition for client-driven snapshots.

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 Mds.md
Comment on lines +298 to +301
place(volume_id, index):
slots = HRW_choose(width, level=failure_domain, key) // distinct domains
for s in slots: ost = HRW_descend_to_leaf(s, key)
return [(slot_index, ost) ...]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The pseudocode for place is missing the topology parameter in its definition, even though the signature on line 282 defines it as place(volume_id, index, topology). Additionally, the variable key is used within the function body but is not defined or passed in. It would be clearer to show how key is derived from stripe_width and the volume/index.

Suggested change
place(volume_id, index):
slots = HRW_choose(width, level=failure_domain, key) // distinct domains
for s in slots: ost = HRW_descend_to_leaf(s, key)
return [(slot_index, ost) ...]
place(volume_id, index, topology):
key = derive_key(volume_id, index, policy.stripe_width)
slots = HRW_choose(width, level=failure_domain, key, topology) // distinct domains
for s in slots: ost = HRW_descend_to_leaf(s, key, topology)
return [(slot_index, ost) ...]

Comment thread Mds.md
Comment on lines +395 to +398
1. copy the slot to the new OST (resync machinery, source = an IN-SYNC slot)
2. MDS reserves E' = map_epoch + 1; record E' as slot.fence on the OLD owner (fsync'd)
3. MDS: chunk_map[index] slot -> new ost_id, publish map_epoch = E'
4. (later) release the old slot

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

If the MDS crashes after Step 2 (fence recorded on the OLD owner) but before Step 3 (updating the map and publishing the new epoch E'), the system enters an inconsistent state. The OLD owner will reject client writes with STALE because client_map_epoch < slot.fence. However, when the client queries the MDS to refresh its map, the MDS (having restarted and lost the uncommitted state) will return the old map with the old epoch. This will cause the client to loop indefinitely or fail. Consider detailing how the MDS guarantees atomicity or recovers/resumes this multi-node migration sequence (e.g., via a persistent transaction state in SQLite).

Comment thread Mds.md
Comment on lines +427 to +433
snapshot(volume_id):
MDS: VOL_SNAPSHOT begin -> reserve snap_id
client: drain in-flight I/O, FLUSH all IN-SYNC members (point-in-time barrier)
OST*: each IN-SYNC member -> backend CoW (zfs snapshot zvol@<snap_id> / lvcreate -s)
MDS: VOL_SNAPSHOT commit -> record snapshots[snap_id] { members = the IN-SYNC set },
map_epoch++
read: client SET_OBJECT(volume_id, val = snap_id) -> OST serves that version

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

In the client-driven snapshot sequence, the client is responsible for triggering the backend CoW on each IN-SYNC OST member. However, the "Protocol deltas" and "Wire protocol" sections do not define an OST-level opcode for this action (only MDS-level CMD_VOL_* opcodes are listed). To make the design complete, please specify the opcode or mechanism the client uses to instruct an OST to perform the backend CoW (e.g., CMD_OST_SNAPSHOT or an extension of SET_STATE).

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