Skip to content

nvx-rs: compare lock files by their 128-bit file IDs on Windows, as ReFS needs #923

Open

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::unbind opens the sandbox's directory once, and refuses unless the directory's sandbox.lock entry 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 that GetFileInformationByHandle returns: opened_file_identity and handle_identity (windows.rs#L1463-L1475), and Directory::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_file removes 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, which GetFileInformationByHandleEx returns in FILE_ID_INFO. NTFS keeps its 64-bit indexes unique within a volume.
  • A store's directory identities already use 128 bits. Since 46ddf46, identity_of identifies a file or directory by the volume serial number and the 128-bit file ID of FILE_ID_INFO, "which tell the files of ReFS volumes apart too" (lifecycle.rs#L715-L724 and #L741-L749). It takes them from FileSeal::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):

  1. On Windows, compare the lock files by the volume serial number and the 128-bit file ID of FILE_ID_INFO, with FileSeal::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 that identity_of reads, changes no record and no public signature.
  2. 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

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions