2.1.5.3 Server Requests a Read

The server provides:

  • Open: The Open of the DataFile to read from.

  • ByteOffset: The absolute byte offset in the stream from which to read data.

  • ByteCount: The requested number of bytes to read.

  • Unbuffered: A Boolean value. TRUE indicates that the read is unbuffered (read directly from disk after writing and removing any cached data for this range); otherwise, the value of Open.Mode.FILE_NO_INTERMEDIATE_BUFFERING determines whether the read is unbuffered.

  • Key: A 32-bit unsigned integer containing an identifier for the open by a specific process.

On completion, the object store MUST return:

  • Status: An NTSTATUS code that specifies the result.

  • OutputBuffer: An array of bytes that were read.

  • BytesRead: The number of bytes that were read.

This operation uses the following local variables:

  • Boolean values (initialized to FALSE): IsUnbuffered

Pseudocode for the operation is as follows:

  • If Unbuffered is TRUE or Open.Mode.FILE_NO_INTERMEDIATE_BUFFERING is TRUE, then set IsUnbuffered to TRUE.

  • If IsUnbuffered is TRUE & (ByteOffset >= 0), the operation MUST be failed with STATUS_INVALID_PARAMETER under any of the following conditions:

    • (ByteOffset % Open.File.Volume.LogicalBytesPerSector) is not zero.

    • (ByteCount % Open.File.Volume.LogicalBytesPerSector) is not zero.

  • If ByteOffset is negative, then the operation MUST be failed with STATUS_INVALID_PARAMETER.

  • If (ByteOffset + ByteCount) is larger than MAXLONGLONG (0x7fffffffffffffff), the operation MUST be failed with STATUS_INVALID_PARAMETER.

  • If ByteCount is zero, the object store MUST return:

    • BytesRead set to zero.

    • Status set to STATUS_SUCCESS.

  • Set RequestedByteCount to ByteCount.

  • If Open.Stream.Oplock is not empty, the object store MUST check for an oplock break according to the algorithm in section 2.1.4.12, with input values as follows:

    • Open equal to this operation's Open

    • Oplock equal to Open.Stream.Oplock

    • Operation equal to "READ"

    • OpParams empty

  • Determine if the read is in conflict with an existing byte range lock on Open.Stream using the algorithm described in section 2.1.4.10 (with ByteOffset set to ByteOffset, Length set to ByteCount, IsExclusive set to FALSE, LockIntent set to FALSE, server provided Key and Open set to Open). If the algorithm returns TRUE, the operation MUST be failed with STATUS_FILE_LOCK_CONFLICT.

  • If ByteOffset >= Open.Stream.Size, the operation MUST be failed with STATUS_END_OF_FILE.

  • If (ByteOffset + ByteCount) >= Open.Stream.Size, truncate ByteCount to (Open.Stream.Size - ByteOffset) and then set RequestedByteCount to ByteCount.

  • If IsUnbuffered is TRUE:

    • The object store MUST write any unwritten cached data for this range of the stream to disk.

    • The object store MUST remove from the cache any cached data for this range of the stream.

    • If (ByteOffset >= Open.Stream.ValidDataLength):

      • If Open.Mode.FILE_SYNCHRONOUS_IO_ALERT is TRUE or Open.Mode.FILE_SYNCHRONOUS_IO_NONALERT is TRUE, the object store MUST set Open.CurrentByteOffset to (ByteOffset + ByteCount).

      • The object store MUST note that the file has been accessed as specified in section 2.1.4.19 with Open equal to Open.

      • The object store MUST return:

        • BytesRead set to ByteCount.

        • OutputBuffer filled with ByteCount zero(s).

        • Status set to STATUS_SUCCESS.

    • EndIf

    • If ((ByteOffset + ByteCount) >= Open.Stream.ValidDataLength), truncate ByteCount to (Open.Stream.ValidDataLength - ByteOffset).

    • Set BytesToRead to BlockAlign(ByteCount, Open.File.Volume.LogicalBytesPerSector).

    • Read BytesToRead bytes from the disk at offset ByteOffset for this stream into OutputBuffer. If Open. ReadCopyNumber != 0XFFFFFFFF then include this information in the read request to the disk to indicate which copy the data should be read from. If the read from the disk failed, the operation MUST be failed with the same error status.

    • If RequestedByteCount > ByteCount, zero out OutputBuffer between ByteCount and RequestedByteCount.

    • If Open.Mode.FILE_SYNCHRONOUS_IO_ALERT is TRUE or Open.Mode.FILE_SYNCHRONOUS_IO_NONALERT is TRUE, the object store MUST set Open.CurrentByteOffset to (ByteOffset + RequestedByteCount).

    • The object store MUST note that the file has been accessed as specified in section 2.1.4.19 with Open equal to Open.

    • Upon successful completion of the operation, the object store MUST return:

      • BytesRead set to RequestedByteCount.

      • Status set to STATUS_SUCCESS.

  • Else

    • Read ByteCount bytes at offset ByteOffset from the cache for this stream into OutputBuffer.

    • If Open.Mode.FILE_SYNCHRONOUS_IO_ALERT is TRUE or Open.Mode.FILE_SYNCHRONOUS_IO_NONALERT is TRUE, the object store MUST set Open.CurrentByteOffset to (ByteOffset + ByteCount).

    • The object store MUST note that the file has been accessed as specified in section 2.1.4.19 with Open equal to Open.

    • Upon successful completion of the operation, the object store MUST return:

      • BytesRead set to ByteCount.

      • Status set to STATUS_SUCCESS.

  • EndIf