-- LogicalVolume.mesa (last edited by: Fay on: January 20, 1981 4:44 PM)
DIRECTORY
Boot USING [nullDiskFileID, LVBootFiles, VolumeType],
File USING [Capability, ID, lastPageNumber, nullCapability, nullID, PageNumber, Type],
PilotFileTypes USING [PilotRootFileType, tFreePage, tVolumeAllocationMap, tVolumeFileMap],
Space USING [Handle],
Volume USING [ID, PageCount],
VolumeInternal USING [PageNumber];
LogicalVolume: DEFINITIONS =
BEGIN
FileVolumeStatus: TYPE = {ok, volumeUnknown, volumeNotOpen, volumeReadOnly, insufficientSpace, insufficientPermissions};
OpenStatus: TYPE = {ok, wasOpen, Unknown, VolumeNeedsScavenging};
ScavengeContext: TYPE = POINTER TO ScavengeRecord;
ScavengeRecord: TYPE; -- EXPORTED by ScavengeImpl.
VolumeAccessStatus: TYPE = FileVolumeStatus[ok..volumeReadOnly];
ReadOnlyVolume: ERROR; -- This should really be a public error
BeginScavenging: PROCEDURE [pVID: POINTER TO READONLY Volume.ID, context: ScavengeContext];
EndScavenging: PROCEDURE [pVID: POINTER TO READONLY Volume.ID];
OpenLogicalVolume: PROCEDURE [POINTER TO READONLY Volume.ID] RETURNS [OpenStatus];
CloseLogicalVolume: PROCEDURE [POINTER TO READONLY Volume.ID];
PutRootFile: PROCEDURE [pVID: POINTER TO READONLY Volume.ID, type: File.Type, file: POINTER TO READONLY File.Capability];
EraseVolume: PROCEDURE [vol: Handle, space: Space.Handle];
ScavengeVolume: PROCEDURE [vol: Handle, space: Space.Handle, context: ScavengeContext];
-- (Note: A Space.handle is identical to a SimpleSpace.handle.)
VolumeAccess: PROCEDURE [pVID: POINTER TO READONLY Volume.ID, proc: VolumeAccessProc, modify: BOOLEAN ← FALSE] RETURNS [VolumeAccessStatus];
VolumeAccessProc: TYPE = PROCEDURE [volume: Handle] RETURNS [updateMarkers: BOOLEAN];
-- The following two procedures are (he says) interim, and used to implement Volume.Open with deleting temps. FileImpl can’t export Volume because of a conflict in File and Volume Unknown; therefore VolumeImpl.Open is merely a call to FileImpl.OpenAndDeleteTemps, which calls VolumeImpl.OpenVolume. Likely, when a volume is closed, context must be flushed from file Impl. Therefore VolumeImpl.Close calls FileImpl.CloseAndFlushFiles, which calls VolumeImpl.CloseVolume and goes God only know what else. It’s time to rewrite the file manager, folks!
OpenVolumeAndDeleteTemps, CloseVolumeAndFlushFiles: PROCEDURE [POINTER TO READONLY Volume.ID];
seal, Seal: CARDINAL = 131313B; -- word zero of valid logical volume root page
currentVersion: CARDINAL = 5; -- increment each time Descriptor below is reformatted
Descriptor: TYPE = MACHINE DEPENDENT RECORD [
--**~~~~~~~~~~~~~~~~~~~~~~~~ Do not reorder the beginning of this record ~~~~~~~~~~~~~~~~~~~~~~~~~~**
seal (0): CARDINAL ← Seal, -- absolutely must be 1st field
version (1): CARDINAL ← currentVersion, -- must be 2nd field
vID (2): Volume.ID,
labelLength (7): CARDINAL[0..maxLogicalVolumeLabelLength) ← 0,
label (10B): PACKED ARRAY [0..maxLogicalVolumeLabelLength) OF CHARACTER ← nullName,
type (34B): Boot.VolumeType,
volumeSize (35B): Volume.PageCount,
bootingInfo (37B): Boot.LVBootFiles ← nullBoot,
--**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Reorder from here on only~~~~~~~~~~~~~~~~~~~~~~~ **
treeLevel (125B): TreeLevel ← LAST[TreeLevel], -- reduce by considering volsize
changing (126B:0..15): BOOLEAN ← TRUE,
freePageCount (127B): Volume.PageCount ← 0,
vamStart (131B): PageNumber ← 1,
vfmStart (133B): PageNumber ← 2, -- +(volumeSize-1)/(bitsPerWord*wordsPerPage)
lowerBound (135B): PageNumber ← 3, -- maintained by allocater; first page looked at by allocator
rootFileID (137B): ARRAY PilotFileTypes.PilotRootFileType OF File.ID ← nullRootFileIDs,
clientRootFile (214B): File.Capability ← File.nullCapability,
interval (222B): Intervals ← nullIntervals,
fill (362B): ARRAY [0..377B-362B) OF WORDALL[0], -- fill to whole page
checksum (377B): CARDINAL ← 0]; -- Must be the last field
Handle: TYPE = LONG POINTER TO Descriptor;
Interval: TYPE = MACHINE DEPENDENT RECORD [
key (0): Key,
volumePage (7): PageNumber,
nextKey (11B): Key];
Intervals: TYPE = ARRAY Level OF Interval; -- lives in volRootPage
Key: TYPE = MACHINE DEPENDENT RECORD [
fileID (0): File.ID,
filePage (5): File.PageNumber];
LSMSeal: CARDINAL = 151515B; -- word zero of a valid subvolume end marker page
LSMCurrentVersion: CARDINAL = 0;-- increment each time SubVolEndMarkerDesc is reformatted
-- The subvolume end marker page marks the end of each subvolume on a physical volume and contains non-reconstructable information from both the physical and logical (following) volume root pages, and a checksum.
LogicalSubvolumeMarker: TYPE = MACHINE DEPENDENT RECORD [
seal (0): CARDINAL ← LSMSeal, -- must be 1st field
version (1): CARDINAL ← LSMCurrentVersion, -- must be 2nd field
-- "Constant" information, that is set only at logical volume creation
labelLength (2:0..5): CARDINAL [0..maxLogicalVolumeLabelLength) ← 0,
type (2:6..7): Boot.VolumeType,
pad (2:8..15): [0..256) ← 0,
label (3): PACKED ARRAY [0..maxLogicalVolumeLabelLength) OF CHARACTER ← nullName,
-- Updatable information
bootingInfo (27B): Boot.LVBootFiles ← nullBoot,
clientRootFile (115B): File.Capability ← File.nullCapability];
Level: TYPE = [0..6); -- six levels of worst case branching of 24 (=16) reaches 224 pages
TreeLevel: TYPE = Level; -- has two names, TreeLevel and Level
PageNumber: TYPE = VolumeInternal.PageNumber;
-- Procs to get/Set Free, Vam, Vfm (this junk is because we don’t have macros!!!!)
-- Following necessary to get around a compiler bug
tFreePage: CARDINAL = LOOPHOLE[PilotFileTypes.tFreePage, CARDINAL];
tVolumeAllocationMap: CARDINAL = LOOPHOLE[PilotFileTypes.tVolumeAllocationMap, CARDINAL];
tVolumeFileMap: CARDINAL = LOOPHOLE[PilotFileTypes.tVolumeFileMap, CARDINAL];
Free: PROCEDURE[v: Handle] RETURNS[File.ID] =
INLINE BEGIN RETURN[v.rootFileID[tFreePage]]; END;
Vam: PROCEDURE[v: Handle] RETURNS[File.ID] =
INLINE BEGIN RETURN[v.rootFileID[tVolumeAllocationMap]]; END;
Vfm: PROCEDURE[v: Handle] RETURNS[File.ID] =
INLINE BEGIN RETURN[v.rootFileID[tVolumeFileMap]]; END;
SetFree: PROCEDURE[v: Handle, f: File.ID] =
INLINE BEGIN v.rootFileID[tFreePage] ← f; END;
SetVam: PROCEDURE[v: Handle, f: File.ID] =
INLINE BEGIN v.rootFileID[tVolumeAllocationMap] ← f; END;
SetVfm: PROCEDURE[v: Handle, f: File.ID] =
INLINE BEGIN v.rootFileID[tVolumeFileMap] ← f; END;
-- Space should really be allocated, not this dribble
FreeVolumePages: PROCEDURE[l: Handle] RETURNS[Volume.PageCount] = INLINE BEGIN RETURN[MAX[LONG[5], l.freePageCount-(l.freePageCount/16)]-5]; END;
-- CONSTANTS
descriptorSize: CARDINAL [0..256] = SIZE[Descriptor];-- compile time check
maxLogicalVolumeLabelLength: CARDINAL = 40;
maxIDRep: RECORD [a, b, c, d, e: WORD] = [177777B, 177777B, 177777B, 177777B, 177777B];
maxID: File.ID = LOOPHOLE[maxIDRep];
maxKey: Key = [maxID, File.lastPageNumber];
nullBoot: Boot.LVBootFiles = ALL[Boot.nullDiskFileID];
nullID: File.ID = File.nullID;
nullInterval: Interval = Interval[nullKey, nullVolumePage, nullKey];
nullIntervals: ARRAY Level OF Interval = ALL[nullInterval];
nullKey: Key = Key[nullID, 0];
nullName: PACKED ARRAY [0..maxLogicalVolumeLabelLength) OF CHARACTER = ALL[0C];
nullRootFileIDs: ARRAY PilotFileTypes.PilotRootFileType OF File.ID = ALL[nullID];
nullVolumePage: PageNumber = 0;
rootPageNumber: PageNumber = 0;
END.
LOG
For earlier log entries see Teak archive version.
Time: February 27, 1980 10:50 AMBy: ForrestAction: Added OpenVolume, CloseVolume, OpenVolumeAndDeleteTemps, CloseVolumeAndFlushFiles. Sigh.
Time: March 5, 1980 10:12 AMBy: ForrestAction: Made OpenVolume return the success boolean. Eliminated op and size from FileAccess Proc
Time: March 7, 1980 11:38 PMBy: ForrestAction: Moved FreeVolumePages here from VolumeImplInterface. Changed OpenVolume and VolumeAccess to return status, and defined status. Eliminated below:
-- NOTE: LogicalVolumeOps.Operations MUST be coordinated with File.Permissions
-- (This should be cleaned up somehow to eliminate parallel definitions...)
Operations: TYPE = [0..256);
noOp:Operations = 0;
-- File.Permissions slip in here
create:Operations = 32;
setVolumeAttributes:Operations = 64;
setFileAttributes:Operations = 128;
Time: April 10, 1980 10:36 AMBy: KnutsenAction: Changed arg of ScavengeVolume from SimpleSpace.handle to Space.handle to reduce compilation dependencies. ScavengeImpl can still use SimpleSpace.handle, which is equivalent.
Time: April 25, 1980 1:40 PMBy: ForrestAction: Changes to get around Mesa 6.0 compiler Bug.
Time: May 30, 1980 3:02 PMBy: LuniewskiAction: {Open Close}Volume => {Open Close}LogicalVolume to get around a multiple export problem in VolumeImpl.
Time: June 16, 1980 9:59 AMBy: LuniewskiAction: Added BeginScavenging, EndScavenging.
Time: June 16, 1980 11:11 AMBy: McJonesAction: Changes for 48-bit processor ids.
Time: July 22, 1980 4:58 PMBy: LuniewskiAction: Interim addition of ReadOnlyVolume (until made public).
Time: September 11, 1980 2:44 PMBy: LuniewskiAction: Changes for new logical volume format
Time: January 20, 1981 4:44 PMBy: FayAction: Added EraseVolume (split off from ScavengeVolume); added ScavengeContext & ScavengeRecord; replaced erase parameter of ScavengeVolume with context parameter; added context parameter to BeginScavenging.