-- File: DiskIODefs.mesa
-- Last edited by Levin: 24-Nov-80 13:30:15
DIRECTORY
AltoDefs USING [MaxFilePage, PageNumber],
AltoFileDefs USING [DISK, eofDA, fillinDA, SN, vDA, vDC];
DiskIODefs: DEFINITIONS =
BEGIN
-- A brief discourse on the design and intended use of this interface:
-- This interface is intended to be a functional replacement for the DiskDefs
-- interface of Alto/Mesa, which in turn is a version of the low-level parts of
-- the original BCPL BFS package. The major difference is that DiskIODefs, as
-- distinct from Mesa's DiskDefs, offers asynchronous disk transfers. The package
-- is capable of queuing multi-page transfer requests at once, and can take
-- advantage of the chaining tricks used in the BFS. However, this interface does
-- not force its clients to understand how disk control blocks are constructed and
-- manipulated. Thus, the BFS concepts of 'CBZone' and a 'CB' are not needed here.
-- All disk transfer requests that this interface supports are expressed in a
-- 'DiskRequest', defined below. The implicit assumptions in the design of this
-- structure are the following (it may be helpful to refer to the definition of
-- 'DiskRequest' while reading this list):
-- 1) Each DiskRequest transfers a sequence of consecutive pages within a single
-- file. (Exception: in the case of operations used for file extension, some
-- pages may not (yet) be part of the file.)
-- 2) A file is uniquely identified by its file ID (FID), and a page within the
-- file is uniquely identified by a page number. These are the standard
-- conventions of the Alto file system.
-- 3) Pages are transfered strictly in the order that they appear in the 'xfers'
-- array, that is, in order of increasing page number within the file.
-- 4) A CompletionProcedure will be invoked as each page transfer completes. (For
-- an exception, see item 6, below.) If the transfer produces an error, the
-- transfer will be retried an appropriate number of times. Thus, the
-- CompletionProcedure will be invoked only when the transfer has either completed
-- successfully or when a permanent error has occurred. (However, a permanent
-- error causes all subsequently queued transfers to be inhibited. These
-- inhibited requests will cause the completion procedure to be invoked with
-- status = neverStarted.)
-- 5) A VerboseCompletionProcedure should be used only when the requestor wishes
-- to obtain information stored in the header or label of the disk page. Calling
-- a VerboseCompletionProcedure requires substantially more computation than
-- calling a NormalCompletionProcedure.
-- 6) 'xfers[i]' identifies a page to be transferred. These pages are implicitly
-- sequential in the file, the first being 'firstPage+pagesToSkip'. Each
-- XferSpec contains a pointer to the buffer for the page, the associated disk
-- address, and an identifier supplied by the caller which will identify the page
-- to the CompletionProcedure. If the disk address is 'fillInvDA', the disk
-- driver will attempt to deduce the address from the label of the previous page
-- in the file. This implies that if xfers[0].vDA is 'fillInvDA', the disk
-- driver must read pages from the disk beginning at 'firstPage' and continuing
-- for 'pagesToSkip-1' pages in order to determine the disk address. If a
-- VerboseCompletionProcedure has been specified, it will be called for each
-- such read operation. The 'id' parameter in this case will be the value
-- 'request.nonXferID', which the client should ensure is distinct from all
-- 'xfers[i].id'. A NormalCompletionProcedure will not be invoked for such
-- reads. (The buffer used to hold the data for such reads is supplied
-- by the disk driver.)
-- 7) If 'pagesToSkip' is non-zero, the client must supply the disk address
-- corresponding to 'fileID' and 'firstPage' in 'firstPagevDA'. In this case,
-- xfers[i].vDA should be 'fillInvDA', and the disk driver behaves as described
-- in item 6 above. If 'pagesToSkip' is zero, 'firstPagevDA' is ignored and
-- xfers[0].vDA cannot be 'fillInvDA'. Some initial subsequence of the 'xfers'
-- must have valid addresses in their vDA fields. Once xfers[k].vDA equals
-- 'fillInvDA', for some k, xfers[i].vDA should be 'fillInvDA' for all i>k.
-- 8) DiskRequests that specify writing of labels (WriteHLD or WriteLD) must
-- furnish additional information to complete the label field. The 'next' and
-- 'prev' fields of the variant record are used by the disk driver to complete
-- the labels at the ends of the consecutive page sequence described by 'xfers'.
-- The 'lastByteCount' field permits the last page of the file to be partially
-- used; it will be ignored unless 'next' is 'eofvDA'. In addition, 'pagesToSkip'
-- must be zero and all elements of 'xfers' must contain explicit disk addresses
-- (NOT 'fillInvDA') when either WriteHLD or WriteLD is specified. This
-- requirement is imposed because the disk driver will overwrite the labels
-- instead of reading them, and therefore cannot use the existing links in
-- them for chaining purposes. For related reasons, the same restrictions on
-- 'pagesToSkip' and vDA fields apply to ReadHLD. (Clients that write labels
-- should be careful not to violate the invariants of the Alto File System.)
-- 9) The client of this interface can freely release the storage used to hold the
-- DiskRequest or XferSpecs immediately after InitiateDiskIO returns.
-- Specifically, these data structures need not be retained until
-- CompletionProcedures are invoked.
-- Types and Related Constants --
vDA: TYPE = AltoFileDefs.vDA;
vDC: TYPE = AltoFileDefs.vDC;
SN: TYPE = AltoFileDefs.SN;
DISK: TYPE = AltoFileDefs.DISK;
FID: TYPE = MACHINE DEPENDENT RECORD [version: CARDINAL, serial: SN];
PageCount: TYPE = [0..AltoDefs.MaxFilePage];
eofvDA: vDA = AltoFileDefs.eofDA;
fillInvDA: vDA = AltoFileDefs.fillinDA;
DiskRequest: TYPE = RECORD [
firstPage: AltoDefs.PageNumber,
fileID: FID,
firstPagevDA: vDA,
pagesToSkip: PageCount,
nonXferID: RequestID,
xfers: DESCRIPTOR FOR ARRAY OF XferSpec,
proc: CompletionProcedure,
noRestore: BOOLEAN,
command: SELECT action: vDC FROM
ReadHLD, ReadLD, ReadD, WriteD, SeekOnly, DoNothing => NULL,
WriteHLD, WriteLD => [next, prev: vDA, lastByteCount: CARDINAL],
ENDCASE];
XferSpec: TYPE = RECORD [buffer: POINTER, diskAddress: vDA, id: RequestID];
CompletionProcedure: TYPE = RECORD [
SELECT tag: * FROM
normal => [proc: NormalCompletionProcedure],
verbose => [proc: VerboseCompletionProcedure],
ENDCASE];
NormalCompletionProcedure: TYPE = PROCEDURE [id: RequestID, status: CompletionStatus];
VerboseCompletionProcedure: TYPE = PROCEDURE [
id: RequestID, status: CompletionStatus, header: POINTER TO vDH, label: POINTER TO vDL];
CompletionStatus: TYPE = {
noStatus, ok, neverStarted, checkError, checksumError, diskOffline, dataLate,
seekFailure, badDiskAddress};
RequestID: TYPE = UNSPECIFIED;
vDH: TYPE = MACHINE DEPENDENT RECORD [packID: CARDINAL, diskAddress: vDA];
vDL: TYPE = MACHINE DEPENDENT RECORD [
next, prev: vDA,
undefined1: UNSPECIFIED,
bytes: CARDINAL,
undefined2: [0..1],
page: AltoDefs.PageNumber,
fileID: FID];
RequestError: TYPE = {badvDA, illegalvDASequence, tooManyTransfers, illegalTransfer};
-- Procedures and Signals --
InitializeDiskIO: PRIVATE PROCEDURE [minOps: CARDINAL] RETURNS [nOps: CARDINAL];
-- initializes the disk IO package with a minimum of 'minOps' page transfers
-- permitted simultaneously. The actual number permitted is returned. Note that this
-- procedure is PRIVATE, and should therefore be called only by knowledgeable clients
-- (i.e., the VM level).
FinalizeDiskIO: PRIVATE PROCEDURE;
-- finalizes the disk IO package. Note that this is a private procedure, and should
-- therefore be called only by knowledgeable clients (i.e., the VM level).
ResetDiskShape: PRIVATE PROCEDURE [disk: DISK];
-- resets the parameters that describe the shape of the disk. Note that this
-- procedure is PRIVATE, and should therefore be called only by knowledgeable clients
-- (i.e., the VM level).
InitiateDiskIO: PROCEDURE [operation: POINTER TO DiskRequest];
-- initiates the requested disk transfers and returns to the caller. The
-- CompletionProcedure in the argument DiskRequest is invoked as each transfer
-- terminates. If 'operation' is somehow invalid or malformed, 'BogusDiskRequest'
-- will be raised.
BogusRequest: ERROR [reason: RequestError, operation: POINTER TO DiskRequest];
-- raised by InitiateDiskIO because the disk request is invalid for some reason.
-- The 'reason' parameter indicates why the request is unacceptable.
DiskError: ERROR [status: CompletionStatus];
-- a convenient signal for use by higher levels (strange as that may seem).
END.