Repository navigation
nvx-rs: compare lock files by their 128-bit file IDs on Windows, as ReFS needs #923
Description
Related: a follow-up to #885 (#839's PR 3), whose removal check this concerns. Refs #839. Needs: #885.
Goal. On Windows, the checks that tell whether two handles or paths reach the same lock file tell any two files of a volume apart, ReFS volumes included, as a store's directory identities already do.
Today (#885's head 4a8b5341):
- A removal's unbinding compares 64-bit file indexes.
LockedStore::unbindopens the sandbox's directory once, and refuses unless the directory'ssandbox.lockentry is the file whose lock the removal holds (lifecycle.rs#L382-L392). On Windows, both sides are the volume serial number and the 64-bit file index thatGetFileInformationByHandlereturns:opened_file_identityandhandle_identity(windows.rs#L1463-L1475), andDirectory::entry_identity(windows.rs#L1299-L1318). - The lock checks compare the same identity. After it takes a lock, the sandbox store keeps it only if the path still names the locked file (
take_lock,store/mod.rs#L575-L585), as nvx-rs: add the template store #881's template store does (template/store.rs#L799-L806).remove_unprovisioned_lock_fileremoves the lock file only if it is the held one (lifecycle.rs#L248-L253). - ReFS doesn't keep those indexes unique.
BY_HANDLE_FILE_INFORMATION: "The 64-bit identifier in this structure is not guaranteed to be unique on ReFS." ReFS identifies a file by 128 bits, whichGetFileInformationByHandleExreturns inFILE_ID_INFO. NTFS keeps its 64-bit indexes unique within a volume. - A store's directory identities already use 128 bits. Since 46ddf46,
identity_ofidentifies a file or directory by the volume serial number and the 128-bit file ID ofFILE_ID_INFO, "which tell the files of ReFS volumes apart too" (lifecycle.rs#L715-L724and#L741-L749). It takes them fromFileSeal::of, which falls back to the 64-bit index on a volume without file ID information (seal/windows.rs#L47-L68).
Why it matters. Two files of one ReFS volume that share a 64-bit index pass these checks as one file.
- The unbinding's check keeps a link in the sandbox's path, changed after the removal took its lock, from redirecting the unbinding to another sandbox, whose binding a clone may still need (#885's review). A collision between the two sandboxes' lock files reopens that race.
- A collision between a replaced lock file and its replacement lets one transition keep a lock on the replaced file while another one locks the new file.
Scope (one PR, after #885):
- On Windows, compare the lock files by the volume serial number and the 128-bit file ID of
FILE_ID_INFO, withFileSeal::of's fallback, in the unbinding's check and in the lock checks above. These checks compare two files at one moment, so a crate-internal identity, such as the one thatidentity_ofreads, changes no record and no public signature. - Tests that two files of one directory get different identities, and that each identity matches the file's
FileSeal.
Not in scope: FileIdentity, whose index is 64 bits (filesystem.rs#L189-L197), which the launch journal records for its claimed log, and which log_claim_held checks (windows.rs#L1503-L1519); and the public platform::file_identity (windows.rs#L1240-L1249). Widening them changes a record format and the crate's API, which a later issue can decide.
Done when: on Windows, the unbinding's check and the lock checks compare 128-bit file IDs wherever the volume provides them, and the tests pass.
Activity